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;
문이 필요하지 않습니다 .
A 에 x 속성 이 있는지 확인하려면 :
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 가지 일이 발생합니다.
- 완전히 새로운 빈 개체가 생성되고에 할당됩니다
a1
.a1 = {}
a1.__proto__
A.prototype
(다른 빈 객체 {}) 를 가리키는 것과 같은 지점에 속성이 할당됩니다.이 함수
A()
는this
1 단계에서 생성 된 비어있는 새 개체 로 설정된 상태 로 실행됩니다 (위에서this
변경된 이유에 대해 위에서 언급 한 답변을 읽어보십시오a1
).
이제 다른 개체를 만들어 보겠습니다.
var a2 = new A();
1,2,3 단계가 반복됩니다. 뭔가 눈치 채 셨나요? 핵심 단어는 반복입니다. 1 단계 : a2
새로운 빈 객체 __proto__
가됩니다 . 2 단계 : 속성이 동일한 것을 A.prototype
가리키고 가장 중요한 것은 3 단계 : 함수 A()
가 다시 실행 a2
됩니다. 즉, 함수 가 hey
포함 된 속성을 가져옵니다 . a1
및 a2
라는 두 개의 별도의 속성이 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 단계에서 각 새 객체 생성시 기능이 중복되는 부분을 제거합니다. 대신에 a1
와 a2
별도 가지는 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의 함수는 특수 개체입니다. 호출되는 것 외에도 함수는 다른 객체와 마찬가지로 속성을 저장할 수 있습니다.
이 경우 Car
A는 기능 ( 도 생각 개체를 당신이하는 데 사용됩니다로 호출 할 수 있습니다). 속성 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
를 통해 링크 오브젝트 constructor
에 Car
자체, 즉 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
예제에서 변수).
이것이 우리가 자바 스크립트에서 슈퍼 클래스 나 서브 클래스와 같은 개념을 적용 할 수있게 해주는 것입니다.
자유롭게 추가하거나 편집하십시오. 한 번 더 완료되면 아마도 이것을 커뮤니티 위키로 만들 수 있습니다.
나는 이것이 죽음에 대한 답변을 받았음을 알고 있지만 속도 차이의 실제 예를 보여주고 싶습니다.
여기서 우리는 print
Chrome 의 메서드를 사용하여 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
'development' 카테고리의 다른 글
파이 계산이 정확한지 어떻게 확인합니까? (0) | 2020.09.29 |
---|---|
값별로 사전을 정렬하는 방법은 무엇입니까? (0) | 2020.09.29 |
CSS 불투명도는 텍스트가 아닌 배경색에만 적용 되나요? (0) | 2020.09.29 |
jQuery / JavaScript : iframe 콘텐츠 액세스 (0) | 2020.09.29 |
Git : 두 가지의 가장 최근 공통 조상 찾기 (0) | 2020.09.29 |