dynamic-languages 사용 - JavaScript.prototype은 어떻게 작동합니까?




이유 차이 (20)

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

프로토 타입은 모델을 기반으로합니다. 모델을 기반으로 제품을 만듭니다. 이해해야 할 중요한 점은 다른 객체를 프로토 타입으로 사용하여 객체를 만들면 프로토 타입과 제품 간의 연결이 끊임없이 지속된다는 것입니다. 예를 들면 :

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가 반환됩니다.
  • 특성이 쓰여지면 (변경된 경우), 특성은 항상 제품 오브젝트 에 기록됩니다 . 는 IF 제품은 이미 그러한 속성이 없습니다, 그것은 내재적으로 작성하고 작성된 것입니다.

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

또한이 slides 실제로 많은 도움이되었습니다.


여기에는 뚜렷하지만 관련이있는 엔티티가 두 가지 있습니다.

  • .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속성 에는b.[[Prototype]]때 지정할 객체 가 들어 있습니다 var b = new Bar. 이것을 쉽게 검사 할 수 있습니다 :

// 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 . 이 프로토 타입은 모든 [[Prototype]]체인에 포함 된 프로토 타입 객체를 보유 합니다. 그 위에 새로운 객체에 대해 사용 가능한 모든 메소드가 정의됩니다.

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

이제는 .prototype객체이기 때문에 [[Prototype]]속성이 있습니다. 당신은 어떤 지정하지 않을 경우 Function.prototype1, .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.


이 기사는 길다. 그러나 JavaScript 상속의 "프로토 타입"성격에 관한 대부분의 쿼리를 삭제할 것이라고 확신합니다. 그리고 훨씬 더. 전체 기사를 읽으십시오.

JavaScript는 기본적으로 두 가지 종류의 데이터 유형

  • 비 객체
  • 사물

비 객체

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

  • 숫자 (NaN 및 Infinity 포함)
  • 부울 값 (true, false)
  • 정의되지 않은

typeof 연산자를 사용하면 이러한 데이터 형식이 다음과 같이 반환됩니다.

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

typeof 5 (또는 숫자 리터럴 또는 숫자 리터럴 또는 NaN 또는 Infynity가 포함 된 변수) === 'number'

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

typeof undefined (또는 정의되지 않은 변수 또는 정의되지 않은 변수) === 'undefined'

문자열 , 숫자부울 데이터 유형은 객체비 객체 로 나타낼 수 있습니다. 객체 로 표시 될 때 typeof는 항상 === '객체'입니다. 우리가 객체 데이터 유형을 이해하면 우리는 이것을 다시 볼 것입니다.

사물

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

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

기능 유형의 객체는 문자열을 반환 그들이다 '기능을'대한 typeof 연산자. 모든 사용자 정의 함수와 new 연산자를 사용하여 새 객체를 만들 수있는 모든 JavaScript 내장 객체가이 범주에 속합니다. 예를 들면.

  • 목적
  • 번호
  • 부울
  • 정렬
  • 형식화 된 배열
  • RegExp
  • 기능
  • 다른 모든 개체는 new 연산자를 사용하여 새 개체를 만들 수 있습니다.
  • function UserDefinedFunction () {/ * 사용자 정의 코드 * /}

그래서 대해서 typeof (객체) === 대해서 typeof (문자열) === 대해서 typeof (수) === 대해서 typeof (부울) === 대해서 typeof (배열) === 대해서 typeof (정규식) === 대해서 typeof (기능) == = typeof (UserDefinedFunction) === 'function'

모든 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")

앞서 언급했듯이 함수 유형 객체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 type 객체 이며 typeof === 'object'를 반환합니다 . 이 모든 경우에 객체 "a"는 new 연산자를 사용하여 객체를 더 이상 만들 수 없습니다. 그래서 다음은 잘못되었습니다.

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

내장 오브젝트 수학typeof === 'object' 입니다. 따라서 수학 연산자 유형의 새 객체는 새 연산자로 만들 수 없습니다.

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.

함수 유형 객체 는 새로운 객체를 생성 할 수 있기 때문에 생성자 라고도 합니다.

모든 생성자 / 함수 (빌트인 또는 사용자 정의)는 자동으로 정의 될 때 "prototype" 이라는 속성을 가지며,이 속성은 기본적으로 객체로 설정됩니다. 이 객체 자체에는 기본적으로 생성자 / 함수를 다시 참조하는 "생성자" 라는 속성이 있습니다.

예를 들어 함수를 정의 할 때

