development

JavaScript에서 'prototype'과 'this'의 사용?

big-blog 2020. 9. 29. 08:05
반응형

JavaScript에서 'prototype'과 'this'의 사용?


차이점은 무엇입니까

var A = function () {
    this.x = function () {
        //do something
    };
};

var A = function () { };
A.prototype.x = function () {
    //do something
};

예제는 결과가 매우 다릅니다.

차이점을 살펴보기 전에 다음 사항에 유의해야합니다.

  • 생성자의 프로토 타입 은 인스턴스의 private [[Prototype]]속성을 통해 인스턴스간에 메서드와 값을 공유하는 방법을 제공 합니다.
  • 함수의 이것은 함수가 호출되는 방법 또는 bind를 사용하여 설정됩니다 (여기에서는 설명하지 않음). 함수는 객체 (예를 들면 호출되는 경우 myObj.method()그 다음) 있어서 참조 내의 개체. 어디 이이 호출 또는 사용으로 설정되지 않습니다 바인딩 , 그것은 (브라우저의 창) 전역 객체에 대한 기본값 또는 엄격 모드는 정의되지 않은 상태로 유지됩니다.
  • JavaScript는 객체 지향 언어입니다. 즉, 대부분의 값은 함수를 포함한 객체입니다. (문자열, 숫자 및 부울은 객체 아닙니다 .)

따라서 문제의 스 니펫은 다음과 같습니다.

var A = function () {
    this.x = function () {
        //do something
    };
};

이 경우 변수 A에는 함수에 대한 참조 값이 할당됩니다. 해당 함수가를 사용하여 호출 될 때 A()함수의 this 는 호출에 의해 설정되지 않으므로 전역 개체로 기본 설정되고 표현식 this.x이 유효 window.x합니다. 그 결과 오른쪽의 함수 표현식에 대한 참조가에 할당됩니다 window.x.

다음의 경우 :

var A = function () { };
A.prototype.x = function () {
    //do something
};

매우 다른 일이 발생합니다. 첫 번째 줄에서 변수 A에는 함수에 대한 참조가 할당됩니다. JavaScript에서 모든 함수 객체에는 기본적으로 프로토 타입 속성이 있으므로 A.prototype 객체 를 생성하는 별도의 코드가 없습니다 .

두 번째 줄에서 A.prototype.x 에는 함수에 대한 참조가 할당됩니다. x 속성이 없으면 생성하고 , 존재하는 경우 새 값을 할당합니다. 따라서 객체의 x 속성이 표현식에 포함 된 첫 번째 예제와의 차이점입니다 .

다른 예는 다음과 같습니다. 첫 번째 것과 비슷합니다 (그리고 아마도 물어 보려고했던 것) :

var A = new function () {
    this.x = function () {
        //do something
    };
};

이 예에서는 new함수가 생성자로 호출되도록 함수 표현식 앞에 연산자가 추가되었습니다. 와 함께 호출 될 때 new함수의 this[[Prototype]]생성자의 공개 프로토 타입 을 참조하도록 private 속성이 설정된 새 Object 를 참조하도록 설정됩니다 . 따라서 할당 문 x에서이 새 개체에 속성이 생성됩니다. 생성자로 호출 될 때 함수는 기본적으로 this 객체를 반환 하므로 별도의 return this;문이 필요하지 않습니다 .

Ax 속성 있는지 확인하려면 :

console.log(A.x) // function () {
                 //   //do something
                 // };

생성자를 참조하는 유일한 방법은 A.constructor 를 사용하는 것이므로 new 의 드문 사용입니다 . 다음을 수행하는 것이 훨씬 더 일반적입니다.

var A = function () {
    this.x = function () {
        //do something
    };
};
var a = new A();

유사한 결과를 얻는 또 다른 방법은 즉시 호출되는 함수 표현식을 사용하는 것입니다.

var A = (function () {
    this.x = function () {
        //do something
    };
}());

이 경우 A오른쪽에 함수 호출의 반환 값을 할당합니다. 여기서도 이것이 호출에 설정되지 않았기 때문에 전역 개체를 참조하고 this.x유효 window.x합니다. 이 함수는 아무것도 반환하지 않으므로 A값은 undefined.

