JS 프로토타입 및 프로토타입 체인에 대한 자세한 설명(딥 러닝)

1. 일반 객체와 함수 객체(모든 것이 객체입니다.)

자바스크립트에서는 일반 객체와 함수 객체 로 나뉘는데 객체와 함수는 JS와 함께 제공되는 함수 객체입니다. 다음 예는 다음을 보여줍니다.

var obj1 = {};

var obj2 = new Object();

var obj3 = new fun1();


function fun1(){};

var fun2 = function(){};

var fun3 = new Function();

 
console.log(typeof Object);   //function

console.log(typeof Function); //function  


console.log(typeof obj1);     //object

console.log(typeof obj2);     //object

console.log(typeof obj3);     //object


console.log(typeof fun1);     //function

console.log(typeof fun2);     //function

console.log(typeof fun3);     //function   




 

위의 예에서 obj1 obj2 obj3은 공통 객체이고 fun1 fun2 fun3은 함수 객체입니다. 구분하는 방법은 사실 매우 간단합니다 new Function()을 통해 생성된 모든 객체는 함수 객체이고 나머지는 일반 객체입니다. fun1, fun2는 최종 분석에서 모두 new Function()을 통해 생성됩니다. 함수 개체는 New Function() 을 통해서도 생성됩니다 .

아래에서 자주 사용하게 될 일반 객체와 함수 객체를 구별해야 합니다.

그림과 같이:

 

 

2. 생성자

 

먼저 생성자에 대한 지식을 검토해 보겠습니다.

function Fun(name, age, job) {

 this.name = name;

 this.age = age;

 this.job = job;

 this.sayName = function() { alert(this.name) }

}

var fun1 = new Fun('dragon1', 29, 'hello');

var fun2 = new Fun('dragon2', 26, 'hello');

위의 예에서 fun1 과 fun2 는 모두 Fun 의 인스턴스 입니다 . 인스턴스 모두 Fun을 가리키는 (포인터인) 생성자(constructor) 속성을 가지고 있습니다. 지금 바로:

  console.log(fun1.constructor == 재미); //진실

  console.log(fun2.constructor == 재미); //진실

두 가지 개념(생성자, 인스턴스)을 기억해야 합니다.

fun1과 fun2는 모두 생성자 Fun의 인스턴스입니다.

참고: 인스턴스의 생성자 속성(constructor)은 생성자를 가리킵니다.

3. 프로토타입 개체

JavaScript에서 개체(함수는 개체)가 정의될 ​​때마다 개체에는 미리 정의된 속성이 포함됩니다. 함수 객체에는 함수의 프로토타입 객체를 가리키는 프로토타입 속성이 있습니다 .

 

다음 예는 다음을 보여줍니다.

function Fun() {}

Fun.prototype.name = 'dragon';

Fun.prototype.age  = 28;

Fun.prototype.job  = 'Web';

Fun.prototype.sayName = function() {

  alert(this.name);

}

var fun1 = new Fun();

fun1.sayName(); // 'dragon'

var fun2 = new Fun();

fun2.sayName(); // 'dragon'


console.log(fun1.sayname == fun2.sayname); //true

 알아채다:

모든 객체에는 __proto__ 속성이 있지만 함수 객체에만 프로토타입 속성이 있습니다.

1. 프로토타입 객체란 무엇입니까?

위의 예에 따르면:

Fun.prototype = {

   name:  'dragon',

   age: 28,

   job: 'Web',

   sayName: function() {

     alert(this.name);

   }

}

프로토타입 객체는 이름에서 알 수 있듯이 일반 객체입니다. 지금부터 프로토타입 객체가 Fun.prototype이라는 것을 명심해야 합니다.

기본적으로 모든 프로토타입 객체는 프로토타입 속성이 있는 함수(Fun)를 가리키는 생성자(생성자) 속성을 자동으로 가져 옵니다 .

위의 문장이 좀 거창하다면, 자세히 설명하겠습니다.

var F = Fun.prototype ;

F에는 Fun에 대한 포인터인 기본 생성자 특성이 있습니다.

即:Fun.prototype.constructor == 재미; //진실

인스턴스의 생성자 속성(constructor)은 생성자를 가리킵니다.

fun1.constructor == 재미; //진실

2. fun1에 생성자 속성이 있는 이유는 무엇입니까?

      fun1은 Person의 인스턴스이기 때문입니다.

3. Fun.prototype에 생성자 속성이 있는 이유는 무엇입니까?

     Fun.prototype(F로 생각하면 됩니다)도 Fun의 인스턴스입니다.

