etc./StackOverFlow

JavaScript .prototype은 어떻게 작동합니까?

청렴결백한 만능 재주꾼 2021. 12. 1. 00:00
반응형

질문자 :John Leidegren


저는 동적 프로그래밍 언어에 익숙하지 않지만 JavaScript 코드를 상당 부분 작성했습니다. 저는 이 프로토타입 기반 프로그래밍에 대해 전혀 머리를 쓰지 못했습니다. 이것이 어떻게 작동하는지 아는 사람이 있습니까?

 var obj = new Object(); obj.prototype.test = function() { alert('Hello?'); }; var obj2 = new obj(); obj2.test();

나는 얼마 전에 사람들과 많은 토론을 했던 것을 기억합니다(제가 무엇을 하는지 정확히 모르겠습니다). 그러나 제가 이해하기로는 수업에 대한 개념이 없습니다. 그것은 단지 개체이고 그 개체의 인스턴스는 원본의 클론입니다. 그렇죠?

그러나 JavaScript에서 이 ".prototype" 속성의 정확한 목적은 무엇입니까? 객체를 인스턴스화하는 것과 어떤 관련이 있습니까?

업데이트: 올바른 방법

 var obj = new Object(); // not a functional object obj.prototype.test = function() { alert('Hello?'); }; // this is wrong! function MyObject() {} // a first class functional object MyObject.prototype.test = function() { alert('OK'); } // OK

또한 이 슬라이드는 정말 많은 도움이 되었습니다.



Java, C# 또는 C++와 같은 고전적 상속을 구현하는 언어에서는 객체에 대한 청사진인 클래스를 생성하여 시작한 다음 해당 클래스에서 새 객체를 생성하거나 클래스를 확장하여 확장하는 새 클래스를 정의할 수 있습니다. 원래 수업.

JavaScript에서는 먼저 객체(클래스 개념 없음)를 만든 다음 자신의 객체를 보강하거나 이 객체에서 새 객체를 만들 수 있습니다. 어렵지는 않지만 고전적인 방식에 익숙한 사람에게는 약간 생소하고 대사하기 어렵습니다.

예시:

 //Define a functional object to hold persons in JavaScript var Person = function(name) { this.name = name; }; //Add dynamically to the already defined object a new getter Person.prototype.getName = function() { return this.name; }; //Create a new object of type Person var john = new Person("John"); //Try the getter alert(john.getName()); //If now I modify person, also John gets the updates Person.prototype.sayMyName = function() { alert('Hello, my name is ' + this.getName()); }; //Call the new method on john john.sayMyName();

지금까지 기본 개체를 확장해 왔으며 이제 다른 개체를 만든 다음 Person에서 상속합니다.

 //Create a new object of type Customer by defining its constructor. It's not //related to Person for now. var Customer = function(name) { this.name = name; }; //Now I link the objects and to do so, we link the prototype of Customer to //a new instance of Person. The prototype is the base that will be used to //construct all new instances and also, will modify dynamically all already //constructed objects because in JavaScript objects retain a pointer to the //prototype Customer.prototype = new Person(); //Now I can call the methods of Person on the Customer, let's try, first //I need to create a Customer. var myCustomer = new Customer('Dream Inc.'); myCustomer.sayMyName(); //If I add new methods to Person, they will be added to Customer, but if I //add new methods to Customer they won't be added to Person. Example: Customer.prototype.setAmountDue = function(amountDue) { this.amountDue = amountDue; }; Customer.prototype.getAmountDue = function() { return this.amountDue; }; //Let's try: myCustomer.setAmountDue(2000); alert(myCustomer.getAmountDue()); 

 var Person = function (name) { this.name = name; }; Person.prototype.getName = function () { return this.name; }; var john = new Person("John"); alert(john.getName()); Person.prototype.sayMyName = function () { alert('Hello, my name is ' + this.getName()); }; john.sayMyName(); var Customer = function (name) { this.name = name; }; Customer.prototype = new Person(); var myCustomer = new Customer('Dream Inc.'); myCustomer.sayMyName(); Customer.prototype.setAmountDue = function (amountDue) { this.amountDue = amountDue; }; Customer.prototype.getAmountDue = function () { return this.amountDue; }; myCustomer.setAmountDue(2000); alert(myCustomer.getAmountDue());

말했듯이 나는 사람에 대해 setAmountDue(), getAmountDue()를 호출할 수 없습니다.

 //The following statement generates an error. john.setAmountDue(1000);

stivlo

모든 JavaScript 개체에는 값이 null 또는 object [[Prototype]] 이라는 내부 "슬롯" 이 있습니다. 슬롯은 작성하는 코드에서 숨겨진 JavaScript 엔진 내부의 객체 속성으로 생각할 수 있습니다. [[Prototype]] 주위의 대괄호는 의도적이며 내부 슬롯을 나타내는 ECMAScript 사양 규칙입니다.

[[Prototype]] 이 가리키는 값은 구어체로 "해당 객체의 프로토타입"으로 알려져 있습니다.

obj.propName ) 또는 대괄호( obj['propName'] ) 표기법을 통해 속성에 액세스하고 객체에 직접 이러한 속성이 없는 경우(즉, 자체 속성 obj.hasOwnProperty('propName') 통해 확인할 수 있음) obj.hasOwnProperty('propName') ), 런타임은 대신 [[Prototype]] 에서 참조하는 개체에서 해당 이름을 가진 속성을 찾습니다. [[Prototype]] 에도 이러한 속성이 없으면 [[Prototype]] 이 차례로 확인되는 식입니다. 이런 식으로 원본 개체의 프로토타입 체인 은 일치하는 항목을 찾거나 끝 부분에 도달할 때까지 진행됩니다. 프로토타입 체인의 맨 위에는 null 값이 있습니다.

최신 JavaScript 구현은 다음과 같은 방식으로 [[Prototype]] 에 대한 읽기 및/또는 쓰기 액세스를 허용합니다.

  1. new 연산자(생성자 함수에서 반환된 기본 개체에 대한 프로토타입 체인 구성),
  2. extends 키워드(클래스 구문을 사용할 때 프로토타입 체인 구성),
  3. Object.create 는 제공된 인수를 [[Prototype]] 으로 설정합니다.
  4. Object.getPrototypeOfObject.setPrototypeOf (객체 생성 [[Prototype]] 가져오기/설정) 및
  5. __proto__ 라는 표준화된 접근자(예: getter/setter) 속성(4와 유사)

Object.getPrototypeOfObject.setPrototypeOf __proto__ 보다 선호됩니다. 부분적으로 null 프로토타입이 있을 때 o.__proto__ 의 동작이 비정상적 이기 때문입니다.

개체의 [[Prototype]] 은 개체 생성 중에 초기에 설정됩니다.

new Func() 를 통해 새 객체를 생성하는 경우 객체의 [[Prototype]] Func.prototype 참조하는 객체로 설정됩니다.

따라서 new 연산자와 함께 사용할 수 있는 모든 함수에는 자체 [[Prototype]] 내부 슬롯 .prototype 이라는 속성이 있습니다. "프로토타입"이라는 단어의 이중 사용은 언어를 처음 접하는 사람들 사이에서 끝없는 혼란의 근원입니다.

new 를 사용하면 JavaScript에서 고전 상속을 시뮬레이션할 수 있습니다. JavaScript의 상속 시스템은 우리가 보았듯이 클래스 기반이 아니라 프로토타입입니다.

JavaScript에 클래스 구문이 도입되기 전에는 생성자 함수가 클래스를 시뮬레이션하는 유일한 방법이었습니다. 생성자 함수의 .prototype 속성이 참조하는 객체의 속성을 공유 멤버로 .prototype 즉. 각 인스턴스에 대해 동일한 구성원입니다. 클래스 기반 시스템에서 메서드는 각 인스턴스에 대해 동일한 방식으로 구현되므로 메서드는 개념적으로 .prototype 속성에 추가됩니다. 그러나 개체의 필드는 인스턴스에 따라 다르므로 구성 중에 개체 자체에 추가됩니다.

클래스 구문이 없으면 개발자는 수동으로 프로토타입 체인을 구성하여 클래식 상속과 유사한 기능을 구현해야 했습니다. 이로 인해 이를 달성하기 위한 다양한 방법이 우세했습니다.

한 가지 방법은 다음과 같습니다.

 function Child() {} function Parent() {} Parent.prototype.inheritedMethod = function () { return 'this is inherited' } function inherit(child, parent) { child.prototype = Object.create(parent.prototype) child.prototype.constructor = child return child; } Child = inherit(Child, Parent) const o = new Child console.log(o.inheritedMethod()) // 'this is inherited'

...또 다른 방법이 있습니다.

 function Child() {} function Parent() {} Parent.prototype.inheritedMethod = function () { return 'this is inherited' } function inherit(child, parent) { function tmp() {} tmp.prototype = parent.prototype const proto = new tmp() proto.constructor = child child.prototype = proto return child } Child = inherit(Child, Parent) const o = new Child console.log(o.inheritedMethod()) // 'this is inherited'

