1

私の理解では、プロトタイプチェーンをチェックせずにオブジェクトに特定のメンバーがある場合、「hasOwnProperty」はtrueを返します。しかし、他のオブジェクトから継承すると、最後のオブジェクト自体にすべてのメンバーが表示されます。

次の例を考えてみましょう。

var Object1 = function (param) {
    this.prop1 = "p1 " + param;
    this.prop2 = "p2 " + param;
};

var Object2 = function (param) {
    Object1.apply(this, arguments);
    this.prop3 = 'p3' + param;
};

Object2.prototype = new Object1();

var b = new Object2('this is Object 2');

for (var v in b)
    print(v + ": " + b[v] + (b.hasOwnProperty(v)?' (own)':' (inherited)'));

このコードは次のように出力します。

--prop1: p1 this is Object 2 (own)
--prop2: p2 this is Object 2 (own)
--prop3: p3this is Object 2 (own)

デバッガーを見ると、次のように表示されます。

b
  Object2
    prop1: "p1 this is Object 2"
    prop2: "p2 this is Object 2"
    prop3: "p3this is Object 2"
    __proto__: Object1

しかし、私はその行を削除しapplyます。すべてがより理にかなっていますが、ベースオブジェクトは初期化されていません。

--prop3: p3this is Object 2 (own)
--prop1: p1 undefined (inherited)
--prop2: p2 undefined (inherited)

これで、デバッガーに次のように表示されます。

b
  Object2
    prop3: "p3this is Object 2"
    __proto__: Object1
      prop1: "p1 undefined"
      prop2: "p2 undefined"
      __proto__: Object

私の知る限り、これapplyは...スーパークラスコンストラクターを実行するようなものなので、スーパーメンバーは正しく初期化されますが、明らかに子オブジェクトの形状が変わります。

なぜこうなった?JSで継承する正しい方法(または少なくとも面倒ではない方法)は何ですか?

私はそれについていくつかの情報を調べています、そしてどうやら各開発者はそれを行う方法について異なる感情を持っています。

よろしく。

4

1 に答える 1

2

applyスーパークラスコンストラクターの実行とはまったく異なります。コンストラクトとして、最初に指定された引数のスコープ内で任意の関数を実行します。関数 (コンストラクターとしてではなく関数として実行する) に渡す場合、2 番目の関数 ( ) が実行されているスコープを通過します。thisObject1Object2

何が起こっているかを確認するには、Object1("param") なし newで実行してみてください:

Object1("test");

実行するnew Object1("test")と、次のようなオブジェクトが返されます。

Object { prop1="p1 test", prop2="p2 test"}

しかし、実行すると ...Object1("test")が返され、 (ブラウザ JavaScript の場合に最も可能性が高い) にundefined等しいオブジェクトで、2 つの新しい変数 ...とが見つかります。thiswindowprop1prop2

どうしたの?

ここでの鍵は次のとおりです。

Object1("param") !== new Object1("param");

The first version (Object1("param")) executes a function (Object1) in some already existing scope (in browser JavaScript the most common scope is the top-level scope where this === window.) This is the way you are invoking Object1 when you call Object1.apply(this).

The second version (new Object1("param")) executes a function as a constructor - that is, it creates a new object and sets this to be that new object. If we were to use the same apply function to demonstrate this we would write Object1.apply({});

For one of the most definitive answers I have ever seen on the subject of how to do OOP-like programming right in a JavaScript environment, see Bobince's answer to this question.

于 2011-09-12T15:54:28.347 に答える