深入理解原型

468 阅读1分钟

一、一道面试题引发的深思

function A(){

}
var B = {};
console.log(A.constructor); 
console.log(B.constructor);
var a = new A();  
A.prototype = {};  
var b = new A();  
console.log(A.constructor);  
console.log(b.constructor);  
b.constructor = A.constructor;
console.log(a.constructor);  //[Function: A]
console.log(b.constructor);  //[Function: Function]
console.log(b.constructor === a.constructor);   //false
console.log(a instanceof A);  //false
console.log(b instanceof A);  //true

step1

function A(){

}
var B = {};
console.log(A.constructor);
console.log(B.constructor);


解释:

引擎创建了 Object.prototype ,然后创建了 Function.prototype 。

Object 是所有对象的爸爸,所有对象都可以通过 __proto__.constructor 找到它。

Function 是所有函数的爸爸,所有函数都可以通过 __proto__.constructor 找到它。

step2

var a = new A();   //这里a的constructor指向A
console.log(A.prototype.constructor);   //[Function: A]
A.prototype = {};  //重写原型
console.log(A.prototype.constructor);   //[Function: Object]
var b = new A();   //这里b的construcor指向Object
console.log(A.constructor);    //[Function: Function]    A的constructor前后没有发生变化
console.log(b.constructor);    //[Function: Object]

重写原型之前A.prototype.constructor如图所示:


var a = new A();后a.__proto__constructor指向A;


A.prototype = {};重写原型后,A.prototype.constructor指向Object。


var b = new A();时b的__proto__指向A的原型,但是A的原型里面的constructor指向Object。

所以b.constructor为[Function: Object]


step3

b.constructor = A.constructor;
console.log(b.constructor === a.constructor);   //false

解释

a.constructor在重写A的原型之前,指向构造函数A;

b.constructor = A.constructor;后,b.constructor指向Function;

所以b.constructor === a.constructor为false;


step4

console.log(a instanceof A);  //false
console.log(b instanceof A);  //true

剖析instanceof原理,其内部机制是通过判断对象的原型链中是否能找到类型的prototype。

instanceof的代码实现:

function instacne_of(L,R){
    var O = R.prototype;
    L = L.__proto__;
    if(L === null){
        return false;
    }
    if(O === L){
        return true;
    }
    L = L.__proto__;
}

所以a.__proto__为function A;b.__proto__为Object;A.prototype为Object;