JavaScript 프로토타입 이해

高洛峰
풀어 주다: 2016-11-25 15:33:59
원래의
844명이 탐색했습니다.

Javascript 프로토타입은 항상 사람들에게 혼란을 야기합니다. 경험이 풍부한 전문가이든 작성자 자신이든 이 개념에 대한 이해가 부족한 경우가 많습니다. 이미 제작된 프로토타입을 처음 접할 때 이러한 혼란이 시작되는 것 같습니다. 특히 함수의 프로토타입 속성은 new 및 생성자와 관련이 있는 경우가 많습니다. 사실 프로토타입은 매우 간단한 개념이다. 이를 더 잘 이해하려면 먼저 생성자 프로토타입에 대해 배운 내용을 잊어버리는 원칙을 기억해야 합니다.

프로토타입이란 무엇인가요?

프로토타입은 다른 객체가 속성 상속을 구현할 수 있는 객체입니다.

어떤 물체라도 프로토타입이 될 수 있나요?



프로토타입이 있는 객체

모든 객체에는 기본적으로 프로토타입이 있습니다. 프로토타입 자체도 객체이기 때문에 각 프로토타입 자체에는 프로토타입 Prototype( 한 가지 예외는 기본 객체 프로토타입이 프로토타입 체인의 최상위에 있습니다. 프로토타입 체인에 대한 자세한 내용은 나중에 소개하겠습니다.)

자, 다시 한 번 돌아가서 객체란 무엇인가요?

JavaScript에서 객체는 순서가 지정되지 않은 키-값 쌍의 모음입니다. 기본 데이터 유형(정의되지 않음, null, 부울, 숫자 또는 문자열)이 아닌 경우 객체입니다.

당신 모든 객체에는 프로토타입이 있다고 했는데, ({}).prototype으로 작성하면 null이 표시됩니다. 맞나요?

프로토타입 속성에 대해 배운 모든 내용을 잊어버리십시오. 프로토타입에 대한 혼란의 원인이 될 수 있습니다. 객체의 실제 프로토타입은 객체 내부의 [[Prototype]] 속성에 의해 유지됩니다. ECMA는 표준 객체 프로토타입 접근자 Object.getPrototype(object)를 도입했으며 지금까지 Firefox와 Chrome만이 이 접근자를 구현했습니다. IE 외에도 다른 브라우저는 비표준 접근자 __proto__를 지원합니다. 이들 중 어느 것도 작동하지 않으면 객체 생성자에서 해당 프로토타입 속성을 찾아야 합니다. 다음 코드는 객체 프로토타입을 가져오는 방법을 보여줍니다.
var a = {};

//Firefox 3.6 및 Chrome 5

Object.getPrototypeOf(a) //[object Object ]

//Firefox 3.6, Chrome 5 및 Safari 4

a.__proto__; //[object Object]

//모든 브라우저

a .constructor.prototype; //[object Object]
좋아요, 모든 것이 잘 진행되고 있지만 false는 분명히 주요 데이터 유형이지만 false.__proto__는 값을 반환합니다

기본 데이터 유형의 프로토타입이 객체로 강제되었습니다

//(IE에서도 작동하지만 우연히 발생함)

false .__proto__ === 부울(false). __proto__; //true
상속에서 프로토타입을 사용하고 싶은데 어떻게 해야 하나요?

인스턴스에만 프로토타입을 사용하는 것은 이 인스턴스에 직접 속성을 추가하는 것과 같습니다. 이미 인스턴스 객체를 생성했다면 기존 객체를 상속하려고 합니다. . Array와 같은 객체의 기능은 다음과 같이 수행할 수 있습니다(__proto__를 지원하는 브라우저에서)
//특이한 경우이며 IE에서는 작동하지 않습니다
var a = {};
a. __proto__ = Array.prototype;
a.length; //0
——————————————————————————— ———–
번역자 주: 위의 예에서는 먼저 a 객체가 생성된 후 a
의 프로토타입을 통해 기존 객체 Array를 상속하는 기능이 구현됩니다.—————— —— —————————————————————————————

프로토타입의 진정한 매력은 여러 인스턴스가 공통 프로토타입을 공유한다는 것입니다. 프로토타입 객체(참고: 객체의 프로토타입이 참조하는 객체)의 속성이 정의되면 이를 참조하는 여러 인스턴스에 의해 상속될 수 있습니다(참고: 이러한 인스턴스 객체의 프로토타입은 다음을 가리킵니다). 이 프로토타입 객체) , 성능 및 유지 관리 측면에서 이 작업의 중요성은 자명합니다

이것이 생성자의 존재 이유이기도 합니까?

그렇습니다. 생성자는 생성 시 인스턴스에 공통 프로토타입을 제공할 수 있는 편리한 크로스 브라우저 메커니즘을 제공합니다.

예제를 제공하기 전에 constructor.prototype 속성이 실제로 무엇인지 알아야 합니다. 그것?