ES2015에 도입된 클래스 구문은 JavaScript에서 고전적인 상속을 시뮬레이션하기 위해 프로토타입 체인을 구성하는 "단 하나의 진정한 방법"으로 extends

따라서 위의 코드와 유사하게 클래스 구문을 사용하여 다음과 같이 새 객체를 생성하는 경우:

 class Parent { inheritedMethod() { return 'this is inherited' } } class Child extends Parent {} const o = new Child console.log(o.inheritedMethod()) // 'this is inherited'

...결과 객체의 [[Prototype]] [[Prototype]]Parent.prototypeParent 의 인스턴스로 설정됩니다.

Object.create(foo) 를 통해 새 객체를 생성하면 결과 객체의 [[Prototype]] foo 로 설정됩니다.


Christoph

이것은 설명 중에 샘플로 간주되는 매우 간단한 프로토타입 기반 개체 모델이며 아직 설명이 없습니다.

 function Person(name){ this.name = name; } Person.prototype.getName = function(){ console.log(this.name); } var person = new Person("George");

프로토타입 개념을 살펴보기 전에 고려해야 할 몇 가지 중요한 사항이 있습니다.

1- JavaScript 기능이 실제로 작동하는 방식:

첫 번째 단계를 밟기 위해 우리는 JavaScript 함수가 실제로 어떻게 작동 this 키워드를 사용하는 클래스와 같은 클래스 또는 인수가 있는 일반 함수로서 수행하는 작업과 반환하는 내용을 파악해야 합니다.

Person 객체 모델을 만들고 싶다고 가정해 봅시다. 하지만 이 단계에서 나는 prototypenew 키워드를 사용하지 않고 똑같은 일을 하려고 할 것입니다.

따라서 이 단계에서는 functions , objectsthis 키워드만 있으면 됩니다.

첫 번째 질문은 this new 키워드를 사용하지 않고 어떻게 유용할 수 있느냐는 것입니다.

따라서 빈 객체가 있고 다음과 같은 두 가지 기능이 있다고 가정해 보겠습니다.

 var person = {}; function Person(name){ this.name = name; } function getName(){ console.log(this.name); }

이제 new 키워드를 사용하지 않고 이러한 기능을 어떻게 사용할 수 있는지 알아보겠습니다. 따라서 JavaScript에는 이를 수행하는 3가지 다른 방법이 있습니다.

NS. 첫 번째 방법은 함수를 일반 함수로 호출하는 것입니다.

 Person("George"); getName();//would print the "George" in the console

이 경우 현재 컨텍스트 객체가 됩니다. 일반적으로 window 객체 또는 Node.js GLOBAL 입니다. 이는 "George"를 값으로 하여 브라우저에 window.name을, Node.js에 GLOBAL.name을 가질 수 있음을 의미합니다.

NS. 우리는 그것들을 속성으로 객체에 붙일 수 있습니다

- 이를 수행 하는 가장 쉬운 방법 person 개체를 수정하는 것입니다.

 person.Person = Person; person.getName = getName;

이렇게 하면 다음과 같이 호출할 수 있습니다.

 person.Person("George"); person.getName();// -->"George"

이제 person 객체는 다음과 같습니다.

 Object {Person: function, getName: function, name: "George"}

- 객체에 속성을 추가하는 다른 방법 __proto__ 라는 이름의 JavaScript 객체에서 찾을 수 있는 해당 객체 prototype 을 사용하는 것이며 요약 부분에서 약간 설명하려고 했습니다. 따라서 다음을 수행하여 비슷한 결과를 얻을 수 있습니다.

 person.__proto__.Person = Person; person.__proto__.getName = getName;

그러나 이런 식으로 우리가 실제로 하고 있는 것은 Object.prototype { ... } )을 사용하여 JavaScript 객체를 생성할 때마다 Object.prototype 기반으로 생성되기 때문에 새로 생성된 객체에 첨부된다는 의미입니다. __proto__ 라는 속성으로 변경하면 이전 코드 스니펫에서 수행한 것처럼 모든 JavaScript 개체가 변경되지만 좋은 방법은 아닙니다. 이제 더 나은 방법은 무엇입니까?

 person.__proto__ = { Person: Person, getName: getName };

이제 다른 개체는 평화롭지만 여전히 좋은 습관은 아닌 것 같습니다. 그래서 아직 하나의 솔루션이 더 있지만 이 솔루션을 사용하려면 person 객체가 생성된 var person = {}; )로 돌아가서 다음과 같이 변경해야 합니다.

 var propertiesObject = { Person: Person, getName: getName }; var person = Object.create(propertiesObject);

그것이 하는 일은 새로운 JavaScript Object propertiesObject__proto__ 속성에 첨부하는 것입니다. 따라서 다음을 수행할 수 있습니다.

 console.log(person.__proto__===propertiesObject); //true

person 객체의 첫 번째 수준 __proto__ 에 정의된 모든 속성에 액세스할 수 있다는 것입니다(자세한 내용은 요약 부분 참조).


이 두 가지 방법 중 하나를 사용하는 것을 볼 수 있듯이 this person 객체를 가리킬 것입니다.

씨. JavaScript에는 함수를 호출하기 위해 호출 또는 적용 을 사용하는 this 와 함께 함수를 제공하는 또 다른 방법이 있습니다.

apply() 메서드는 주어진 this 값과 배열(또는 배열과 유사한 객체)로 제공된 인수로 함수를 호출합니다.

그리고

call() 메소드는 주어진 이 값과 개별적으로 제공된 인수로 함수를 호출합니다.

내가 가장 좋아하는 이 방법으로 다음과 같은 함수를 쉽게 호출할 수 있습니다.

 Person.call(person, "George");

또는

 //apply is more useful when params count is not fixed Person.apply(person, ["George"]); getName.call(person); getName.apply(person);

이 3가지 방법은 .prototype 기능을 파악하기 위한 중요한 초기 단계입니다.


new 키워드는 어떻게 작동합니까?

.prototype 기능을 이해하는 두 번째 단계입니다. 이것이 제가 프로세스를 시뮬레이션하는 데 사용하는 것입니다.

 function Person(name){ this.name = name; } my_person_prototype = { getName: function(){ console.log(this.name); } };

이 부분에서 나는 사용하지 않고, 자바 스크립트가 수행하는 모든 조치를 취하려고 할거야 new 키워드 및 prototype 사용할 때, new 키워드를. new Person("George") 을 수행할 때 Person 함수는 생성자 역할을 합니다. JavaScript가 하나씩 수행하는 작업은 다음과 같습니다.

NS. 우선 다음과 같은 빈 객체, 기본적으로 빈 해시를 만듭니다.

 var newObject = {};

NS. JavaScript가 취하는 다음 단계는 모든 프로토타입 객체를 새로 생성된 객체 에 첨부하는 것입니다.

여기에 프로토타입 객체와 유사한 my_person_prototype

 for(var key in my_person_prototype){ newObject[key] = my_person_prototype[key]; }

JavaScript가 프로토타입에 정의된 속성을 실제로 첨부하는 방식이 아닙니다. 실제 방법은 프로토타입 체인 개념과 관련이 있습니다.


NS. & NS. 이 두 단계 대신 다음을 수행하여 똑같은 결과를 얻을 수 있습니다.

 var newObject = Object.create(my_person_prototype); //here you can check out the __proto__ attribute console.log(newObject.__proto__ === my_person_prototype); //true //and also check if you have access to your desired properties console.log(typeof newObject.getName);//"function"

my_person_prototype getName 함수를 호출할 수 있습니다.

 newObject.getName();

씨. 그런 다음 해당 객체를 생성자에 제공합니다.

다음과 같은 샘플로 이 작업을 수행할 수 있습니다.

 Person.call(newObject, "George");

또는

 Person.apply(newObject, ["George"]);

그러면 생성자는 원하는 모든 작업을 수행할 수 있습니다. 해당 생성자 내부의 this 는 방금 생성된 객체이기 때문입니다.

이제 다른 단계를 시뮬레이션하기 전의 최종 결과: Object {name: "George"}


요약:

기본적으로 함수에서 new 키워드를 사용하면 해당 함수를 호출하고 해당 함수가 생성자 역할을 하므로 다음과 같이 말할 수 있습니다.

 new FunctionName()

JavaScript는 내부적으로 객체, 즉 빈 해시를 만든 다음 해당 객체를 생성자에 제공합니다. 그러면 생성자는 원하는 모든 작업을 수행할 수 있습니다. 해당 생성자 내부의 this 는 방금 생성된 객체이고 물론 해당 객체를 제공하기 때문입니다. 함수에서 return 문을 사용하지 않았거나 return undefined; 함수 본문의 끝에서.