두 접근 방식 간의 이러한 차이점은 JSON으로 /에서 Javascript 객체를 직렬화 및 역 직렬화하는 경우에도 나타납니다. 객체의 프로토 타입에 정의 된 메서드는 객체를 직렬화 할 때 직렬화되지 않습니다. 예를 들어 객체의 데이터 부분 만 직렬화하려고 할 때 편리 할 수 ​​있습니다.

var A = function () { 
    this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance)); 
// {"objectsOwnProperties":"are serialized"} 

관련 질문 :

사이드 노트 : 두 접근 방식간에 상당한 메모리 절약이 없을 수 있지만 프로토 타입을 사용하여 메서드와 속성을 공유하면 각 인스턴스가 자체 복사본을 갖는 것보다 적은 메모리를 사용할 수 있습니다.

JavaScript는 저수준 언어가 아닙니다. 프로토 타이핑이나 기타 상속 패턴을 메모리 할당 방식을 명시 적으로 변경하는 방법으로 생각하는 것은 그리 중요하지 않을 수 있습니다.


다른 사람들이 첫 번째 버전을 말했듯이 "this"를 사용하면 클래스 A의 모든 인스턴스가 함수 메서드 "x"의 자체 독립 복사본을 갖게됩니다. "prototype"을 사용한다는 것은 클래스 A의 각 인스턴스가 "x"메서드의 동일한 복사본을 사용함을 의미합니다.

다음은이 미묘한 차이를 보여주는 코드입니다.

// x is a method assigned to the object using "this"
var A = function () {
    this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
    this.x = function() { alert( value ); }
};

var a1 = new A();
var a2 = new A();
a1.x();  // Displays 'A'
a2.x();  // Also displays 'A'
a1.updateX('Z');
a1.x();  // Displays 'Z'
a2.x();  // Still displays 'A'

// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };

B.prototype.updateX = function( value ) {
    B.prototype.x = function() { alert( value ); }
}

var b1 = new B();
var b2 = new B();
b1.x();  // Displays 'B'
b2.x();  // Also displays 'B'
b1.updateX('Y');
b1.x();  // Displays 'Y'
b2.x();  // Also displays 'Y' because by using prototype we have changed it for all instances

다른 사람들이 언급했듯이 한 가지 방법을 선택하는 데는 여러 가지 이유가 있습니다. 내 샘플은 그 차이를 명확하게 보여주기위한 것입니다.


다음 두 가지 예를 살펴보십시오.

var A = function() { this.hey = function() { alert('from A') } };

var A = function() {}
A.prototype.hey = function() { alert('from prototype') };

여기에있는 대부분의 사람들 (특히 최고 등급 답변)은 이유를 설명하지 않고 어떻게 다른지 설명하려고했습니다. 틀린 것 같고 기본을 먼저 이해하면 그 차이가 분명해질 것입니다. 먼저 기본 사항을 설명하겠습니다.

