__proto__는 constructor.prototype과 어떻게 다릅니 까?


163
function Gadget(name, color)
{
   this.name = name;
   this.color = color;
}

Gadget.prototype.rating = 3

var newtoy = new Gadget("webcam", "black")

newtoy.constructor.prototype.constructor.prototype.constructor.prototype 

항상 등급이 3 인 객체를 반환합니다.

그러나 내가 다음을 수행하면 :

newtoy.__proto__.__proto__.__proto__

체인이 돌아갑니다 null.

또한 Internet Explorer에서 __proto__속성 이 없으면 null을 어떻게 확인 합니까?


30
그래프 다이어그램 은 프로토 타입과 프로토 의 차이점을 이해하는 데 도움이됩니다 . newtoy 객체 의 프로토 체인을 따라갈 수 있으며 , newtoy의 3 번째 프로토 가 null 인 이유를 알 수 있습니다 .
비트

또한 newtoy.prototype같지 않은 다이어그램에서 명확 newtoy.constructor.prototype하므로 newtoy.constructor.prototype이라는 속성이 없습니다 rating. 마찬가지로 newtoy.constructor.prototype.constructor.property이라는 속성이 없습니다 rating.
비트

마지막 주석의 오타 : 따라서 newtoy.constructor.prototyperating이라는 속성이 있습니다. 마찬가지로 newtoy.constructor.prototype.constructor.property등급이라는 속성도 있습니다.
비트


1
@ Royi Namir github에 jsViz 를 업로드 했습니다 . 여기 데모 사이트가 있습니다 . 실제 코드가 유지 관리되지 않은 (더러운) 상태는 중요하지 않습니다. 내가 만지지 않은 매우 오래된 프로젝트.
비트

답변:


210

최근에 머리를 감싸려고했지만 마침내이 "지도"를 생각해 내었습니다.

http://i.stack.imgur.com/KFzI3.png 여기에 이미지 설명을 입력하십시오

나는 내가 이것을 처음 만드는 사람이 아니라는 것을 알고 있지만 그것을 발견하는 것이 더 흥미로웠다 :-). 어쨌든, 그 후에 나는 예를 들어 기본적으로 같은 다른 다이어그램을 발견했습니다.

자바 스크립트 객체 레이아웃

나에게 가장 놀라운 것은 대신 을 Object.__proto__가리키는 것을 발견하고 있었지만 그만한 이유가 있다고 확신합니다. :-)Function.prototypeObject.prototype

누군가 이미지를 테스트하고 싶다면 이미지에 언급 된 코드를 여기에 붙여 넣으십시오. 몇 가지 점프 후의 위치를 ​​쉽게 알 수 있도록 일부 속성이 객체에 추가됩니다.

Object.O1='';
Object.prototype.Op1='';

Function.F1 = '';
Function.prototype.Fp1 = '';

Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';

mycat = new Cat();
o = {};

// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);

2
@utsaina 매우 시원합니다. OP가 게시 한 코드의 다른 그래픽 표현 을 확인하십시오. 그리고 우리의 도표는 기술적 세부 사항의 관점에서 일치한다고 생각합니다.
비트

43
그 이유 왜 Object.__proto__점에 Function.prototype있기 때문이다 Object()자체 것은 빈 객체를 인스턴스화 기본 기능입니다. 따라서 Object()기능입니다. 다른 모든 주요 기본 유형의 __proto__속성은을 가리 킵니다 Function.prototype. Object, Function, String, Number, 및 Array기능 프로토 타입 상속 모든.
스위블

@drodsou 당신의 두 번째 링크는 굉장합니다. 지금 확인하십시오;) mollypages.org/misc/js.mp 좋은 설명 : D
abhisekp

@Swivel "따라서 Object ()는 함수입니다"-Object가 함수라고 말했습니까? without ()
giorgim

2
@GiorgiMoniava 맞습니다. Object그 자체는 기능이다. callable 실행 결과 Object(즉, running 반환 값 Object())는 함수가 아닙니다.
Swivel

67

constructorprototype함수 객체 의 속성으로 가리키는 객체의 사전 정의 된 [[DontEnum]] 속성이며 처음에는 함수 객체 자체를 가리 킵니다.