따라서 JavaScript가 객체의 속성을 조회할 때 가장 먼저 하는 일은 해당 객체에서 조회하는 것입니다. 그리고 비밀 속성 [[prototype]] 이 있습니다. 일반적으로 __proto__ 와 같은 속성을 가지고 있으며 그 속성은 JavaScript가 다음에 살펴보는 것입니다. __proto__ 통해 볼 때 또 다른 JavaScript 객체인 한 자체 __proto__ __proto__ 가 null인 지점에 도달할 때까지 계속 올라갑니다. 요점은 JavaScript에서 __proto__ 속성이 null인 Object.prototype 객체라는 것입니다.

 console.log(Object.prototype.__proto__===null);//true

이것이 JavaScript에서 상속이 작동하는 방식입니다.

프로토타입 체인

다시 말해서, 함수에 대한 프로토타입 속성이 있고 그것에 대해 new를 호출하면 JavaScript가 속성에 대해 새로 생성된 객체를 살펴본 후 함수의 .prototype 살펴보고 이 객체가 자체 내부 프로토타입이 있습니다. 등등.


Mehran Hatami

프로토타입의 일곱 Koans

Ciro San이 깊은 명상을 한 후 Mount Fire Fox를 내려왔을 때 그의 마음은 깨끗하고 평화로웠습니다.

그러나 그의 손은 쉬지 않고 스스로 붓을 잡고 다음과 같은 메모를 적었다.


0) 두 가지 다른 것을 "프로토타입"이라고 부를 수 있습니다.

  • obj.prototype 에서와 같이 프로토타입 속성

  • 프로토타입 내부 속성, ES5에서 [[Prototype]] 으로 표시됩니다.

    Object.getPrototypeOf() 를 통해 검색할 수 있습니다.

    Firefox는 확장으로 __proto__ 속성을 통해 액세스할 수 있도록 합니다. ES6은 이제 __proto__ 대한 몇 가지 선택적 요구 사항을 언급합니다.


1) 이러한 개념은 다음 질문에 답하기 위해 존재합니다.

obj.property 할 때 .property 어디에서 찾습니까?

직관적으로 클래식 상속은 속성 조회에 영향을 미칩니다.


2)

  • __proto__ 는 점에 사용됩니다 . obj.property 에서와 같이 속성 조회.
  • .prototype조회에 직접 사용되지 않고 new 로 객체 생성 시 __proto__ 를 결정하기 때문에 간접적으로만 사용됩니다.

조회 순서는 다음과 같습니다.

  • obj.p = ... 또는 Object.defineProperty(obj, ...) 추가된 obj
  • obj.__proto__ 속성
  • obj.__proto__.__proto__ 속성 등
  • 일부 __proto__null undefined 반환합니다.

이것이 이른바 프로토타입 체인 입니다.

피할 수 있습니다 . obj.hasOwnProperty('key')Object.getOwnPropertyNames(f) 조회


3) obj.__proto__ 를 설정하는 두 가지 주요 방법이 있습니다.

  • new :

     var F = function() {} var f = new F()

    그런 다음 new 가 설정했습니다.

     f.__proto__ === F.prototype

    여기 에서 .prototype 이 사용됩니다.

  • Object.create :

     f = Object.create(proto)

    세트:

     f.__proto__ === proto

4) 코드:

 var F = function(i) { this.i = i } var f = new F(1)

다음 다이어그램에 해당합니다(일부 Number 은 생략됨).

 (Function) ( F ) (f)----->(1) | ^ | | ^ | i | | | | | | | | | | | | +-------------------------+ | | | |constructor | | | | | | | | +--------------+ | | | | | | | | | | | | | | | | | |[[Prototype]] |[[Prototype]] |prototype |constructor |[[Prototype]] | | | | | | | | | | | | | | | | | | +----------+ | | | | | | | | | | | | | | +-----------------------+ | | | | | | | | v | vv | v | (Function.prototype) (F.prototype) | | | | | | | |[[Prototype]] |[[Prototype]] [[Prototype]]| | | | | | | | +-------------------------------+ | | | | vvv (Object.prototype) (Number.prototype) | | ^ | | | | | +---------------------------+ | | | | +--------------+ | | | | | | | |[[Prototype]] |constructor |prototype | | | | | | | | -------------+ | | | vv | (null) (Object)

이 다이어그램은 사전 정의된 많은 언어 개체 노드를 보여줍니다.

  • null
  • Object
  • Object.prototype
  • Function
  • Function.prototype
  • 1
  • Number.prototype (1).__proto__ 에서 찾을 수 있으며, 구문을 충족하려면 괄호가 필수임)

2줄의 코드는 다음과 같은 새 객체만 생성했습니다.

  • f
  • F
  • F.prototype

i f 의 속성입니다. 왜냐하면 당신이 할 때:

 var f = new F(1)

그 평가 F 가진 this 그 가치 new 다음 지정된 도착 반환, f .


5) .constructor 일반적에서 오는 F.prototype 관통 . 조회:

 f.constructor === F !f.hasOwnProperty('constructor') Object.getPrototypeOf(f) === F.prototype F.prototype.hasOwnProperty('constructor') F.prototype.constructor === f.constructor

f.constructor 를 작성할 때 JavaScript는 . 다음과 같이 조회:

  • f .constructor 가 없습니다.
  • f.__proto__ === F.prototype 에는 .constructor === F 가 있으므로 가져오세요.

f.constructor == F 결과는 직관적으로 정확합니다. F 는 고전적인 OOP 언어에서와 같이 필드를 설정하는 것과 같이 f 를 구성하는 데 사용되기 때문입니다.


6) 프로토타입 체인을 조작하여 고전적인 상속 구문을 얻을 수 있습니다.

ES6은 이전에 가능했던 프로토타입 조작 광기에 대한 대부분의 구문 설탕인 class 추가하고 extends

 class C { constructor(i) { this.i = i } inc() { return this.i + 1 } } class D extends C { constructor(i) { super(i) } inc2() { return this.i + 2 } }
 // Inheritance syntax works as expected. c = new C(1) c.inc() === 2 (new D(1)).inc() === 2 (new D(1)).inc2() === 3
 // "Classes" are just function objects. C.constructor === Function C.__proto__ === Function.prototype D.constructor === Function // D is a function "indirectly" through the chain. D.__proto__ === C D.__proto__.__proto__ === Function.prototype
 // "extends" sets up the prototype chain so that base class // lookups will work as expected var d = new D(1) d.__proto__ === D.prototype D.prototype.__proto__ === C.prototype // This is what `d.inc` actually does. d.__proto__.__proto__.inc === C.prototype.inc
 // Class variables // No ES6 syntax sugar apparently: // http://stackoverflow.com/questions/22528967/es6-class-variable-alternatives Cc = 1 Cc === 1 // Because `D.__proto__ === C`. Dc === 1 // Nothing makes this work. dc === undefined

사전 정의된 모든 개체가 없는 단순화된 다이어그램:

 (c)----->(1) | i | | |[[Prototype]] | | v __proto__ (C)<--------------(D) (d) | | | | | | | | | |prototype |prototype |[[Prototype]] | | | | | | | | | | | +---------+ | | | | | | | | | | vv |[[Prototype]] (D.prototype)--------> (inc2 function object) | | | inc2 | | | | | |[[Prototype]] | | | | | | | | +--------------+ | | | | | | | vv | (C.prototype)------->(inc function object) | inc v Function.prototype

다음이 어떻게 작동하는지 잠시 살펴보겠습니다.

 c = new C(1) c.inc() === 2

첫 번째 줄은 "4)"에서 설명한 대로 ci1

두 번째 줄에서 다음을 수행합니다.

 c.inc()
  • .inc [[Prototype]] 체인을 통해 찾을 수 있습니다 c -> C -> C.prototype -> inc
  • 자바스크립트에서 함수를 XY() 로 호출하면 자바스크립트는 자동으로 Y() 함수 호출 내에서 this X 와 동일하게 설정합니다!

똑같은 논리로 d.incd.inc2 도 설명합니다.

이 기사 https://javascript.info/class#not-just-a-syntax-sugar 는 알 가치가 class 추가 효과에 대해 언급합니다. class 키워드 없이는 달성할 수 없습니다(TODO 확인):


Ciro Santilli 新疆再教育营六四事件法轮功郝海东

prototype 사용하면 클래스를 만들 수 있습니다. prototype 을 사용하지 않으면 정적이 됩니다.

다음은 짧은 예입니다.

 var obj = new Object(); obj.test = function() { alert('Hello?'); };

위의 경우 정적 함수 호출 테스트가 있습니다. 이 함수는 obj가 클래스라고 상상할 수 있는 obj.test에서만 액세스할 수 있습니다.

아래 코드에서와 같이

 function obj() { } obj.prototype.test = function() { alert('Hello?'); }; var obj2 = new obj(); obj2.test();

