프로토 타입 체인은 이해하기가 약간 혼란스럽고 온라인 정보가 많이 있습니다. 밤에 잠을 잘 수 없을 때마다 항상 온라인으로 프로토 타입 체인과 클로저 기사를 읽고 싶습니다. 매우 효과적입니다.
이러한 많은 용어에 대해 걱정하지 마십시오. 뇌를 비틀어주는 것 외에는 실제로 도움이되지 않습니다. 프로토 타입 체인을 간단하고 대략적으로보고 인간, 악마 및시 메일 남성과 같이 코드와 관련이없는 것들에 대해 생각하십시오.
1) 사람들은 인간이 태어나고 괴물은 악마에 의해 태어납니다. 인간과 악마는 모두 대상의 사례이며 인간과 악마는 프로토 타입입니다. 프로토 타입은 또한 프로토 타입 객체라고하는 객체입니다.
2) 사람의 어머니와 그의 아버지는 많은 아기를 낳을 수 있으며, 악마 어머니와 그의 아버지는 많은 아기를 낳을 수 있습니다. 남자의 아내와 남자는 많은 아기를 낳을 수 있습니다. 남자는 일반적으로 사람으로 알려진 생성자입니다.
3) 사람들은 섹스에 관한 정보를 기록 할 수 있으므로 사람들은 성별을 통해성에 대한 정보를 찾을 수 있습니다. 즉, 프로토 타입 객체를 통해 생성자를 찾을 수 있습니다.
4) 사람들은 어머니의 많은 아기를 낳을 수 있지만,이 아기는 한 명의 어머니 만 가지고 있으며, 이는 프로토 타입의 독창성입니다.
5) 사람들은 또한 사람들에 의해 태어나고 사람들을 통해 사람들을 찾은 다음 사람들을 통해 사람들을 찾습니다 ...이 관계는 프로토 타입 체인이라고합니다.
6) 프로토 타입 체인은 무한하지 않습니다. 당신이 사람들을 계속 바라 볼 때, 당신은 사람들이 빌어 먹을 인간이 아니라는 것을 알게 될 것입니다. 즉, 프로토 타입 체인은 마침내 널을 가리 킵니다.
7) 엄마와 함께 태어난 사람들은 사람처럼 보이고 엄마와 함께 태어난 괴물은 못 생겼습니다. 이것을 상속이라고합니다.
8) 당신은 어머니의 피부색을 물려 받았습니다. 어머니는 어머니의 피부색을 물려 받았습니다 ... 이것은 프로토 타입 체인의 상속입니다.
9) 집이 없다면 집은 어머니의 집을 말합니다. 당신의 어머니가 집이 없다면, 당신의 집은 당신의 어머니의 집을 말합니다. 이것은 프로토 타입 체인을 위쪽으로 찾는 것입니다.
10) 어머니의 외모를 물려받을 수 있지만 머리카락, 샴푸, 컷 및 블로우, 즉 물체의 속성을 사용자 정의 할 수 있으며 상속 된 속성을 무시할 수 있습니다.
11) 당신은 씻고, 자르고, 날아 가고, 염색하고 염색 한 노란 머리카락을 만들었지 만, 당신은 어머니의 외모를 바꿀 수 없습니다. 어머니에게 태어난 남동생 자매는 노란 머리를 씻고 자르고 날아간 노란 머리카락과 관련이 없습니다. 즉, 객체 인스턴스는 프로토 타입의 특성을 변경할 수 없습니다.
12) 그러나 집이 당신에 의해 태워지면, 그것은 당신의 어머니와 당신의 형제가 불에 태워 졌다는 것을 의미하며, 이것은 프로토 타입 속성의 공유입니다.
13) 당신의 어머니의 별명은 Azhen이고, 그녀의 이웃의 이모는 당신을 Azhener라고 부르지 만, 어머니의 머리카락이 Piaorou에서 Golden Lion King으로 돌린 후 옆집 이모가 그녀의 말을 바꾸고 당신을 황금 사자 왕자라고 불렀습니다. 이것을 프로토 타입의 동적 특성이라고합니다.
14) 당신의 어머니는 아름다움을 사랑하고 성형 수술을 위해 한국에 갔다. 그녀는 어머니를 인식조차 할 수 없었습니다. 어머니의 머리카락이 부드러움으로 바뀌더라도 옆집 이웃은 여전히 당신을 황금 사자 왕자라고 불렀습니다. 아무도 당신의 어머니를 인식하지 못했기 때문에, 당신의 어머니는 성형 수술 후 공장으로 돌아 왔습니다. 이것은 프로토 타입의 전반적인 재 작성입니다.
젠장! 당신은 충분합니다! BB를하지 마십시오! 코드를 보여주세요!
기능인 (이름) {this.name = 이름; } function mother () {} mother.prototype = {// 어머니의 프로토 타입 연령 : 18, 홈 : [ '베이징', '상하이']}; person.prototyp = new Mother (); // 사람의 프로토 타입은 어머니입니다. // 크롬 디버깅 도구를 사용하여 프로토 타입을보고 프로토 타입 var p1 = new Person ( 'Jack')을 볼 수 있도록 __proto__ 인터페이스를 제공합니다. // p1 : '잭'; __proto __ : 18, [ '베이징', '상하이'] var p2 = 새로운 사람 ( 'mark'); // p2 : 'Mark'; __proto __ : 18, [ '베이징', '상하이'] p1.age = 20; /* 인스턴스는 프로토 타입의 기본 값 속성을 변경할 수 없습니다. 노란색 머리카락을 씻고 자르고 날려 버리고 염색하는 것처럼 어머니와 아무 관련이 없습니다.* P1 인스턴스에서 연령 속성을 추가하는 일반적인 작업은 프로토 타입과 관련이 없습니다. var o {}와 동일합니다. O.age = 20. * P1 : 아래에 추가 속성 연령이 있으며 __proto__는 Mother.Prototype, Age = 18과 동일합니다. * p2 : 속성 이름 만, __proto__는 ahoy.prototype*/p1.home [0] = 'shenzhen'; /* 프로토 타입에서 참조 유형 속성 공유는 집을 태우는 것과 같습니다. 온 가족의 집을 태우고 있습니다* 이것은 약간의 패스입니다. * P1 : 'Jack', 20; __proto __ : 18, [ 'Shenzhen', 'Shanghai']* p2 : 'mark'; __proto __ : 18, [ 'Shenzhen', 'Shanghai']*/p1.home = [ 'hangzhou', 'Guangzhou']; /* 실제로 P1.age = 20과 동일한 작업. 이 이해로 변경 : var o {}; O.House = [ 'big', 'house']* p1 : 'jack', 20, [ 'hangzhou', 'Gugangzhou']; __proto __ : 18, [ 'Shenzhen', 'Shanghai']* p2 : 'mark'; __proto __ : 18, [ 'Shenzhen', 'Shanghai']*/p1.age; /* 사용자 정의 속성을 삭제 한 후 원래 덮어 쓰기 된 프로토 타입 값이 다시 예상됩니다. 이것은 상향 검색 메커니즘이므로 다음과 같은 역학* p1 : 'jack', [ 'hangzhou', 'Guangzhou']; __proto __ : 18, [ 'Shenzhen', 'Shanghai']* p2 : 'mark'; __proto __ : 18, [ 'Shenzhen', 'Shanghai']*/person.prototype.lastname = 'Jin'; /* 프로토 타입을 다시 작성하고 인스턴스에 동적으로 반응합니다. 당신의 어머니가 트렌디 한 사람이 된 것처럼, 이웃 사람들은 당신이 그것을 언급 할 때 트렌디 한 여성의 아들이라고 말합니다. 다른 수준을 변경하면 효과가 매우 다릅니다. * P1 : 'Jack', [ 'hangzhou', 'Guangzhou']; __proto __ : 'Jin'; __ proto __ : 18, [ 'Shenzhen', 'Shanghai']* p2 : 'mark'; __proto __ : 'jin'; __ proto __ : 18, [ 'shenzhen', 'shanghai']*/person.prototype = {age : 28, 주소 : {Country : 'USA', 'Washington'}}; var p3 = 새로운 사람 ( 'Obama'); /* 프로토 타입을 다시 작성하십시오! 현재 사람의 프로토 타입은 완전히 새로운 대상이되었으며, 이는 사람이 어머니를 바꿨다는 것을 의미합니다. * 이것을 이해하려면 : var a = 10; b = a; a = 20; c = a. 따라서 B는 변경되지 않고 C가되므로 P3은 변하고 어머니와 아무 관련이 없습니다. * P1 : 'Jack', [ 'hangzhou', 'Guangzhou']; __proto __ : 'Jin'; __ proto __ : 18, [ 'Shenzhen', 'Shanghai']* p2 : 'mark'; __proto __ : 'jin'; __ proto __ : 18, [ 'shenzhen', 'shanghai']* p3 : '오바마'; __ proto_ : 28 {Country : 'USA', 'Washington'}*/mother.prototype.NO = 9527; 당신의 어머니가 새로운 트렌드가 된 것처럼, 이웃 사람들은 당신이 정말로 트렌디 한 할머니라고 말합니다. * P1 : 'Jack', [ 'hangzhou', 'Guangzhou']; __proto __ : 'Jin'; __ proto __ : 18, [ 'Shenzhen', 'Shanghai'], 9527* p2 : 'mark'; __proto __ : 'Jin'; __ proto __ : 18, [ 'Shenzhen', 'Shanghai'], 9527* p3 : '오바마'; __proto__ : 28 {Country : 'USA', City : 'Washington'}*/mother.prototype = {Car : 2, 취미 : [ 'run', 'walk'}; var p4 = 새로운 사람 ( 'Tony');/* 프로토 타입의 프로토 타입을 다시 작성하십시오! 현재 어머니의 프로토 타입은 완전히 새로운 대상이되었습니다! * 사람과 어머니가 위에서 분리되었으므로 어머니의 변화는 더 이상 사람에게 영향을 미치지 않습니다. * P4 : 'Tony'; __ proto__ : 28 {Country : 'USA', City : 'Washington'}*/person.prototype = new Mother (); // var var p5 = 새로운 사람 ( 'luffy'); //이 변경 사항을 적용해야한다면,이 변경 사항을 적용해야한다면, 사람의 프로토 타입을 어머니에게 다시 바운드해야합니다. // p5 : 'luffy'; __ proto_ : 2, [ 'run', 'walk'] p1. MOTHER.당신은 그것을 읽은 후에 기본적으로 이해할 수 있습니까?
이제 p1.age = 20, p1.home = [ 'hangzhou', 'Guangzhou'] 및 p1.home [0] = 'shenzhen'의 차이에 대해 이야기 해 봅시다. p1.home [0] = 'shenzhen'; 요약하면, 그것은 p1.object.method, p1.object.property와 같은 형식입니다.
p1.age = 20; p1.home = [ 'hangzhou', 'Guangzhou']; 이 두 문장은 이해하기 쉽습니다. 프로토 타입을 먼저 잊어 버리고 일반적인 개체에 속성을 추가하는 방법에 대해 생각해보십시오.
var obj = new Object (); obj.name = 'xxx'; obj.num = [100, 200];
이런 식으로 이해하십니까? 동일합니다.
그렇다면 왜 p1.home [0] = 'Shenzhen'이 P1에서 홈 어레이 속성을 만들고 첫 번째 위치를 'Shenzhen'으로 설정하지 않습니까? 먼저 이것을 잊어 버리자 위의 OBJ 객체에 대해 생각해 보겠습니다. var obj.name = 'xxx', obj.num = [100, 200]처럼 작성된 경우 원하는 결과를 얻을 수 있습니까? 분명히, 당신은 오류를 제외하고는 아무것도 얻지 못할 것입니다. OBJ는 아직 정의되지 않았기 때문에 어떻게 추가 할 수 있습니까? 마찬가지로, p1.home [0]의 주택은 P1에 의해 정의되지 않으므로 집을 직접 정의하는 것은 불가능합니다 [0]. P1에 따라 홈 어레이를 만들려면 다음과 같이 작성됩니다.
p1.home = []; p1.home [0] = 'shenzhen';
이것이 가장 일반적으로 사용되는 방법이 아닙니까?
p1.home [0] = 'shenzhen'이 오류를 직접보고하지 않는 이유는 프로토 타입 체인에 검색 메커니즘이 있기 때문입니다. p1.object를 입력하면 프로토 타입 체인의 검색 메커니즘은 먼저 인스턴스에서 해당 값을 검색하는 것입니다. 찾을 수없는 경우 프로토 타입에서 검색됩니다. 찾을 수없는 경우 프로토 타입 체인의 이전 레벨에서 검색됩니다. 프로토 타입 체인의 끝에 도달합니다. 즉, 아직 발견되지 않은 경우 정의되지 않은 것으로 반환됩니다. p1.home [0]을 입력하면 동일한 검색 메커니즘도 마찬가지입니다. 먼저 P1을 검색하여 집이라는 이름의 속성과 메소드가 있는지 확인한 다음 단계별로 위쪽으로 검색하십시오. 마지막으로 우리는 어머니의 프로토 타입에서 그것을 발견 했으므로 수정하는 것은 어머니의 프로토 타입을 수정하는 것과 같습니다.
요약 : p1.home [0] = 'shenzhen'은 Mother.prototype.home [0] = 'Shenzhen'과 동일합니다.
위의 분석에서 프로토 타입 체인 상속의 주요 문제는 속성 공유에 있다는 것을 알 수 있습니다. 여러 번 우리는 방법 만 공유하고 싶지만 속성은 아닙니다. 이상적으로는 각 인스턴스에는 독립적 인 속성이 있어야합니다. 따라서 프로토 타입 상속을 개선하는 두 가지 방법이 있습니다.
1) 조합 상속
기능 Mother (Age) {this.age = age; this.hobby = [ 'running', 'football']} mother.prototype.showage = function () {console.log (this.age); }; 기능인 (이름, 나이) {Mother.Call (this, age); // 두 번째 실행 this.name = 이름; } person.prototype = new Mother (); // 첫 번째 실행 person.prototype.constructor = person.prototype.howname = function () {console.log (this.name);} var p1 = new Person ( 'Jack', 20); p1.hobby.push ( '농구'); // p1 : '잭'; __proto __ : 20, [ 'Running', 'Football'] var p2 = 새로운 사람 ( 'Mark', 18); // p2 : 'Mark'; __proto __ : 18, [ '달리기', '축구']]결과는 자주색입니다.
첫 번째 실행이 여기에서 수행되면 person.prototype.age = undefined, person.prototype.hobby = [ 'Running', 'Football']를 얻을 수 있습니다. 두 번째 실행은 var p1 = new Person ( 'Jack', 20)이고 p1.age = 20, p1.hobby = [ 'running', 'football']가 나타납니다. 밀고 나면 p1.hobby = [ '런닝', '축구', '농구']가됩니다. 실제로, 이것의 변화를 이해하는 것은 비교적 간단합니다. 이것을 간단히 교체 하여이 결과를 얻을 수 있습니다. 이해하는 것이 약간 혼란 스럽다고 생각되면 마음 속에 개념을 버리고 브라우저로 코드를 위에서 아래로 실행하십시오. 나올까요?
프로토 타입 생성자 Mother ()를 두 번째로 실행함으로써 객체 인스턴스에서 프로토 타입의 특성 사본을 복사하여 프로토 타입 속성과 분리하고 분리 할 수 있습니다. 당신이 조심한다면, 우리가 처음으로 Mother ()를 불렀을 때 사용되지 않는 것 같습니다. 우리는 어떻게 그것을 부를 수 없습니까? 예, 기생 조합 상속이 있습니다.
2) 기생 조합 상속
함수 객체 (o) {function f () {} f.prototype = o; return new f ();} 함수 inheritPrototype (person, mother) {var prototype = object (while.prototyp); 프로토 타입 .constructor = person; person.prototype = 프로토 타입; } 기능 어머니 (Age) {this.age = age; this.hobby = [ 'running', 'football']} mother.prototype.showage = function () {console.log (this.age); }; 기능인 (이름, 나이) {Mother.Call (this, age); this.name = 이름; } inheritPrototype (사람, 어머니); person.prototype.howname = function () {console.log (this.name);} var p1 = 새로운 사람 ( 'Jack', 20); p1.hobby.push ( 'basketball'); // p1 : 'jack'; __proto __ : 20, [ 'Running', 'Football'] var p2 = 새로운 사람 ( 'Mark', 18); // p2 : 'Mark'; __proto __ : 18, [ '달리기', '축구']]결과는 자주색입니다.
프로토 타입에는 더 이상 나이와 취미 속성이 없으며 두 가지 방법 만 있습니다. 정확히 우리가 원하는 결과입니다!
핵심 요점은 객체 (O)에 있는데, 여기서 임시 객체가 새 Mother ()를 영리하게 전화하지 않기 위해 여기서 빌린 다음 프로토 타입 O로 새 개체 인스턴스를 반환하여 프로토 타입 체인의 설정을 완료합니다. 매우 혼란 스럽습니까? 그것은 우리가 사람을 설정할 수 없기 때문입니다. prototype = mother.prototype를 직접.
요약
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
너무 많은 말을했지만 실제로는 하나의 핵심이 있습니다 : 속성 공유 및 독립적 인 제어. 객체 인스턴스에 독립적 인 속성이 필요한 경우 모든 관행의 본질은 객체 인스턴스에서 속성을 만드는 것입니다. 너무 많이 생각하지 않으면 프로토 타입의 속성을 덮어 쓰는 데 직접 필요한 독립 속성을 직접 정의 할 수 있습니다. 요컨대, 프로토 타입 상속을 사용할 때는 프로토 타입의 속성에 특별한주의를 기울여야합니다. 이들은 전신에 영향을 미치는 모든 존재이기 때문입니다.
아래는 JS에서 객체를 만드는 다양한 방법의 간단한 목록입니다. 가장 일반적으로 사용되는 방법은 이제 조합 모드입니다. 친숙한 학생들은 기사 끝까지 건너 뛰고 좋아할 수 있습니다.
1) 원래 모드
// 1. 원래 모드, 객체 문자 모드 var person = {name : 'jack', age : 18, sayname : function () {alert (this.name); }}; // 1. 원래 모드, 객체 생성기 모드 var person = new Object (); person.name = 'Jack'; person.age = 18; person.sayname = function () {alert (this.name);};분명히, 우리가 person1, person2의 배치를 만들고 싶을 때, 우리는 매번 많은 코드를 입력해야하며, 심지어 선임 코피 피스터조차도 그것을 견딜 수 없습니다! 그런 다음 대량 생산 공장 모델이 있습니다.
2) 공장 모델
// 2. 팩토리 모드, 객체 함수 생성 기능을 정의합니다. person.name = name; person.age = age; person.sayname = function () {alert (this.name);}; return temp; }공장 모드는 대량 생산이며 간단한 전화 (Papapapa ...)로 사람 제작 모드에 들어갈 수 있습니다. 당신은 당신의 이름과 나이를 지정하여 많은 아기를 만들고 손을 자유롭게 할 수 있습니다. 그러나 공장에서 운영되므로 인간이든 개이든간에 객체의 유형이 무엇인지 식별 할 수 없습니다 (테스트 인스턴스는 대상입니다). 또한 인간을 만들 때마다 독립 온도 객체를 만들어야하고 코드가 부풀어 오르고 나비는 우아합니다.
3) 생성자
// 3. 생성자 모드, 객체 함수 직원 (이름, age)의 생성자 함수 정의 {this.name = name; this.age = age; this.sayname = function () {alert (this.name);}; } var p1 = 새로운 사람 ( 'Jack', 18); // P1 객체 사람을 만듭니다 ( 'Jack', 18); // 속성 메소드는 Window 객체, window.name = 'Jack', Window.sayName ()가 Jack을 출력합니다.생성자는 C ++ 및 Java의 클래스 생성자와 유사하며 이해하기 쉽습니다. 또한 사람은 유형 인식으로 사용될 수 있습니다 (인스턴스 테스트는 사람과 대상입니다). 그러나 모든 인스턴스는 여전히 독립적이며 다른 인스턴스의 방법은 실제로 다른 기능입니다. 여기서 단어 기능을 잊어 버리십시오. 즉, Zhang San의 Sayname과 Li Si의 Sayname은 다른 존재를 가지고 있지만 분명히 우리가 기대하는 것은 메모리를 저장하기 위해 SayName을 공유하는 것입니다.
4) 프로토 타입 모드
// 4. 프로토 타입 모드, 프로토 타입 속성 함수 직함 () {} person.name = 'jack'; person.prototype.age = 18; person.prototype.sayname = function () {alert (this.name); }; // 4. 프로토 타입, 리터럴 정의 방법 함수 person () {} person.prototype = {이름 : 'jack', age : 18, sayname : function () {alert (this.name); }}; var p1 = new Person (); // name = 'Jack'var p2 = new Person (); // 이름 = '잭'여기에 주목해야 할 것은 프로토 타입 속성 및 메소드의 공유입니다. 즉, 모든 인스턴스는 프로토 타입의 속성 메소드만을 참조하고 모든 장소에서 생성 된 변경으로 인해 다른 인스턴스의 변경이 발생합니다.
5) 혼합 모드 (건축 + 프로토 타입)
// 5. 프로토 타입 구성 조합 모드, 기능인 (이름, 나이) {this.name = name; this.age = age;} person.prototype = {취미 : [ 'running', 'football']; sayname : function () {alert (this.name); }, sayage : function () {alert (this.age); }}; var p1 = 새로운 사람 ( 'Jack', 20); // p1 : '잭', 20; __proto__ : [ 'Running', 'Football'], sayname, sayagevar p2 = 새로운 사람 ( 'Mark', 18); // p1 : 'mark', 18; __ proto__ : [ 'Running', 'Football'], sayname, sayage접근법은 독립적 인 속성 방법을 생성자에 넣는 것이며, 공유 할 수있는 부품은 프로토 타입에 배치됩니다. 이렇게하면 객체 인스턴스의 독립성을 유지하면서 메모리 절약을 최대화 할 수 있습니다.