まず、JavaScriptはクラスベースの言語ではなく、主にプロトタイプ言語であることを覚えておいてください1。はクラスではなく、オブジェクトである関数です。キーワードを使用して、その関数からオブジェクトをインスタンス化できます。これにより、標準のOOP言語のクラスに似たものを作成できます。Foo
new
__proto__
クロスブラウザーのサポートが不十分であるため、ほとんどの場合は無視することをお勧めしprototype
ます。代わりに、動作方法の学習に重点を置きます。
関数2から作成されたオブジェクトのインスタンスがあり、そのメンバー(メソッド、属性、プロパティ、定数など)の1つに何らかの方法でアクセスする場合、アクセスはプロトタイプ階層をたどって(a)が見つかるまで続きますメンバー、または(b)別のプロトタイプが見つからない。
階層は、呼び出されたオブジェクトから始まり、そのプロトタイプオブジェクトを検索します。プロトタイプオブジェクトにプロトタイプがある場合、それが繰り返され、プロトタイプが存在しない場合undefined
は返されます。
例えば:
foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"
foo = {};
console.log(foo.bar); // logs undefined
function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
これらの「基本的な」部分はすでにある程度理解しているように見えますが、念のため、それらを明示的にする必要があります。
JavaScriptでは、すべてがオブジェクトです3。
すべてがオブジェクトです。
function Foo(){}
新しい関数を定義するだけでなく、を使用してアクセスできる新しい関数オブジェクトを定義しFoo
ます。
これがFoo
のプロトタイプにアクセスできる理由ですFoo.prototype
。
また、次の機能を設定することもできますFoo
。
Foo.talk = function () {
alert('hello world!');
};
この新しい機能には、次の方法でアクセスできます。
Foo.talk();
これで、関数オブジェクトの関数と静的メソッドの類似点に気付くでしょう。
f = new Foo();
クラスインスタンスの作成、クラスFoo.prototype.bar = function(){...}
の共有メソッドのFoo.baz = function(){...}
定義、およびクラスのパブリック静的メソッドの定義と考えてください。
ECMAScript 2015は、これらの種類の宣言にさまざまな構文シュガーを導入し、それらを実装しやすくすると同時に読みやすくしました。したがって、前の例は次のように書くことができます。
class Foo {
bar() {...}
static baz() {...}
}
次のbar
ように呼び出すことができます:
const f = new Foo()
f.bar()
次のbaz
ように呼び出されます:
Foo.baz()
1:class
ECMAScript 5仕様の「Future Reserved Word」でしたが、ES6では、class
キーワードを使用してクラスを定義する機能が導入されています。
2:本質的にはコンストラクターによって作成されたクラスインスタンスですが、誤解を招きたくない微妙な違いがあります。
3:プリミティブ値(、、ブール値、数値、文字列を含む)はundefined
、null
低水準言語の実装であるため、技術的にはオブジェクトではありません。ブール値、数値、および文字列は、オブジェクトのようにプロトタイプチェーンと相互作用するため、この回答の目的のために、完全ではないとしても、それらを「オブジェクト」と見なす方が簡単です。
Foo.talk = function ...