これがうまくいくことはわかっています:
function Foo() {};
Foo.prototype.talk = function () {
alert('hello~\n');
};
var a = new Foo;
a.talk(); // 'hello~\n'
でも電話したいなら
Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly
仕事をするためのいくつかの方法を見つけたFoo.talk
。
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
これを行う他の方法はありますか? それが正しいかどうかはわかりません。JavaScript コードではクラス メソッドと静的メソッドのどちらを使用していますか?
ベストアンサー1
まず、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 仕様では「将来の予約語」でしたが、ES6 ではキーワードを使用してクラスを定義する機能が導入されましたclass
。
2: 基本的にはコンストラクタによって作成されたクラスインスタンスですが、誤解を招かないように微妙な違いがたくさんあります。
3:プリミティブ値( undefined
、null
、ブール値、数値、文字列など) は、低レベル言語の実装であるため、技術的にはオブジェクトではありません。ブール値、数値、文字列は、オブジェクトであるかのようにプロトタイプ チェーンと対話するため、この回答では、完全にはオブジェクトではないものの、それらを「オブジェクト」と見なす方が簡単です。