JS의 프로토 타입을 이해하려면 먼저 다음 개념을 이해해야합니다.
1. JS의 모든 것은 물체입니다
2. JS의 모든 것은 물체에서 파생됩니다.
// [ "생성자", "TOSTRING", "TOLOCALESTRING", "ValueOf", "hasOwnProperty", "isprototypof", // "propertyisEnumerable", "__defineGetter__", "__lookupgetter__", "__definesetter__", // "__lookupsetter__"] Console.log (Object.getownPropertyNames (Object.Prototype));
3. JS의 생성자와 인스턴스 (객체) 간의 미묘한 관계
생성자는 프로토 타입을 정의하여 인스턴스의 사양에 동의 한 다음 새로 인스턴스를 구성합니다. 그들의 기능은 물체를 생산하는 것입니다.
생성자 (메소드) 자체는 메소드 (함수)의 인스턴스이므로 __proto __ (protochain)에 대해서도 찾을 수 있습니다.
Object / Function F () {} 이것은 생성자이며, 하나는 JS Native API에 의해 제공되고 다른 하나는 사용자 정의됩니다.
new Object () / new f ()가 인스턴스입니다
이 예제는 "만"만 볼 수 있도록 "만"만 볼 수 있습니다.
인스턴스를 "재정의 할 수없는"프로토 타입은 인스턴스의 인스턴스를 생성하기 위해 스스로를 용서합니다.
진정한 지식을 만들어 내고 자신을 관찰/생각 함으로써만 진정으로 이해할 수 있습니다.
// 생성자가 무엇인지 // function empty () {} function empty () {} console.log (function.prototype, function .__ proto__)를 살펴 보겠습니다. // object {} 함수 empty () {} console.log (Object.Prototype, object .__ proto__); function f () {} // f {} function empty () {} console.log (f.prototype, f .__ proto__);당신은 현기증 일 수 있습니다.
원기
프로토 타입 출력의 형식은 다음과 같습니다. 생성자 이름 프로토 타입
먼저 어떤 개체. 프로로 타입 출력을 살펴 보겠습니다.
객체 {} -> 이전 객체는 생성자의 이름이고 다음 객체는 프로토 타입을 나타냅니다. 다음은 {}, 즉 객체 객체 (빈 개체)의 인스턴스입니다.
그런 다음 f {} 우리는 그것이 의미하는 바를 이해합니다. F는 생성자의 이름이며 프로토 타입도 빈 개체입니다.
// 생성자 var o = new Object ()가 구성한 예제를 살펴 보겠습니다. // var o = {}; // 정의되지 않은 개체 {} console.log (O.Prototype, o .__ proto__); 함수 f () {} var i = new f (); // 정의되지 않은 f {} console.log (i.prototype, i .__ proto__);조금 더 깊이 가고 F의 프로토 타입을 정의하여 어떤 일이 일어날 지 확인하자?
함수 f () {} f.prototype.a = function () {}; var i = 새로운 f (); // 정의되지 않은 f {a : function} console.log (i.prototype, i .__ proto__);이런 식으로, 우리는 내가 f로 구성되었음을 분명히 알 수 있으며, 프로토 타입은 {a : function}이므로 메소드 A가 원래 빈 객체 프로토 타입에 추가되었음을 의미합니다.
상황을 바꾸겠습니다. F를 완전히 다루는 프로토 타입이 있으면 어떻게됩니까?
함수 f () {} f.prototype = {a : function () {}}; var i = 새로운 f (); // 정의되지 않은 개체 {a : function} console.log (i.prototype, i .__ proto__);안녕 ~ 왜 내가 물체로 구성되었다고 여기에 표시합니까? 아니요!
F의 프로토 타입을 완전히 덮어 쓰기 때문에 프로토 타입을 객체 {a : function}로 지정하지만 원래 생성자 정보가 손실되고 객체 {a : function}에 의해 지정된 생성자가됩니다.
그렇다면 객체 {a : function}의 생성자는 무엇입니까?
객체 {a : function}은 실제로 관련이 있기 때문입니다
var o = {a : function () {}} // 새 개체그런 다음 O의 생성자는 물론 객체입니다.
이 오류를 수정합시다
함수 f () {} f.prototype = {a : function () {}} // 올바른 생성자 f.prototype.constructor = f; var i = 새로운 f (); // 정의되지 않은 f {a : 함수, 생성자 : function} console.log (i.prototype, i .__ proto__);이제 올바른 프로토 타입 정보를 다시 얻을 수 있습니다 ~
프로토 타입 체인
그렇다면 프로토 타입 체인이 무엇인지 살펴 보겠습니다.
간단히 말해서, 그것은 OOP의 상속 관계 (체인)와 동일합니다. 최종 객체가 될 때까지 레이어별로 레이어를 찾으십시오
가장 중요한 것은 JS에서 (인스턴스) 객체인지 알아내는 것입니다. 이것은 간단합니다. JS의 모든 것이 객체입니다!
그런 다음 모든 객체에 프로토 타입이 있음을 알아 내야합니다!
그런 다음 그것을 증명합시다 :
객체 // 기능은 함수의 인스턴스 객체이므로 객체입니다. // true function // 이것은 또한 함수이기도합니다. 예! function .__ proto__ == function.prototype // true function a () {} // 이것은 사용자 정의 함수이며 결국 기능입니다. a .__ proto__ == function.prototype // 모든 함수는 기능의 인스턴스입니다. var a = new a () a .__ proto__ == A. prototype // 인스턴스 A는 생성자에 의해 구성되므로 A의 프로토 타입은 A.prototype의 프로토 타입 속성에 의해 정의됩니다.프로토 타입 및 __proto__
각 객체에는 객체의 "프로토 타입"을 가리키는 __proto__가 포함되어 있습니다.
비슷한 점은 각 함수에 프로토 타입이 포함되어 있다는 것입니다. 이 프로토 타입 객체는 무엇입니까?
생성자를 사용하여 객체를 만드는 다음 코드를 살펴 보겠습니다 (위는 문자 형식 형식의 개체를 작성하는 것입니다).
함수 foo () {}; var foo = new foo (); console.log (foo .__ proto__);이 foo 객체의 __proto__가 무엇을 가리킬 것인가?
생성자 속성을 포함하는 객체? 당신이 그것을 많이 이해하지 못하든 상관 없습니다. FOON의 프로토 타입 속성을 인쇄하고 알고 비교하십시오.
함수 foo () {}; var foo = new foo (); console.log (foo .__ proto __); console.log (foo.prototype); console.log (foo .__ proto__ == foo.prototype);새로운에서 나오는 개체 foo의 __proto__는 기능 foo의 프로토 타입을 가리킨다는 것이 밝혀졌습니다.
foo .__ proto__-> foo.prototype
이와 같은 JS를 디자인하는 요점은 무엇입니까? JS의 세계에서 위에서 언급 한 내용을 상기하면 객체는 클래스 (금형)를 기반으로 생성되지 않지만 프로토 타입 (다른 객체)에서 파생됩니다.
새로운 객체를 만들기 위해 새로운 작업을 수행 할 때, 우리는 새로운 운영의 특정 구현에 깊이 들어 가지 않을 것이지만, 한 가지를 확신합니다.
이 코드 만
함수 foo () {}; var foo = new foo ();foo .__ proto__를 가리키는 사람은 누구입니까? FOO 자체 기능을 지적 할 수없는 이유는 무엇입니까? 기능도 대상이지만 기회가 있다면 자세히 이야기하겠습니다. 그러나 foo는 많은 논리 코드가있는 함수이기 때문에 foo .__ proto_foo를 가리키는 것은 확실히 적절하지 않습니다. 대상으로서, 논리적 처리를 상속하는 것은 의미가 없습니다. 상속하고 싶은 것은 "프로토 타입 객체"의 속성입니다.
따라서 각 함수는 프로토 타입 객체를 자동으로 생성 하며이 함수에서 새로운 개체의 __proto__는이 기능의 프로토 타입을 가리 킵니다.
foo .__ proto__-> foo.prototype
요약
너무 많이 말한 후에도 여전히 그것을 완전히 설명하지 않았으므로 이전 사진에있는 것이 낫습니다. 나는 다른 네티즌의 사진을 참조했지만 항상 명확하게 설명하지 않았다고 생각하기 때문에 사진을 직접 그렸습니다. 내 것이 좋다고 생각한다면 제발 좋아하세요! (나는 그것을 그리기 위해 최선을 다했습니다).
이 사진을 찍고 다음과 같은 사실을 기억합시다.
1. 각 객체에는 _proto_ 속성이 있습니다.
JS 세계에는 클래스 (금형)의 개념이 없습니다. 객체는 다른 객체 (프로토)에서 파생되므로 각 객체에 프로토 타입 객체를 가리키는 _proto_ 속성이 있습니다. (왼쪽 상단 모서리에 문자 그대로 정의 된 OBJ를 참조하십시오. 메모리에 객체의 특성을 저장하는 공간을 열고 프로토 타입을 가리키는 _proto_를 생성합니다.
2. 각 함수에는 프로토 타입 속성이 있습니다.
"생성자"가 생성자라고하는 이유는 무엇입니까? 객체를 구성하고 싶기 때문입니다. 위의 첫 번째 사실에 따르면, 구성된 새 개체의 _proto_ 속성은 누가 지적합니까? 생성자 자체를 가리킬 수는 없습니다. 그것은 또한 객체이지만, 당신은 새로운 객체가 함수의 특성과 방법을 물려 받기를 원하지 않습니다. 따라서, 각 생성자는 프로토 타입 속성을 가지며,이 생성자에 의해 구성된 새로운 객체의 프로토 타입으로 객체를 가리키는 프로토 타입 속성을 갖습니다.
3. 기능도 객체입니다.
각 함수에는 apply ()/call () 등과 같은 몇 가지 공통 속성과 메소드가 있습니다. 그러나 이러한 일반적인 방법은 어떻게 상속됩니까? 기능은 어떻게 생성됩니까? 단지 모든 것이 함수를 포함한 객체이며 생성자를 통해 구성된 물체라고 상상해보십시오. 그런 다음 위의 두 번째 사실에 따르면, 각 함수에는 생성자를 가리키는 프로토 타입이 있습니다. 이 생성자의 기능은 기능이며 JS의 모든 함수는 기능으로 구성됩니다. 기능의 일반적인 특성 및 방법은 프로토 타입 객체 함수에 저장됩니다.