头部背景图片
吉水于人的笔记 |
吉水于人的笔记 |

我理解的原型链

原型链,开始看资料时觉得还能理解,到后面就有点绕晕了,在看了几篇文章之后,我将关键点剥离出来,进行整理,这样一来,整个原型链就得到了一个很好的理解。那么首先,我们要明确几个概念。

  • 函数(Function)拥有prototype属性,对象(除了null)拥有__proto__
  • 除了__proto__属性,对象还拥有constructor属性,这个属性使得一个对象指向一个函数,即指向该对象的构造函数,每个对象都具有一个构造函数(本身拥有或继承而来),Function对象的构造函数是它本身,所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function函数。
  • 对象所拥有的__proto__是当访问一个对象当属性时,没有找到该属性,就会去它的__proto__属性所指向的那个对象(父对象)里找,一直寻找,直到__proto__属性的值为null,返回undefined,通过__proto__属性将对象连接起来的这条链路就是原型链
  • 在js中一切都为对象,正是因为这个,函数也是一个对象,所以函数在作为对象时拥有__proto__constructor,作为函数时又拥有prototype属性。

根据上面几个概念,我们来做几个测试。

1.函数及其实例化对象之间的关系

var obj=function(){}; // 定义一个函数,此时它既是函数也是对象,所以同时拥有prototype和__proto__属性
console.log(obj.prototype)  // => {constructor: ƒ}
console.log(obj.__proto__)  // => ƒ () { [native code] }
var o=new obj();  // 实例化一个o对象
console.log(o.__proto__)  // =>{constructor: ƒ}

我理解的就是obj的prototype属性constructor指向obj本身,而其实例化的o的__proto__属性也是指向obj原型,故相等

o.__proto__ === obj.prototype  // => true

现在我们知道对象o的__proto__属性的constructor也是ƒ (){},而obj本身就是一个ƒ (){},自然相等

o.__proto__.constructor===obj // => true

2.obj与构造函数Function的关系
我们知道每个对象都具有一个__proto__属性,而每个构造函数都有一个prototype方法,每个对象的__proto__属性指向自身构造函数的prototype

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

3.Function和Object
ECMAScript规定了两个特殊的内置对象:Object和Function。他们的特殊性在于,他们本身既是对象又是函数,而他们同时也是对象和函数的构造器。

// 构造器Function的构造器是它自身
Function.constructor=== Function // => true

// 构造器Object的构造器是Function (所有构造器的constructor都指向Function)
Object.constructor === Function  // => true

// 构造器Function的__proto__是一个特殊的匿名函数function() {}
console.log(Function.__proto__)  // => function() {}

// 这个特殊的匿名函数的__proto__指向Object的prototype原型
Function.__proto__.__proto__ === Object.prototype // => true

// Object的__proto__指向Function的prototype,也就是上面所述的特殊匿名函数
Object.__proto__ === Function.prototype  // => true
Function.__proto__ === Function.prototype // => true 

注:

  • 所有的构造器的constructor都指向Function
  • Function的__proto__指向一个匿名函数,而这个匿名函数的__proto__指向Object.prototype

instanceof

instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上

function Person() {}
console.log(Object instanceof Object);     //true
//第一个Object的原型链:Object=>
//Object.__proto__ => Function.prototype=>Function.prototype.__proto__=>Object.prototype
//第二个Object的原型:Object=> Object.prototype

console.log(Function instanceof Function); //true
//第一个Function的原型链:Function=>Function.__proto__ => Function.prototype
//第二个Function的原型:Function=>Function.prototype

console.log(Function instanceof Object);   //true
//Function=>
//Function.__proto__=>Function.prototype=>Function.prototype.__proto__=>Object.prototype
//Object => Object.prototype

console.log(Person instanceof Function);      //true
//Person=>Person.__proto__=>Function.prototype
//Function=>Function.prototype

console.log(String instanceof String);   //false
//第一个String的原型链:String=>
//String.__proto__=>Function.prototype=>Function.prototype.__proto__=>Object.prototype
//第二个String的原型链:String=>String.prototype

console.log(Boolean instanceof Boolean); //false
//第一个Boolean的原型链:Boolean=>
//Boolean.__proto__=>Function.prototype=>Function.prototype.__proto__=>Object.prototype
//第二个Boolean的原型链:Boolean=>Boolean.prototype

console.log(Person instanceof Person); //false
//第一个Person的原型链:Person=>
//Person.__proto__=>Function.prototype=>Function.prototype.__proto__=>Object.prototype
//第二个Person的原型链:Person=>Person.prototype