function UserDefinedFunction()
{
}

다음과 같이 자동으로 발생합니다.

UserDefinedFunction.prototype={constructor:UserDefinedFunction}

"프로토 타입"속성Function 유형 객체 에만 존재 합니다 (그리고 Non Function 유형 객체 에는 절대로 존재 하지 않습니다 ).

이것은 new 연산자를 사용하여 새 객체가 생성 될 때 Constructor 함수의 현재 프로토 타입 객체에서 모든 속성과 메서드를 상속 받기 때문에 내부 참조 가 생성자 함수의 현재 프로토 타입 객체에서 참조하는 객체를 참조하는 새로 만든 객체에 만들어 지기 때문 입니다.

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

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

모든 함수 유형 객체에 대해 생성자 함수는 항상 function입니다. Function () {}

들어 비 기능 형 객체 (Math 객체 내장 예를 들어 자바 스크립트) 생성자 함수를 생성하는 기능입니다. 를 들어 수학 객체 그것이 기능 개체 () {} .

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

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
  • 단순 객체 (새 Object () 또는 Math 객체가 내장 된 {}로 작성됨) -> Object.prototype -> null
  • new 또는 Object.create -> One 또는 More 프로토 타입 체인으로 작성된 오브젝트 -> Object.prototype -> null

프로토 타입을 사용하지 않고 객체를 만들려면 다음을 사용하십시오.

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

Constructor의 프로토 타입 속성을 null로 설정하면 null 프로토 타입이있는 객체가 만들어집니다. 그러나 새로 생성 된 객체의 프로토 타입은 Object.prototype으로 설정되고 생성자는 Object로 설정됩니다. 이것은 다음 코드에 의해 증명됩니다.

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 유형 객체입니다. 비 함수 타입 오브젝트는 상기 오브젝트를 생성 할 수없는 새로운 오퍼레이터 .

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

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

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

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

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

  • typeof (new Array ()) === 'object'Douglas Crockford가 지적한 실수가 아니라 언어의 디자인입니다

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

희망이 도움이됩니다.


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 함수를 가지고 있습니다.

위 내용은 내 이해입니다. 나는 그것을 공동체 위키로 만들고있어 사람들이 틀렸다면 나를 바로 잡을 수있다.


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


저는 JavaScript 선생님으로서의 역할을하고 있습니다. 프로토 타입 개념은 항상 가르 칠 때 다루어야 할 논란의 주제였습니다. 개념을 명확하게하는 데 좋은 방법을 생각해 내는데 시간이 걸렸습니다. 이제이 텍스트에서 JavaScript의 .prototype 작동 방식을 설명하려고합니다.

이것은 매우 간단한 프로토 타입 기반의 객체 모델입니다. 설명하는 동안 샘플로 간주되며 주석이 없습니다.

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

프로토 타입 개념을 검토하기 전에 고려해야 할 몇 가지 중요한 포인트가 있습니다.

1- JavaScript 함수가 실제로 작동하는 방식 :

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

우리가 Person 객체 모델을 만들고 싶다고합시다. 하지만이 단계 에서는 prototypenew 키워드를 사용하지 않고 똑같은 작업수행 하려고 합니다 .

그래서이 단계에서 functions , objectsthis 키워드가 모두 있습니다.

첫 번째 질문은 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 객체이거나 Node.js GLOBAL 입니다. 우리가 브라우저에서 window.name을, Node.js에서 GLOBAL.name을, 그 값으로 "George"를 가질 것임을 의미합니다.

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

가장 쉬운 방법 은 다음과 같이 빈 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 기반으로 만들어지기 때문에 새로 작성된 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는 함수를 호출하기 위해 call 이나 apply 를 사용하는 함수를 제공하는 또 다른 방법을 가지고있다.

apply () 메소드는이 값과 인자 (array-like 객체)를 인자로 가지는 함수를 호출한다.

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 키워드를 사용할 때 new 키워드와 prototype 을 사용하지 않고 JavaScript가 취하는 모든 단계를 수행하려고합니다. 그래서 new Person("George") 할 때, Person 함수는 생성자 역할을합니다. 이것들은 JavaScript가하는 것입니다.

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

var newObject = {};

비. 자바 스크립트가 취하는 다음 단계는 모든 프로토 타입 객체를 새로 생성 된 객체에 첨부 하는 것입니다

우리는 프로토 타입 객체와 비슷한 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"

이제 my_person_prototype 에서 getName 함수를 호출 할 수 있습니다.

newObject.getName();

