프로토 타입 객체 또는 생성자를 통해 메소드를 설정하십시오. [복제하다

StackOverflow https://stackoverflow.com/questions/422476

문제

이 질문은 이미 여기에 답이 있습니다.

생성자와 프로토 타입 객체를 통해 메소드 설정의 차이점을 설명해 주시겠습니까? 다음 코드는이 두 가지 방법을 메소드를 설정하는 방법을 보여줍니다. say_hello 그리고 say_bye 둘 다 잘 작동합니다 :

function MessageClass() {
  this.say_bye = function() { alert('see ya'); };
}

MessageClass.prototype.say_hello = function() { alert('hello'); };

x = new MessageClass();
x.say_hello();
x.say_bye();
도움이 되었습니까?

해결책

Foxxtrot과 Annakata는 모두 정확하지만 2 센트로 던질 것입니다.

프로토 타입을 사용하는 경우 "MessageClass"의 각 인스턴스는 실제로 동일한 기능을 참조합니다. 함수는 메모리에 한 번만 존재하며 모든 인스턴스에 사용됩니다. 프로토 타입이 아닌 생성자의 메소드를 구체적으로 선언하는 경우 (또는 그렇지 않으면 특정 인스턴스에 추가) MessageClass의 각 인스턴스에 대해 새로운 기능이 생성됩니다.

즉, 대부분의 경우 눈에 띄는 성능 차이가 없을 것입니다. 메모리 사용 차이도 볼 수는 없습니다. 당신이 달리 할 수있는 강력한 이유가 없다면 프로토 타입 방법을 가지고 갈 것입니다. 내가 당신이 생성자에서 메소드를 선언하고 싶을 수있는 유일한 이유는 폐쇄가 필요한 경우 때문입니다. 예를 들어, 이벤트 핸들러가 있거나 Getters/Setters로 개인 속성을 시뮬레이션하려면 다음을 수행 할 수 있습니다.

function MessageClass() {
    var self = this;
    this.clickHander = function(e) { self.someoneClickedMe = true; };

    var _private = 0;
    this.getPrivate = function() { return _private; };
    this.setPrivate = function(val) { _private = val; };
}

편집하다: 생성자에 함수가 할당 된 다른 객체가 다른 객체에 의해 확장 된 효과에 대한 논의가 있었기 때문에 조금 더 자세한 내용을 추가하고 있습니다. "클래스"라는 용어를 사용하여 토론을 단순화 할 수도 있지만 JS는 클래스를 지원하지 않는다는 점에 유의해야합니다 (즉, 우리가 좋은 OO 개발을 할 수 없다는 것을 의미하지는 않습니다).

대부분의 JavaScript 라이브러리는 기본 클래스 및 하위 클래스에서 생성자를 호출합니다. (예 : 프로토 타입 .js의 개체. extend) 이것은 각각의 생성자에 할당 된 메소드가 결과 객체에서 사용할 수 있음을 의미합니다. 그러나 객체를 확장하면 예상치 못한 결과가있을 수 있습니다.

MessageClass를 위에서 가져와 확장하면 :

function ErrorMessageClass() {}
ErrorMessageClass.prototype = new MessageClass();

errorMsg = new ErrorMessageClass();

그런 다음 errormsg는 get -frivate 및 set -frivate 메소드를 가지고 있지만 예상대로 행동하지 않을 수 있습니다. 이러한 기능은 할당되었을 때 (즉, "errormessageclass.prototype = new MessageClass ()에서 지정 되었기 때문에 get/setprivate 메소드가 공유 될뿐만 아니라 _private 변수는 ErrormessAgeClass의 모든 인스턴스에서 공유됩니다. errormessageclass의 정적 속성. 예를 들어 :

var errorA = new ErrorMessageClass();
var errorB = new ErrorMessageClass();
errorA.setPrivate('A');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'A'
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'B'

마찬가지로 클릭 핸들러 함수 및 someoneclickedme 속성과 마찬가지로 :

errorA.clickHandler();
console.log(errorA.someoneClickedMe); // prints 'true'
console.log(errorB.someoneClickedMe); // prints 'true'

그러나이 기능 정의를 변경 하여이 기능을 사용하십시오 ._private :

this.getPrivate = function() { return this._private; };
this.setPrivate = function(val) { this._private = val; };

그리고 errormessageclass의 사례의 행동은 당신이 기대할 수있는 것의 더 많은 것입니다.

errorA.setPrivate('A');
errorB.setPrivate('B');
console.log(errorA.getPrivate()); // prints 'A'
console.log(errorB.getPrivate()); // prints 'B'

다른 팁

프로토 타입으로 메소드를 바인딩하는 경우 JS는 한 번만 수행해야하며 객체 클래스에 바인딩합니다 (OO JS 확장에 적합합니다).

"클래스"함수 내에서 바인딩을 수행하는 경우 JS는 각각의 모든 인스턴스를 작성하고 할당하는 작업을 수행해야합니다.

차이점은 메시지 클래스에서 클래스를 도출 할 때입니다. 프로토 타입에서 선언 된 방법 만 자식 클래스의 메시지에 사용할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top