原型陷阱

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原型陷阱相关的知识,希望对你有一定的参考价值。

 处理原型问题时,我们需要特别注意一下两种行为。
1、当我们对原型对象执行完全替换时,可能会触发原型链中的某种异常
2、prototype。constructor属性是不可靠的
下面,我们来新建一个简单的构造器函数,并用它再创建两个对象;
function Dog() {
this.tail = true;
}
var benji = new Dog();
var rusty = new Dog();

/*
* 即便在benji和rusty对象创建之后,我们也依然能为Dog();的原型添加属性,并且在属性被添加之前就已经存在的对象
* 也可以随时访问这些新属性。现在,让我们放一个say()方法进去*/
Dog.prototype.say = function () {
return ‘Woof‘;
};
/*这样,上面的两个对象都可以访问该新方法了;*/
console.log(benji.say());//Woof
console.log(rusty.say());//Woof
/*检查一下这些对象的构造器函数,就会发现一切正常*/
console.log(benji.constructor === Dog); //true
console.log(rusty.constructor === Dog); //true

/*现在我们用一个新对象完全覆盖掉原有的原型对象;*/
Dog.prototype = {
paws : 4,
hair : true
};

/*事实证明,这会使原有对象不能访问原型的新增属性,他们依然通过那个神秘的链接与原有的原型对象保持联系*/
console.log(typeof benji.paws); //undefined
console.log(benji.say()); //Woof
console.log(typeof benji.__proto__.say); //function
console.log(typeof benji.__proto__.paws); //undefined

/*而我们之后创建的所有对象使用的都是被更新后的prototype对象.*/

var lucy = new Dog();
// console.log(lucy.say());//Uncaught TypeError: lucy.say is not a function
console.log(lucy.paws); //4

/*并且,其秘密链接_proto_也指向了新的prototype对象;*/
console.log(typeof lucy.__proto__.say); //undefined
console.log(typeof lucy.__proto__.paws); //number

/*但这时候,新对象的constructor属性就不能保持正确了,原本原本应该是Dog();的引用只想了Object.*/
console.log(lucy.constructor); //function Object() { [native code] }
console.log(benji.constructor);/*
Dog() {
this.tail = true;
}
*/

/*当然,我们可以通过重新设置constructor属性来解决上述所有的异常行为*/
function Dog(){}
Dog.prototype = {};
console.log(new Dog().constructor ===Dog);//false


Dog.prototype.constructor = Dog;
console.log(new Dog().constructor === Dog);//true

/*
* 声明:
* 本文借鉴javascript面向对象编程指南(第二版)
* */

以上是关于原型陷阱的主要内容,如果未能解决你的问题,请参考以下文章

sprintf/snprintf 陷阱[转]

读书笔记《你不知道的JavaScript(上卷)》——第二部分 this和对象原型

JavaScript 原型对象原型链

08.22 javaScript 原型的定义 原型链 获取原型 操作原型的属性 判断原型是自有的还是继承的 各种方法

JavaScript高级原型和继承相关:原型对象函数原型原型链和继承继承的优化对象判断相关方法

JavaScript高级原型和继承相关:原型对象函数原型原型链和继承继承的优化对象判断相关方法