obj는 이제 인스턴스화할 수 있는 클래스가 되었습니다. obj의 여러 인스턴스가 존재할 수 있으며 모두 test 기능이 있습니다.

이상은 제 이해입니다. 나는 그것을 커뮤니티 위키로 만들고 있으므로 사람들이 내가 틀렸다면 나를 고칠 수 있습니다.


Community Wiki

이 스레드를 읽은 후 JavaScript Prototype Chain과 혼동을 느끼다가 이 차트를 찾았습니다.

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance *[[protytype]]* 및 함수 객체의 <code>prototype</code> 속성

Prototype Chain에 의한 JavaScript 상속을 보여주는 명확한 차트입니다.

그리고

http://www.javascriptbank.com/javascript/article/JavaScript_Classical_Inheritance/

여기에는 코드와 몇 가지 멋진 다이어그램이 포함된 예제가 포함되어 있습니다.

프로토타입 체인은 궁극적으로 Object.prototype으로 대체됩니다.

프로토타입 체인은 하위 클래스의 프로토타입을 상위 클래스의 객체와 동일하게 설정하여 매번 원하는 만큼 기술적으로 확장할 수 있습니다.

JavaScript Prototype Chain을 이해하는 데에도 도움이 되길 바랍니다.


rockXrock

모든 객체에는 내부 속성 [[Prototype]] 이 있으며 이를 다른 객체에 연결합니다.

 object [[Prototype]] → anotherObject

전통적인 자바스크립트에서 연결된 객체는 prototype 속성입니다.

 object [[Prototype]] → aFunction.prototype

일부 환경에서는 [[Prototype]]__proto__ 로 노출합니다.

 anObject.__proto__ === anotherObject

객체를 생성할 때 [[Prototype]] 링크를 생성합니다.

 // (1) Object.create: var object = Object.create(anotherObject) // object.__proto__ = anotherObject // (2) ES6 object initializer: var object = { __proto__: anotherObject }; // object.__proto__ = anotherObject // (3) Traditional JavaScript: var object = new aFunction; // object.__proto__ = aFunction.prototype

따라서 다음 명령문은 동일합니다.

 var object = Object.create(Object.prototype); var object = { __proto__: Object.prototype }; // ES6 only var object = new Object;

실제로 새 문에서 링크 대상( Object.prototype )을 볼 수 없습니다. 대신 대상은 생성자( Object )에 의해 암시됩니다.

기억하다:

  • 모든 객체에는 [[Prototype]] 링크가 있으며 때로는 __proto__ 로 표시 됩니다.
  • 모든 함수에는 prototype 속성이 있으며 처음에는 빈 객체를 보유합니다.
  • new 로 생성된 객체는 생성자 prototype 속성에 연결됩니다.
  • 함수가 생성자 prototype 속성이 사용되지 않습니다.
  • 생성자가 필요하지 않다면 new 대신 Object.create 를 사용하세요.

sam

Javascript는 일반적인 의미에서 상속이 없지만 프로토타입 체인이 있습니다.

프로토타입 체인

개체의 구성원이 개체에서 찾을 수 없으면 프로토타입 체인에서 찾습니다. 체인은 다른 개체로 구성됩니다. 주어진 인스턴스의 프로토타입은 __proto__ 변수를 사용하여 액세스할 수 있습니다. 자바스크립트에서 클래스와 인스턴스 간에 차이가 없기 때문에 모든 객체에는 하나가 있습니다.

프로토타입에 함수/변수를 추가할 때의 이점은 모든 인스턴스가 아니라 한 번만 메모리에 있어야 한다는 것입니다.

프로토타입 체인은 다른 많은 객체로 구성될 수 있기 때문에 상속에도 유용합니다.


Georg Schölly

글이 깁니다. 그러나 JavaScript 상속의 "프로토타입" 특성에 대한 대부분의 질문이 해결될 것이라고 확신합니다. 그리고 더. 전체 기사를 읽으십시오.

JavaScript에는 기본적으로 두 가지 종류의 데이터 유형이 있습니다.

  • 비 객체
  • 사물

비 객체

다음은 비 객체 데이터 유형입니다.

  • 숫자(NaN 및 무한대 포함)
  • 부울 값(true, false)
  • 찾으시는 주소가 없습니다

이러한 데이터 유형은 typeof 연산자를 사용할 때 다음을 반환합니다.

typeof "문자열 리터럴" (또는 문자열 리터럴을 포함하는 변수) === '문자열'

typeof 5 (또는 숫자 리터럴 또는 숫자 리터럴 또는 NaN 또는 Infynity를 포함하는 변수) === '숫자'

typeof true (또는 false 또는 true 또는 false를 포함하는 변수) === 'boolean'

typeof undefined (또는 undefined 변수 또는 undefined 를 포함하는 변수) === 'undefined'

string , numberboolean 데이터 유형은 객체비 객체 로 모두 표시될 수 있습니다. 객체로 표시될 때 해당 유형은 항상 === '객체'입니다. 객체 데이터 유형을 이해하면 이 문제로 다시 돌아올 것입니다.

사물

객체 데이터 유형은 두 가지 유형으로 더 나눌 수 있습니다.

  1. 함수 유형 객체
  2. 비 함수 유형 객체

함수 유형 객체 는 typeof 연산자와 함께 문자열 'function' 을 반환하는 객체입니다. new 연산자를 사용하여 새로운 객체를 생성할 수 있는 모든 사용자 정의 함수 및 모든 JavaScript 내장 객체가 이 범주에 속합니다. 예를 들어

  • 물체
  • 숫자
  • 부울
  • 정렬
  • 유형이 지정된 배열
  • 정규 표현식
  • 기능
  • new 연산자를 사용하여 새 객체를 생성할 수 있는 다른 모든 내장 객체
  • function UserDefinedFunction (){ /*사용자 정의 코드 */ }

따라서 typeof(Object) === typeof(String) === typeof(Number) === typeof(Boolean) === typeof(Array) === typeof(RegExp) === typeof(Function) == = typeof(UserDefinedFunction) === '함수'

모든 Function 유형 객체 는 실제로 내장 JavaScript 객체 Function 의 인스턴스입니다(Function 객체 포함, 즉 재귀적으로 정의됨). 이러한 객체는 다음과 같이 정의된 것과 같습니다.

 var Object= new Function ([native code for object Object]) var String= new Function ([native code for object String]) var Number= new Function ([native code for object Number]) var Boolean= new Function ([native code for object Boolean]) var Array= new Function ([native code for object Array]) var RegExp= new Function ([native code for object RegExp]) var Function= new Function ([native code for object Function]) var UserDefinedFunction= new Function ("user defined code")

언급했듯이 Function 유형 객체 는 new 연산자를 사용하여 새 객체를 추가로 생성할 수 있습니다. 예를 들어 Object , String , Number , Boolean , Array , RegExp 또는 UserDefinedFunction 유형의 개체는 다음을 사용하여 만들 수 있습니다.

 var a=new Object() or var a=Object() or var a={} //Create object of type Object var a=new String() //Create object of type String var a=new Number() //Create object of type Number var a=new Boolean() //Create object of type Boolean var a=new Array() or var a=Array() or var a=[] //Create object of type Array var a=new RegExp() or var a=RegExp() //Create object of type RegExp var a=new UserDefinedFunction()

이렇게 생성된 객체는 모두 Non Function 유형 객체 이며 해당 typeof === 'object' 를 반환합니다. 이 모든 경우에 개체 "a"는 new 연산자를 사용하여 개체를 더 이상 만들 수 없습니다. 그래서 다음은 틀리다.

 var b=new a() //error. a is not typeof==='function'

내장 객체 Mathtypeof === 'object' 입니다. 따라서 Math 유형의 새 객체는 new 연산자로 생성할 수 없습니다.

 var b=new Math() //error. Math is not typeof==='function'

또한 Object , ArrayRegExp 함수는 new 연산자를 사용하지 않고도 새 객체를 생성할 수 있습니다. 그러나 다음은 그렇지 않습니다.

 var a=String() // Create a new Non Object string. returns a typeof==='string' var a=Number() // Create a new Non Object Number. returns a typeof==='number' var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'

사용자 정의 함수는 특별한 경우입니다.

 var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.

Function 유형 객체 는 새 객체를 생성할 수 있으므로 생성자 라고도 합니다.

모든 생성자/함수 (내장 또는 사용자 정의)는 자동으로 정의될 때 값이 기본적으로 객체로 설정되는 "prototype"이라는 속성을 갖습니다. 이 객체 자체에는 기본적으로 Constructor/Function을 다시 참조하는 "constructor" 라는 속성이 있습니다.

예를 들어 함수를 정의할 때

 function UserDefinedFunction() { }

다음은 자동으로 발생합니다

 UserDefinedFunction.prototype={constructor:UserDefinedFunction}

"prototype" 속성 은 Function 유형 객체 에만 존재합니다( Non Function 유형 객체에는 없음 ).

