四条大规则
原型和原型链,大体可以用以下几条规则概括,弄清楚了这几条,也就基本吃透了原型和原型链。
- 所有的引用类型都有一个__proto__属性,属性值是一个普通对象
- 所有的函数都有一个prototype属性,属性值也是一个普通对象
- 所有引用类型的__proto__属性值指向其构造函数的prototype属性值
- 当试图得到一个对象的某个属性值时,如果这个对象本身没有该属性,就会去它的__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。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。