JavaScript原型链
1.原型链的产生
JavaScrip可以采用构造器(constructor)生成一个新的对象,每个构造器都拥有一个prototype属性,而每个通过此构造器生成的对象都有一个指向该构造器原型(prototype)的内部私有的链接(proto),而这个prototype因为是个对象,它也拥有自己的原型,这么一级一级指导原型为null,这就构成了原型链.
2.例子加深理解
function ClassA(){ } ClassA.prototype.name = 'A'; ClassA.prototype.sayName = function(){ alert(this.name); } function ClassB(){ } ClassB.prototype = new ClassA(); var b1 = new ClassB(); b1.sayName();//A
b1对象上未定义sayName方法,但其构造器ClassB的原型prototype上定义了sayName方法。通过原型链(主要是__proto__属性),b1也拥有sayName方法。
function ClassA(){ } ClassA.prototype.name = 'A'; ClassA.prototype.sayName = function(){ alert(this.name); } var ClassB = new ClassA(); ClassA.sayName();// Uncaught TypeError: ClassA.sayName is not a function
访问ClassA.sayName时,基于原型链不应该访问 ClassA.prototype.sayName 吗?为什么本题没有访问ClassA.prototype.sayName呢?
其实这个问题问的就是错误的,JavaScript的原型链实际是靠__proto__形成的,而非prototype。所以查找原型链,查找的是__proto__,而非prototype。函数的prototype不属于自身的原型链。
3.原型链的实现代码
function getProperty(obj, prop) { if (obj.hasOwnProperty(prop)) //首先查找自身属性,如果有则直接返回 return obj[prop] else if (obj.__proto__ !== null) return getProperty(obj.__proto__, prop) //如何不是私有属性,就在原型链上一步步向上查找,直到找到,如果找不到就返回undefind else return undefined }
4.总结:
1).原型链的形成真正是靠__proto__ 而非prototype,当JS引擎执行对象的方法时,先查找对象本身是否存在该方法,如果不存在,会在原型链上查找,但不会查找自身的prototype。
2).一个对象的__proto__记录着自己的原型链,决定了自身的数据类型,改变__proto__就等于改变对象的数据类型。
3).函数的prototype不属于自身的原型链,它是子类创建的核心,决定了子类的数据类型,是连接子类原型链的桥梁。
4).在原型对象上定义方法和属性的目的是为了被子类继承和使用。
参考文章:
1.JS核心系列:浅谈 原型对象和原型链