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

나는 동적 프로그래밍 언어로는 아니지만 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

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



답변

모든 자바 스크립트 객체는 내부 “슬롯”이 라고 [[Prototype]]그 값 중 하나 null또는를 object. 슬롯은 JavaScript 코드 내부에있는 객체의 속성으로 작성하는 코드에서 숨겨져 있다고 생각할 수 있습니다. 주위의 대괄호 [[Prototype]]는 의도적이며 내부 슬롯을 나타내는 ECMAScript 사양 규칙입니다.

[[Prototype]]객체가 가리키는 값을 구어체 적으로 “해당 객체의 프로토 타입”이라고합니다.

점 ( obj.propName) 또는 괄호 ( obj['propName']) 표기법을 통해 속성에 액세스 하고 객체에 이러한 속성이없는 경우 (예 :을 통해 확인할 수 있는 자체 속성obj.hasOwnProperty('propName') ) 런타임은 참조 된 객체에서 해당 이름의 속성을 찾습니다. 바이 [[Prototype]]대신. (가) 경우 [[Prototype]] 같은 속성이 없습니다, 그것은 [[Prototype]]다시 확인 등이다. 이런 식으로, 원본 객체의 프로토 타입 체인 은 일치하는 것이 발견되거나 그 끝에 도달 할 때까지 진행됩니다. 프로토 타입 체인의 최상위에는 null가치가 있습니다.

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

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

Object.getPrototypeOf그리고 Object.setPrototypeOf보다 선호하는 __proto__의 행동 때문에 부분적으로 o.__proto__ 드문 객체의 프로토 타입이있는 경우 null.

객체 [[Prototype]]는 초기에 객체 생성 중에 설정됩니다.

를 통해 새 객체를 만들면 기본적으로 new Func()객체의 [[Prototype]]의지는로 참조되는 객체로 설정됩니다 Func.prototype.

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

new생성자 함수와 함께 사용하면 JavaScript에서 클래식 상속을 시뮬레이션 할 수 있습니다. 우리가 본 것처럼 JavaScript의 상속 시스템은 프로토 타입이며 클래스 기반이 아닙니다.

JavaScript에 클래스 구문을 도입하기 전에 생성자 함수는 클래스를 시뮬레이션하는 유일한 방법이었습니다. 생성자 함수의 .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에 도입 된 클래스 구문 extends은 JavaScript에서 고전적인 상속을 시뮬레이션하기 위해 프로토 타입 체인을 구성하는 “한 가지 진정한 방법” 으로 제공함으로써 사물을 단순화 합니다.

따라서 클래스 구문을 사용하여 다음과 같이 새 객체를 만드는 경우 위의 코드와 유사합니다.

class Parent { inheritedMethod() { return 'this is inherited' } }
class Child extends Parent {}

const o = new Child
console.log(o.inheritedMethod()) // 'this is inherited'

… 결과 개체의이 [[Prototype]]인스턴스로 설정됩니다 Parent, 누구의 [[Prototype]]차례입니다 Parent.prototype.

마지막으로를 통해 새 객체를 만들면 Object.create(foo)결과 객체 [[Prototype]]가로 설정됩니다 foo.


답변

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());

내가 말했듯이 Person에서 setAmountDue (), getAmountDue ()를 호출 할 수는 없습니다.

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


답변

설명없이 샘플로 간주되는 매우 간단한 프로토 타입 기반 객체 모델입니다.

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

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

1- JavaScript 함수의 실제 작동 방식 :

첫 번째 단계를 수행하려면 JavaScript 함수가 실제로 어떻게 작동하는지, this키워드 를 키워드로 사용하는 함수와 같은 클래스 또는 인수가있는 일반 함수, 수행하는 작업 및 반환되는 작업으로 파악해야합니다.

Person객체 모델 을 만들고 싶다고 가정 해 봅시다 . 그러나이 단계 에서는 prototypeand newkeyword 를 사용하지 않고 동일한 작업수행 하려고 합니다 .

그래서이 단계에서 functions, objects그리고 this키워드, 우리 모두입니다.

첫 번째 질문이 될 것이다 어떻게 this키워드를 사용하지 않고 유용 할 수 있습니다 new키워드를 .

그래서 대답하기 위해 빈 객체가 있고 두 가지 기능이 있다고 가정 해 봅시다.

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

function getName(){
    console.log(this.name);
}