a) 함수는 JavaScript의 객체입니다. 자바 스크립트의 모든 객체는 내부 속성을 가져옵니다 (즉, Chrome과 같은 브라우저를 제외하고는 다른 속성처럼 액세스 할 수 없음). 종종 참조 __proto__(실제로 anyObject.__proto__Chrome에 입력 하여 참조하는 내용을 볼 수 있습니다. , 속성, 그 이상 없음 JavaScript의 속성 = 객체 내부의 변수, 그 이상 없음 변수의 기능은 무엇입니까?

그렇다면이 __proto__속성 은 무엇을 가리 킵니까? 글쎄, 일반적으로 다른 개체입니다 (이유는 나중에 설명하겠습니다). __proto__속성이 다른 객체를 가리 키지 않도록 JavaScript를 강제하는 유일한 방법 은를 사용하는 것 var newObj = Object.create(null)입니다. 이렇게하더라도 __proto__속성은 여전히 ​​객체의 속성으로 존재하며 다른 객체를 가리 키지 않고를 가리 킵니다 null.

대부분의 사람들이 혼란스러워하는 부분은 다음과 같습니다.

JavaScript에서 새 함수 (객체이기도합니다. 기억하십니까?)를 만들 때, 정의되는 순간 JavaScript는라는 함수에 새 속성을 자동으로 만듭니다 prototype. 시도 해봐:

var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined

A.prototype__proto__속성과 완전히 다릅니다 . 이 예에서 'A'는 이제 'prototype'및 __proto__. 이것은 사람들에게 큰 혼란입니다. prototype__proto__특성과 관련된 어떠한 방식으로, 그들은 별도의 값을 가리키는 별도의 일을 것입니다.

왜 자바 스크립트가 __proto__모든 단일 객체에 속성을 생성 하는가? 글쎄요, 한 마디 : 위임 . 객체에 대한 속성을 호출 할 때 객체에 속성이 없으면 JavaScript는에서 참조하는 객체를 검색하여 해당 속성 __proto__이 있는지 확인합니다. 그것이 없다면, 그것은 그 객체의 __proto__속성 등을 봅니다 ... 체인이 끝날 때까지. 따라서 이름 프로토 타입 체인 . 물론, __proto__객체를 가리 키지 않고 대신를 가리키면 null, JavaScript는이를 인식 undefined하고 속성에 대해 반환합니다 .

prototype함수를 정의 할 때 JavaScript가 함수에 대해 호출되는 속성을 생성하는 이유가 궁금 할 수도 있습니다. 그것은 당신을 속이려고하기 때문에 그것이 클래스 기반 언어처럼 작동한다는 것을 당신을 속 입니다.

예제를 계속 진행하고 다음에서 "객체"를 생성 해 보겠습니다 A.

var a1 = new A();

이 일이 일어 났을 때 배경에서 뭔가가 일어나고 있습니다. a1새 빈 개체가 할당 된 일반 변수입니다.

new함수 호출 전에 연산자를 사용했다는 사실 A()은 백그라운드에서 추가 작업을 수행했습니다. new키워드는 이제 참조를 새로운 객체를 생성 a1하고 그 객체가 비어 있습니다. 추가로 발생하는 사항은 다음과 같습니다.

우리는 각 함수 정의에 prototype( __proto__속성 과는 달리 접근 할 수있는) 라는 새로운 속성이 생성되었다고 말했습니다 . 글쎄, 그 속성은 지금 사용되고 있습니다.

이제 우리는 갓 구운 빈 a1개체 가있는 지점에 있습니다 . JavaScript의 모든 객체는 null이든 다른 객체 든 __proto__무언가를 가리키는 내부 속성을 가지고 있다고 말했습니다 a1. 무엇 new운영자가하는 것은 그 설정이다 __proto__함수의에 지점 속성을 prototype속성입니다. 다시 읽어보세요. 기본적으로 다음과 같습니다.

a1.__proto__ = A.prototype;

A.prototype(정의하기 전에 다른 것으로 변경하지 않는 한) 이것은 빈 객체에 지나지 않는다고 말했습니다 a1. 이제 기본적으로 a1.__proto__동일한 것을 A.prototype가리키는 빈 객체를 가리 킵니다. 둘 다이 라인이 발생했을 때 생성 된 동일한 객체를 가리 킵니다.

A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}

이제 var a1 = new A()문이 처리 될 때 또 다른 일이 발생 합니다. 기본적 A()으로 실행되고 A가 다음과 같은 경우 :

var A = function() { this.hey = function() { alert('from A') } };

내부의 모든 것이 function() { }실행될 것입니다. this.hey..라인에 도달하면 this로 변경되고 다음 a1과 같이 표시됩니다.

a1.hey = function() { alert('from A') }

this변경 되었는지는 다루지 a1않겠지 만 이것은 더 많은 것을 배울 수 있는 훌륭한 대답 입니다.

요약하면 다음과 var a1 = new A()같이 백그라운드에서 3 가지 일이 발생합니다.

  1. 완전히 새로운 빈 개체가 생성되고에 할당됩니다 a1.a1 = {}
  2. a1.__proto__A.prototype(다른 빈 객체 {}) 가리키는 것과 같은 지점에 속성이 할당됩니다.

  3. 이 함수 A()this1 단계에서 생성 된 비어있는 새 개체 설정된 상태 로 실행됩니다 (위에서 this변경된 이유에 대해 위에서 언급 한 답변을 읽어보십시오 a1).

이제 다른 개체를 만들어 보겠습니다.

var a2 = new A();

