js函数(类)的继承机制的设计与实现(三)

  • 本文将介绍如何在本文设计的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对象不能修改从父函数继承的属性的问题。

猜你喜欢

转载自blog.csdn.net/u012409928/article/details/51325731