本文将介绍如何在本文设计的js继承机制实现模板中,通过obj_this来修改父亲函数的属性。
正常情况下,无法通过obj_this修改父函数的属性值。测试代码如下:
function test(){
var b = B().instantiate();
console.log("继承父函数的属性name_a,值为:" + b.name_a);//读取继承的属性name_a
b.name_a = "PARENT A";//普通方法修改name_a的值
console.log("修改属性name_a的值后,值为:" + b.name_a);//打印修改后的name_a
b.show_a();//通过继承的方法来打印name_a的值,看是否发生变化
}
function A(){
var obj_this = this;
obj_this.name_a = "A";
obj_this.instantiate = function(){
obj_this = new A();
obj_this.assign(obj_this);
return obj_this;
};
obj_this.assign = function(obj){
obj_this = obj;
};
obj_this.show_a = function(){
console.log("父函数的属性name_a,值为:"+ obj_this.name_a);
}
return obj_this;
}
function B(){
var obj_this = this;
obj_this.name_b = "B";
obj_this.instantiate = function(){
B.prototype = A().instantiate();
B.prototype.construct = B;
obj_this = new B();
obj_this.assign(obj_this);
return obj_this;
};
this.assign = function(obj){
obj_this = obj;
};
return obj_this;
}
测试结果
测试结果表明,对象b能够访问从父函数继承来的name_a,但是当通过b.name_a赋值来直接修改name_a的值时,b.name_a的值是变化了,但是当调用b.show_a()函数时,其中的值name_a却并没有改变。也就是说,通过b可以读取继承的属性,但却不能真正修改继承的属性。原因很简单,这与js本身的prototype设计有关。实际上,b继承的属性和方法都在prototype对象中,当执行b.xxxx或者b.yyyy()这样读取操作时,首先会去B函数本身申明的属性和方法中查找,如果没有,再去prototype中的继承属性中查找(这个访问方式和C++差不多)。我们知道,js对象的一个非常方便的地方就是,能够通过b.attr=value(attr你要添加的属性的名称,value是属性的值)这样的赋值操作,就能很方便地为对象添加一个属性,因此,在之执行b.name_a = “PARENT_A”这样的写入操作时,首先也是去B函数本身申明的属性中查找,发现没有name_a这个属性,此时便直接给b本身新建了一个属性name_a,而不会去查找prototype中的继承属性了。也就是说,在对象读属性的时候,会查找prototype对象,而再写属性的时候,不会去查找prototype对象。因此,在本例中,b.name_a进行赋值后的name_a与show_a()中的name_a不是同一个属性,所以无法通过b来直接修改它继承的属性name_a的值。
那么如何通过对象修改从父函数继承来的属性值呢?很简单,通过set方法来赋值。测试代码如下:
function test(){
var b = B().instantiate();
console.log("继承父函数的属性name_a,值为:" + b.name_a);//读取继承的属性name_a
b.set_name_a("PARENT A");//通过set方法来修改name_a的值
console.log("修改属性name_a的值后,值为:" + b.name_a);//打印修改后的name_a
b.show_a();//通过继承的方法来打印name_a的值,看是否发生变化
}
function A(){
var obj_this = this;
obj_this.name_a = "A";
obj_this.instantiate = function(){
obj_this = new A();
obj_this.assign(obj_this);
return obj_this;
};
obj_this.assign = function(obj){
obj_this = obj;
};
obj_this.show_a = function(){
console.log("父函数的属性name_a,值为:"+ obj_this.name_a);
}
obj_this.set_name_a = function(value){
obj_this.name_a = value;
};
return obj_this;
}
function B(){
var obj_this = this;
obj_this.name_b = "B";
obj_this.instantiate = function(){
B.prototype = A().instantiate();
B.prototype.construct = B;
obj_this = new B();
obj_this.assign(obj_this);
return obj_this;
};
this.assign = function(obj){
obj_this = obj;
};
return obj_this;
}
- 测试结果
- 结果表明,通过添加set方法可以解决js对象不能修改从父函数继承的属性的问题。