1,2,3 단계가 반복됩니다. 뭔가 눈치 채 셨나요? 핵심 단어는 반복입니다. 1 단계 : a2새로운 빈 객체 __proto__가됩니다 . 2 단계 : 속성이 동일한 것을 A.prototype가리키고 가장 중요한 것은 3 단계 : 함수 A()가 다시 실행 a2됩니다. 즉, 함수 hey포함 된 속성을 가져옵니다 . a1a2라는 두 개의 별도의 속성이 hey이 개 별도의 기능을 가리! 우리는 이제 같은 일을하는 같은 두 개의 다른 객체에 중복 된 함수가 있습니다. 죄송합니다 ... new A모든 함수 선언이 숫자 2와 같은 것보다 더 많은 메모리를 차지한 후에로 생성 된 1000 개의 객체가 있다면 이것의 메모리 의미를 상상할 수 있습니다 . 이것을 어떻게 방지합니까?

__proto__모든 객체에 속성이 존재하는 이유를 기억 하십니까? 따라서 (존재하지 않는) yoMan속성 을 검색하면 a1해당 __proto__속성이 참조됩니다. 객체 인 경우 (대부분의 경우), 포함되어 있는지 확인하고 포함 yoMan하지 않는 경우 확인합니다. 그것은 그 객체의 __proto__등등 을 참조 할 것입니다 . 만약 그렇다면, 그것은 그 속성 값을 당신에게 보여줄 것입니다.

그래서 누군가는이 사실과 당신이를 만들 때 a1그것의 __proto__속성이 같은 (빈) 객체를 A.prototype가리키고 이것을한다는 사실을 사용하기로 결정했습니다 .

var A = function() {}
A.prototype.hey = function() { alert('from prototype') };

멋있는! 이제를 만들 때 a1다시 위의 3 단계를 모두 거치고 3 단계에서는 function A()실행할 것이 없기 때문에 아무 작업도 수행하지 않습니다 . 그리고 우리가 할 경우 :

a1.hey

a1포함되지 않은 것을 볼 수 hey있으며 __proto__속성 개체 가 있는지 확인하기 위해 속성 개체를 확인합니다.

이 접근 방식을 사용하면 3 단계에서 각 새 객체 생성시 기능이 중복되는 부분을 제거합니다. 대신에 a1a2별도 가지는 hey속성을, 지금 그들 중 누구도 그것을이 없습니다. 당신은 지금 쯤 당신 자신을 알아 낸 것 같아요. 그게 좋은 것입니다 ... __proto__그리고 를 이해한다면 Function.prototype이와 같은 질문은 매우 분명 할 것입니다.

참고 : 어떤 사람들은 내부 Prototype 속성을라고 부르지 않는 경향이 있습니다 __proto__. 저는이 이름을 게시물을 통해 사용하여 Functional.prototype속성을 두 가지 다른 것으로 명확하게 구분했습니다 .


대부분의 경우 본질적으로 동일하지만 두 번째 버전은 각 객체에 대해 별도의 함수 대신 함수의 인스턴스가 하나만 있기 때문에 메모리를 절약합니다.

첫 번째 양식을 사용하는 이유는 "비공개 구성원"에 액세스하기위한 것입니다. 예를 들면 :

var A = function () {
    var private_var = ...;

    this.x = function () {
        return private_var;
    };

    this.setX = function (new_x) {
        private_var = new_x;
    };
};

자바 스크립트의 범위 지정 규칙으로 인해 private_var는 this.x에 할당 된 함수에서 사용할 수 있지만 개체 외부에서는 사용할 수 없습니다.


첫 번째 예제는 해당 개체에 대한 인터페이스 만 변경합니다. 두 번째 예제는 해당 클래스의 모든 객체에 대한 인터페이스를 변경합니다.


사용에 궁극적 인 문제 this대신이 prototype방법을 재정의하는 경우 기본 클래스의 생성자는 여전히 오버라이드 (override) 된 메소드를 참조하는 것입니다. 이걸 고려하세요:

BaseClass = function() {
    var text = null;

    this.setText = function(value) {
        text = value + " BaseClass!";
    };

    this.getText = function() {
        return text;
    };

    this.setText("Hello"); // This always calls BaseClass.setText()
};

