サーチ…
標準関数プロトタイプ
まず、コンストラクタとして使用するFoo
関数を定義します。
function Foo (){}
Foo.prototype
を編集することで、 Foo
すべてのインスタンスで共有されるプロパティとメソッドを定義できます。
Foo.prototype.bar = function() {
return 'I am bar';
};
new
キーワードを使用してインスタンスを作成し、メソッドを呼び出すことができます。
var foo = new Foo();
console.log(foo.bar()); // logs `I am bar`
Object.keyとObject.prototype.keyの違い
Pythonのような言語とは異なり、コンストラクタ関数の静的プロパティはインスタンスに継承されません 。インスタンスは、プロトタイプを親クラスのプロトタイプから継承したプロトタイプのみを継承します。静的プロパティは継承されません。
function Foo() {};
Foo.style = 'bold';
var foo = new Foo();
console.log(Foo.style); // 'bold'
console.log(foo.style); // undefined
Foo.prototype.style = 'italic';
console.log(Foo.style); // 'bold'
console.log(foo.style); // 'italic'
プロトタイプからの新しいオブジェクト
JavaScriptでは、どのオブジェクトも別のオブジェクトのプロトタイプになる可能性があります。オブジェクトが別のオブジェクトのプロトタイプとして作成されると、そのオブジェクトはすべての親のプロパティを継承します。
var proto = { foo: "foo", bar: () => this.foo };
var obj = Object.create(proto);
console.log(obj.foo);
console.log(obj.bar());
コンソール出力:
> "foo"
> "foo"
注意 Object.create
はECMAScript 5から利用できますが、ここではECMAScript 3のサポートが必要な場合はpolyfillを使用します
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Object.create()
Object.create()メソッドは、指定されたプロトタイプオブジェクトとプロパティを使用して新しいオブジェクトを作成します。
構文: Object.create(proto[, propertiesObject])
パラメータ :
- proto (新しく作成されたオブジェクトのプロトタイプでなければならないオブジェクト)
- propertiesObject (オプション、未定義でない場合は、列挙可能なプロパティ(すなわち、プロトタイプチェーンに沿って列挙可能なプロパティではなくプロパティ自体に定義されているプロパティ)を持つオブジェクトは、新しく作成されたオブジェクトに追加するプロパティ記述子を指定します。これらのプロパティは、Object.defineProperties()の2番目の引数に対応します。
戻り値
指定されたプロトタイプオブジェクトとプロパティを持つ新しいオブジェクト。
例外
protoパラメータがnullでもオブジェクトでもない場合は、 TypeError例外が発生します。
プロトタイプ継承
prototype
と呼ばれる単純なオブジェクトがあるとします。
var prototype = { foo: 'foo', bar: function () { return this.foo; } };
今、私たちはと呼ばれる別のオブジェクトたいobj
から継承されprototype
と言うと同じで、 prototype
プロトタイプであるobj
var obj = Object.create(prototype);
prototype
すべてのプロパティとメソッドがobj
に利用できるようになりました。
console.log(obj.foo);
console.log(obj.bar());
コンソール出力
"foo"
"foo"
プロトタイプの継承はオブジェクト参照を介して内部的に行われ、オブジェクトは完全に変更可能です。つまり、プロトタイプに対して行った変更は、プロトタイプがプロトタイプである他のすべてのオブジェクトに即座に影響します。
prototype.foo = "bar";
console.log(obj.foo);
コンソール出力
"bar"
Object.prototype
はすべてのオブジェクトのプロトタイプですので、特にサードパーティのライブラリを使用している場合は、特に混乱しないようにしてください。
Object.prototype.breakingLibraries = 'foo';
console.log(obj.breakingLibraries);
console.log(prototype.breakingLibraries);
コンソール出力
"foo"
"foo"
楽しい事実私はこれらの例を作るためにブラウザコンソールを使い、このbreakingLibraries
プロパティを追加してこのページをbreakingLibraries
ました。
擬似古典的継承
これはプロトタイプがどれほど強力かを示すプロトタイプの継承を使用して古典的な継承をエミュレートしたものです。他の言語のプログラマーにとって、その言語をより魅力的にするために作られました。
「クラス」は、 new
オペランドで呼び出されるように作られた関数であり、コンストラクタとして使用されます。
function Foo(id, name) {
this.id = id;
this.name = name;
}
var foo = new Foo(1, 'foo');
console.log(foo.id);
コンソール出力
1
fooはFooのインスタンスです。JavaScriptコーディング規約では、関数が大文字の大文字小文字で始まる場合は、( new
オペランドを使用して)コンストラクタとして呼び出すことができます。
"クラス"にプロパティやメソッドを追加するには、それらをプロトタイプに追加する必要があります。これはコンストラクタのprototype
プロパティにあります。
Foo.prototype.bar = 'bar';
console.log(foo.bar);
コンソール出力
バー
実際、Fooが "コンストラクタ"として行っているのは、 Foo.prototype
をプロトタイプとしてオブジェクトを作成することだけです。
すべてのオブジェクトのコンストラクタへの参照を見つけることができます
console.log(foo.constructor);
関数Foo(id、name){...
console.log({ }.constructor);
function Object(){[ネイティブコード]}
また、オブジェクトがinstanceof
演算子で指定されたクラスのインスタンスであるかどうかをチェックする
console.log(foo instanceof Foo);
真実
console.log(foo instaceof Object);
真実
オブジェクトのプロトタイプを設定する
ES5 +では、 Object.create
関数を使用して、プロトタイプとして他のObjectを持つObjectを作成できます。
const anyObj = {
hello() {
console.log(`this.foo is ${this.foo}`);
},
};
let objWithProto = Object.create(anyObj);
objWithProto.foo = 'bar';
objWithProto.hello(); // "this.foo is bar"
プロトタイプなしで明示的にオブジェクトを作成するには、プロトタイプとしてnull
を使用しnull
。これは、ObjectがObject.prototype
から継承しないことを意味し、存在チェック辞書に使用されるObject、たとえば
let objInheritingObject = {};
let objInheritingNull = Object.create(null);
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false
ES6から、既存のObjectのプロトタイプはObject.setPrototypeOf
を使用して変更できます。
let obj = Object.create({foo: 'foo'});
obj = Object.setPrototypeOf(obj, {bar: 'bar'});
obj.foo; // undefined
obj.bar; // "bar"
これは、 this
オブジェクトやコンストラクタを含むほとんどの場所で行うことができます。
注意:このプロセスは現在のブラウザでは非常に遅く、控えめに使用する必要があります。目的のプロトタイプでObjectを作成してみてください。
ES5以前では、手動で定義されたプロトタイプを使用してオブジェクトを作成する唯一の方法は、 new
で構築することでした
var proto = {fizz: 'buzz'};
function ConstructMyObj() {}
ConstructMyObj.prototype = proto;
var objWithProto = new ConstructMyObj();
objWithProto.fizz; // "buzz"
この動作は、Polycomを記述することが可能であることをObject.create
に十分に近似しています。