자바 스크립트 : Class.method vs. Class.prototype.method


498

다음 두 선언의 차이점은 무엇입니까?

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

첫 번째 명령문을 정적 메소드의 선언으로 생각하고 두 번째 명령문을 인스턴스 메소드의 선언으로 생각해도됩니까?

답변:


696

예, 첫 번째 함수는 해당 생성자 함수 의 객체 인스턴스와 아무런 관련이 없으므로 '정적 메소드' 처럼 생각할 수 있습니다 .

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

1
그러나 왜 Function.prototype.method == Function.method입니까?
Raghavendra

1
@ Raghavendra 그것은 아니다
조르가 톤

1
@Menda 귀하의 링크가 죽었습니다
Eugen

19

MyClass 인스턴스를 두 개 이상 만들면 여전히 메모리에 publicMethod 인스턴스가 하나만있을 수 있지만 privilegedMethod의 경우 많은 인스턴스가 만들어지고 staticMethod는 객체 인스턴스와 관련이 없습니다.

이것이 프로토 타입이 메모리를 절약하는 이유입니다.

또한 부모 개체의 속성을 변경하면 자식의 해당 속성이 변경되지 않은 경우 업데이트됩니다.


15

시각 학습자의 경우없이 함수를 정의 할 때 .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&가 위의 코드를 통해 단계에 jsbin 링크를 클릭합니다. 댓글 섹션을 +로 전환JS Bin

ctrl/


15

예, 첫 번째 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}`;
   }
}

staticstatic 메소드를 선언하기 위해 키워드가 어떻게 사용 되었는지 살펴보십시오 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은 주로 기존의 프로토 타입 기반 상속 모델을 통해 구문 설탕입니다.


"ES6에서는"구문 설탕 만 설명합니다. 이것은 "ES2015"가 아닙니다 (모두 ES6 사용을 중지하고 적절한 용어 ES2015를 사용하십시오). 그것은 단순히 그것을하는 또 다른 방법이며 제 생각에는 잘못된 방법입니다.
K-SO의 독성이 증가하고 있습니다.

2
@KarlMorrison Aminu는 "그것을하는 길"을 쓰지 않았습니다. 당신은 그 자신을 직접 쓰고 예외를 취했습니다. ES6 대 ES2015에 대해서는 귀하의 의견이 공정 할 수 있지만 대화에서 사람들은 종종 효율성을 높이기 위해 더 짧은 협약에 의지하기 때문에 쓰기에서 제거하는 것이 불가능하거나 확실하게 생각합니다.
wuliwong

답변의 ES6 부분에 감사드립니다. 특히 위의 2 개의 "공개 + 권한있는"답변과 결합 될 때 많은 내용이 명확 해집니다. 그러나 나는하고 철저하게 사용자의 혼동 obj.constructor === Person존재의 true예를 생각 ... Whaaaat? 클래스 인스턴스의 생성자 ===는 클래스 자체를 어떻게 할 수 있습니까? (세트의 하위 세트가 세트 자체라고 말하는 것과 같습니다.)
Andrew

아 .... 이것으로 말하면, 말 그대로, 생성자가 JS 클래스가 실제로 끝나는 전부입니까? 다른 모든 것은 생성자에 쌓여 있거나 이름 / 개념을 제외하고 클래스에서 격리 된 정적 구조 (그리고 암시 된 "this"가 명백하게 제공되는 것처럼)입니까? (따라서 제가 세트의 서브 세트 라고 생각한 것은 실제로 서브 세트가 아닙니다.)
Andrew
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.