25

コードは3行しかありませんが、これを完全に把握するのに問題があります。

Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
};
newObject = Object.create(oldObject);

プロトタイプの継承から)

  1. Object.create()と呼ばれる空の関数を作成することから始めますF。関数は一種のオブジェクトだと思います。このFオブジェクトはどこに保存されていますか?世界的に私は推測します。

  2. 次に、oldObjectとして渡されたo、が関数のプロトタイプになりますF。関数(つまり、オブジェクト)は、名前解決がそれを経由するという意味で、F私たちから「継承」するようになりました。oldObject良いですが、オブジェクトのデフォルトのプロトタイプが何であるか知りたいのですが、Object?それは関数オブジェクトにも当てはまりますか?

  3. 最後に、Fがインスタンス化されて返され、私たちのになりますnewObject。ここでのnew操作は厳密に必要ですか?必要なものをまだ提供していませんFか、または関数オブジェクトと非関数オブジェクトの間に重大な違いがありますか?明らかに、この手法を使用してコンストラクター関数を作成することはできません。

次回Object.create()はどうなりますか?グローバル関数はF上書きされますか?以前に構成されたオブジェクトが変更されるため、再利用されないことは確かです。また、複数のスレッドが呼び出された場合はどうなりますか?Object.create()競合状態を防ぐための同期はありますFか?

4

4 に答える 4

30

1)Object.create()は、Fという空の関数を作成することから始まります。関数は一種のオブジェクトだと思います。このFオブジェクトはどこに保存されていますか?世界的に私は推測します。

いいえ、関数のローカルスコープに保存され、この関数Object.createを呼び出すたびに再作成されます。Object.createF

Fクロージャーに保存して再利用することで、よりメモリ効率の高い実装を作成することもできます。

if (typeof Object.create !== "function") {
  Object.create = (function () {
    function F() {} // created only once
    return function (o) {
      F.prototype = o; // reused on each invocation
      return new F();
    };
  })();
}

2)次に、oとして渡されたoldObjectは、関数Fのプロトタイプになります。関数(つまり、オブジェクト)Fは、名前解決がoldObjectを経由するという意味で、oldObjectから「継承」します。良いですが、オブジェクトのデフォルトのプロトタイプが何であるか知りたいのですが、Object?それは関数オブジェクトにも当てはまりますか?

すべてのオブジェクトには、プロトタイプチェーンを構築する内部プロパティがあります。このプロパティは[[Prototype]]、内部プロパティと呼ばれますが、一部の実装では、mozillaのように、obj.__proto__プロパティを使用してアクセスできます。

[[Prototype]]新しいオブジェクトを作成するときのデフォルト、つまりvar obj = {};Object.prototypeです。

すべての関数にはプロパティがあります。このプロパティは、関数がコンストラクターprototypeとして使用され、演算子で呼び出されるときに使用されます。new

舞台裏で作成された新しいオブジェクトインスタンスであり、このオブジェクト[[Prototype]]はそのコンストラクタのprototypeプロパティに設定されます。

3)最後に、Fがインスタンス化されて返され、newObjectになります。ここで「新しい」操作は厳密に必要ですか?Fはすでに必要なものを提供していませんか、それとも関数オブジェクトと非関数オブジェクトの間に決定的な違いがありますか?明らかに、この手法を使用してコンストラクター関数を作成することはできません。

はい、newこの方法では演算子が不可欠です。

new演算子は[[Prototype]]、オブジェクトの内部プロパティを設定する唯一の標準的な方法です。オブジェクトがどのように機能するかについて知りたい場合は、内部操作を確認できます[[Construct]]

次にObject.create()が呼び出されたときに何が起こりますか?グローバル関数Fは上書きされますか?以前に構成されたオブジェクトが変更されるため、再利用されないことは確かです。また、複数のスレッドがObject.create()を呼び出すとどうなりますか?Fの競合状態を防ぐための同期はありますか?