SubClass = function() {
    // setText is not overridden yet,
    // so the constructor calls the superclass' method
    BaseClass.call(this);

    // Keeping a reference to the superclass' method
    var super_setText = this.setText;
    // Overriding
    this.setText = function(value) {
        super_setText.call(this, "SubClass says: " + value);
    };
};
SubClass.prototype = new BaseClass();

var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!

subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

대:

BaseClass = function() {
    this.setText("Hello"); // This calls the overridden method
};

BaseClass.prototype.setText = function(value) {
    this.text = value + " BaseClass!";
};

BaseClass.prototype.getText = function() {
    return this.text;
};

SubClass = function() {
    // setText is already overridden, so this works as expected
    BaseClass.call(this);
};
SubClass.prototype = new BaseClass();

SubClass.prototype.setText = function(value) {
    BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};

var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

이것이 문제가 아니라고 생각한다면, 개인 변수없이 살 수 있는지, 누수를 볼 때 누수를 알 수있을만큼 충분한 경험이 있는지에 달려 있습니다. 또한 메서드 정의 뒤에 생성자 논리를 넣어야하는 것도 불편합니다.

var A = function (param1) {
    var privateVar = null; // Private variable

    // Calling this.setPrivateVar(param1) here would be an error

    this.setPrivateVar = function (value) {
        privateVar = value;
        console.log("setPrivateVar value set to: " + value);

        // param1 is still here, possible memory leak
        console.log("setPrivateVar has param1: " + param1);
    };

    // The constructor logic starts here possibly after
    // many lines of code that define methods

    this.setPrivateVar(param1); // This is valid
};

var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0

a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0

대:

var A = function (param1) {
    this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
    this.publicVar = value; // No private variable
};

var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1

모든 개체는 프로토 타입 개체에 연결됩니다. 존재하지 않는 속성에 액세스하려고 할 때 JavaScript는 해당 속성에 대한 개체의 프로토 타입 개체를 찾고 존재하는 경우 반환합니다.

prototype함수 생성자 속성은를 사용할 때 해당 함수로 생성 된 모든 인스턴스의 프로토 타입 객체를 참조합니다 new.


첫 번째 예에서는 함수로 x생성 된 각 인스턴스에 속성 추가 A합니다.

var A = function () {
    this.x = function () {
        //do something
    };
};

var a = new A();    // constructor function gets executed
                    // newly created object gets an 'x' property
                    // which is a function
a.x();              // and can be called like this

두 번째 예제에서는로 만든 모든 인스턴스가 A가리키는 프로토 타입 개체에 속성을 추가합니다 .

var A = function () { };
A.prototype.x = function () {
    //do something
};

var a = new A();    // constructor function gets executed
                    // which does nothing in this example

a.x();              // you are trying to access the 'x' property of an instance of 'A'
                    // which does not exist
                    // so JavaScript looks for that property in the prototype object
                    // that was defined using the 'prototype' property of the constructor

결론적으로 첫 번째 예 에서는 함수의 복사본이 각 인스턴스에 할당됩니다 . 두 번째 예 에서는 함수의 단일 복사본이 모든 인스턴스에서 공유됩니다 .


차이점이 뭐야? => 많이.

this버전은 캡슐화, 즉 데이터 숨김을 활성화하는 데 사용됩니다. 개인 변수를 조작하는 데 도움이됩니다.

다음 예를 살펴 보겠습니다.

var AdultPerson = function() {

  var age;

  this.setAge = function(val) {
    // some housekeeping
    age = val >= 18 && val;
  };

  this.getAge = function() {
    return age;
  };

  this.isValid = function() {
    return !!age;
  };
};

이제 prototype구조는 다음과 같이 적용 할 수 있습니다.

성인마다 연령이 다르지만 모든 성인은 동일한 권리를 갖습니다.
그래서이 대신 프로토 타입을 사용하여 추가합니다.

AdultPerson.prototype.getRights = function() {
  // Should be valid
  return this.isValid() && ['Booze', 'Drive'];
};

이제 구현을 살펴 보겠습니다.

var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )

var p2 = new AdultPerson;
p2.setAge(45);    
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***

도움이 되었기를 바랍니다.