이는 새 객체가 생성될 때(new 연산자를 사용하여) 생성자 함수의 현재 프로토타입 객체에서 모든 속성과 메서드를 상속하기 때문입니다. 즉, 생성자 함수의 현재 프로토타입 객체가 참조하는 객체를 참조하는 새로 생성된 객체에 내부 참조가 생성되기 때문입니다.

상속된 속성을 참조하기 위해 개체에서 생성되는 이 "내부 참조" 는 개체의 프로토타입 으로 알려져 있습니다(이는 생성자의 "prototype" 속성에서 참조하지만 다른 개체를 참조함). 모든 객체(Function 또는 Non Function)에 대해 Object.getPrototypeOf() 메서드를 사용하여 검색할 수 있습니다. 이 방법을 사용하면 객체의 프로토타입 체인을 추적할 수 있습니다.

또한 생성되는 모든 객체 ( 함수 유형 또는 비함수 유형 )에는 생성자 함수의 프로토타입 속성에서 참조하는 객체에서 상속되는 "생성자" 속성이 있습니다. 기본적으로 이 "생성자" 속성은 이를 생성 한 생성자 함수 를 참조합니다(생성자 함수의 기본 "프로토타입"이 변경되지 않은 경우).

모든 함수 유형 객체의 경우 생성자 함수는 항상 function Function(){}

비 함수 유형 객체 (예: Javascript Built in Math 객체)의 경우 생성자 함수는 이를 생성한 함수입니다. Math 객체의 경우 function Object(){} 입니다.

위에서 설명한 모든 개념은 지원 코드 없이는 이해하기 어려울 수 있습니다. 개념을 이해하기 위해 다음 코드를 한 줄씩 살펴보십시오. 더 나은 이해를 위해 그것을 실행하십시오.

 function UserDefinedFunction() { } /* creating the above function automatically does the following as mentioned earlier UserDefinedFunction.prototype={constructor:UserDefinedFunction} */ var newObj_1=new UserDefinedFunction() alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays true alert(newObj_1.constructor) //Displays function UserDefinedFunction //Create a new property in UserDefinedFunction.prototype object UserDefinedFunction.prototype.TestProperty="test" alert(newObj_1.TestProperty) //Displays "test" alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test" //Create a new Object var objA = { property1 : "Property1", constructor:Array } //assign a new object to UserDefinedFunction.prototype UserDefinedFunction.prototype=objA alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays false. The object referenced by UserDefinedFunction.prototype has changed //The internal reference does not change alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction alert(newObj_1.TestProperty) //This shall still Display "test" alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test" //Create another object of type UserDefinedFunction var newObj_2= new UserDefinedFunction(); alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true. alert(newObj_2.constructor) //Displays function Array() alert(newObj_2.property1) //Displays "Property1" alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1" //Create a new property in objA objA.property2="property2" alert(objA.property2) //Displays "Property2" alert(UserDefinedFunction.prototype.property2) //Displays "Property2" alert(newObj_2.property2) // Displays Property2 alert(Object.getPrototypeOf(newObj_2).property2) //Displays "Property2"

모든 객체의 프로토타입 체인은 궁극적으로 Object.prototype(자체에는 프로토타입 객체가 없음)으로 추적됩니다. 다음 코드는 개체의 프로토타입 체인을 추적하는 데 사용할 수 있습니다.

 var o=Starting object; do { alert(o + "\n" + Object.getOwnPropertyNames(o)) }while(o=Object.getPrototypeOf(o))

다양한 객체에 대한 프로토타입 체인은 다음과 같이 작동합니다.

  • 모든 Function 객체(내장 Function 객체 포함)-> Function.prototype -> Object.prototype -> null
  • 단순 객체(내장 Math 객체를 포함하여 new Object() 또는 {}에 의해 생성됨)-> Object.prototype -> null
  • new 또는 Object.create -> 하나 이상의 프로토타입 체인 -> Object.prototype -> null로 생성된 객체

프로토타입 없이 객체를 생성하려면 다음을 사용하십시오.

 var o=Object.create(null) alert(Object.getPrototypeOf(o)) //Displays null

생성자의 프로토타입 속성을 null로 설정하면 null 프로토타입이 있는 객체가 생성된다고 생각할 수도 있습니다. 그러나 이러한 경우 새로 생성된 객체의 프로토타입은 Object.prototype으로 설정되고 생성자는 함수 객체로 설정됩니다. 이것은 다음 코드로 증명됩니다.

 function UserDefinedFunction(){} UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.) var o=new UserDefinedFunction() alert(Object.getPrototypeOf(o)==Object.prototype) //Displays true alert(o.constructor) //Displays Function Object

이 기사의 요약에 따르면

  • 객체에는 기능 유형비 기능 유형 의 두 가지 유형이 있습니다.
  • 함수 유형 객체new 연산자를 사용하여 새 객체를 생성할 수 있습니다. 이렇게 생성된 객체는 Non Function 유형 객체입니다. 비 함수 유형 객체 는 new 연산자를 사용하여 더 이상 객체를 생성할 수 없습니다.

  • 모든 함수 유형 개체 에는 기본적으로 "프로토타입" 속성이 있습니다. 이 "프로토타입" 속성은 기본적으로 함수 유형 개체 자체를 참조하는 "생성자" 속성이 있는 개체를 참조합니다.

  • 모든 객체( 함수 유형비 함수 유형 )에는 기본적으로 이를 생성 한 함수 유형 객체 / 생성자 를 참조하는 "생성자" 속성이 있습니다.

  • 생성되는 모든 객체는 내부적으로 생성한 생성자의 "prototype" 속성에서 참조하는 객체를 참조합니다. 이 객체는 생성된 객체의 프로토타입 으로 알려져 있습니다(참조하는 Function 유형 객체 "prototype" 속성과 다름). 이렇게 하면 생성된 객체는 생성자의 "prototype" 속성이 참조하는 객체에 정의된 메서드와 속성에 직접 액세스할 수 있습니다(객체 생성 시).

  • 객체의 프로토타입 (따라서 상속된 속성 이름)은 Object.getPrototypeOf() 메서드를 사용하여 검색할 수 있습니다. 사실 이 방법은 개체의 전체 프로토타입 체인을 탐색하는 데 사용할 수 있습니다.

  • 모든 객체의 프로토타입 체인은 궁극적으로 Object.prototype으로 다시 추적됩니다(객체가 프로토타입이 없는 경우 Object.create(null)을 사용하여 객체를 생성하지 않는 한).

  • typeof(new Array())==='object' 는 언어의 설계에 의한 것이며 Douglas Crockford가 지적한 실수가 아닙니다.

  • 생성자의 프로토타입 속성을 null(또는 undefined,number,true,false,string)로 설정하면 null 프로토타입이 있는 개체가 생성되지 않습니다. 이러한 경우 새로 생성된 객체의 프로토타입은 Object.prototype으로 설정되고 생성자는 함수 객체로 설정됩니다.

도움이 되었기를 바랍니다.


Arup Hore

prototypal 상속의 개념은 많은 개발자에게 가장 복잡한 개념 중 하나입니다. prototypal inheritance 더 잘 이해하기 위해 문제의 근원을 이해하려고 노력합시다. plain 함수로 시작합시다.

여기에 이미지 설명 입력

Tree function new 연산자를 사용하는 경우 constructor 함수로 호출합니다.

여기에 이미지 설명 입력

모든 JavaScript 함수에는 prototype 있습니다. Tree.prototype 을 기록하면 다음을 얻습니다.

여기에 이미지 설명 입력

위의 console.log() Tree.prototype 의 생성자 속성과 __proto__ 속성도 볼 수 있습니다. __proto__ 는 이 function 기반 prototype inheritance 설정되지 않은 JavaScript function 이므로 JavaScript에 내장된 Object prototype 을 나타냅니다...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

.toString, .toValue, .hasOwnProperty 등과 같은 것들이 있습니다.

__proto__ 는 더 이상 사용되지 않으며 Object.getPrototypeOf object's prototype 을 가져옵니다.

여기에 이미지 설명 입력

 Object.getPrototypeOf(Tree.prototype); // Object {}

Tree prototype 메서드를 추가해 보겠습니다.

여기에 이미지 설명 입력

Root 수정하고 거기에 function 분기를 추가했습니다.

여기에 이미지 설명 입력

Tree instance 를 만들 때 branch 메서드를 호출할 수 있습니다.

여기에 이미지 설명 입력

Prototype primitivesobjects 를 추가할 수도 있습니다.

여기에 이미지 설명 입력

Tree child-tree 를 추가해 보겠습니다.

여기에 이미지 설명 입력

