web-dev-qa-db-ja.com

JavaScript:Class.methodとClass.prototype.method

次の2つの宣言の違いは何ですか?

Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }

最初のステートメントを静的メソッドの宣言として、2番目のステートメントをインスタンスメソッドの宣言として考えても大丈夫ですか?

472
postrational

はい、最初の関数はその コンストラクタ関数 のオブジェクトインスタンスとは関係がありません。 'staticのように考えることができます。方法'

JavaScriptでは、関数は ファーストクラス のオブジェクトです。つまり、他のオブジェクトと同じように扱うことができます。この場合は、関数オブジェクトにプロパティを追加するだけです。

2番目の関数は、コンストラクター関数のプロトタイプを拡張しているので、 new キーワードで作成されたすべてのオブジェクトインスタンス、およびその関数( this キーワード)は、それを呼び出した実際のオブジェクトインスタンスを参照します。

この例を考えてください。

// constructor function
function MyClass () {
  var privateVariable; // private member only available within the constructor fn

  this.privilegedMethod = function () { // it can access private members
    //..
  };
}

// A 'static method', it's just like a normal function 
// it has no relation with any 'MyClass' object instance
MyClass.staticMethod = function () {};

MyClass.prototype.publicMethod = function () {
  // the 'this' keyword refers to the object instance
  // you can access only 'privileged' and 'public' members
};

var myObj = new MyClass(); // new object instance

myObj.publicMethod();
MyClass.staticMethod();
670
CMS

MyClassのインスタンスを複数作成しても、publicMethodのインスタンスはメモリ内に1つしか存在しませんが、PrivilegedMethodの場合は多数のインスタンスを作成することになり、staticMethodはオブジェクトインスタンスとは無関係です。

プロトタイプがメモリを節約するのはそのためです。

また、親オブジェクトのプロパティを変更しても、子の対応するプロパティは変更されていない場合は、更新されます。

17
user2440156

視覚的学習者のために、.prototypeなしで関数を定義するとき

ExampleClass = function(){};
ExampleClass.method = function(customString){
             console.log((customString !== undefined)? 
                          customString : 
                          "called from func def.");}
ExampleClass.method(); // >> output: `called from func def.`  

var someInstance = new ExampleClass();
someInstance.method('Called from instance');
    // >> error! `someInstance.method is not a function`  

同じコードで、.prototypeを追加すると、

ExampleClass.prototype.method = function(customString){
             console.log((customString !== undefined)? 
                          customString : 
                          "called from func def.");}
ExampleClass.method();  
      // > error! `ExampleClass.method is not a function.`  

var someInstance = new ExampleClass();
someInstance.method('Called from instance');
                 // > output: `Called from instance`

明確にするために、

ExampleClass = function(){};
ExampleClass.directM = function(){}  //M for method
ExampleClass.prototype.protoM = function(){}

var instanceOfExample = new ExampleClass();

ExampleClass.directM();     ✓ works
instanceOfExample.directM();   x Error!

ExampleClass.protoM();     x Error!
instanceOfExample.protoM();  ✓ works

****上記の例では、someInstance.method()は次のようには実行されません。
ExampleClass.method()が原因でエラーが発生したため、実行を続行できません。
しかし、説明と理解を容易にするために、私はこの順序を守りました。****

chrome developer consoleJS Bin から生成された結果
上のjsbinリンクをクリックしてコードをステップスルーしてください。
コメント付きセクションを切り替える ctrl+/

12
SAm

はい、最初のものはstatic methodとも呼ばれるclass methodで、2番目のものはinstance methodです。

より詳しく理解するために、次の例を検討してください。

ES5の場合

function Person(firstName, lastName) {
   this.firstName = firstName;
   this.lastName = lastName;
}

Person.isPerson = function(obj) {
   return obj.constructor === Person;
}

Person.prototype.sayHi = function() {
   return "Hi " + this.firstName;
}

上記のコードでは、isPersonは静的メソッドで、sayHiPersonのインスタンスメソッドです。

以下はPersonコンストラクタからオブジェクトを作成する方法です。

var aminu = new Person("Aminu", "Abubakar");

静的メソッドisPersonを使用します。

Person.isPerson(aminu); // will return true

インスタンスメソッドsayHiを使用します。

aminu.sayHi(); // will return "Hi Aminu"

ES6では

class Person {
   constructor(firstName, lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
   }

   static isPerson(obj) {
      return obj.constructor === Person;
   }

   sayHi() {
      return `Hi ${this.firstName}`;
   }
}

静的メソッドstaticの宣言にisPersonキーワードがどのように使用されていたかを調べてください。

Personクラスのオブジェクトを作成します。

const aminu = new Person("Aminu", "Abubakar");

静的メソッドisPersonを使用します。

Person.isPerson(aminu); // will return true

インスタンスメソッドsayHiを使用します。

aminu.sayHi(); // will return "Hi Aminu"

注:どちらの例も基本的に同じです。JavaScriptはクラスレス言語のままです。 ES6で導入されたclassは、主に既存のプロトタイプベースの継承モデルに対する構文上の糖です。

6
Aminu Kano