JavaScript: Class.method vs. Class.prototype.method

В чем разница между следующими двумя объявлениями?

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

Можно ли считать первый оператор как объявление статического метода, а второй - объявлением метода экземпляра?

Ответ 1

Да, первая функция не имеет отношения к экземпляру объекта этой конструкторской функции , вы можете рассматривать ее как "статический метод".

В функциях JavaScript есть объекты first-class, что означает, что вы можете относиться к ним точно так же, как к любому объекту, в этом случае вы добавляете только свойство объекта функции.

Вторая функция, поскольку вы расширяете прототип функции конструктора, будет доступна для всех экземпляров объектов, созданных с помощью 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 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();

Ответ 2

Когда вы создаете несколько экземпляров MyClass, у вас будет только один экземпляр publicMethod в памяти, но в случае privilegedMethod вы создадите множество экземпляров, а staticMethod не будет иметь отношения к экземпляру объекта.

Вот почему прототипы сохраняют память.

Кроме того, если вы измените свойства родительского объекта, дочернее соответствующее свойство не было изменено, оно будет обновлено.

Ответ 3

Для визуальных учащихся при определении функции без .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 console и JS Bin
Нажмите на ссылку jsbin выше, чтобы перейти через код.
Переключить секцию комментария с помощью ctrl + /