즉, Fun이 생성되면 Fun의 인스턴스 객체가 생성되어 프로토타입에 할당됩니다.기본 프로세스는 다음과 같습니다.

 var F= 새로운 재미();

 Fun.prototype = F;

결론: 프로토타입 객체(Fun.prototype)는 생성자(Fun)의 인스턴스입니다.

프로토타입 객체는 실제로 일반 객체입니다(Function.prototype은 함수 객체이지만 매우 특별하고 프로토타입 속성이 없습니다(앞서 언급했듯이 함수 객체에는 프로토타입 속성이 있음)). 아래 예를 참조하십시오.

function Fun(){};

 console.log(Fun.prototype)                       //Fun{}

 console.log(typeof Fun.prototype)                //Object

 console.log(typeof Function.prototype)           // Function 

 console.log(typeof Object.prototype)             // Object

 console.log(typeof Function.prototype.prototype) //undefined

4. Function.prototype이 함수 객체인 이유는 무엇입니까?

 var F = 새 함수();

 함수.프로토타입 = F;

new Function()에 의해 생성된 모든 객체는 함수 객체입니다 .

F는 함수 객체이므로 Function.prototype은 함수 객체입니다.

4. __프로토__

JS가 객체(일반 객체든 함수 객체든)를 생성할 때 객체를 생성한 생성자의 프로토타입 객체를 가리키는 데 사용되는 __proto__  라는 내장 속성이 있습니다 . 객체 fun1은 __proto__ 속성을 가지고 있고, 이를 생성하는 생성자는 Fun이고, 생성자의 프로토타입 객체는 Fun.prototype입니다.
 

fun1.__proto__ == Fun.prototype

Fun.prototype.constructor == Fun;

fun1.__proto__ == Fun.prototype;

fun1.constructor == Fun;

그러나 분명히 해야 할 정말 중요한 점은 이 연결이 인스턴스( fun1 )와 생성자( Fun ) 사이가 아니라 생성자( Fun )의 인스턴스( fun1 )와 프로토타입 객체( Fun.prototype ) 사이 존재 한다는 입니다 . . 

참고: __proto__ 속성은 대부분의 브라우저에서 지원하기 때문에 ES6에 추가되었습니다(ES5도 일부 브라우저에서 지원되지만 아직 표준은 아닙니다).

5. 생성자

Javascript에 익숙한 아동용 신발은 다음과 같은
var obj = {}와 같은 객체를 생성할 수 있다는 것을 알고 있습니다 . var obj = new Object()

obj는 생성자(객체)의 인스턴스입니다. 따라서:
obj.constructor === 객체
obj.__proto__ === 객체.프로토타입

새로운 객체 obj는 new 연산자 다음에 생성자를 사용하여 생성 됩니다. 생성자(Object) 자체는 함수(즉, 위에서 언급한 함수 객체)이며, 위의 생성자 Person과 유사합니다. 새로운 객체를 생성하기 위한 목적으로 함수가 정의되었을 뿐입니다. 그러니 Object에게 겁먹지 마세요.

마찬가지로 객체를 생성할 수 있는 생성자는 Object뿐만 아니라 Array, Date, Function 등입니다.
따라서 배열, 날짜, 함수를 생성하는 함수를 구성할 수도 있습니다.

var a = new Array();
a.constructor === Array;             //true
a.__proto__ === Array.prototype;     //true

var b = new Date(); 
b.constructor === Date;              //true
b.__proto__ === Date.prototype;      //true

var c = new Function();
c.constructor === Function;          //true
c.__proto__ === Function.prototype;  //true

 

다음은 함수 개체입니다.

typeof Boolean      'function'

typeof Number       'function'
 
typeof Date         'function'
 
typeof Array        'function'
 
typeof String       'function'
 
typeof Function     'function'
 
typeof Object       'function'
 

6. 프로토타입 체인

프로토타입을 사용하여 한 참조 유형이 다른 참조 유형의 속성과 메서드를 상속하도록 합니다.

각 생성자에는 프로토타입 객체가 있고 프로토타입 객체에는 생성자(생성자)에 대한 포인터가 포함되며 인스턴스 객체에는 프로토타입 객체(__proto__)에 대한 내부 포인터가 포함됩니다. 프로토타입 객체가 다른 타입의 인스턴스와 같으면 이때 프로토타입 객체는 다른 프로토타입(__proto__)에 대한 포인터를 포함하고 다른 프로토타입도 다른 생성자(constructor)에 대한 포인터를 포함합니다. 다른 프로토타입이 다른 유형의 인스턴스인 경우... 이것은 인스턴스와 프로토타입의 체인을 구성합니다.

그림과 같이:

 예를 들어:

function Fun(){  
    this.type = "web";  
}  
Fun.prototype.getType = function(){  
    return this.type;  
}  
  
function Fun1(){  
    this.name = "dragon";  
}  
Fun1.prototype = new Fun();  
  
Fun1.prototype.getName = function(){  
    return this.name;  
}  
  
var fl = new Fun1();  

산출: 

 fun1.__proto__ === Fun.prototype                //true

 Fun.__proto__ === Function.prototype            //true

 Fun.prototype.__proto__ === Object.prototype    //true

 Object.prototype.__proto__ === null             //true

 7. 요약:

위의 결론에서:

여기에 이미지 설명 삽입

(1) 모든 함수 객체 의 __proto__는 빈 함수(Empty function)인 Function.prototype을 가리킨다.

 예:

Number.__proto__ === Function.prototype  // true
Number.constructor == Function           //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function          //true

String.__proto__ === Function.prototype  // true
String.constructor == Function           //true

 (2) 루트 생성자 Object 및 Function 자체를 포함하여 모든 생성자는 Function.prototype에서 옵니다.

 예:

Function.__proto__ === Function.prototype  // true
Function.constructor == Function           //true

Array.__proto__ === Function.prototype     // true
Array.constructor == Function              //true

RegExp.__proto__ === Function.prototype    // true
RegExp.constructor == Function             //true

Error.__proto__ === Function.prototype     // true
Error.constructor == Function              //true 

Date.__proto__ === Function.prototype      // true
Date.constructor == Function               //true

  (3) 함수가 호출될 때만 JS 엔진에 의해 생성되며, Math와 JSON은 new가 없는 객체 형태로 존재합니다. 그들의 프로토타입은 Object.prototype입니다. 다음과 같이:

Math.__proto__ === Object.prototype      // true
Math.construrctor == Object              // true
 
JSON.__proto__ === Object.prototype      // true
JSON.construrctor == Object              //true
 

모든 생성자(내장 및 사용자 정의 포함)의 __proto__가 Function.prototype이라는 것을 알고 있습니다. Function.prototype의 __proto__는 누구입니까?
JavaScript의 함수도 일급 시민이라고 들었는데 어떻게 반영 할 수 있습니까? 다음
console.log(Function.prototype.__proto__ === Object.prototype) // true
는 모든 생성자가 공통 JS 객체이며 생성자에 속성을 추가/삭제할 수 있음을 의미합니다. 동시에 Object.prototype의 모든 메서드(toString, valueOf, hasOwnProperty 등)도 상속합니다. (첫 번째 문장도 이해해야 합니다. 다음 섹션에서 두 번째 문장에 대해 계속 이야기할 것입니다. 구멍을 파지 않아도 바로 지금 같은 구멍입니다. 

Object.prototype 의 프로토타입은 누구입니까 ?
Object.prototype.__proto__ === null // 참

(4), 프로토타입

ECMAScript 코어에 의해 정의된 모든 속성 중에서 가장 흥미로운 속성은 프로토타입 속성입니다. ECMAScript의 참조 유형의 경우 프로토타입은 모든 인스턴스 메서드가 저장되는 실제 위치입니다. 즉, toString() 및 valuseOf()와 같은 메서드는 실제로 프로토타입 이름으로 저장되지만 해당 개체의 인스턴스를 통해 액세스됩니다.

1. 개체 인스턴스를 생성할 때:

var Person = new Object()
Person은 Object의 인스턴스이므로 Person은  Object의 프로토타입 객체인 Object.prototype의 모든 메서드를 상속합니다 .

 

 

Object의 모든 인스턴스에는 위의 속성과 메서드가 있습니다.
따라서 Fun.constructor 또는 Fun.hasOwnProperty를 사용할 수 있습니다.

2. 어레이 인스턴스를 생성할 때:

 

var num = new Array()
num은 Array의 인스턴스이므로 num은  Array의 프로토타입 객체인 Array.prototype의 모든 메서드를 상속합니다 .

3. 함수를 만들 때:

var fun = new Function("x","return x*x;");

//当然你也可以这么创建 fun = function(x){ return x*x }

console.log(fun.arguments)            //null  arguments 方法从哪里来的?

console.log(fun.call(window))         //NaN   call 方法从哪里来的?

console.log(Function.prototype)       // function() {} (一个空的函数)

console.log(Object.getOwnPropertyNames(Function.prototype)); 

//['length', 'name', 'arguments', 'caller', 'constructor', 'apply', 'bind', 'call', 'toString']

모든 함수 개체 proto는 빈 함수인 Function.prototype을 가리킵니다(빈 함수).

글쎄, 우리는 그것이 빈 기능임을 확인했습니다. 그러나 문장의 전반부를 무시하지 마십시오. 모든 메서드를 열거하므로 모든 함수 개체를 사용할 수 있습니다. 예를 들면 다음과 같습니다.

 (5), __proto__

모든 함수 객체의 __proto__는 빈 함수(빈 함수)인 Function.prototype을 가리킵니다.

먼저 JS 내장 생성자를 살펴보십시오.

 

var obj = {name: 'dragon'};
var arr = [1,2,3,4,5];
var reg = /hello/g;
var date = new Date;
var err = new Error('pp');

console.log(obj.__proto__  === Object.prototype) // true
console.log(arr.__proto__  === Array.prototype)  // true
console.log(reg.__proto__  === RegExp.prototype) // true
console.log(date.__proto__ === Date.prototype)   // true
console.log(err.__proto__  === Error.prototype)  // true

 Fun이 정의된 사용자 정의 생성자를 다시 살펴보십시오.

function Fun(name) {
  this.name = name;
}
var pp = new Fun('dragon');

console.log(pp.__proto__ === Person.prototype); // true

pp는 Fun의 인스턴스 객체이고 pp의 내부 프로토타입은 항상 생성자 Fun의 프로토타입 객체 프로토타입을 가리킵니다.

모든 개체에는 해당 생성자에 액세스할 수 있는 생성자 속성이 있으므로 결과도 동일합니다.

function Fun(name) {
    this.name = name
}
var pp = new Fun('jack')
console.log(pp.__proto__ === pp.constructor.prototype) // true

上面的Person没有给其原型添加属性或方法,这里给其原型添加一个getName方法:

function Fun(name) {
    this.name = name
}
// 修改原型  增加一个方法
Fun.prototype.getName = function() {}
var pp = new Fun('dragon')
console.log(pp.__proto__ === Fun.prototype)            // true
console.log(pp.__proto__ === pp.constructor.prototype) // true

pp.__proto__, Fun.prototype 및 pp.constructor.prototype이 모두 동일하다는 것을 알 수 있습니다. 즉, 모두 동일한 객체를 가리킵니다.

프로토타입을 다른 방식으로 설정하면 결과가 약간 다릅니다.

function Fun(name) {
    this.name = name
}
// 重写原型
Fun.prototype = {
    getName: function() {}
}
var pp = new Fun('dragon')
console.log(pp.__proto__ === Fun.prototype)            // true
console.log(pp.__proto__ === pp.constructor.prototype) // false

여기서 Fun.prototype은 직접 재작성됩니다(참고: 이전 예제는 프로토타입을 수정하는 것입니다). 출력은 pp.__proto__가 여전히 pp.constructor.prototype 대신 Fun.prototype을 가리키고 있음을 보여줍니다.

Fun.prototype에 할당된 것은 객체 리터럴 {getName: function(){}}이며, 객체 리터럴 메서드를 사용하여 정의된 객체의 생성자(constructor)는 루트 생성자 Object를 가리키고, Object .prototype은 빈 객체 {}이며, {}는 당연히 {getName: function(){}}과 같지 않습니다. 다음과 같이:

var pp = {}
console.log(Object.prototype)                              // 为一个空的对象{}
console.log(pp.constructor === Object)                     // 对象直接量方式定义的对象其constructor为Object
console.log(pp.constructor.prototype === Object.prototype) // 为true

(5) 프로토타입 체인. (검토 중)

예제를 읽고 나면 다음을 이해할 수 있습니다.

function Fun(){}
var fun1 = new Fun();

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

console.log(Fun.__proto__ == Function.prototype);          //true
console.log(Function.prototype);                           // function(){}(空函数)

var num = new Array();
console.log(num.__proto__ == Array.prototype);              // true
console.log(Array.prototype.__proto__ == Object.prototype); // true
console.log(Array.prototype);                               // [] (空数组)
console.log(Object.prototype.__proto__);                    //null

console.log(Array.__proto__ == Function.prototype);         // true

рекомендация

отblog.csdn.net/qq_35404844/article/details/129981635