지금은 사용하지 않고 new키워드를 우리는 이러한 기능을 사용할 수있는 방법에 대해 설명합니다. 따라서 JavaScript에는 3 가지 방법이 있습니다.

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

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

이 경우 이는 현재 컨텍스트 객체이며 일반적으로 window브라우저 또는 의 전역 객체 GLOBAL입니다 Node.js. “George”를 값으로 사용하여 브라우저의 window.name 또는 Node.js의 GLOBAL.name을 갖습니다.

비. 속성으로 객체에 첨부 할 수 있습니다

가장 쉬운 방법 은 다음 person과 같이 빈 개체를 수정하는 것입니다.

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

이런 식으로 우리는 다음과 같이 호출 할 수 있습니다.

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

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

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

속성 을 객체 에 첨부하는 다른 방법prototype 은 이름이 __proto__인 JavaScript 객체에서 찾을 수있는 객체를 사용 하는 것입니다. 요약 부분에서 조금 설명하려고했습니다. 따라서 다음을 수행하여 비슷한 결과를 얻을 수 있습니다.

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

그러나 여기서 까다로운 점 __proto__person객체 의 첫 번째 수준에 정의 된 모든 속성에 액세스 할 수 있다는 것입니다 (자세한 내용은 요약 부분을 읽으십시오).


이 두 가지 방법 중 하나를 사용 this하면 person객체 를 정확하게 가리킬 수 있습니다.

씨. JavaScript에는 함수를 제공하는 또 다른 방법이 있습니다.이 함수 this호출 또는 적용 을 사용 하여 함수를 호출합니다.

apply () 메소드는 주어진이 값과 배열 (또는 배열과 같은 객체)로 제공된 인수로 함수를 호출합니다.

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 기능을 파악하기위한 중요한 초기 단계입니다.


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

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

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

이 부분에서는 new키워드 prototype를 사용할 때 키워드 를 사용하지 않고 JavaScript가 취하는 모든 단계를 수행하려고 new합니다. 그래서 우리가 할 때 new Person("George"), Person함수는 생성자 역할을합니다. 이것은 JavaScript가 하나씩하는 것입니다.

ㅏ. 우선 빈 객체, 기본적으로 빈 해시를 만듭니다.

var newObject = {};

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

우리가 my_person_prototype여기에 프로토 타입 객체에 대한 유사.

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

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


ㅏ. & b. 이 두 단계 대신 다음을 수행하여 동일한 결과를 얻을 수 있습니다.

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"

이제 우리는 getName함수를 호출 할 수 있습니다 my_person_prototype:

newObject.getName();

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

우리는 다음과 같은 샘플로 이것을 할 수 있습니다 :

Person.call(newObject, "George");

또는

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

다음 생성자가 있기 때문에, 원하는 무엇이든 할 수있는 그 생성자의 내부 방금 생성 된 개체입니다.

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


요약:

기본적으로 함수 에서 new 키워드 를 사용하면 해당 키워드를 호출하고 해당 함수가 생성자로 사용되므로 다음과 같이 말할 때 :

new FunctionName()

자바 스크립트는 내부적으로 객체, 빈 해시를 만든 다음이 생성자에 그 객체를 제공하고 생성자가 있기 때문에, 원하는 무엇이든 할 수있는 그 생성자의 내부 방금 생성 된 개체이며, 그것은 당신에게 물론 그 객체를 제공합니다 함수에서 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에서 상속이 작동하는 방식입니다.

프로토 타입 체인

즉, 함수에 프로토 타입 속성이 있고 새로 호출하면 JavaScript가 새로 작성된 속성에 대한 객체를 찾은 후 함수를 살펴보고이 .prototype객체에 해당 객체가있을 수 있습니다. 자체 내부 프로토 타입. 등등.


답변

프로토 타입의 7 개 Koans

깊은 명상 후 시로 산이 파이어 폭스 산으로 내려 갔을 때 그의 마음은 깨끗하고 평화로웠다.

그러나 그의 손은 불안했고, 그 자체로 붓을 잡고 다음 음표를 적어 두었다.


0) 두 가지 다른 것을 “시제품”이라고 부를 수 있습니다.

  • 와 같은 프로토 타입 속성 obj.prototype

  • 원형 내부 속성으로 표시 [[Prototype]] ES5에서 .

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

    Firefox는 __proto__속성을 통해 확장 기능으로 액세스 할 수 있습니다 . ES6는 이제에 대한 선택적 요구 사항을 언급 합니다 __proto__.


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

