• 原型链的继承


    原型链的问题

    原型链的作用很强大,可以用来实现继承,但是也会有一些问题,最大的问题就是引用类型值得原型属性会被所有实例共享

    实例是什么? 实例就是 new 对象名称() ; 例如: var instance=new Person();  instance就是实例;

    例如: 

        var SuperType=function(){
          this.colors=["red","black"];
        }
        var SubType=function(){};
        SubType.prototype=new SuperType();//继承
    
        var subType=new SubType();
        subType.colors.push("green");
        console.log(subType.colors);
    
        var subType2=new SubType();
        console.log(subType2.colors);

    这段代码输出结果都是:"red","black","green"

    这是怎么回事了?

    这是因为SubType的所有实例都会共享colors属性,而我们对subType.colors的修改,能够通过subtype2.colors反映出来。

    借用构造函数

    在解决原型中引用类型值得问题中,可以通过借用构造函数的技术来实现;即:就是通过子类型的构造函数调用父类的构造函数(可以通过call或者apply调用父类构造函数)

    以上面的例子改成如下:

    var SuperType=function(){
          this.colors=["red","black"];
        }
        var SubType=function(){
            SuperType.call(this) //调用父类的构造函数
        };
        SubType.prototype=new SuperType();//继承
    
        var subType=new SubType();
        subType.colors.push("green");
        console.log(subType.colors);
    
        var subType2=new SubType();
        console.log(subType2.colors);

    输出的结果为:"red","black","green"

                        "red","black"

    这样我们实际是在(未来将要)新创建的SubType实例环境下调用了SupType构造函数

    这样就会在新的SubType对象上执行SuperType函数,而SubType的每个实例都会具有colors属性的副本;

    最基本的原型继承

           var Parent=function(name){
                 this.name=name || "parent";
           }
    
           Parent.prototype.getName=function(){
                 return this.name;
           }
    
           var Child=function(name,age){
                  this.name=name;
                  this.age=age;
           }
    
           Child.prototype=new Parent();//通过此种方法继承
    
           var parent=new Parent("this is a parent");
           var child=new Child("I'm a child",22);
           console.log(parent.getName()); //this is a parent
           console.log(child.getName());//I'm a child
           console.log(child.age);//22

    这种优点是简单,缺点是如果子类需要做跟父类构造函数中相同的初始化动作,需要在子类的构造函数中再重新做一遍,例如:Child中初始化name

    如果初始化工作不断增加,这种方式很不方便;

    这时候可以借用构造函数,例如:

            var Parent=function(name){
                  this.name=name || "parent";
             }
    
             Parent.prototype.getName=function(){
                  return this.name;
             }
    
             Parent.prototype.obj={a:1};
    
            
             var Child=function(name,age){
                  //通过apply调用父类构造函数进行初始化工作
                  //这样不管父类执行多少初始化工作,子类也可以执行同样的初始化工作
                  Parent.apply(this,arguments);
                  this.age=age;
             }
    
             Child.prototype=new Parent();
             //Child.prototype=Parent.prototype;
    
             var child=new Child("alice",22);
             var parent=new Parent("stone");
             console.log(child.getName());
             console.log(parent.getName());

    这种方式可以解决初始化的问题,但是父类构造函数会被执行两次,一次在子类构造函数中,一次是在赋值子类原型链中,

    可以通过

            Child.prototype=Parent.prototype;//代替 Child.prototype=new Parent();

    即子类和父类指向相同的原型链,但是这样会存在一个问题,修改子类的原型链,会影响父类的原型链,例如:

      var Parent=function(name){
                  this.name=name || "parent";
             }
    
             Parent.prototype.getName=function(){
                  return this.name;
             }
    
             Parent.prototype.obj={a:1};
    
            
             var Child=function(name,age){
                  //通过apply调用父类构造函数进行初始化工作
                  //这样不管父类执行多少初始化工作,子类也可以执行同样的初始化工作
                  Parent.apply(this,arguments);
                  this.age=age;
             }
    
             Child.prototype=new Parent();
             //Child.prototype=Parent.prototype;
    
             var child=new Child("alice",22);
             var parent=new Parent("stone");
             console.log(child.getName());
             console.log(parent.getName());
    
             Child.prototype.obj.a=26;
             console.log(child.obj.a);//26
             console.log(parent.obj.a);//26

    当我改变 Child.prototype.obj.a时,会同时改变父类的原型链。

    那又什么好的办法?

  • 相关阅读:
    aspjpeg 组件在asp中的使用
    C# 使用 fckeditor 上传文件中文名乱码的问题---转
    我来挑战主页绑定,浏览器被绑架之终极方案!
    nginx简易配置
    树莓派安装中文输入法
    树莓派4超频至2.0GHz
    python3 requests使用连接池
    python3 语言特性5
    git日常使用
    python3 时间格式化
  • 原文地址:https://www.cnblogs.com/alice626/p/5277805.html
Copyright © 2020-2023  润新知