__proto__ 객체의 내부 [[Prototype]] 속성, 즉 실제 프로토 타입과 같습니다.

new연산자 를 사용하여 객체를 만들면 내부 [[Prototype]] 속성이 생성자 함수의 prototype속성이 가리키는 객체로 설정됩니다 .

이것은 즉, 객체를 생성하는데 사용 된 생성자 함수로 .constructor평가 될 것이며 .__proto__.constructor, 우리가 알게 된 것처럼 protoype이 함수 의 속성은 객체의 [[Prototype]]을 설정하는데 사용되었습니다.

다음과 .constructor.prototype.constructor동일합니다 .constructor(이러한 속성을 덮어 쓰지 않는 한). 자세한 설명 은 여기 를 참조 하십시오 .

__proto__사용 가능한 경우 객체의 실제 프로토 타입 체인을 걸을 수 있습니다. JavaScript는 깊은 상속 계층 구조를 위해 설계되지 않았기 때문에 일반 ECMAScript3에서는이를 수행 할 방법이 없습니다.


3
그 '여기'링크는 금본위 제입니다. 전체 설명을 원하면 거기로 가십시오.
칼신

.constructor.prototype체이닝에 좋은 캐치 . 내가 톱하지 않았다 동안 나는 또한 나를 위해 불분명 .constructor동일입니다 .__proto__.constructor. 이는 단순히 생성자 함수와 프로토 타입 간의 순환을 의미합니다.
Johnny_D

30

JavaScript의 Prototypal Inheritance는 __proto__각 객체가 해당 __proto__속성이 참조하는 객체의 내용을 상속한다는 의미 에서 속성을 기반으로 합니다.

prototype속성은 Function객체에만 적용되며 new연산자를 사용하여 Function생성자 로 호출 할 때만 특별합니다 . 이 경우 생성 된 객체 __proto__는 constructor로 설정됩니다 Function.prototype.

이는에 추가 Function.prototype하면를 __proto__참조하는 모든 객체에 자동으로 반영됩니다 Function.prototype.

생성자 Function.prototype를 다른 객체로 바꾸면 기존 객체의 속성이 업데이트 되지 않습니다__proto__ .

주의 __proto__속성에 직접 액세스 할 수 없습니다해야한다는 Object.getPrototypeOf (개체) 대신에 사용되어야한다.

첫 번째 질문에 답하기 위해 맞춤식 다이어그램 __proto__prototype참조를 만들었습니다. 불행히도 stackoverflow로 인해 "10 평판 미만"의 이미지를 추가 할 수 없습니다. 지금 말고.

[편집] 그림은 ECMAScript 사양이 내부 객체를 참조하는 방식이기 때문에 [[Prototype]]대신 사용 __proto__합니다. 나는 당신이 모든 것을 알아낼 수 있기를 바랍니다.

다음은 그림을 이해하는 데 도움이되는 힌트입니다.

red    = JavaScript Function constructor and its prototype
violet = JavaScript Object constructor and its prototype
green  = user-created objects
         (first created using Object constructor or object literal {},
          second using user-defined constructor function)
blue   = user-defined function and its prototype
         (when you create a function, two objects are created in memory:
          the function and its prototype)

주의 constructor속성이 만든 개체에 존재하지 않지만, 프로토 타입에서 상속됩니다.

여기에 이미지 설명을 입력하십시오


@xorcus이 설명해 주시겠습니까 것은 : new MyFunction()그것의 개체 인스턴스 생성 __proto__자사의 ctor에 프로토 타입을 참조해야합니다 MyFunction.prototype.왜 수행 MyFunction.prototype.__proto__에 referes를 Object.prototype? 그것은 어떤 자사의 ctor의 프로토 타입 (내 첫 번째 샘플 등) referene한다 MyFunction.prototype(통지 MyFunction.prototype의 instnace입니다 Myfunction)
Royi Namir

@Royi Namir : MyFunction.prototype은 객체이므로 MyFunction.prototype .__ proto__는 Object.prototype을 참조합니다. Object.prototype은 모든 객체에 의해 상속됩니다 (일반적으로 프로토 타입 상속 체인이 끝나는 지점). MyFunction.prototype이 MyFunction의 인스턴스라는 데 동의하지 않습니다. obj instanceof MyFunction <=> MyFunction.prototype.isPrototypeOf (obj) <=> MyFunction.prototype은 obj 프로토 타입 체인에 있습니다. 즉 MyFunction.prototype 객체의 경우에는 해당되지 않습니다
xorcus

14

ObjectEve Function는 (는) Adam이며 Adam ( Function)은 자신의 뼈 ( Function.prototype)를 사용하여 Eve ( Object) 를 만듭니다 . 그러면 누가 아담 ( Function) 을 만들었 습니까? -JavaScript 언어의 발명자 :-).

utsaina의 답변에 따르면 더 유용한 정보를 추가하고 싶습니다.

나에게 가장 놀라운 것은 대신 을 Object.__proto__ 가리키는 것을 발견하고 있었지만 그만한 이유가 있다고 확신합니다. :-)Function.prototypeObject.prototype

해서는 안됩니다. Object.__proto__를 가리켜서는 안됩니다 Object.prototype. 대신, 인스턴스 Object o, o.__proto__가리켜 야합니다 Object.prototype.

(용어 사용에 대한 용서 classinstance자바 스크립트,하지만 당신은 그것을 알고 :-)

나는 클래스 생각 Object자체의 인스턴스 인 Function이유, Object.__proto__ === Function.prototype. 그러므로 : Object이브이고 Function아담이며, Adam ( Function)은 자신의 뼈 ( Function.prototype)를 사용하여 Eve ( Object) 를 만듭니다 .

또한, 심지어는 클래스 Function자체의 인스턴스 Function입니다 자체가, Function.__proto__ === Function.prototype그 또한 이유,Function === Function.constructor

또한 또한, 일반 클래스 Cat의 인스턴스입니다 Function즉, Cat.__proto__ === Function.prototype.

위의 이유는 JavaScript로 클래스를 만들 때 실제로 함수를 만드는 것입니다.이 함수는의 인스턴스 여야합니다 Function. Object그리고 Function단지 특별하다, 그러나 동시에 그들은 여전히 클래스입니다 Cat일반 클래스입니다.

Chrome Chrome 엔진에서 다음과 같은 요소는 다음과 같습니다.

  • Function.prototype
  • Function.__proto__
  • Object.__proto__
  • Cat.__proto__

그것들은 모두 ===다른 3과 (절대적으로 동일)이며, 그들의 가치는function Empty() {}

> Function.prototype
  function Empty() {}
> Function.__proto__
  function Empty() {}
> Object.__proto__
  function Empty() {}
> Cat.__proto__
  function Empty() {}
> Function.prototype === Function.__proto__
  true
> Function.__proto__ === Object.__proto__
  true
> Object.__proto__ === Cat.__proto__
  true

확인. 그러면 누가 특별 function Empty() {}( Function.prototype) 을 생성 합니까? 생각 해봐 :-)


마지막 한 가지를 제외하고 동의 function Empty() {}하십시오 : Function.prototype과 같은 것을 말하는 것, 크롬 콘솔에서 사용한 코드는 무엇입니까?
drodsou

2
마지막으로 지적한 사항을 수정했습니다. 그들의 가치는 function Empty() {}Chrome에 있습니다. 또한 콘솔 출력을 추가했습니다.
피터 리

모든 함수는 함수의 인스턴스이므로 모든 함수 _ _proto_ _는 Function.prototype에서 ( )를 상속 합니다. 그것은 간단합니다 :)
xorcus

오래된 스레드에 댓글을 달아 죄송합니다. 그러나 그들은 Inventor of Language에 의해 만들어 졌습니까?
Patel Parth

6

나는 왜 사람들이 당신의 이해에서 실제 문제의 위치에 대해 당신을 수정하지 않았는지 모르겠습니다.

이렇게하면 문제를 쉽게 발견 할 수 있습니다

무슨 일이 일어나고 있는지 보자.

var newtoy = new Gadget("webcam", "black")

newtoy 
  .constructor //newtoy's constructor function is newtoy ( the function itself)
    .prototype // the function has a prototype property.( all functions has)
      .constructor // constructor here is a **property** (why ? becuase you just did `prototype.constructor`... see the dot ? )  ! it is not(!) the constructor function  !!! this is where your mess begins. it points back to the constructor function itself ( newtoy function)
         .prototype // so again we are at line 3 of this code snippet
            .constructor //same as line 4 ...
                .prototype 
                 rating = 3

좋아, 이제 이것을 보자 __proto__

그 전에 다음과 관련된 두 가지 사항을 기억하십시오 __proto__ .

  1. new연산자 를 사용하여 객체를 만들면 원하는 경우 내부 [[Prototype]]/ proto__속성이 "생성자" 의 prototype속성 (1) 으로 설정됩니다 constructor function.

  2. JS 내에서 하드 코딩 된 — : Object.prototype.__proto__입니다 null.

이 두 점을 " bill"라고합니다.

newtoy
     .__proto__ // When `newtoy` was created , Js put __proto__'s value equal to the value of the cunstructor's prototype value. which is `Gadget.prototype`.
       .__proto__ // Ok so now our starting point is `Gadget.prototype`. so  regarding "bill" who is the constructor function now? watch out !! it's a simple object ! a regular object ! prototype is a regular object!! so who is the constructor function of that object ? Right , it's the `function Object(){...}`.  Ok .( continuing "bill" ) does it has a `prototype` property ? sure. all function has. it's `Object.prototype`. just remember that when Gadget.prototype was created , it's internal `__proto__` was refered to `Object.prototype` becuase as "bill" says :"..will be set to the `prototype` property of   its `constructor function`"
          .__proto__ // Ok so now our satrting point is `Object.prototype`. STOP. read bullet 2.Object.prototype.__proto__ is null by definition. when Object.prototype ( as an object) was created , they SET THE __PROTO__ AS NULL HARDCODED

보다 나은?


2

모든 기능은 프로토 타입을 만듭니다. 그리고 함수 생성자를 사용하여 객체를 만들면 객체의 __proto__ 속성이 해당 함수의 프로토 타입을 가리 키기 시작합니다.


1
나는 당신이 그 __proto__속성 을 말하려고했다고 생각합니다 .
demisx

예. 나는 물건의 프로토 속성을 의미했다 . 정보가 도움이 되었기를 바랍니다.
Apoorv Nag

2

모든 수치가 압도적이라면 속성의 의미를 살펴 보겠습니다.

STH.prototype

새로운 함수를 생성 할 때, 빈 객체가 병렬로 생성되고 [[Prototype]]체인으로 함수에 연결됩니다. 이 객체에 접근하기 prototype위해 함수의 속성을 사용 합니다.

function Gadget() {}
// in background, new object has been created
// we can access it with Gadget.prototype
// it looks somewhat like {constructor: Gadget}

마음에 베어 있다고 prototype속성은 기능에만 사용할 수 있습니다.

STH. 생성자

위에서 언급 한 프로토 타입 객체에는 1을 제외한 속성이 없습니다 constructor. 이 속성은 프로토 타입 객체를 만든 함수를 나타냅니다.

var toy = new Gadget();

만들 때 Gadget기능을, 우리는 같은 객체 생성 {constructor: Gadget}과 같은 아무것도 아니다 - 물론을 Gadget.prototype. 마찬가지로 constructor오브젝트의 프로토 타입을 생성하는 기능을 의미 toy.constructor나타내는 Gadget기능. 우리는 쓰고 다시 toy.constructor.prototype받고 {constructor: Gadget}있습니다.

따라서 악순환 toy.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype이 있습니다 Gadget.prototype. 사용할 수 있으며 항상 그렇습니다 .

toy
.constructor    // Gadget
.prototype    // {constructor: Gadget}
.constructor    // Gadget
.prototype    // {constructor: Gadget}
// ...

STH .__ proto__

prototype함수에 고유 한 속성 인 반면 에있는 __proto__모든 개체에 사용할 수 있습니다 Object.prototype. 객체를 생성 할 수있는 함수의 프로토 타입을 나타냅니다.

[].__proto__ === Array.prototype
// true

({}).__proto === Object.prototype
// true

여기는 toy.__proto__입니다 Gadget.prototype. Gadget.prototype객체 ( {})와 마찬가지로 객체는 Object함수 로 생성됩니다 (위 예 참조) Object.prototype. 이것은 JavaScript에서 더 높은 객체이며 __proto__표시 할 수 있습니다 null.

toy
.__proto__    // Gadget.prototype (object looking like {constructor: Gadget})
.__proto__    // Object.prototype (topmost object in JS)
.__proto__    // null - Object.prototype is the end of any chain

0

짧은 대답 : 객체를 생성 한 생성자 __proto__prototype속성에 대한 참조 입니다.

JavaScript의 객체

JavaScript 객체는 0 개 이상의 속성 모음 을 위한 내장 유형입니다 . 속성은 다른 객체, 기본 값 또는 함수를 보유하는 컨테이너입니다.

JavaScript의 생성자

함수는 [[Call]]호출 할 수있는 추가 기능이있는 일반 객체 ( ECMA-262 용어로 구현 )이지만 JavaScript에서 또 다른 역할 을합니다 . 연산자 를 통해 호출하면 생성자 ( 객체의 팩토리 )가됩니다 new. 따라서 생성자는 다른 언어의 클래스와 거의 유사합니다.

모든 JavaScript 함수는 실제로 프로토 타입 기반 상속 및 공유 특성을 구현하는 데 사용되는 Function특수 특성이있는 내장 함수 오브젝트 의 인스턴스입니다 prototype. 생성자 함수로 생성 된 모든 객체에는 생성자 값에 대한 암시 적 참조 (prototype 또는 __proto__)가 prototype있습니다.

생성자 prototype는 생성자 가 만든 모든 객체가에 대한 참조를 상속하므로 생성자 를위한 일종의 청사진 입니다 prototype.

프로토 타입 체인

개체는 내부 속성 [[Prototype]]또는을 통해 프로토 타입을 지정합니다 __proto__. 두 객체 간의 프로토 타입 관계는 상속에 관한 것입니다. 모든 객체는 다른 객체를 프로토 타입으로 가질 수 있습니다. 프로토 타입이 null가치 일 수 있습니다 .

__proto__속성에 의해 연결된 개체 체인을 프로토 타입 체인 이라고합니다 . 객체의 속성에 대한 참조가 이루어지면 해당 이름의 속성이 포함 된 프로토 타입 체인의 첫 번째 객체에서 발견 된 속성이 참조됩니다. 프로토 타입 체인은 마치 단일 객체 인 것처럼 동작합니다.

이 이미지를 참조하십시오 (이 블로그 에서 발췌 ).

proto.jpg

객체의 속성에 액세스하려고 할 때마다 JavaScript는 해당 객체에서 속성 검색을 시작하고 속성이 발견 될 때까지 또는 __proto__값을 보유 할 때까지 프로토 타입, 프로토 타입의 프로토 타입 등을 계속합니다 null.

프로토 타입 체인을 사용하는 이러한 유형의 상속은 종종 클래스 체인을 사용하는 다른 언어와의 혼동을 피하기 위해 위임 이라고 합니다.

프로토 타입 체인의 마지막 Object이므로 거의 모든 객체가의 인스턴스입니다 Object.prototype. 그러나 가치를 보유하고 있기 때문에 Object.prototype실례가 아닙니다 .ObjectObject.prototype.__proto__null

다음과 같은 null프로토 타입으로 객체를 만들 수도 있습니다 .

var dict = Object.create(null);

이러한 객체는 리터럴 객체보다 더 나은 맵 (사전) 이므로이 패턴을 dict 패턴 ( 사전 dict) 이라고도합니다 .

참고 : 사용하여 작성된 문자 객체 {}의 인스턴스 Object이후 ({}).__proto__에 대한 참조입니다 Object.prototype.


사용중인 견적 및 유물의 출처를 인용하십시오. 그림은 giamir.com/pseudoclasses-and-prototypal-inheritance-in-JS 에서 가져온 것 같습니다. 저작권이 있습니까?
Bergi

@ Bergi 나는 이미지의 출처를 인용했다. 내가 중 하나 JS 표준 또는 MDN에서 추출되어 사용되는 따옴표의 대부분
eigenslacker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.