弄清原型和原型链

四条大规则

原型和原型链,大致能够用如下几条规则归纳,弄清楚了这几条,也就基本吃透了原型和原型链。函数

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

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

// 构造函数
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属性指向它自己,实例的隐式原型属性指向其构造函数的显式原型。spa

在实例somebody中并无introduce方法,该方法实际是在Human.prototype中,由上述第四条,当试图获得一个对象的某个属性值时,若是这个对象自己没有该属性,就会去它的__proto__(它构造函数的prototype)中查找,因此somebody的introduce方法其实是somebody.__proto__.introduce,也就是Human.prototype.introduce。prototype

上图帮助理解吧~
原型及原型链code

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

原型相关方法

判断一个对象是否在原型链上能够用instanceof,判断某一个属性是不是自身属性能够用hasOwnProperty。blog

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: hasOwnPropertyip

相关文章
相关标签/搜索