기음. 그 객체를 생성자에게 준다.

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

Person.call(newObject, "George");

또는

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

생성자의 내부가 방금 생성 된 객체이기 때문에 생성자는 원하는 모든 작업을 수행 할 수 있습니다.

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

개요:

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

new FunctionName()

JavaScript는 내부적으로 객체, 빈 해시를 생성 한 다음 해당 객체를 생성자에게 제공합니다. 생성자는 방금 생성 한 객체이므로 생성자가 원하는대로 수행 할 수 있습니다. 그런 다음 해당 객체를 물론 제공합니다. 함수에서 return 문을 사용하지 않았거나 return undefined; 기능 본문의 끝에서

따라서 JavaScript가 객체의 속성을 검색 할 때 가장 먼저 객체에서 그 객체를 찾습니다. 그리고 우리는 일반적으로 __proto__ 와 같은 비밀 속성 [[prototype]] 을 가지고 있으며 그 속성은 JavaScript가 다음에 보게되는 속성입니다. 그리고 __proto__ 살펴볼 때 또 다른 JavaScript 객체 인 한 자체 __proto__ 속성이 있습니다. 다음 __proto__ 이 null 인 지점까지 가져옵니다. 요점은 __proto__ 속성이 null 인 Object.prototype 객체입니다.

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

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

즉, 함수에 프로토 타입 속성이 있고 새 속성을 호출하면 JavaScript가 속성에 대해 새로 만든 개체를 살펴본 후에 함수의 .prototype 살펴 .prototype 개체가 자체 프로토 타입을 가지고 있습니다. 등등.


개요:

  • 함수는 자바 스크립트의 객체이므로 속성을 가질 수 있습니다.
  • (Constructor) 함수는 항상 프로토 타입 속성을가집니다.
  • 함수가 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에는 'prototypal inheritance' 라고하는 객체의 속성을 찾을 때 메커니즘 이 있습니다. 기본적으로 다음과 같습니다.

  • 프로퍼티가 Object 자체에 있으면 먼저 확인합니다. 그렇다면이 속성이 반환됩니다.
  • 프로퍼티가 객체 자체에 있지 않으면 protochain을 올라갈 것입니다. 기본적으로 proto 속성 에 의해 참조되는 객체를 봅니다 . 거기에서 proto가 참조한 객체에서 속성을 사용할 수 있는지 확인합니다.
  • 속성이 proto 객체 에 없으면 proto 체인까지 Object 객체까지 올라갈 것입니다 .
  • 객체와 프로토 타입 체인에서 아무 것도 찾을 수없는 경우 undefined를 반환합니다.

예 :

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

let mySelf = new Person('Willem');

console.log(mySelf.__proto__ === Person.prototype);

console.log(mySelf.__proto__.__proto__ === Object.prototype);


이 스레드를 읽고 나면 JavaScript Prototype Chain과 혼동을 느낀 다음이 차트를 발견했습니다.

http://iwiki.readthedocs.org/en/latest/javascript/js_core.html#inheritance

Prototype Chain에 의한 JavaScript Inheritance를 보여주는 명확한 차트입니다.

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

여기에는 코드와 몇 가지 멋진 다이어그램이 들어 있습니다.

프로토 타입 체인은 궁극적으로 Object.prototype으로 떨어진다.

프로토 타입 체인은 서브 클래스의 프로토 타입을 부모 클래스의 객체와 동일하게 설정할 때마다 원하는만큼 기술적으로 확장 될 수 있습니다.

JavaScript Prototype Chain을 이해하면 도움이되기를 바랍니다.



프로토 타입의 7 Koans

치로 산 (Chero San)이 깊은 명상을 한 후 마운트 파이어 폭스 (Mount Fire Fox)를 강타함에 따라 그의 마음은 분명하고 평화로웠다.

그의 손은 그러나, 불안하지 않았고, 그 자체로 붓을 움켜 잡고 다음의 메모를 적어 두었습니다.

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

  • obj.prototype 의 prototype 프로퍼티

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

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

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

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

obj.property 할 때 JS가 .property 찾는 위치는 어디입니까?

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

2)

  • __proto__ 는 점에 사용됩니다 . obj.property 에서와 같은 속성 조회.
  • .prototypenew 객체 생성시 __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() {}
var f = new F()

다음 다이어그램에 해당합니다.

(Function)       (  F  )                                      (f)
 |  ^             | | ^                                        |
 |  |             | | |                                        |
 |  |             | | +-------------------------+              |
 |  |constructor  | |                           |              |
 |  |             | +--------------+            |              |
 |  |             |                |            |              |
 |  |             |                |            |              |
 |[[Prototype]]   |[[Prototype]]   |prototype   |constructor   |[[Prototype]]
 |  |             |                |            |              |
 |  |             |                |            |              |
 |  |             |                | +----------+              |
 |  |             |                | |                         |
 |  |             |                | | +-----------------------+
 |  |             |                | | |
 v  |             v                v | v
(Function.prototype)              (F.prototype)
 |                                 |
 |                                 |
 |[[Prototype]]                    |[[Prototype]]
 |                                 |
 |                                 |
 | +-------------------------------+
 | |
 v v
(Object.prototype)
 | | ^
 | | |
 | | +---------------------------+
 | |                             |
 | +--------------+              |
 |                |              |
 |                |              |
 |[[Prototype]]   |constructor   |prototype
 |                |              |
 |                |              |
 |                | -------------+
 |                | |
 v                v |
(null)           (Object)

이 다이어그램은 많은 언어 사전 정의 된 객체 노드를 보여줍니다 : null , Object , Object.prototype , FunctionFunction.prototype . 우리의 2 줄의 코드는 f , FF.prototype 만 만들었습니다.

5) F.prototype 는 일반적으로 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 에는 .constructor 가 없습니다 .constructor
  • f.__proto__ === F.prototype 에는 f.__proto__ === F.prototype .constructor === F 가 있으므로 가져 가십시오.

f.constructor == F 는 직관적으로 정확합니다. 왜냐하면 F 는 고전적인 OOP 언어와 마찬가지로 f 를 구성하는 데 사용됩니다 (예 : 필드 설정).

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

ES6는 이전에 가능한 프로토 타입 조작 광기에 대한 단순한 구문 설탕 인 classextends 키워드를 추가합니다.

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.
(new C(1)).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://.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

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

      __proto__
(C)<---------------(D)         (d)
| |                |           |
| |                |           |
| |prototype       |prototype  |__proto__
| |                |           |
| |                |           |
| |                | +---------+
| |                | |
| |                | |
| |                v v
|__proto__        (D.prototype)
| |                |
| |                |
| |                |__proto__
| |                |
| |                |
| | +--------------+
| | |
| | |
| v v
| (C.prototype)--->(inc)
|
v
Function.prototype

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

에있는 new연산자를 사용하면 Tree function이를 constructor함수 라고 부릅니다 .

모든 JavaScript기능에는 a가 prototype있습니다. 당신이 로그하면 Tree.prototype, 당신은 ...

위의 console.log()결과 를 살펴보면 생성자 속성 Tree.prototype__proto__속성도 볼 수 있습니다. 는 __proto__표현 prototype이이 것을 function기반으로하며, 이것은 단지 일반이기 때문에 JavaScript function결코로 inheritance아직 설정, 그것은을 의미 Object prototype하는 단지 자바 스크립트에 내장 뭔가 ...

Object.prototype

이것은 .toString, .toValue, .hasOwnProperty등 같은 것들을 가지고 ...

__proto__내 모질라를 가져온 것은 더 이상 사용되지 않으며 Object.getPrototypeOf를 얻는 방법으로 대체됩니다 object's prototype.

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

우리에게 방법을 추가합시다 Tree prototype.

우리는 the를 수정하고 그것에 branch를 Root추가 function했다.

즉 당신이 만들 때 의미 instance의이 Tree, 당신은 그것의 호출 할 수있는 branch방법.

우리는 또한 추가 할 수 있습니다 primitives또는 objects우리를에 Prototype.

우리에게 a child-tree를 추가합시다 Tree.

여기 에서 Tree를 Child상속받습니다. prototype우리가 여기서 Object.create()하는 일은 당신이 통과 한 것을 기반으로 새로운 객체를 만드는 메소드를 사용하는 것입니다 Tree.prototype. 여기 있습니다 . 이 경우 우리는 Child의 Tree프로토 타입을 프로토 타입 과 동일한 새로운 객체로 설정합니다 . 다음으로 우리는 Child's constructor to Child그것을 설정 하지 않을 경우 가리킬 것 Tree()입니다.

Child지금은 그것의 자신 prototype__proto__포인트 TreeTree's prototype포인트를 가리킨다 Object.

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

이제 원래 사용할 수 있는 instanceof Child및 call branch을 만듭니다 Tree. 우리는 실제로 우리 branch를 정의하지 않았습니다 Child prototype. 그러나 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.

  • Javascriptdelegation기반한 상속을 지원합니다 prototypes.
  • 각각 Function에는 prototype다른 객체를 참조 하는 속성이 있습니다.
  • properties/functions존재하지 않는다면 object자체 또는 prototype체인을 통해 보입니다.

prototypeJS의 A yields는 다른 부모의 부모에게 객체입니다 object. [즉, 대표단] Delegation 은 당신이 무언가를 할 수 없다면, 다른 사람들에게 당신을 위해 그것을하도록 말할 것입니다.

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

위의 바이올린을 살펴보면 개는 toString메소드에 액세스 할 수 있지만 해당 메소드에는 사용할 수 없지만에 위임 한 프로토 타입 체인을 통해 사용할 수 있습니다.Object.prototype

아래 내용을 보면, 우리는 call매번 사용할 수 있는 방법 에 접근하려고 노력하고 있습니다 function.

https://jsfiddle.net/rknffckc/

위의 바이올린을 살펴보면 ProfileFunction은 call메소드에 액세스 할 수 있지만 메소드에는 사용할 수 없지만에 위임 한 프로토 타입 체인을 통해 사용할 수 있습니다.Function.prototype

참고 : prototype 함수 생성자의 속성이며, 반면에 함수 생성자에서 __proto__생성 된 개체의 속성입니다. 모든 함수에는 prototype값이 비어 있는 속성이 object있습니다. 우리가 함수의 인스턴스를 생성 할 때 우리는 내부 속성을 얻 [[Prototype]]거나 __proto__참조가 Function의 프로토 타입이된다 constructor.

위의 다이어그램은 약간 복잡해 보입니다. 그러나 어떻게 prototype chaining작동 하는지 전체적인 그림을 보여줍니다 . 이것을 천천히 걷자.

두 가지 예이다 b1b2그 생성자, Bar부모 푸이며 프로토 체인으로부터의 두 가지 방법이 있습니다 identifyspeak비아 BarFoo

https://jsfiddle.net/kbp7jr7n/

위의 코드를 살펴보면 Foo메서드가있는 생성자 identify()와 메서드가있는 Bar생성자가 있습니다 speak. 우리는이 생성 Barb1b2그 부모 유형입니다 Foo. 이제 speakof의 메소드 를 호출 하는 동안 체인을 Bar통해 말하는 사람을 식별 할 수 prototype있습니다.

Bar이제는 Foo그 안에 정의 된 모든 메소드가 prototype있습니다. 의이 이해를 더 살펴 보겠습니다 Object.prototypeFunction.prototype어떻게 그들이 관련이 있습니다. 당신이의 생성자를 찾으면 Foo, Bar그리고 Object있습니다 Function constructor.

prototypeBarIS Foo, prototypeFooIS Object그리고 만약 당신이 밀접하게 볼 prototypeFoo관련이있다 Object.prototype.

이것을 끝내기 전에 위의 모든 내용요약 하기 위해 여기에 작은 코드 조각으로 마무리하겠습니다 . 우리는 instanceof여기에 연산자 를 사용하여 체인에 다음 중 큰 다이어그램을 요약하는 속성 object이 있는지 확인합니다 .prototypeprototypeconstructor

나는이 add의 정보가 있기를 바란다. 나는 이걸 좀더 이해할 수있을 거라는 것을 알고있다. 간단한 말로 그것은 단지 객체와 연결된 객체이다.


Javascript에는 상속이 없지만 프로토 타입 체인이 있습니다.

프로토 타입 체인

객체의 멤버가 객체에서 발견되지 않으면 프로토 타입 체인에서 객체의 멤버를 찾습니다. 체인은 다른 객체로 구성됩니다. 지정된 인스턴스의 프로토 타입은 __proto__ 변수를 사용하여 액세스 할 수 있습니다. 자바 스크립트에서 클래스와 인스턴스간에 차이가 없기 때문에 모든 객체에는 하나가 있습니다.

프로토 타입에 함수 / 변수를 추가하면 모든 인스턴스가 아닌 한 번만 메모리에 있어야한다는 이점이 있습니다.

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


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

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

  • 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 개의 인스턴스 모두가 각각 자신의 복사본을 갖는 대신이 네 가지 방법을 공유한다는 것입니다.


나는 이런 유형의 물건을 이해할 때 항상 유추를 좋아합니다. 프로토 타입이 훨씬 단순한 패러다임 임에도 불구하고 '프로토 타입 상속'은 제 생각에 클래스베이스 상속과 비교할 때 꽤 혼란 스럽습니다. 실제로 프로토 타입을 사용하면 실제로 상속이 없으므로 그 자체가 오해의 소지가있는 이름이며 '위임'유형입니다.

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

당신은 고등학교에 다니고 있으며, 수업을 듣고 있고 오늘 퀴즈가 있습니다.하지만 답을 채울 수있는 펜이 없습니다. 도!

당신은 펜을 가지고 있을지도 모르는 친구 Finnius 옆에 앉아 있습니다. 당신은 묻습니다. 그리고 그는 그의 책상을 우연히 둘러 본다. 그러나 나는 "나는 펜이 없다"고 말하는 대신, 펜을 가지고 있으면 다른 친구 Derp와 함께 확인하는 좋은 친구 다. Derp는 실제로 여분의 펜을 가지고 그것을 Finnius에게 돌려 주며 Finnius는 퀴즈를 완성하기 위해 그것을 당신에게 넘깁니다. Derp은 펜을 당신에게 사용하도록 위임 한 Finnius에게 펜을 위탁했습니다.

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

이것은 프로토 타입이 작동하는 방식에 대한 간단한 예이며 원하는 데이터를 찾기 위해 검색됩니다.


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

경우에 obj_n.prop_X존재하지 않는 확인 obj_n+1.prop_X어디에obj_n+1 = obj_n.[[prototype]]

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

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

자바 스크립트 객체의 관계 그래프는 다음과 같은 속성을 통해 확인할 수 있습니다.

http://jsobjects.org


모든 객체는 내부 객체 인 [[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;

new 문은 링크 대상 ( Object.prototype ) 자체를 표시하지 않습니다. 대신 대상은 생성자 ( Object )에 의해 암시됩니다.

생각해 내다:

  • 모든 객체에는 [[Prototype]] 링크가 있으며 때때로 __proto__ 노출됩니다.
  • 모든 함수에는 prototype 속성이 있습니다.
  • new 로 생성 된 객체는 해당 생성자의 prototype 속성에 연결됩니다.
  • 함수가 결코 생성자로 사용되지 않으면 prototype 속성은 사용되지 않을 것입니다.
  • 생성자가 필요하지 않은 경우 new 대신 Object.create 를 사용 Object.create .

Object.new를 사용하여 이미 객체를 가지고 있지만 생성자 구문을 사용할 때는 여전히 객체가 없습니다.


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

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

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


__proto__ , 프로토 타입생성자 관계를 표시하는 다른 스키마 :


이것은 몇 가지 다른 답변에 나타나는 클로저에 대한 몇 가지 (가능한) 오해를 해결하려는 시도입니다.

  • 클로저는 내부 함수를 반환 할 때 생성 될뿐만 아니라 사실, 닫는 함수를 생성하기 위해 닫는 함수 를 전혀 반환 할 필요가 없습니다 . 대신 내부 함수를 외부 범위에있는 변수에 할당하거나 나중에 즉시 호출 할 수있는 다른 함수에 인수로 전달할 수 있습니다. 따라서 내부 함수가 호출 될 때마다 내부 함수가 호출 될 때마다 내부 함수가 해당 클로저에 액세스 할 수 있기 때문에 내부 함수 가 호출되는 즉시 내부 함수가 닫히게됩니다.
  • 클로저는 해당 범위 에있는 이전 변수 의 복사본을 참조하지 않습니다 . 변수 자체는 클로저의 일부이므로 해당 변수 중 하나에 액세스 할 때 표시되는 값은 액세스 할 때의 최신 값입니다. 이것은 루프 내부에서 생성 된 내부 함수가 까다로울 수 있습니다. 함수가 생성되거나 호출 될 때 변수 복사본을 얻는 대신 각 외부 변수가 동일한 외부 변수에 액세스 할 수 있기 때문입니다.
  • 클로저의 "변수"에는 함수 내에 선언 된 명명 된 함수포함 됩니다. 또한 함수의 인수를 포함합니다. 클로저는 클로저의 변수를 전역 범위까지 액세스 할 수 있습니다.
  • 클로저는 메모리를 사용하지만 자바 스크립트는 자체적으로 참조되지 않은 순환 구조를 정리하므로 메모리 누수가 발생하지 않습니다 . 클로저를 포함하는 Internet Explorer 메모리 누수는 클로저를 참조하는 DOM 특성 값의 연결이 끊어 질 때 만들어 지므로 순환 구조에 대한 참조가 유지됩니다.






javascript dynamic-languages prototype-oriented