JavaScript: Class.method против Class.prototype.method - PullRequest
473 голосов
/ 28 октября 2009

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

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

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

Ответы [ 4 ]

671 голосов
/ 28 октября 2009

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

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

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

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

Вот почему прототипы экономят память.

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

12 голосов
/ 03 июня 2017

Для визуальных учеников, при определении функции без .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 + /

6 голосов
/ 10 июня 2018

Да, первый - static method, также называемый class method, а второй - 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 является статическим методом, а sayHi является методом экземпляра Person.

Ниже описано, как создать объект из 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 остается бесклассовым языком. class, представленный в ES6 , является в основном синтаксическим сахаром по сравнению с существующей моделью наследования на основе прототипов.

...