프로토 타입은 클래스의 템플릿입니다. 향후 모든 인스턴스에 적용됩니다. 반면 이것은 개체의 특정 인스턴스입니다.


JavaScript 교육 과정에서 배운보다 포괄적 인 답변을 제공합니다.

대부분의 답변은 이미 차이점을 언급했습니다. 즉, 프로토 타입을 만들 때 함수가 모든 (미래) 인스턴스와 공유됩니다. 클래스에서 함수를 선언하면 각 인스턴스에 대한 복사본이 생성됩니다.

일반적으로 옳고 그름은 없으며 요구 사항에 따라 취향이나 디자인 결정의 문제입니다. 그러나 프로토 타입은 객체 지향 방식으로 개발하는 데 사용되는 기술입니다.이 답변의 끝에서 보게 되길 바랍니다.

질문에 두 가지 패턴을 보여주었습니다. 두 가지를 더 설명하고 관련이있는 경우 차이점을 설명하려고합니다. 자유롭게 편집 / 확장하십시오. 모든 예에서 위치가 있고 움직일 수있는 자동차 객체에 관한 것입니다.

개체 데코레이터 패턴

이 패턴이 오늘날에도 여전히 관련이 있는지 확실하지 않지만 존재합니다. 그리고 그것에 대해 아는 것이 좋습니다. 데코레이터 함수에 객체와 속성을 전달하기 만하면됩니다. 데코레이터는 속성과 메서드가있는 객체를 반환합니다.

var carlike = function(obj, loc) {
    obj.loc = loc;
    obj.move = function() {
        obj.loc++;
    };
    return obj;
};

var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();

기능적 클래스

JavaScript의 함수는 특수 개체입니다. 호출되는 것 외에도 함수는 다른 객체와 마찬가지로 속성을 저장할 수 있습니다.

이 경우 CarA는 기능 ( 생각 개체를 당신이하는 데 사용됩니다로 호출 할 수 있습니다). 속성 methods( move함수를 가진 객체 )이 있습니다. Car호출 된되는 extend마법을 수행하고, 확장 호출 기능, Car함수 내에서 정의 된 방법과 (객체를 생각한다) methods.

이 예는 다르지만 질문의 첫 번째 예에 가장 가깝습니다.

var Car = function(loc) {
    var obj = {loc: loc};
    extend(obj, Car.methods);
    return obj;
};

Car.methods = {
    move : function() {
        this.loc++;
    }
};

var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();

프로토 타입 클래스

처음 두 패턴은 기술을 사용하여 공유 메서드를 정의하거나 생성자 본문에 인라인으로 정의 된 메서드를 사용하는 방법을 설명합니다. 두 경우 모두 모든 인스턴스에는 자체 move기능이 있습니다.

프로토 타입 패턴은 프로토 타입 위임을 통한 기능 공유가 바로 프로토 타입 패턴의 목표이기 때문에 동일한 검사에 적합하지 않습니다. 다른 사람들이 지적했듯이 더 나은 메모리 공간을 가질 것으로 예상됩니다.

그러나 한 가지 흥미로운 점이 있습니다. 모든 prototype객체에는 constructor연결된 함수 (생각 객체)를 가리키는 편리한 속성 이 있습니다.

마지막 세 줄에 대해 :

이 예에서 Car받는 링크 prototype를 통해 링크 오브젝트 constructorCar자체, 즉 Car.prototype.constructor이다 Car자체. 이를 통해 어떤 생성자 함수가 특정 객체를 구축했는지 파악할 수 있습니다.

amy.constructor의 조회가 실패 Car.prototype하여 생성자 속성이있는에 위임됩니다 . 그래서 amy.constructor입니다 Car.

또한, amy이다 instanceof Car. instanceof연산자는 오른쪽 피연산자의 프로토 타입 객체가 (경우에보고하여 작동 Car) 왼쪽 피연산자의 프로토 타입 (어디서나 찾을 수 있습니다 amy) 체인.

var Car = function(loc) {
    var obj = Object.create(Car.prototype);
    obj.loc = loc;
    return obj;
};

Car.prototype.move = function() {
        this.loc++;
};

var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();

console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);

일부 개발자는 처음에 혼란 스러울 수 있습니다. 아래 예를 참조하십시오.