우선 JavaScript는 생성자와 다른 함수를 구분하지 않기 때문에 각 함수에는 프로토타입 속성이 있습니다. 반대로, 함수가 아니었다면 그러한 속성도 없었을 것입니다. 아래 코드를 참조하세요

//함수는 생성자가 아니지만 어쨌든 프로토타입 속성을 갖습니다.

Math.max.prototype; //[object Object]

//생성자로 의도된 함수에도 프로토타입이 있습니다

var A = function (name) {

this .name = name;

}

A.prototype; //[객체 객체]

//Math는 함수가 아니므로 프로토타입 속성이 없습니다

Math.prototype; //null
이제 정의를 할 수 있습니다. 함수 A의 프로토타입 속성은 객체입니다. 인스턴스를 생성하기 위해 생성자로 사용되면 함수의 프로토타입 속성이 모든 객체 인스턴스에 프로토타입으로 할당됩니다. (참고: 모든 인스턴스의 프로토타입은 함수의 프로토타입 속성을 나타냅니다.)
————— — ——————————————————————————————-
번역자 주: 다음 코드는 이 모든 것을 더 자세히 설명합니다

//함수 b 만들기
var b = function(){ var one }
//b를 사용하여 객체 인스턴스 만들기 c
var c = new b();
// b 및 c의 생성자 보기
b.constructor; // function Function() { [네이티브 코드]}
b.constructor==Function.constructor; //true
c.constructor; // 인스턴스 c의 생성자는 b입니다. function(){ var one }
c.constructor==b //true
//b는 함수입니다. 다음과 같이 b의 프로토타입을 확인하세요.
b .constructor.prototype // function (){}
b.__proto__ //function (){}

//b는 함수입니다. JavaScript는 생성자와 함수를 구분하지 않습니다. function 생성자와 마찬가지로
//함수의 프로토타입(b.__proto__ 또는 b.construtor.prototype)과 다른 프로토타입 속성을 가집니다.
b.prototype //[object Object] 함수의 프로토타입 b 속성

b.prototype==b.constructor.prototype //fasle
b.prototype==b.__proto__ //false
b.__proto__==b.constructor.prototype // true

//c는 b가 생성한 객체 인스턴스입니다. 다음과 같이 c의 프로토타입을 봅니다.
c.constructor.prototype //[object Object] 객체의 프로토타입입니다
c .__proto__ // [객체 객체] 객체의 프로토타입입니다

c.constructor.prototype==b.constructor.prototype; //false c의 프로토타입과 b의 프로토타입을 비교합니다
c.constructor.prototype==b .prototype; //true c의 프로토타입 속성과 b의 프로토타입 속성을 비교

//속성 추가 max
b.prototype.max = 3
//함수 b의 프로토타입 속성에 대한 인스턴스 c max 속성도 있습니다
c.max //3
위 예에서 객체 인스턴스 c의 프로토타입은 다음의 프로토타입 속성과 동일합니다. b 함수. b의 프로토타입 속성이 변경되면 객체 인스턴스 c
의 프로토타입도 변경됩니다
———————————————————— ———————————————-
이해하기 함수의 프로토타입 속성은 실제 프로토타입과 아무런 관련이 없다는 것이 중요합니다.
//(IE에서는 예제가 실패함)

var A = 함수(이름) {

this .name = 이름;

}

A.prototype == A.__proto__ //false

A.__proto__ == Function.prototype; //true - A의 프로토타입은 생성자의 프로토타입 속성으로 설정됩니다.
예를 들어보세요

이런 수백 개의 자바스크립트를 사용해 본 적이 있을 것입니다. 몇 번이고, 지금 다시 보면 코딩을 할 때 서로 다른 이해가 있을 수 있습니다.



//Constructor. this은 새 객체로 반환되며 내부 [[prototype]] 속성은 생성자의 기본 프로토타입 속성으로 설정됩니다.
var Circle = function (radius) {
this .radius = radius;
//다음 줄은 암시적이며 설명을 위해서만 추가되었습니다.
//this.__proto__ = Circle.prototype;
}
//Augment Circle의 기본 프로토타입 속성을 강화하여 생성된 각 인스턴스의 프로토타입을 강화합니다
Circle.prototype.area = function () {
return Math.PI* this .radius* this .radius;
}
//원의 두 인스턴스를 생성하고 각각이 공통 프로토타입을 활용하도록 만듭니다.
var a = new Circle(3), b = new Circle(4);
a.area().toFixed(2 ); //28.27
b.area().toFixed(2) //50.27
멋지네요. 생성자의 프로토타입을 변경하면 이미 존재하는 해당 생성자의 인스턴스가 생성자의 최신 버전을 얻게 된다는 의미입니까?

꼭 그렇지는 않습니다. 프로토타입 속성이 수정되면 그러한 변경이 발생합니다. a.__proto__는 a가 실제로 생성된 후 A.prototype에 대한 참조이기 때문입니다.

var A = 함수(이름) {
this .name = name;
}
var a = new A( 'alpha' );
a.name; 'alpha'
A.prototype.x = 23;
a.x; //23
————————————————————— —————————
번역자 주: 위의 예와 동일합니다. 인스턴스 객체 a의 프로토타입(a.__proto__)은 함수의 프로토타입 속성(A.prototype)에 대한 참조입니다. A, 그래서 수정된 것이 A의 프로토타입 속성이라면

변경 사항은 A가 만든 객체 인스턴스 a에 영향을 미칩니다. 다음 예에서는 함수 A의 프로토타입이 수정되었지만 A가 만든 인스턴스 a에는 반영되지 않았습니다.

var A = function(name )
{
this.name = 이름;
}
var a = new A('alpha');
a.name; //'alpha'

A.__proto__.max = 19880716;

a.max //정의되지 않음

————————————————————— —— ————————

그러나 이제 A의 프로토타입 속성을 새 객체로 바꾸면 인스턴스 객체의 프로토타입 a.__proto__는 생성 당시의 원래 A를 계속 참조합니다. 속성

var A = 함수(이름) {
this .name = 이름;
}
var a = new A( 'alpha' );
a.name; /'alpha'
A.prototype = {x:23};
a.x; //null
—————————————————— ——————————————
번역자 주: 즉, 인스턴스가 생성된 후 함수의 프로토타입 속성이 가리키는 객체가 변경되면, 즉 가리키는 객체가 인스턴스가 생성될 때 함수의 프로토타입 속성이 변경됩니다. 인스턴스 프로토타입

이 가리키는 객체는 생성된 인스턴스의 프로토타입에 영향을 미치지 않습니다.
————————————————————————————————————-

기본값 프로토타입은 어떤 모습인가요?

var A = function () {};
A.prototype.constructor == A; //true
var a = new A();
a.constructor == A ; //true(a의 프로토타입에서 상속된 생성자 속성)
인스턴스와 프로토타입의 관계

a의 프로토타입이 A의 프로토타입 체인에 속하면 표현식은 A의 인스턴스입니다. 사실이다. 이는 인스턴스를 속여서 작동하지 않게 할 수 있음을 의미합니다.
var A = function () {}

var a = new A();

a.__proto__ = = A.prototype; //true - 따라서 A의 인스턴스는 true를 반환합니다

A의 인스턴스

//a의 프로토타입을 뒤섞습니다

__proto__ = Function.prototype;

//a의 프로토타입은 더 이상 A의 프로토타입 속성과 동일한 프로토타입 체인에 없습니다.

A의 인스턴스 //false
프로토타입으로 또 무엇을 할 수 있나요? ?

내가 언급한 모든 생성자에는 생성하는 각 인스턴스에 프로토타입을 제공하는 데 사용되는 프로토타입 속성이 있다는 점을 기억하세요. 이는 원래 생성자 함수, 문자열 등에 적용됩니다. 이 특성을 확장하면 지정된 생성자의 모든 인스턴스를 확장할 수 있습니다.
함수 확장을 설명하기 위해 이전의 많은 기사에서 이 기술을 사용했습니다. 추적 유틸리티 문서의 모든 문자열 인스턴스는 지정된 횟수만큼 문자열 자체를 복사하는 times 메서드를 구현합니다.
String.prototype.times = function (count) {
return count < new Array(count + 1).join( this );
}

"hello!" .times(3) //"hello!hello!hello!";

"제발..." .times(6); //"제발...제발...제발...제발...제발...제발..."
상속이 어떻게 작동하는지 알려주세요 프로토타입으로. 프로토타입 체인이란 무엇인가요?

모든 객체와 프로토타입에는 프로토타입이 있기 때문입니다(참고: 프로토타입도 객체입니다). 객체의 프로토타입은 객체의 부모를 가리키고, 부모의 프로토타입은 객체의 부모를 가리킵니다. 프로토타입을 통해 레이어별로 연결되는 이 관계를 프로토타입 체인이라고 합니다. 이 체인의 끝은 항상 기본 객체 프로토타입입니다.

a.__proto__ = b;

b.__proto__ = c;

c.__proto__ = {}; //기본 객체

{}. __proto__.__proto__; //null
프로토타입 상속 메커니즘은 내부적으로 발생하며 암시적입니다. 객체 a의 foo 속성 값을 얻으려는 경우 javascript는 프로토타입 체인에서 foo의 존재를 검색합니다. 발견 foo의 값이 반환되고, 그렇지 않으면 정의되지 않은 값이 반환됩니다.

과제는 어떻습니까?

프로토타입 상속은 플레이어가 아닙니다. 속성 값이 a.foo='bar'로 설정되면 값 bar가 a의 foo 속성으로 직접 설정됩니다. 프로토타입에 속성을 추가하려면 프로토타입을 직접 지정해야 합니다.


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