首页 > 代码库 > JavaScript面向对象编程(4)重写prototype造成的混乱

JavaScript面向对象编程(4)重写prototype造成的混乱

先来看两个现象:

1.分量形式声明prototype(部分重写),prototype的构造器为宿主函数而不是Object,就像直接给宿主构造器增加了属性一样

function Dog(){this.tail = true;}
//新建两条狗,注意此时还没有定义prototype
var benji = new Dog();
var rusty = new Dog();

Dog.prototype.say = function(){return 'Woof!';}
//1.部分重写,prototype的构造器为宿主函数而不是Object,就像直接给宿主构造器增加了属性一样
alert("部分重写,其构造器:"+benji.constructor.prototype.constructor);
//正式因为这个特性,在prototype定义之前创建的对象,仍自动获得了prototype的属性
alert("benji.say()==="+benji.say());//正常,可用

2.第二个现象是,如果将prototype直接定义为一个简单对象,这个动作叫做完全重写
这时prototype的构造器为Object,宿主构造器不直接具备prototype的属性

也正式因为如此,在prototype声明之前已经创建好的对象,不能使用prototype的属性

——完全重写将原来的实例和prototype切断了

//用完全重写形式
Dog.prototype = {paws: 4,hair: true};
alert("完全重写,其构造器==="+benji.constructor.prototype.constructor);
/*在prototype声明之前已经创建好的对象,不能使用prototype的属性,完全重写将原来的实例和prototype切断了*/
alert("benji.say()==="+benji.say());//正常
alert("用之前对象访问prototype对象的属性::"+benji.paws);//undefined

所以,你首先必须记住,部分重写就像直接给宿主构造器增加了属性一样,而完全重写则不是。由此引发了旧对象访问新属性能不能访问的区别。

3.完全重写后新建的对象上只具备原始属性和完全重写中定义的属性
 完全重写之前建立的对象上则具备原始属性和之前的部分重写属性

//用完全重写形式
Dog.prototype = {p1: 888,p2: 999};
var lucy = new Dog();//新建对象
for(i in lucy){
	alert(i);//tail p1 p2
}
for (i in benji) {
	alert(i);//tail say
}

4.上面的内容还是比较好理解,部分重写的属性(或方法),重写后新老对象都可以用,完全重写的属性(或方法)只有新对象才能用,完全重写还会屏蔽掉以前的prototype属性;

另外还有一个问题,会造成困扰,就是完全重写后的构造器指针错误:

Dog.prototype = {p1: 888,p2: 999};
var lucy = new Dog();//新建对象
/*4.完全重写后的构造器指针错误*/
alert(lucy.constructor);//Object?

如何修正呢?只需重置下prototype的constructor指向即可:

Dog.prototype = {p1: 888,p2: 999};
Dog.prototype.constructor = Dog; 
var lucy = new Dog();//新建对象
/*重置构造器指针后,正常了*/
alert(lucy.constructor);

这部分内容主要是为“继承”做准备,大家知道继承、封装、多态是面向对象的特征,所以不得不了解js中的继承。

具体怎么做,请看下回分解





JavaScript面向对象编程(4)重写prototype造成的混乱