여기서 Child prototype 을 상속합니다. 여기서 우리가 하는 것은 Object.create() 메서드를 사용하여 전달한 내용을 기반으로 새 개체를 만드는 것입니다 Tree.prototype 입니다. 이 경우 우리가 하고 있는 것은 Child의 프로토타입을 Tree 프로토타입과 동일하게 보이는 새 객체로 설정하는 것입니다. Child's constructor to Child 로 설정하고, 그렇지 않으면 Tree() 가리킵니다.

여기에 이미지 설명 입력

Child 에는 자체 prototype 이 있고 __proto__Tree Tree's prototype 은 기본 Object 가리킵니다.

 Child | \ \ Tree.prototype - branch | | \ \ Object.prototype -toString -valueOf -etc., etc.

Tree 에서 사용할 수 있는 Child instance 를 만들고 branch 를 호출합니다. 우리는 실제로 Child prototypebranch 를 정의하지 않았습니다. 그러나 Child가 상속 Root prototype

여기에 이미지 설명 입력

JS에서는 모든 것이 객체가 아니며 모든 것이 객체처럼 작동할 수 있습니다.

Javascript strings, number, booleans, undefined, null. 과 같은 기본 요소가 있습니다. 그것들은 object(ie reference types) object 처럼 작동할 수 있습니다. 여기에서 예를 살펴보겠습니다.

여기에 이미지 설명 입력

이 목록의 첫 번째 줄에서 primitive 문자열 값이 이름에 할당됩니다. 두 번째 줄은 name을 object 처럼 취급하고 점 표기법을 사용하여 charAt(0) 을 호출합니다.

이것은 배후에서 일어나는 일입니다: // JavaScript 엔진이 하는 일

여기에 이미지 설명 입력

String object 는 소멸되기 전에 하나의 명령문에 대해서만 존재합니다( autoboxing 이라고 하는 프로세스). prototypal inheritance 돌아가 보겠습니다.

  • Javascript prototypes 기반으로 하는 delegation 통한 상속을 지원합니다.
  • Function 에는 다른 객체를 참조 prototype
  • properties/functionsobject 자체에서 또는 존재하지 않는 경우 prototype

prototype JS의 객체입니다 yields 다른 사람의 부모를 object . [ie..delegation] Delegation 이란 자신이 할 수 없는 일을 다른 사람에게 대신 하도록 하는 것을 의미합니다.

여기에 이미지 설명 입력

https://jsfiddle.net/say0tzpL/1/

위의 바이올린을 조회하면 dog는 toString Object.prototype 위임하는 프로토타입 체인을 통해 사용할 수 있습니다.

여기에 이미지 설명 입력

아래를 보면 function 에서 사용할 수 call 방식에 접근하려고 합니다.

여기에 이미지 설명 입력

https://jsfiddle.net/rknffckc/

위의 바이올린을 찾아보면 Profile Function은 call Function.prototype 위임하는 프로토타입 체인을 통해 사용할 수 있습니다.

여기에 이미지 설명 입력

참고: prototype 은 함수 생성자의 속성인 반면 __proto__ 는 함수 생성자에서 생성된 객체의 속성입니다. 모든 함수에는 값이 빈 object prototype 속성이 있습니다. 함수의 인스턴스를 만들 때 constructor 의 프로토타입인 [[Prototype]] 또는 __proto__ 를 얻습니다.

여기에 이미지 설명 입력

prototype chaining 작동하는 방식에 대한 전체 그림을 보여줍니다. 천천히 살펴보겠습니다.

두 개의 인스턴스 b1b2 가 있습니다. 생성자는 Bar 이고 부모는 Foo이며 프로토타입 체인의 두 가지 메서드가 있으며 BarFoo 를 통해 identify 하고 speak

여기에 이미지 설명 입력

https://jsfiddle.net/kbp7jr7n/

위의 코드를 찾아보면 identify() 메소드 Foo 생성자와 speak 메소드 Bar 생성자가 있습니다. 부모 유형이 Foo 인 두 개의 Bar 인스턴스 b1b2 를 만듭니다. Bar speak 메소드를 호출 prototype 체인을 통해 speak를 호출한 사람을 식별할 수 있습니다.

여기에 이미지 설명 입력

Bar prototype 정의된 Foo 모든 메서드를 갖습니다. Object.prototypeFunction.prototype , 그리고 그것들이 어떻게 관련되어 있는지 더 자세히 알아보자. Foo 의 생성자를 조회하면 BarObjectFunction constructor 입니다.

여기에 이미지 설명 입력

prototypeBar 있다 Foo , prototypeFoo 입니다 Object 당신이 자세히 보면 경우 prototypeFoo 관련이 Object.prototype .

여기에 이미지 설명 입력

이 글을 마무리하기 전에 위의 모든 내용 을 요약하기 위해 여기에 작은 코드 조각을 넣어 보겠습니다. 여기에서 instanceof 연산자를 사용하여 objectprototype 체인에 constructor prototype 속성이 있는지 확인하고 아래에 전체 큰 다이어그램이 요약되어 있습니다.

여기에 이미지 설명 입력

나는 이 추가 정보가 약간의 정보가 되기를 바랍니다. 나는 이것이 이해하기 어려울 수 있다는 것을 압니다... 간단히 말해서 그것은 개체에 연결된 개체일 뿐입니다!!!!


Thalaivar

프로토타입 체인을 두 가지 범주로 분류하는 데 도움이 될 수 있습니다.

생성자를 고려하십시오.

 function Person() {}

Object.getPrototypeOf(Person) 의 값은 함수입니다. 사실, 그것은 Function.prototype 입니다. Person 은 함수로 생성되었기 때문에 모든 함수가 가지고 있는 동일한 프로토타입 함수 객체를 공유합니다. Person.__proto__ 와 동일하지만 해당 속성을 사용하면 안 됩니다. 어쨌든 Object.getPrototypeOf(Person) 를 사용하면 프로토타입 체인이라는 사다리를 효과적으로 올라갈 수 있습니다.

위쪽 방향의 체인은 다음과 같습니다.

PersonFunction.prototypeObject.prototype (종료점)

Person 이 구성 할 수 있는 객체와 거의 관련이 없다는 것입니다. 생성된 객체에는 고유한 프로토타입 체인이 있으며 이 체인에는 위에서 언급한 것과 공통적으로 가까운 조상이 없을 수 있습니다.

다음 객체를 예로 들어 보겠습니다.

 var p = new Person();

p 는 Person 과 직접적인 프로토타입 체인 관계가 없습니다. 그들의 관계는 다릅니다. 객체 p 에는 자체 프로토타입 체인이 있습니다. Object.getPrototypeOf 사용하면 다음과 같은 체인을 찾을 수 있습니다.

pPerson.prototypeObject.prototype (종료점)

이 체인에는 함수 개체가 없습니다(있을 수 있지만).

따라서 Person 은 자신의 삶을 사는 두 종류의 사슬과 관련이 있는 것 같습니다. 한 체인에서 다른 체인으로 "점프"하려면 다음을 사용합니다.

  1. .prototype : 생성자의 체인에서 생성된 객체의 체인으로 이동합니다. 따라서 이 속성은 함수 개체에 대해서만 정의됩니다( new 는 함수에만 사용할 수 있음).

  2. .constructor : 생성된 객체의 체인에서 생성자의 체인으로 이동합니다.

다음은 관련된 두 가지 프로토타입 체인을 열로 표시한 시각적 표현입니다.

여기에 이미지 설명 입력

요약하자면:

prototype 속성은 주체의 프로토타입 체인에 대한 정보를 제공하지 않지만 주체에 의해 생성된 객체에 대한 정보를 제공합니다.

prototype 의 이름이 혼동을 일으킬 수 있다는 것은 놀라운 일이 아닙니다. prototypeOfConstructedInstances 또는 그 라인을 따라 이름이 지정되었다면 더 명확했을 것입니다.

두 프로토타입 체인 사이를 앞뒤로 이동할 수 있습니다.

 Person.prototype.constructor === Person

prototype 속성에 다른 객체를 명시적으로 할당하여 깨뜨릴 수 있습니다(나중에 자세히 설명).

하나의 함수를 만들고 두 개의 객체를 가져옵니다

Person.prototype Person 함수가 생성될 때 생성된 객체입니다. 해당 생성자가 실제로 아직 실행되지 않았음에도 불구하고 Person 따라서 두 개의 객체가 동시에 생성됩니다.

  1. 기능 Person 자체
  2. 함수가 생성자로 호출될 때 프로토타입으로 작동할 객체

둘 다 객체이지만 역할이 다릅니다. 함수 객체가 생성 하는 반면 다른 객체는 함수가 생성할 객체의 프로토타입을 나타냅니다. 프로토타입 객체는 프로토타입 체인에서 생성된 객체의 부모가 됩니다.

함수도 객체이기 때문에 자체 프로토타입 체인에 자체 부모도 있지만 이 두 체인은 서로 다른 점을 기억하십시오.

