1. ホーム
  2. ジャバスクリプト

[解決済み】JavaScriptのクラスとスタティックメソッドの比較

2022-04-03 08:08:16

質問

これがうまくいくことは分かっています。

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 を動作させます。

  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk

他の方法はないのでしょうか?そうすることが正しいかどうかわからない。あなたのJavaScriptのコードでは、クラスメソッドやスタティックメソッドを使用していますか?

どのように解決するのですか?

まず最初に、JavaScriptは主に プロトタイピング言語 というより、むしろ クラスベース言語 1 . Foo はクラスではなく、関数であり、オブジェクトである。オブジェクトをインスタンス化することができます から その関数は new というキーワードで、標準的なOOP言語におけるクラスと同様のものを作成することができます。

を無視することをお勧めします。 __proto__ クロスブラウザのサポートが不十分なため、ほとんどの場合、その代わりに prototype が動作します。

関数から生成されたオブジェクトのインスタンスがある場合 2 そのメンバー(メソッド、属性、プロパティ、定数など)に何らかの方法でアクセスすると、(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(){...} をクラスの public static メソッドとして定義しています。


ECMAScript 2015では、この種の宣言に対して様々な構文シュガーが導入され、実装をシンプルにしつつ読みやすくなっています。したがって、前の例は次のように書くことができます。

class Foo {
  bar() {...}

  static baz() {...}
}

これは bar として呼び出すことができます。

const f = new Foo()
f.bar()

baz として呼び出されるようにする。

Foo.baz()


<サブ 1: class は、ECMAScript 5 仕様において "Future Reserved Word" であった。 を使用してクラスを定義する機能が導入されました。 class というキーワードがあります。

<サブ 2: 本来はコンストラクタで生成されるクラスインスタンスだが、ニュアンスの違いが多いので誤解を招かないようにしたい

<サブ 3: プリミティブ値 -を含む。 undefined , null ブーリアン、数値、文字列は、低レベルの言語実装なので、厳密にはオブジェクトではありません。ブール値、数値、文字列は、あたかもオブジェクトであるかのようにプロトタイプチェーンと相互作用します。