JS 프로토타입 체인 및 프로토타입 체인에 사용할 수 없는 이유에 대한 심층 분석
JS 프로토타입 체인을 처음 접할 때 익숙한 명사인 prototype; 을 접하게 됩니다. Prototype 에 깊이 들어가 본 적이 있다면, 또 다른 명사인 _ __proto__ (참고: 양쪽에 각각 두 개의 밑줄, 하나가 아님) 을 접하게 됩니다. 다음은 prototype 과 __proto__ 라는 두 용어를 중심으로 프로토타입 체인에 객체를 사용할 수 없는 이유와 JS 프로토타입 체인의 깊은 원리를 설명합니다.
첫째, 프로토타입 체인에서 객체를 사용할 수 없는 이유:
아주 간단한 예를 들어, 저는 Humans 라는 클래스를 가지고 있습니다. 그리고 저는 Tom (한 사람) 과 Merry (다른 사람) 라는 개체를 가지고 있습니다. Tom 과 Merry 는 모두 Humans 라는 클래스에 의해 인스턴스화된 후 얻은 것이 분명합니다.
Functionhumans () {this.foot = 2;
} humans.prototype.ability = true;
Vartom = newhumans (); Var merry = new humans (); Alert (tom.foot); //결과: 2alert (tom.ability); //결과: truealert (merry.foot); //결과: 2alert(Merry.ability);); //결과: 참
이것은 매우 간단한 객체 지향 예이며, Tom 의 속성 ability 를 수정하려고 하면
를 이해할 수 있을 것으로 믿는다.Functionhumans () {this.foot = 2; }
Humans.prototype.ability = true;;
Vartom = newhumans (); Var merry = new humans (); Tom.ability = false;; Alert (tom.foot); //결과: 2alert (tom.ability); //결과: falsealert (merry.foot); //결과: 2alert(Merry.ability);); //결과: 참
위의 내용은 Tom 의 ability 속성 값이 변경되었지만 Merry 의 ability 속성 값에 영향을 주지 않는다는 것을 알 수 있습니다. 이것이 바로 우리가 원하는 결과이자 객체 지향 이점입니다. 동일한 클래스에서 인스턴스화된 개별 객체는 서로 간섭하지 않습니다. OK, 다음으로 ability 를 object 개체로 바꾸면 어떨까요? 코드는 다음과 같습니다.
Functionhumans () {this.foot = 2;
}Humans.prototype.ability = {
실행:' 100m /10 초',
Jump:' 3 미터'
} Vartom = newhumans (); Var merry = new humans (); Tom.ability = {
실행:' 50m /10 초',
Jump:' 2 미터'
}
Alert (tom.ability.run); //결과:' 50m /10 초'
경고 (tom.ability.jump); //결과:' 2 미터'
경고 (merry.ability.run); //결과:' 100m /10 초'
경고 (merry.ability.jump); //결과:' 3m'
위의 코드는 프로토타입 체인에서 객체를 사용하지만
위의 코드에서 볼 수 있듯이 Tom 의 ability 속성의 변경 사항은 Merry 의 ability 속성에 전혀 영향을 미치지 않습니다. 따라서 프로토타입 체인에서 객체를 사용할 수 없는 이유는 무엇입니까? 다음 코드는 매우 다르게 보일 것이며 프로토타입 체인에서 오브젝트를 사용할 위험을 완전히 표현할 수 있습니다.
Functionhumans () {this.foot = 2;
}
Humans.prototype.ability = {
실행:' 100m /10 초',
Jump:' 3 미터'}; Vartom = newhumans (); Varmerry = newhumans (); Tom.ability.run = '50 미터 /10 초';
Tom.ability.jump = '2 미터'; Alert (tom.ability.run); //결과:' 50m /10 초'
경고 (tom.ability.jump); //결과:' 2 미터'
경고 (merry.ability.run); //결과:' 50m /10 초'
경고 (merry.ability.jump); //결과:' 2 미터'
예, 위 코드의 출력에서 Tom 의 ability 속성 변경이 Merry 의 ability 속성에 영향을 미친다는 것을 알 수 있으므로 프로토타입 체인에서 객체를 사용하는 것은 매우 위험하며 인스턴스화된 객체 간의 상호 독립성을 쉽게 깨뜨릴 수 있다는 것을 알 수 있습니다. 이것이 프로토타입 체인에서 객체를 사용할 수 없는 이유입니다. 네, 하지만 제가 말하고자 하는 것은 그것뿐만이 아니라, 그 원리입니다. 뒤에 있는 JS 프로토타입 체인의 심층적인 원리를 보고 나면, 당신이 완전히 이해할 수 있을 것이라고 믿습니다. (데이비드 아셀, Northern Exposure (미국 TV 드라마), 예술명언)
다음 두 번째 부분에서는 JS 프로토타입 체인의 깊은 원리를 설명하기 전에 프로토타입 체인의 속성이나 메서드가 인스턴스화된 객체 * * * 에 의해 사용되었기 때문에 위의 tom.ability.run =' 50m /10 초' 가 프로토타입 연결을 변경한다는 개념을 명확히 합니다 대답은 Tom.ability = {......} 가 프로토타입 체인의 ability 속성을 변경하지 않고 Tom 에 자체 속성 ability 를 추가했다는 것입니다. 나중에 Tom.ability 에 액세스할 때 프로토타입 체인의 ability 에 더 이상 액세스할 필요가 없습니다. 대신 자체 속성 ability 에 액세스합니다 OK, 만약 당신이 여전히 의문이 있다면, 종이펜으로 당신의 의문을 적어서 계속 내려다보면 더 잘 이해할 수 있을 것입니다.
둘째, JS 프로토 타입 체인의 깊은 원리:
먼저 명사 __proto__, __proto__ 이 무엇입니까? 내 이해에서 __proto__ 는 진정한 프로토타입 체인이고, prototype 은 껍데기일 뿐이다.
Chrome 브라우저를 사용한다면 Alert (Tom. _ _ proto _ _. ability.run) 를 사용해 볼 수 있습니다 물론, IE 브라우저로 달려가서 시도하면 반드시 오류를 보고할 수 있습니다. 사실 IE 브라우저는 __proto__ 에 대한 액세스를 금지하고 chrome 은 허용됩니다. 물론 실제 개발에서는 __proto__ 라는 속성을 직접 사용하는 것을 권장하지 않습니다. 어떤 사람들은 Tom.__proto__ 와 Humans.prototype 이 어떤 관계인지 물어볼 수 있습니다. 둘 사이의 관계를 정리하기 위해
1, 객체는 __proto__ 속성이 있지만 prototype; 은 없습니다. 예: Tom.__proto__ 는 있지만 Tom.prototype 은 없습니다.
2, 클래스에는 __proto__ 속성이 없지만 prototype; 이 있습니다. 예: Humans.__proto__ 는 없지만 Humans.prototype 이 있습니다 따라서 humans. _ _ proto _ _ = = = Function.prototype 은 절대적으로 사실이며, 특히 이 경우 function.prototype 은 Empty (null) 함수를 가리킵니다
3, 동일한 클래스 인스턴스화 (new) 에서 얻은 객체의 __proto__ 는 해당 클래스의 prototype (즉, 참조 전달) 을 참조합니다. 예를 들어 Tom 과 Merry 의 __proto__ 는 모두 Humans 의 prototype 에서 참조됩니다.
OK, 위에서 말한 Tom.ability={......}} 는 프로토타입 체인의 ability 속성을 변경하지 않았거나 Tom.__proto__.ability 를 변경하지 않고 Tom 에 자체 ability 를 추가했습니다
Functionhumans () {this.foot = 2;
}
Humans.prototype.ability = {
실행:' 100m /10 초',
Jump:' 3 미터'}; Vartom = newhumans (); Varmerry = newhumans (); Tom.ability = {
실행:' 50m /10 초',
Jump:' 2 미터'}; Alert (tom.ability.run); //결과:' 50 미터 /10 초' alert (tom.ability.jump); //결과:' 2 미터' 경보 (merry.ability.run); //결과:' 100m /10 초' 경보 (merry.ability.jump); //결과:' 3m'
Tom.ability 에 새 값을 부여하면 Tom.ability 에 다시 액세스할 때 더 이상 Tom.__proto__.ability 를 가리키지 않습니다