JavaScript のキーワードnew
は、初めて遭遇したときには非常に混乱を招く可能性があります。JavaScript はオブジェクト指向プログラミング言語ではないと考える傾向があるためです。
- それは何ですか?
- どのような問題を解決しますか?
- いつが適切で、いつが不適切でしょうか?
ベストアンサー1
それは5つのことを行います:
- 新しいオブジェクトを作成します。このオブジェクトの型は単純にobjectです。
- この新しいオブジェクトの内部のアクセス不可能な
[[prototype]]
(つまり__proto__
) プロパティを、コンストラクター関数の外部のアクセス可能なオブジェクトに設定しますprototype
(すべての関数オブジェクトには自動的にprototype
プロパティがあります)。 this
変数が新しく作成されたオブジェクトを指すようにします。- 指定された場合は、新しく作成されたオブジェクトを使用してコンストラクター関数を実行します
this
。 - コンストラクター関数が非
null
オブジェクト参照を返さない限り、新しく作成されたオブジェクトを返します。この場合、代わりにそのオブジェクト参照が返されます。
注:コンストラクタ関数は、キーワードの後の関数を指しますnew
。
new ConstructorFunction(arg1, arg2)
これが完了すると、新しいオブジェクトの未定義のプロパティが要求された場合、スクリプトは[[prototype]]
代わりにオブジェクトのオブジェクトでそのプロパティをチェックします。これにより、JavaScript で従来のクラス継承に似たものを実現できます。
最も難しいのは、ポイント 2 です。すべてのオブジェクト (関数を含む) には、 と呼ばれる内部プロパティがあります[[prototype]]
。これは、オブジェクトの作成時に、 、、またはリテラルに基づいて (関数はデフォルトで、数値はなど) のみで設定できます。 でのみ読み取ることができます。この値を取得または設定する他の方法はありません。new
Object.create
Function.prototype
Number.prototype
Object.getPrototypeOf(someObject)
関数には、hidden プロパティに加えてprototype[[prototype]]
と呼ばれるプロパティもあり、これにアクセスして変更することで、作成するオブジェクトに継承されたプロパティとメソッドを提供できます。
次に例を示します。
ObjMaker = function() { this.a = 'first'; };
// `ObjMaker` is just a function, there's nothing special about it
// that makes it a constructor.
ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible `prototype` property that
// we can alter. I just added a property called 'b' to it. Like
// all objects, ObjMaker also has an inaccessible `[[prototype]]` property
// that we can't do anything with
obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called `obj1`. At first `obj1`
// was just `{}`. The `[[prototype]]` property of `obj1` was then set to the current
// object value of the `ObjMaker.prototype` (if `ObjMaker.prototype` is later
// assigned a new object value, `obj1`'s `[[prototype]]` will not change, but you
// can alter the properties of `ObjMaker.prototype` to add to both the
// `prototype` and `[[prototype]]`). The `ObjMaker` function was executed, with
// `obj1` in place of `this`... so `obj1.a` was set to 'first'.
obj1.a;
// returns 'first'
obj1.b;
// `obj1` doesn't have a property called 'b', so JavaScript checks
// its `[[prototype]]`. Its `[[prototype]]` is the same as `ObjMaker.prototype`
// `ObjMaker.prototype` has a property called 'b' with value 'second'
// returns 'second'
これはクラス継承に似ています。これで、 を使用して作成したすべてのオブジェクトnew ObjMaker()
も 'b' プロパティを継承しているように見えるようになります。
サブクラスのようなものが必要な場合は、次のようにします。
SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);
SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype
obj2.c;
// returns 'third', from SubObjMaker.prototype
obj2.b;
// returns 'second', from ObjMaker.prototype
obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype
// was created with the ObjMaker function, which assigned a for us
私はこの件に関して大量のくだらないことを読んだが、ついにこのページ、これは素晴らしい図で非常にわかりやすく説明されています。