나는 자바 스크립트의 커튼 장면을 이해하려고 노력하고 있으며 내장 객체, 특히 객체 및 기능과 객체 간의 관계를 이해하는 데 집중하고 있습니다.
복잡하고, 오해하기 쉬우 며, 많은 초보 자바 스크립트 책이 잘못 이해하므로 읽은 모든 것을 신뢰하지 마십시오.
저는 1990 년대와 표준화위원회에서 Microsoft JS 엔진을 구현 한 사람 중 한 사람이었으며이 답변을 구성하는 데 많은 실수를했습니다. (15 년 이상이 일을 해본 적이 없어서 용서받을 수 있습니다.) 까다로운 일입니다. 그러나 프로토 타입 상속을 이해하면 모든 것이 의미가 있습니다.
Array, String 등과 같은 모든 내장 객체가 Object에서 확장 (상 속됨)이라는 것을 읽을 때 Object는 객체가 생성되고 나머지 객체가 상속되는 첫 번째 내장 객체라고 가정했습니다.
클래스 기반 상속에 대해 알고있는 모든 것을 버리십시오. JS는 프로토 타입 기반 상속을 사용합니다.
다음으로, "상속"이 의미하는 바를 머리 속에 아주 명확하게 정의하십시오. C #, Java 또는 C ++와 같은 OO 언어에 익숙한 사람들은 상속이 하위 유형을 의미한다고 생각하지만 상속이 하위 유형을 의미하는 것은 아닙니다. 상속은 한 가지 일원이 다른 일의 일원임을 의미합니다 . 반드시 그런 것들 사이에 하위 유형 관계가 있다는 것을 의미 하지는 않습니다 ! 유형 이론에 대한 많은 오해는 사람들이 차이가 있다는 것을 깨닫지 못한 결과입니다.
그러나 객체는 함수로만 만들 수 있지만 함수는 함수의 객체 일 뿐이라는 것을 알면 의미가 없습니다.
이것은 단순히 거짓입니다. 일부 함수는 일부 함수 를 호출 하여 작성 되지 않습니다 . 일부 객체는 JS 런타임에 의해 전혀 생성되지 않습니다. 닭이 낳지 않은 알이있다 . 시작시 런타임에 의해 생성되었습니다.new F
F
규칙이 무엇인지, 어쩌면 도움이 될지 말해 봅시다.
- 모든 객체 인스턴스에는 프로토 타입 객체가 있습니다.
- 경우에 따라 해당 프로토 타입이 될 수 있습니다
null
.
- 객체 인스턴스의 멤버에 액세스하고 객체에 해당 멤버가없는 경우 객체는 프로토 타입을 연기하거나 프로토 타입이 null 인 경우 중지됩니다.
prototype
객체 의 멤버는 일반적으로 객체 의 프로토 타입이 아닙니다 .
- 오히려
prototype
함수 객체 F 의 멤버는로 만든 객체의 프로토 타입이 될 객체입니다 new F()
.
- 일부 구현에서 인스턴스
__proto__
는 실제로 프로토 타입을 제공 하는 멤버를 얻습니다 . (이제 더 이상 사용되지 않습니다. 의존하지 마십시오.)
- 함수 객체는 새로운 기본 객체를
prototype
만들 때 할당됩니다 .
- 함수 객체의 프로토 타입은 물론
Function.prototype
입니다.
요약하자.
- 의 프로토 타입
Object
은Function.prototype
Object.prototype
객체 프로토 타입 객체입니다.
- 의 프로토 타입
Object.prototype
은null
- 의 프로토 타입
Function
IS Function.prototype
- 이것은 드문 경우 중 하나입니다 Function.prototype
사실의 프로토 타입입니다 Function
!
Function.prototype
함수 프로토 타입 객체입니다.
- 의 프로토 타입
Function.prototype
은Object.prototype
함수 Foo를 만든다고 가정 해 봅시다.
- 의 프로토 타입은
Foo
입니다 Function.prototype
.
Foo.prototype
Foo 프로토 타입 객체입니다.
- 의 프로토 타입은
Foo.prototype
입니다 Object.prototype
.
우리가 말한다고 가정 해 봅시다 new Foo()
- 새로운 객체의 프로토 타입은
Foo.prototype
이해가 되십시오. 그려 봅시다. 타원은 객체 인스턴스입니다. 가장자리는 __proto__
"의 프로토 타입"또는 prototype
"의 prototype
속성 "을 의미합니다 .
런타임은 모든 객체를 생성하고 그에 따라 다양한 속성을 할당하기 만하면됩니다. 어떻게되는지 알 수있을 것입니다.
이제 지식을 테스트하는 예제를 보자.
function Car(){ }
var honda = new Car();
print(honda instanceof Car);
print(honda.constructor == Car);
이것은 무엇을 인쇄합니까?
무엇을 instanceof
의미합니까? honda instanceof Car
" 의 프로토 타입 체인 Car.prototype
에있는 객체와 동일 honda
합니까?"
그렇습니다. honda
의 프로토 타입 Car.prototype
이 완성되었습니다. 이것은 사실을 인쇄합니다.
두 번째는 어떻습니까?
honda.constructor
존재하지 않으므로 프로토 타입을 참조하십시오 Car.prototype
. Car.prototype
객체가 생성 되면 에 자동으로 constructor
동일한 속성이 부여 Car
되었으므로 이는 사실입니다.
이제 이건 어때?
var Animal = new Object();
function Reptile(){ }
Reptile.prototype = Animal;
var lizard = new Reptile();
print(lizard instanceof Reptile);
print(lizard.constructor == Reptile);
이 프로그램은 무엇을 인쇄합니까?
다시 말하지만, lizard instanceof Reptile
" 의 프로토 타입 체인 Reptile.prototype
에있는 객체와 동일 lizard
합니까?"
그렇습니다. lizard
의 프로토 타입 Reptile.prototype
이 완성되었습니다. 이것은 사실을 인쇄합니다.
이제는 어떻습니까
print(lizard.constructor == Reptile);
lizard
으로 구성 new Reptile
되었지만 잘못 되었을 수도 있으므로 이것이 사실이라고 생각할 수도 있습니다 . 그것을 추론하십시오.
- 않습니다
lizard
이 constructor
속성을? 따라서 프로토 타입을 살펴 봅니다.
- 의 프로토 타입은
lizard
이다 Reptile.prototype
인 Animal
.
- 않습니다
Animal
이 constructor
속성을? 아닙니다. 그래서 우리는 프로토 타입을 봅니다.
- 의 프로토 타입
Animal
이며 Object.prototype
, 그리고 Object.prototype.constructor
런타임에 의해 만들어 같다 Object
.
- 따라서 이것은 거짓을 인쇄합니다.
우리는 Reptile.prototype.constructor = Reptile;
어느 시점에서 말해야 했지만 기억하지 못했습니다!
모든 것이 당신에게 의미가 있는지 확인하십시오. 여전히 혼란 스러우면 일부 상자와 화살표를 그립니다.
다른 매우 혼란스러운 것은 console.log(Function.prototype)
기능을 인쇄 console.log(Object.prototype)
하지만 인쇄하면 객체를 인쇄한다는 것입니다. Function.prototype
함수가 목적인 이유는 무엇 입니까?
함수 프로토 타입은 호출 될 때를 반환하는 함수로 정의됩니다 undefined
. 우리는 이미 알고 Function.prototype
는 IS Function
이상하게도, 프로토 타입. 그러므로 Function.prototype()
합법적이며, 그렇게하면 undefined
다시 돌아옵니다. 기능입니다.
Object
프로토 타입이 속성이 없습니다; 호출 할 수 없습니다. 그것은 단지 객체입니다.
당신 console.log(Function.prototype.constructor)
은 다시 함수입니다.
Function.prototype.constructor
그냥 Function
분명히. 그리고 Function
기능입니다.
이제 어떻게 무언가를 사용하여 스스로 만들 수 있습니까 (마음 = 날려).
당신은 이것을 너무 많이 생각하고 있습니다. 필요한 것은 런타임이 시작될 때 많은 객체를 생성한다는 것입니다. 객체는 문자열을 객체와 연결하는 조회 테이블입니다. 런타임이 시작되면이 할 수있는 모든이 할당 시작 후 수십 빈 객체를 생성하고, 인 prototype
, __proto__
, constructor
, 그래서 그들이해야하는 그래프를 만들 때까지 각 개체의 속성에.
위에서 설명한 다이어그램을 가져 와서 constructor
가장자리를 추가하면 도움이됩니다 . 이 그래프는 매우 간단한 객체 그래프이며 런타임에 생성시 아무런 문제가 없음을 곧 알 수 있습니다.
좋은 운동은 스스로하는 것입니다. 여기부터 시작하겠습니다. 우리는 사용합니다 my__proto__
의미 "의 프로토 타입 객체"하고 myprototype
"의 프로토 타입 속성"을 의미 할 수 있습니다.
var myobjectprototype = new Object();
var myfunctionprototype = new Object();
myfunctionprototype.my__proto__ = myobjectprototype;
var myobject = new Object();
myobject.myprototype = myobjectprototype;
등등. "실제"Javascript 내장 오브젝트와 동일한 토폴로지를 갖는 오브젝트 세트를 구성하기 위해 나머지 프로그램을 채울 수 있습니까? 그렇게하면 매우 쉽다는 것을 알게 될 것입니다.
JavaScript의 객체는 문자열을 다른 객체와 연결하는 조회 테이블 일뿐 입니다. 그게 다야! 여기 마법이 없습니다. 모든 객체가 생성자에 의해 생성되어야하는 것처럼 실제로 존재하지 않는 구속 조건을 상상하기 때문에 매듭에 묶여 있습니다.
함수는 추가 기능이있는 객체 일뿐입니다. 따라서 작은 시뮬레이션 프로그램을 살펴보고 .mycallable
호출 가능한지 여부를 나타내는 속성을 모든 객체에 추가하십시오 . 그렇게 간단합니다.
Function.prototype
될 수 있고 내부 필드를 가질 수 있습니다. 따라서 프로토 타입 함수가 구조를 통과 할 때 실행하지 않습니다. 마지막으로 객체와 기능이 아마 엔진 내에서가 아니라 자바 스크립트에서 특별한 참조처럼 생성되도록, 자바 스크립트를 해석 엔진이 있음을 기억Function.prototype
하고Object.prototype
바로 엔진에 의해 특별한 방법으로 해석 될 수 있습니다.