JavaScript: Class.method'a karşı Class.prototype.method


498

Aşağıdaki iki bildirim arasındaki fark nedir?

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

İlk ifadeyi statik bir yöntemin, ikinci ifadeyi bir örnek yöntemin bildirimi olarak düşünmek uygun mudur?

Yanıtlar:


695

Evet, ilk işlevin bu yapıcı işlevinin nesne örneği ile bir ilişkisi yoktur , bunu 'statik yöntem' gibi düşünebilirsiniz .

JavaScript işlevlerinde birinci sınıf nesneler vardır, bu da onlara herhangi bir nesne gibi davranabileceğiniz anlamına gelir, bu durumda yalnızca işlev nesnesine bir özellik eklersiniz .

İkinci işlev, yapıcı işlev prototipini genişlettiğinizde, newanahtar sözcükle oluşturulan tüm nesne örnekleri için kullanılabilir olacak ve bu işlevdeki ( thisanahtar kelime) bağlam, onu çağırdığınız gerçek nesne örneğine atıfta bulunacaktır.

Bu örneği düşünün:

// 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();

1
Ama neden Function.prototype.method == Function.method?
Raghavendra

1
@Raghavendra değil
Zorgatone

1
@Menda bağlantınız öldü
Eugen Sunic

19

Birden fazla MyClass örneği oluşturduğunuzda, bellekte yalnızca bir tane publicMethod örneğiniz olur, ancak privilegedMethod durumunda çok sayıda örnek oluşturur ve staticMethod'un bir nesne örneğiyle ilişkisi yoktur.

Bu yüzden prototipler hafızayı kurtarır.

Ayrıca, üst nesnenin özelliklerini değiştirirseniz, çocuğun karşılık gelen özelliği değiştirilmediyse güncellenir.


15

Görsel öğrenenler için, fonksiyonu olmadan tanımlarken .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`  

Aynı kodla, eğer .prototype eklenirse,

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`

Daha açık hale getirmek için,

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

**** Yukarıdaki örnek için not, someInstance.method () yöntemi çalıştırılmaz,
ÖrnekClass.method () hataya ve yürütmenin devam edememesine neden olur.
Ancak illüstrasyon ve kolay anlaşılması uğruna, bu sırayı korudum. ****

Kodda adım atmak için yukarıdaki jsbin bağlantısından oluşturulan chrome developer console& Tıkla sonuçları . Yorumlanan bölümü + ile değiştirJS Bin

ctrl/


15

Evet, birincisi static methodde denir class method, ikincisi iseinstance method .

Daha ayrıntılı olarak anlamak için aşağıdaki örnekleri düşünün.

ES5'te

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;
}

Yukarıdaki kodda, isPersonstatik bir yöntem varken sayHi,Person .

Aşağıda, Personyapıcıdan nasıl nesne oluşturulacağı açıklanmaktadır.

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

Statik yöntemi kullanarak isPerson.

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

Örnek yöntemini kullanarak sayHi.

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

ES6'da

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

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

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

staticStatik yöntemi bildirmek için anahtar kelimenin nasıl kullanıldığına bakın isPerson.

PersonSınıf nesnesi oluşturmak için .

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

Statik yöntemi kullanarak isPerson.

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

Örnek yöntemini kullanarak sayHi.

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

NOT: Her iki örnek de aynıdır, JavaScript sınıfsız bir dil olarak kalır. classTanıtılan ES6 öncelikle mevcut prototip tabanlı miras modeli üzerinde sözdizimsel şekerdir.


"ES6'da" yalnızca sözdizimi şekerini tanımlarsınız. Bu "ES2015" değil (lütfen herkes ES6'yı kullanmayı bırakın uygun ES2015 terimini kullanın). Bunu yapmanın başka bir yolu ve bence yanlış yol.
K - SO'da toksisite artıyor.

2
@KarlMorrison Aminu "bunu yapmanın bir yolunu" yazmadı, sadece kendin yazdın ve onu istisna ettin. ES6 vs ES2015 hakkında adil olabilirsiniz, ancak konuşmada insanlar genellikle verimlilik için daha kısa bir sözleşmeye başvururlar, bu yüzden yazımdan kaldırmak mümkün değildir veya kesinlikle tavsiye edilebilir.
wuliwong

Cevabınızın ES6 kısmı için teşekkür ederiz; özellikle yukarıdaki 2 "genel + ayrıcalıklı" cevapla birleştirildiğinde çok şey açıklığa kavuşur. Ben ancak ben iyice senin tarafından karıştı obj.constructor === Personvarlık trueörnek olsa ... Whaaaat? Sınıf örneğinin yapıcısını ===sınıfın kendisi nasıl yapabilir ...? (Bu, bir kümenin alt kümesinin kümenin kendisi olduğunu söylemek gibidir, vb ...)
Andrew

Ohhh ... o zaman söylemek istediğim, yapıcı bir JS sınıfının günün sonunda olduğu tek şey mi? Geri kalan her şey ya kurucuya yığılmış ya da tamamen isim / kavram dışında sınıftan izole edilmiş statik bir yapıya (ve zımni bir "bu" açıkça sunuluyor gibi)? (Böylece, setin bir alt kümesi olduğunu düşündüğüm aslında bir alt küme değildi.)
Andrew
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.