若单独使用原型链来实现继承,会存在引用类型在所有子类中共享的问题。
function SuperType(){
this.name=['hello'];// 数组为一种引用类型
}
function SubType(){
}
SubType.prototype=new SuperType();
var sub=new SubType();
var sub1=new SubType();
console.log(sub.name);// hello
sub.name.push(' world');
console.log(sub1.name);// hello world
console.log(sub.name);// hello world
通过程序运行的结果来看,虽然只是在sub
这一个实例中修改了name
属性的值,但是 在另一个实例sub1
中,name
的属性值也发生了改变。
具体原因是因为name是引用类型,所有的name
都指向同一块内存空间,所以一次改变就会引起全局改变,相当于其他语言的静态变量。
但是如果不是引用类型就不存在这种问题,每创建一个实例,都会为每个实例的name
属性重新分配一个内存空间,相互之间不干扰。
function SuperType1(){
this.name='hello';
}
function SubType1(){
}
SubType1.prototype=new SuperType1();
var sub=new SubType1();
var sub1=new SubType1();
console.log(sub.name);// hello
sub.name='hello world';
console.log(sub1.name);// hello
console.log(sub.name);//hello world
另外,就算给name
刚开始赋值为String类型,由于后期的字符串操作函数返回的都只是一个字符串而不是一个String的引用类型,所以导致name
本身类型的改变(不再是引用类型),不会引起子类共享的问题。
function SuperType1(){
var hel=new String('hello');
this.name=hel;
}
function SubType1(){
}
SubType1.prototype=new SuperType1();
var sub=new SubType1();
var sub1=new SubType1();
console.log(sub.name);//
sub.name=sub.name.toUpperCase();
console.log(sub.name instanceof String);//false,不再是String类型
console.log(sub1.name);//
console.log(sub.name);//
程序运行结果如下
参考资料:JavaScript高级程序设计(第三版)第6章