var Dog = function() {
  return {legs: 4, bark: alert};
};

var fido = Dog();
console.log(fido instanceof Dog);

instanceof운영자 반환 false때문에 Dog'의 프로토 타입은 어디서나 찾을 수 없습니다 fido의 프로토 타입 체인'. fido객체 리터럴로 생성 된 간단한 객체입니다 Object.prototype. 즉, .

의사 고전 패턴

이것은 단순한 형태의 프로토 타입 패턴의 또 다른 형태 일 뿐이며 new생성자를 사용하기 때문에 예를 들어 Java로 프로그래밍하는 사람들에게 더 친숙합니다 .

그것은 실제로 프로토 타입 패턴에서와 동일합니다. 그것은 단지 프로토 타입 패턴 위에있는 문법적 설탕 일뿐입니다.

그러나 주요 차이점은 의사 고전 패턴을 사용할 때만 적용되는 JavaScript 엔진에 구현 된 최적화가 있다는 것입니다. pseudoclassical 패턴은 아마도 프로토 타입 패턴의 더 빠른 버전이라고 생각하십시오. 두 예의 객체 관계는 동일합니다.

var Car = function(loc) {
    this.loc = loc;
};

Car.prototype.move = function() {
        this.loc++;
};

var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();

마지막으로 객체 지향 프로그래밍이 어떻게 수행 될 수 있는지 깨닫는 것이 너무 어렵지 않아야합니다. 두 개의 섹션이 있습니다.

프로토 타입 (체인)에서 공통 속성 / 방법을 정의하는 섹션입니다.

그리고 객체를 서로 구별하는 정의를 넣는 또 다른 섹션 ( loc예제에서 변수).

이것이 우리가 자바 스크립트에서 슈퍼 클래스 나 서브 클래스와 같은 개념을 적용 할 수있게 해주는 것입니다.

자유롭게 추가하거나 편집하십시오. 한 번 더 완료되면 아마도 이것을 커뮤니티 위키로 만들 수 있습니다.


나는 이것이 죽음에 대한 답변을 받았음을 알고 있지만 속도 차이의 실제 예를 보여주고 싶습니다.

물체에 직접 작용

프로토 타입의 기능

여기서 우리는 printChrome 메서드를 사용하여 2,000,000 개의 새 개체를 만듭니다 . 우리는 모든 객체를 배열에 저장하고 있습니다. 퍼팅 print프로토 타입에하는 것은 긴으로 1/2 정도 걸립니다.


@Matthew Crumley가 옳다고 믿습니다. 그들은 기능적으로 , 그렇지 않은 경우 구조적으로 동일합니다. Firebug를 사용하여를 사용하여 생성 된 객체를 살펴보면 두 객체가 new동일하다는 것을 알 수 있습니다. 그러나 내 선호는 다음과 같습니다. 나는 그것이 내가 C # / Java에서 익숙한 것과 더 비슷해 보인다고 생각합니다. 즉, 클래스를 정의하고 필드, 생성자 및 메서드를 정의합니다.

var A = function() {};
A.prototype = {
    _instance_var: 0,

    initialize: function(v) { this._instance_var = v; },

    x: function() {  alert(this._instance_var); }
};

편집 변수의 범위가 개인이라는 것을 의미하는 것이 아니라 자바 스크립트에서 클래스를 정의하는 방법을 설명하려고했습니다. 이를 반영하기 위해 변수 이름이 변경되었습니다.


다른 답변에서 논의했듯이 프로토 타입의 함수는 각 인스턴스화에 대해 생성되는 함수가 아닌 모든 인스턴스화와 공유되기 때문에 실제로 성능 고려 사항입니다.

이것을 보여주기 위해 jsperf를 모았습니다. 많은 인스턴스를 만드는 경우에만 실제로 관련이 있지만 클래스를 인스턴스화하는 데 걸리는 시간에는 극적인 차이가 있습니다.

http://jsperf.com/functions-in-constructor-vs-prototype


정적으로 형식화 된 언어에 대해 생각해보십시오.의 항목 prototype은 정적이며 항목 this은 인스턴스와 관련이 있습니다.

참고 URL : https://stackoverflow.com/questions/310870/use-of-prototype-vs-this-in-javascript

반응형