다음은 문제를 파악하는 데 도움이 될 수 있는 몇 가지 평등입니다. 이 모든 것이 true 인쇄됩니다.

 function Person() {}; // This is prototype chain info for the constructor (the function object): console.log(Object.getPrototypeOf(Person) === Function.prototype); // Step further up in the same hierarchy: console.log(Object.getPrototypeOf(Function.prototype) === Object.prototype); console.log(Object.getPrototypeOf(Object.prototype) === null); console.log(Person.__proto__ === Function.prototype); // Here we swap lanes, and look at the constructor of the constructor console.log(Person.constructor === Function); console.log(Person instanceof Function); // Person.prototype was created by Person (at the time of its creation) // Here we swap lanes back and forth: console.log(Person.prototype.constructor === Person); // Although it is not an instance of it: console.log(!(Person.prototype instanceof Person)); // Instances are objects created by the constructor: var p = new Person(); // Similarly to what was shown for the constructor, here we have // the same for the object created by the constructor: console.log(Object.getPrototypeOf(p) === Person.prototype); console.log(p.__proto__ === Person.prototype); // Here we swap lanes, and look at the constructor console.log(p.constructor === Person); console.log(p instanceof Person);

프로토타입 체인에 레벨 추가

프로토타입 객체는 생성자 함수를 생성할 때 생성되지만 해당 객체를 무시하고 해당 생성자가 생성한 후속 인스턴스의 프로토타입으로 사용해야 하는 다른 객체를 할당할 수 있습니다.

예를 들어:

 function Thief() { } var p = new Person(); Thief.prototype = p; // this determines the prototype for any new Thief objects: var t = new Thief();

이제 t 의 프로토타입 체인 은 p 의 프로토타입 체인보다 한 단계 더 깁니다.

tpPerson.prototypeObject.prototype (종료점)

다른 프로토타입 체인은 더 이상 없습니다. ThiefPerson 은 프로토타입 체인에서 동일한 부모를 공유하는 형제입니다.

Person }
Thief } → Function.prototypeObject.prototype (종료점)

이전에 제시된 그래픽은 다음으로 확장될 수 있습니다(원래 Thief.prototype 은 생략됨).

여기에 이미지 설명 입력

파란색 선은 프로토타입 체인을 나타내고 다른 색 선은 다른 관계를 나타냅니다.

  • 객체와 생성자 사이
  • 생성자와 객체 생성에 사용될 프로토타입 객체 사이

trincot

이 ".prototype" 속성의 정확한 목적은 무엇입니까?

표준 클래스에 대한 인터페이스를 확장할 수 있습니다. 예를 들어 Array 클래스를 사용 중이고 모든 배열 개체에 대한 사용자 지정 직렬 변환기도 추가해야 합니다. 하위 클래스를 코딩하는 데 시간을 할애하거나 구성을 사용하거나 ... 프로토타입 속성은 사용자가 클래스에서 사용할 수 있는 정확한 멤버/메서드 집합을 제어할 수 있도록 하여 이 문제를 해결합니다.

프로토타입을 추가 vtable 포인터로 생각하십시오. 원래 클래스에서 일부 멤버가 누락된 경우 런타임 시 프로토타입이 조회됩니다.


dirkgently

객체 지향 JavaScript에 대한 확실한 가이드 - 질문에 대한 매우 간결하고 명확한 ~30분 비디오 설명(Prototypal Inheritance 주제는 5:45 부터 시작하지만 전체 비디오를 듣고 싶습니다). 이 영상의 작가는 자바스크립트 객체 시각화 웹사이트 http://www.objectplayground.com/ 도 만들었습니다. 여기에 이미지 설명 입력 여기에 이미지 설명 입력


Bad

obj_n.prop_X 가 참조될 때 "프로토타입 체인"을 재귀 규칙으로 설명하는 것이 도움이 된다는 것을 알았습니다.

obj_n.prop_X 가 존재하지 않으면 obj_n+1.prop_X 확인하십시오. 여기서 obj_n+1 = obj_n.[[prototype]]

k번째 프로토타입 객체에서 prop_X 가 마침내 발견되면

obj_1.prop_X = obj_1.[[prototype]].[[prototype]]..(k-times)..[[prototype]].prop_X

여기에서 속성별로 Javascript 객체의 관계 그래프를 찾을 수 있습니다.

js 객체 그래프

http://jsobjects.org


B M

생성자가 개체를 만들 때 해당 개체는 속성 참조를 확인하기 위해 생성자의 "프로토타입" 속성을 암시적으로 참조합니다. 생성자의 "prototype" 속성은 프로그램 표현식 constructor.prototype에 의해 참조될 수 있으며 개체의 프로토타입에 추가된 속성은 상속을 통해 프로토타입을 공유하는 모든 개체에서 공유됩니다.


Tom

여기에 설명이 필요한 두 가지 별개의 관련 엔터티가 있습니다.

  • 함수의 .prototype 속성입니다.
  • 모든 객체의 [[Prototype]] [1] 속성 [2] .

이것은 두 가지 다른 것입니다.

[[Prototype]] 속성:

이것은 모든 [2] 객체에 존재하는 속성입니다.

여기에 저장된 것은 또 다른 객체로, 객체 자체로서 다른 객체를 가리키는 자체 [[Prototype]] 그 다른 개체에는 [[Prototype]] 자체가 있습니다. .toString 와 같은)에서 액세스할 수 있는 메서드를 제공하는 프로토타입 객체에 도달할 때까지 계속됩니다.

[[Prototype]] [[Prototype]] 체인을 구성하는 부분입니다. [[Prototype]] 객체 체인은 예를 들어 객체에 대해 [[Get]] 또는 [[Set]] 작업이 수행될 때 검사되는 것입니다.

 var obj = {} obj.a // [[Get]] consults prototype chain obj.b = 20 // [[Set]] consults prototype chain

.prototype 속성:

이것은 함수에서만 볼 수 있는 속성입니다. 매우 간단한 기능 사용:

 function Bar(){};

.prototype 속성 var b = new Bar 를 수행할 때 b.[[Prototype]] 할당될 객체를 보유합니다 . 다음과 같이 쉽게 검사할 수 있습니다.

 // Both assign Bar.prototype to b1/b2[[Prototype]] var b = new Bar; // Object.getPrototypeOf grabs the objects [[Prototype]] console.log(Object.getPrototypeOf(b) === Bar.prototype) // true

.prototype 중 하나는 Object 함수 입니다. [[Prototype]] 체인이 포함하는 프로토타입 객체를 보유합니다. 여기에 새 개체에 사용할 수 있는 모든 메서드가 정의됩니다.

 // Get properties that are defined on this object console.log(Object.getOwnPropertyDescriptors(Object.prototype))

이제 .prototype 은 객체이므로 [[Prototype]] 속성이 있습니다. Function.prototype 할당하지 않으면 .prototype[[Prototype]] 은 프로토타입 객체( Object.prototype )를 가리킵니다. 이것은 새 기능을 만들 때마다 자동으로 수행됩니다.

new Bar; 를 할 때마다; 프로토타입 체인이 설정되면 Bar.prototype Object.prototype 정의된 모든 것을 얻을 수 있습니다.

 var b = new Bar; // Get all Bar.prototype properties console.log(b.__proto__ === Bar.prototype) // Get all Object.prototype properties console.log(b.__proto__.__proto__ === Object.prototype)

당신이 만드는 할당을 Function.prototype 다른 객체를 포함하는 프로토 타입 체인을 확장하고 모든 일을. 단일 연결 목록에 삽입하는 것과 같습니다.

이것은 기본적으로 [[Prototype]] Function.prototype 에 할당된 객체에 정의된 속성을 함수에 의해 생성된 모든 객체에서 볼 수 있도록 합니다.


