1. ホーム
  2. ジャバスクリプト

[解決済み】プロトタイプを使用する利点と、コンストラクタで直接メソッドを定義する利点は?重複

2022-04-16 23:38:06

質問

どれを使っても良いということはないのでしょうか、また、どちらにすれば良いのでしょうか。

コンストラクタのアプローチ。

var Class = function () {

    this.calc = function (a, b) {
        return a + b;
    };

};

プロトタイプのアプローチ。

var Class = function () {};

Class.prototype.calc = function (a, b) {
    return a + b;
};

プロトタイプを使用すると、メソッドの定義がクラスから分離されるのが気に入らないのですが、最初のアプローチではなくこれを使用しなければならない特別な理由があるのかどうかはわかりません。

また、関数定義だけでなく、関数リテラルを使用して "クラス" を定義する利点はありますか。

var Class = function () {};

function Class () {};

ありがとうございました。

解決方法は?

プロトタイプチェーンを介して継承されるメソッドは、例えば、すべてのインスタンスに対して普遍的に変更することができます。

function Class () {}
Class.prototype.calc = function (a, b) {
    return a + b;
}

// Create 2 instances:
var ins1 = new Class(),
    ins2 = new Class();

// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2

// Change the prototype method
Class.prototype.calc = function () {
    var args = Array.prototype.slice.apply(arguments),
        res = 0, c;

    while (c = args.shift())
        res += c;

    return res; 
}

// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3

メソッドを変更すると、両方のインスタンスに適用されることにお気づきですか? これは ins1ins2 は、同じ calc() 関数を使用します。 構築中に作成されたパブリックメソッドでこれを行うには、作成された各インスタンスに新しいメソッドを割り当てなければなりませんが、これは厄介な作業です。 というのも ins1ins2 は、それぞれ個別に作成された calc() 関数を使用します。

コンストラクタの内部でメソッドを作成することのもうひとつの副作用は、パフォーマンスの低下です。 各メソッドは、コンストラクタ関数が実行されるたびに作成する必要があります。 プロトタイプチェーン上のメソッドは一度生成された後、各インスタンスに継承されます。 一方、publicメソッドはprivate変数にアクセスできますが、継承されたメソッドではアクセスできません。

については function Class() {}var Class = function () {} の質問では、前者は実行前に現在のスコープの先頭に "hoisted"されます。 後者の場合、変数宣言はホイストされますが、代入はホイストされません。 例えば

// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); } 

// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }