>웹 프론트엔드 >JS 튜토리얼 >JavaScript 프로토타입과 상속

JavaScript 프로토타입과 상속

高洛峰
高洛峰원래의
2016-11-26 11:38:061127검색

1. 함수 생성 과정

프로토타입 체인을 이해하기 전에 먼저 생성 과정에서 함수가 수행하는 작업을 살펴보겠습니다.

1 function A() {};

코드에서 이렇게 빈 함수를 선언할 때 js 파싱의 본질은 다음과 같습니다(피상적인 이해가 깊어져야 함).

1. 객체(생성자 속성 및 [[Prototype]] 속성 포함), ECMA에 따르면 [[Prototype]] 속성은 표시되지 않고 열거할 수 없습니다.

2. 함수를 생성합니다(이름 및 프로토타입 속성 포함). 그런 다음 프로토타입 속성을 통해 참조합니다. 생성된 객체

3. 아래와 같이 변수 A를 생성하고 변수 A

에 함수 참조를 할당합니다.

JavaScript 프로토타입과 상속

(참고로 그림은 모두 "참고"형입니다.)


각 기능의 생성은 위와 같은 과정을 거칩니다.

2. 생성자
그렇다면 생성자는 무엇일까요?
ECMA의 정의에 따르면
생성자는 새로 생성된 객체를 생성하고 초기화하는 함수입니다.
생성자는 새로운 객체를 생성하고 초기화하는 데 사용되는 함수입니다.
새 개체를 생성하고 초기화하는 데 동시에 어떤 종류의 기능을 사용할 수 있나요? 답은 빈 함수를 포함한 모든 함수입니다.
결론은 모든 함수가 생성자가 될 수 있다는 것입니다.

3. 프로토타입
이전 빈 함수 생성 다이어그램에 따르면 각 함수가 생성될 때 자동으로 프로토타입 속성이 추가되는 것을 알 수 있습니다. 그 본질은 객체에 대한 참조입니다(이 객체는 일시적으로 프로토타입 객체로 명명됩니다).
일반 객체처럼 함수의 프로토타입 객체를 조작할 수 있습니다! 함께 확인해 볼까요?
방금 생성한 빈 함수 주위에 몇 가지 코드를 추가합니다.
function A() {
this.width = 10;
this.data = [1,2,3] ;
this .key = "이것은 A입니다";
}
A._objectNum = 0;//A의 속성 정의
A.prototype.say = function(){//A에 속성 추가 프로토타입 객체
경고("hello world")
}
코드의 7~9번째 줄은 함수의 프로토타입 객체에 say 속성을 추가하고 "함수 생성"에 따라 익명 함수를 참조합니다. " process , 다이어그램은 다음과 같습니다.

JavaScript 프로토타입과 상속

(회색 배경은 빈 함수를 기반으로 추가된 속성입니다.)
간단히 말하면 프로토타입은 의 속성입니다. 함수 생성 과정에서 js 컴파일러에 의해 자동으로 추가됩니다.
그렇다면 프로토타입의 용도는 무엇인가요?
먼저 new 연산자를 이해하면 다음과 같습니다.
1
2 var a1 = new A;
var a2 = new A;
생성자를 통해 객체를 생성하는 방법은 다음과 같습니다. 직접 var a1 = {}; 대신에 이와 같은 객체를 생성해야 하는 이유는 무엇입니까? 여기에는 new의 특정 단계가 포함됩니다. 여기서 새 작업은 세 단계로 나눌 수 있습니다(a1 생성을 예로 들어):
1. 새 객체를 생성하고 이를 변수 a1에 할당합니다. var a1 = {} ;
2, 이 객체의 [[Prototype]] 속성을 함수 A의 프로토타입 객체로 지정합니다: a1.[[Prototype]] = A.prototype
3. 객체 초기화를 위해 1에서 생성된 객체 a1을 가리킵니다: A.apply(a1,arguments)
구조 다이어그램은 다음과 같습니다:

JavaScript 프로토타입과 상속

그림에서 볼 수 있듯이 객체 a1이든 a2이든 함수 A의 프로토타입 객체에 대한 참조를 저장하는 속성이 있습니다. 이러한 객체에 대한 몇 가지 일반적인 메소드는 객체의 프로토타입에서 찾을 수 있습니다. 기능, 메모리 공간 절약.

4. 프로토타입 체인
새로운 연산자와 프로토타입의 역할을 이해한 후, [[Prototype]]이 무엇인지 살펴보겠습니다. 그리고 객체는 이 참조에 따라 속성을 어떻게 검색합니까?
JS의 세계에서 각 객체는 기본적으로 [[Prototype]] 속성을 가지며, 객체가 저장하는 주소는 객체가 생성될 때 js 컴파일러에 의해 자동으로 추가됩니다. 그 값은 new 연산자의 오른쪽 매개변수에 의해 결정됩니다. var object1 = {};인 경우, object1의 [[Prototype]]은 Object 생성자의 프로토타입 객체를 가리킵니다. 왜냐하면 var object1 = {}; to var object = new Object(); (이유는 위의 new A 분석 과정을 참고하세요.)
객체는 속성을 찾을 때 먼저 자신의 속성을 순회합니다. 속성이 없으면 [[Prototype]]에서 참조하는 객체를 계속 검색합니다. [[Prototype]].[[Prototype].] 참조 객체 등을 검색하려면 [[Prototype]]...[[Prototype]]이 정의되지 않을 때까지([[Prototype]] of Object가 정의되지 않음)
위 그림과 같이:
//a1.fGetName을 얻으려고 합니다
Alert(a1.fGetName);//Output undefine
//1. a1 객체 자체를 탐색합니다 www.2cto .com
//결과적으로 a1 객체 자체에는 fGetName 속성이 없습니다
//2. 해당 객체 A.prototype인 a1의 [[Prototype]]을 찾아 동시에 탐색합니다. time
//결과적으로 A.prototype에는 이 속성이 없습니다.
//3. A.prototype 찾기 객체의 [[Prototype]]은 해당 객체를 가리킵니다. Object.prototype
//결과적으로 Object.prototype에는 fGetName
이 없습니다. //4. Object.prototype의 [[Prototype]] 속성을 찾으면 결과가 정의되지 않은 상태로 반환됩니다. 이는 a1.fGetName의 값입니다.
간단히 말하면, 해당 객체의 [[Prototype]]을 통해 다른 객체에 대한 참조를 저장하고, 이 참조를 통해 위쪽으로 속성을 검색하는 것이 프로토타입 체인입니다.

5. 상속
프로토타입 체인의 개념으로 상속이 가능합니다.
1개의 함수 B() {};
이때 B의 프로토타입 B.prototype이 생성됩니다
프로토타입 자체가 Object 객체인데 어떤 데이터가 들어있는지 알 수 있습니다
B.prototype Actual 위의 내용은 {constructor: B, [[Prototype]]: Object.prototype}
프로토타입 자체가 Object 개체의 인스턴스이므로 프로토타입 체인이 Object
B의 프로토타입을 가리킵니다. 프로토타입 = A.prototype ;//B의 프로토타입을 A의 프로토타입으로 가리키는 것과 동일합니다. 이는 A의 프로토타입 메소드만 상속하고 A의 사용자 정의 메소드는 상속하지 않습니다.
B.prototype.thisisb = "이것은 생성자 B입니다." ;/ /이것은 또한
의 프로토타입을 변경합니다. 하지만 우리는 B의 프로토타입 체인을 A로 가리키고 싶습니다. 어떻게 해야 할까요?
첫 번째는 프로토타입 체인 참조 주소를 변경하는 것입니다
1 B.prototype.__proto__ = A.prototype;
ECMA에는 __proto__ 메소드가 없습니다. 이는 ff 및 chrome과 같은 js 인터프리터에 의해 추가됩니다. , 이는 EMCA의 [[Prototype]]과 동일합니다. 이것은 표준 방법이 아닌데 어떻게 표준 방법을 사용합니까?
new를 실행할 때 실제로 인스턴스 객체의 프로토타입 체인을 생성자의 프로토타입 주소 블록으로 지정하면 다음과 같이 작동할 수 있다는 것을 알고 있습니다.
1 B.prototype = new A();
이 방법의 결과는 다음과 같습니다.
는 A의 인스턴스를 생성하고 이를 B의 프로토타입에 할당합니다. 즉, B.prototype은 객체 {width: 10, data: [1,2,3]과 동일합니다. , key: "this is A " , [[Prototype]] : A.prototype}
이런 방식으로 A의 프로토타입은 객체 속성 B.prototype.[[Prototype]]을 통해 저장되어 다음 링크를 형성합니다. 프로토타입
그러나 이런 방식으로 B 생성된 객체의 생성자가 변경되었습니다. 왜냐하면 B에는 생성자 속성이 없고 A.prototype은 프로토타입 체인에서만 찾을 수 있고 생성자를 읽어오기 때문입니다. out: A
var b = new B;
console.log(b .constructor);//output A
따라서 B 자체를 수동으로 다시 설정해야 합니다
B.prototype.constructor = B ;
//이제 B의 프로토타입은 {width: 10, data : [1,2,3] , key : "this is A" , [[Prototype]] : A.prototype , constructor : B} console.log(b.constructor);//output B
//동시에 B는 프로토타입을 통해 A의 사용자 정의 속성인 너비와 이름을 직접 상속합니다
console.log(b.data) / /output [1,2,3]
//단점은
b.data.push(4);//프로토타입의 데이터 배열을 직접 변경함(참조)
var c = new B ;
Alert(c.data);//output [1,2,3 ,4]
//실제로 우리가 원하는 것은 B에서 A의 사용자 정의 속성을 정의하고 싶습니다. (프로토타입에는 없음)
//상속 방법은?
//A에 사용자 정의 속성이 필요하지 않으므로 이를 필터링하는 방법을 찾을 수 있습니다.
//새 빈 함수를 만들 수 있습니다.
function F(){}
//빈 함수의 프로토타입을 생성자 A의 프로토타입을 가리킨다
F.prototype = A.prototype;
//이때 B.prototype의 프로토타입 체인을 가리키도록 new 연산을 사용한다. F의 프로토타입으로
B.prototype = new F;
//이때 B의 프로토타입은 다음과 같습니다. {[[Prototype]]: F.prototype}
//여기서 F.prototype은 실제로는 주소에 대한 참조일 뿐입니다
//그러나 인스턴스의 생성자는 B가 A를 가리키므로 여기서는 B.prototype
B.prototype.constructor = B;
//이때 B의 프로토타입은 {constructor: B, [[Prototype]]: F.prototype}
//A에서 B의 프로토타입 상속을 구현합니다.
다이어그램은 다음과 같으며 빨간색 부분은 프로토타입 체인을 나타냅니다.

JavaScript 프로토타입과 상속

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.