[1: 아무도 혼동하지 않을 것입니다. 많은 구현에서 __proto__ 속성 을 통해 사용할 수 있습니다.
[2]: null 제외한 모든 것.


Dimitris Fasarakis Hilliard

프로토타입에 대한 제 이해를 말씀드리겠습니다. 여기서는 상속을 다른 언어와 비교하지 않을 것입니다. 사람들이 언어 비교를 멈추고 언어 자체를 이해하기를 바랍니다. 프로토타입과 프로토타입 상속을 이해하는 것은 매우 간단합니다. 아래에서 보여드리겠습니다.

프로토타입은 제품을 만드는 데 기반을 둔 모델과 같습니다. 이해해야 할 중요한 점은 다른 개체를 프로토타입으로 사용하여 개체를 만들 때 프로토타입과 제품 간의 연결이 영원히 지속된다는 것입니다. 예를 들어:

 var model = {x:2}; var product = Object.create(model); model.y = 5; product.y =>5

Object.getPrototypeOf() 함수로 액세스할 수 있는 [[prototype]]이라는 내부 속성이 있습니다. Object.create(model) 은 새 객체를 만들고 [[prototype]] 속성을 객체 모델로 설정 합니다. Object.getPrototypeOf(product) 를 수행 하면 객체 모델 을 얻게 됩니다.

제품의 속성은 다음과 같은 방식으로 처리됩니다.

  • 값을 읽기 위해 속성에 액세스하면 범위 체인에서 조회됩니다. 변수 검색은 제품 에서 시작하여 프로토타입까지 시작됩니다. 검색에서 이러한 변수가 발견되면 바로 검색이 중지되고 값이 반환됩니다. 범위 체인에서 이러한 변수를 찾을 수 없으면 undefined가 반환됩니다.
  • 속성이 기록(변경)되면 속성은 항상 제품 개체에 기록됩니다. 제품에 이미 그러한 속성이 없으면 암시적으로 생성되고 작성됩니다.

이러한 프로토타입 속성을 사용하여 객체를 연결하는 것을 프로토타입 상속이라고 합니다. 너무 간단합니다. 동의하십니까?


Aravind

더 나은 그림 으로 JavaScript 프로토타입 기반 상속 을 설명하려는 또 다른 시도

단순 객체 상속


rus1

keyValueStore 객체를 고려하십시오.

 var keyValueStore = (function() { var count = 0; var kvs = function() { count++; this.data = {}; this.get = function(key) { return this.data[key]; }; this.set = function(key, value) { this.data[key] = value; }; this.delete = function(key) { delete this.data[key]; }; this.getLength = function() { var l = 0; for (p in this.data) l++; return l; } }; return { // Singleton public properties 'create' : function() { return new kvs(); }, 'count' : function() { return count; } }; })();

다음을 수행하여 이 개체의 새 인스턴스를 만들 수 있습니다.

 kvs = keyValueStore.create();

이 개체의 각 인스턴스에는 다음과 같은 공용 속성이 있습니다.

  • data
  • get
  • set
  • delete
  • getLength

keyValueStore 개체의 100개 인스턴스를 생성한다고 가정합니다. get , set , delete , getLength 가 이 100개의 인스턴스 각각에 대해 정확히 동일한 작업을 수행하지만 모든 인스턴스에는 이 함수의 자체 복사본이 있습니다.

get , set , deletegetLength 복사본이 하나만 있고 각 인스턴스가 동일한 기능을 참조한다고 상상해보십시오. 이것은 성능에 더 좋고 더 적은 메모리를 필요로 합니다.

그것이 프로토타입이 필요한 곳입니다. 프로토타입은 상속되지만 인스턴스에 의해 복사되지 않는 속성의 "청사진"입니다. 따라서 이는 개체의 모든 인스턴스에 대해 메모리에 한 번만 존재하고 해당 인스턴스 모두에서 공유됨을 의미합니다.

이제 keyValueStore 객체를 다시 고려하십시오. 다음과 같이 다시 작성할 수 있습니다.

 var keyValueStore = (function() { var count = 0; var kvs = function() { count++; this.data = {}; }; kvs.prototype = { 'get' : function(key) { return this.data[key]; }, 'set' : function(key, value) { this.data[key] = value; }, 'delete' : function(key) { delete this.data[key]; }, 'getLength' : function() { var l = 0; for (p in this.data) l++; return l; } }; return { 'create' : function() { return new kvs(); }, 'count' : function() { return count; } }; })();

이것은 모든 메서드가 이제 프로토타입에 배치된다는 점을 제외하고 keyValueStore 객체의 이전 버전과 정확히 동일합니다. 이것이 의미하는 바는 100개의 모든 인스턴스가 이제 각각 고유한 복사본을 갖는 대신 이 네 가지 메서드를 공유한다는 것입니다.


John Slegers

요약:

  • 함수는 자바스크립트의 객체이므로 속성을 가질 수 있습니다.
  • (생성자) 함수에는 항상 프로토타입 속성이 있습니다.
  • new 키워드와 함께 생성자로 사용될 때 객체는 프로토타입을 얻습니다. 이 프로토타입에 대한 참조는 새로 생성된 객체 __proto__
  • __proto__ 속성은 생성자 함수 prototype

예시:

 function Person (name) { this.name = name; } let me = new Person('willem'); console.log(Person.prototype) // Person has a prototype property console.log(Person.prototype === me.__proto__) // the __proto__ property of the instance refers to prototype property of the function.

이것이 유용한 이유:

Javascript에는 '프로토타입 상속' 이라고 하는 객체의 속성을 조회할 때 기본적으로 수행되는 작업이 있습니다.

  • 먼저 속성이 개체 자체에 있는지 확인합니다. 그렇다면 이 속성이 반환됩니다.
  • 속성이 개체 자체에 없으면 '프로토체인 위로 올라갑니다'. 기본적으로 proto 속성이 참조하는 객체를 살펴봅니다. 거기에서 proto가 참조하는 객체에서 속성을 사용할 수 있는지 확인합니다.
  • 속성이 proto 개체에 없으면 개체 개체까지 프로토 체인을 올라갑니다.
  • 객체와 프로토타입 체인에서 속성을 찾을 수 없으면 정의되지 않은 값을 반환합니다.

예를 들어:

 function Person(name) { this.name = name; } let mySelf = new Person('Willem'); console.log(mySelf.__proto__ === Person.prototype); console.log(mySelf.__proto__.__proto__ === Object.prototype);

업데이트:

__proto__ 속성은 더 이상 사용되지 않지만 대부분의 최신 브라우저에서 구현되지만 프로토타입 개체 참조를 얻는 더 좋은 방법은 다음과 같습니다.

Object.getPrototypeOf()


Willem van der Veen

나는 항상 이런 종류의 것들을 이해할 때 비유를 좋아합니다. 프로토타입이 훨씬 단순한 패러다임임에도 불구하고 '프로토타입 상속'은 클래스 베이스 상속에 비해 상당히 혼란스럽습니다. 실제로 프로토타입에는 상속이 없으므로 이름 자체가 오해의 소지가 있으므로 일종의 '위임'에 가깝습니다.

이것을 상상해보십시오 ....

당신은 고등학생이고 수업 중이고 오늘 마감인 퀴즈가 있지만 답을 채울 펜이 없습니다. 도!

당신은 펜을 가지고 있을지도 모르는 친구 Finnius 옆에 앉아 있습니다. 당신이 물었고 그는 성공하지 못하고 책상을 둘러봅니다. 그러나 그는 "나는 펜이 없어요"라고 말하는 대신에 다른 친구인 Derp에게 펜이 있는지 확인하는 좋은 친구입니다. Derp는 실제로 여분의 펜을 가지고 있으며 Finnius에게 다시 전달하면 Finnius는 퀴즈를 완료하기 위해 그것을 전달합니다. Derp는 펜을 사용하도록 위임한 Finnius에게 펜을 위임했습니다.

여기서 중요한 것은 Derp와 직접적인 관계 가 없기 때문에 Derp가 펜을 주지 않는다는 것입니다.

이것은 데이터 트리에서 찾고 있는 것을 검색하는 프로토타입 작동 방식의 간단한 예입니다.


Louis Moore

__proto__ , 프로토타입생성자 관계를 보여주는 또 다른 체계: 여기에 이미지 설명 입력


IvanM

Object.new 가 포함된 객체가 이미 있지만 생성자 구문을 사용할 때 객체가 없다는 것입니다.


shiva kumar

Object.getPrototypeOf(obj) 또는 더 이상 사용되지 않는 __proto__ 속성을 통해 사용 가능)과 생성자 함수 prototype 속성 사이에는 차이가 있음을 이해하는 것이 중요합니다. 전자는 각 인스턴스의 속성이고 후자는 생성자의 속성입니다. 즉, Object.getPrototypeOf(new Foobar()) Foobar.prototype 과 동일한 객체를 참조합니다.

참조: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes


Baraa Al-Tabbaa

Prototype기존 객체 를 복제하여 새로운 객체를 생성합니다 . 그래서 실제로 프로토타입에 대해 생각할 때 무언가를 만드는 대신 복제하거나 복사하는 것을 생각할 수 있습니다.


Arif

프로토타입 및 프로토타입 기반 상속의 개념을 기본부터 이해하고 싶다면 공식 MDN 문서를 확인하십시오. 잘 설명되어 있습니다.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

상속과 관련하여 JavaScript에는 객체라는 하나의 구조만 있습니다. 각 객체에는 프로토타입이라는 다른 객체에 대한 링크를 보유하는 개인 속성이 있습니다. 그 프로토타입 객체에는 자체 프로토타입이 있으며, 프로토타입이 null인 객체에 도달할 때까지 계속됩니다. 정의에 따라 null에는 프로토타입이 없으며 이 프로토타입 체인의 최종 링크 역할을 합니다.

또한 간단한 예제를 사용하여 설명하는 또 다른 좋은 리소스가 있습니다. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes


kabirbaidhya

출처 : http:www.stackoverflow.com/questions/572897/how-does-javascript-prototype-work

반응형