내가 할 때 obj.propertyJS는 어디를 찾는가 .property?

직관적 인 고전 상속은 속성 조회에 영향을 미칩니다.


2)

  • __proto__.에서와 같이 도트 속성 조회에 사용됩니다 obj.property.
  • .prototype를 사용 하여 객체를 생성 할 때 간접적으로 만 직접 조회하는 데 사용 되지 않습니다 .__proto__new

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

  • objobj.p = ...또는로 추가 된 속성Object.defineProperty(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  |             v                v | v                                |
(Function.prototype)              (F.prototype)                         |
 |                                 |                                    |
 |                                 |                                    |
 |[[Prototype]]                    |[[Prototype]]          [[Prototype]]|
 |                                 |                                    |
 |                                 |                                    |
 | +-------------------------------+                                    |
 | |                                                                    |
 v v                                                                    v
(Object.prototype)                                       (Number.prototype)
 | | ^
 | | |
 | | +---------------------------+
 | |                             |
 | +--------------+              |
 |                |              |
 |                |              |
 |[[Prototype]]   |constructor   |prototype
 |                |              |
 |                |              |
 |                | -------------+
 |                | |
 v                v |
(null)           (Object)

이 다이어그램은 많은 언어 사전 정의 된 오브젝트 노드를 보여줍니다.

  • null
  • Object
  • Object.prototype
  • Function
  • Function.prototype
  • 1
  • Number.prototype( (1).__proto__구문을 만족시키기 위해 필수 인 괄호 로 찾을 수 있음 )

우리의 두 줄의 코드는 다음과 같은 새로운 객체 만 만들었습니다.

  • f
  • F
  • F.prototype

if당신이 할 때 의 속성입니다 :

var f = new F(1)

이 평가 Fthis가치있는 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.constructorJavaScript는 다음 .과 같이 조회를 수행합니다.

  • f 이 없습니다 .constructor
  • f.__proto__ === F.prototype가지고 .constructor === F, 가지고

클래식 OOP 언어와 매우 유사한 방식으로 필드 설정 등 을 구성하는 데 사용 f.constructor == F되므로 결과 는 직관적으로 정확 합니다.Ff


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

ES6는 이전에 가능한 프로토 타입 조작 광기를위한 구문 설탕 인 classand 및 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
C.c = 1
C.c === 1
// Because `D.__proto__ === C`.
D.c === 1
// Nothing makes this work.
d.c === undefined

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

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

다음이 어떻게 작동하는지 연구 해 봅시다.

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

첫번째 라인 세트 c.i1 “4)”에 설명 된대로 .

두 번째 줄에서, 우리가 할 때 :

c.inc()
  • .inc[[Prototype]]체인을 통해 발견됩니다 : c-> C-> C.prototype->inc
  • Javascript로 함수를 호출하면 X.Y()JavaScript 가 함수 호출 내에서 자동으로 this동일하게 설정 됩니다 !XY()

똑같은 논리도 설명 d.inc하고d.inc2 있습니다.

이 기사 https://javascript.info/class#not-just-a-syntax-sugarclass알 가치가있는 추가 효과를 언급합니다 . 일부 class키워드 는 키워드 가 없으면 달성 할 수 없습니다 (TODO check which).


답변

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 기능이 있습니다.

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


답변

이 글을 읽은 후 JavaScript Prototype Chain과 혼동 된 느낌이 들었습니다.

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

프로토 타입 체인 별 JavaScript 상속을 표시하는 명확한 차트입니다

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

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

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

서브 클래스의 프로토 타입을 상위 클래스의 오브젝트와 동일하게 설정하여 매번 프로토 타입 체인을 기술적으로 확장 할 수 있습니다.

JavaScript 프로토 타입 체인을 이해하는 데 도움이되기를 바랍니다.


답변

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

object [[Prototype]]  anotherObject

전통적인 자바 스크립트에서 링크 된 객체는 prototype함수 의 속성입니다 :

object [[Prototype]]  aFunction.prototype

일부 환경은 [[프로토 타입]]__proto__다음 과 같이 노출합니다 .

anObject.__proto__ === anotherObject

당신은 만들 [[프로토 타입]] 객체를 생성 링크를.

// (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 로 사용되지 않으면 속성이 사용되지 않습니다.
  • 생성자가 필요하지 않으면 대신 Object.create 를 사용 하십시오new .