次回Object.create呼び出されると、メソッド呼び出しのスコープ内でのみ新しいローカル関数がインスタンス化されます。競合状態Fについて心配する必要はありません。

この実装は、 ECMAScript 5th Edition仕様Object.createで説明されているものにほとんど準拠していないことに注意してください。そのメソッドでは、プロパティ記述子を渡してオブジェクトを初期化できます。

すべてのブラウザベンダーが実装しています(Firefox 3.7アルファ版、最新のWekit Nightly Builds、Chrome 5ベータ版ですでに利用可能です)。したがって、オーバーライドする前に、少なくともネイティブ実装が存在するかどうかを確認することをお勧めします。

于 2010-05-04T14:56:24.660 に答える
7

1)関数は確かに一種のオブジェクトです。識別子を持つ関数オブジェクトは、が呼び出されるFたびに作成さObject.createれ、の実行内でその識別子を使用してのみアクセスできますObject.create。したがって、Object.createが呼び出されるたびに、異なる関数オブジェクトを取得しますFconstructorこの関数オブジェクトは、によって返されるオブジェクトのプロパティとして存続しますObject.create

2)

Fは、名前解決がoldObjectを経由するという意味で、oldObjectから「継承」するようになりました。

これは本当に正しくありません。関数のプロパティにオブジェクトsomeObjectを割り当てるというprototypeことは、この関数をコンストラクターとして呼び出すことによって作成される将来のオブジェクトのプロトタイプがになることを意味しますsomeObject

3)newこのテクニックには絶対に不可欠です。関数をコンストラクターとして呼び出すことによってのみ、新しいオブジェクトが生成され、そのオブジェクトのプロトタイプ(通常はアクセスできません)がコンストラクター関数のprototypeプロパティに設定されます。オブジェクトのプロトタイプを設定する他の(標準化された)方法はありません。

最後に、ブラウザのJavaScriptはシングルスレッドであるため、説明したような競合状態は発生しません。

于 2010-05-04T14:25:19.580 に答える
2

ここでのあなたの主な誤解は、Fがグローバルスコープを持っているということです。Object.createの本体で宣言されているため、そのメソッドブロック内のスコープ内にのみ存在します。

于 2010-05-04T14:24:25.900 に答える
2

>明らかに、この手法を使用してコンストラクター関数を作成することはできません。

この手法は、new F()を返すため、すでにオブジェクトコンストラクターですが、たとえばnew man('John'、'Smith')のようにプロパティ値を設定することはできません。ただし、Object.createコードを変更すると、インスタンス化が可能になります。たとえば、以下のsarahオブジェクトは、Object.creatorを使用して構築およびインスタンス化でき、getNameメソッドを継承します。

var girl = {
   name: '',
   traits: {},
   getName: function(){return this.name}
}

var sarah = Object.creator(girl, 'Sarah', {age:29,weight:90})

その場合、sarahオブジェクトは独自のプロパティ{name:'Sarah'、traits:{age:9、weight:49}}で構成され、継承されたプロトタイプsarah.getName()は'Sarah'を生成します。

次のメソッドは、作成順に'for(prop in o)'で列挙する独自のプロパティに依存しています。ECMAの仕様では保証されていませんが、この例(およびいくつかのより複雑な例)は、テストされたすべての主要なブラウザー(4)で機能し、hasOwnProperty()が使用されました。

Object.creator = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

公式のECMAObject.createには、プロパティ値をインスタンス化できるオプションの2番目のパラメーターpropertiesObjectがありますが、これは通常のリストではなくオブジェクトであり、使いにくいように見えます。例:私は信じています:-

o2 = Object.create({}, { p: { value: 42, writable: true, enumerable: true, configurable: true } });

はるかに単純な古い方法と同等です:-

o2 = new function(p) { this.p=p }(42)

o2 = Object.creator({p:''}, 42)
于 2011-07-04T00:53:27.647 に答える