弄清原型和原型链

四条大规则

原型和原型链,大体可以用以下几条规则概括,弄清楚了这几条,也就基本吃透了原型和原型链。

  1. 所有的引用类型都有一个__proto__属性,属性值是一个普通对象
  2. 所有的函数都有一个prototype属性,属性值也是一个普通对象
  3. 所有引用类型的__proto__属性值指向其构造函数的prototype属性值
  4. 当试图得到一个对象的某个属性值时,如果这个对象本身没有该属性,就会去它的__proto__(它构造函数的prototype)中查找

(为了方便起见,下文中__proto__用隐式原型代替,prototype用显式原型代替)
举个栗子:

// 构造函数
function Human(name) {
    this.name = name;
}
Human.prototype.introduce = function(){
    console.log('My name is', this.name);
}

var somebody = new Human('somebody');
console.log(Human.prototype); // Function
console.log(Human.prototype.constructor === Human); // true
console.log(somebody.__proto__ === Human.prototype);  // true
somebody.introduce(); // "My name is somebody"

在上述例子中,Human是构造函数,而somebody是Human的一个实例。从console输出结果可以验证,构造函数的显式原型的constructor属性指向它本身,实例的隐式原型属性指向其构造函数的显式原型。

在实例somebody中并没有introduce方法,该方法实际是在Human.prototype中,由上述第四条,当试图得到一个对象的某个属性值时,如果这个对象本身没有该属性,就会去它的__proto__(它构造函数的prototype)中查找,所以somebody的introduce方法实际上是somebody.__proto__.introduce,也就是Human.prototype.introduce。

上图帮助理解吧~
《弄清原型和原型链》

实例的隐式原型属性指向其构造函数的显式原型属性。
所有的一层一层的__proto__连起来,就构成了原型链。例如,在Object.prototype上有一方法toString,而somebody也有,但其实somebody的toString方法并非自身所有(除非单独有声明),而是来自于somebody.__proto__.__proto__.__proto__(即Object.prototype),这一点可以通过hasOwnProperty证明。

原型相关方法

判断一个对象是否在原型链上可以用instanceof,判断某一个属性是否是自身属性可以用hasOwnProperty。

console.log(somebody.hasOwnProperty('name')) // true
console.log(somebody instanceof Object); // true

//语法
// obj.hasOwnProperty(prop)
// object instanceof constructor

后续再出一期与new运算符相关的还有与原型继承、class相关的吧,排期ing。

参考阅读

MDN: instanceof
MDN: constructor
MDN: hasOwnProperty

    原文作者:小乐
    原文地址: https://segmentfault.com/a/1190000015789349
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