• [ JavaScript ] JavaScript 实现继承.


    对于javascript中的继承,因为js中没有后端语言中的类式继承。所以js中的继承,一般都是原型继承(prototype)。

    function P (name){
    	this.name = name;
    	this.say = function(){
    		console.log('p');
    	}
    }
    
    function S (name,id){
    	this.id = id;
    
    	this.eat = function(){
    		console.log('s');
    	}
    }
    
    S.prototype = P.prototype;
    
    var s = new S();

    以上代代码存在一个重要问题:

    S.prototype = P.prototype;

    该句代码会导致,在改动子类的prototype的时候,相同会影响父类的prototype元素。

    解决方案一般採用new 父级对象的方式:

    S.prototype = new P();
    这里涉及到new 的工作原理,new P(), 会依据P的prototype对象建立一个实例,然后将构造方法中的成员变量和成员方法设置进去。

    此种方式, 改动子类的prototype则不会影响父类的prototpye(因为是新建了一个对象,不再是指向同一个prototype).

    设置prototype之后。还须要重置子类S的contrustor,让其重指向 S。而不是new P() 所相应的construstor. 例如以下:

    S.prototype.constructor = S;

    非常多时候这里不重置。不会出现故障,可是假设后面须要用到constructor 来创建实例,或者判定实例类型,则会出现错误。

    所以这里最好是重置。


    上面所述的原型继承。尽管能够通过JavaScript原型继承,可是相同存在不足。

    此种继承方式。不可以继承在构造方法设置的成员变量和成员方法。仅仅能继承在原型中设置的方法,或者属性。

    如:

    var s = new S('yang','01');
    当中的第一个參数,并不能传递给到name属性。


    于是引出另外一种继承方式: 对象冒充。

    function P (name){
    	this.name = name;
    	this.say = function(){
    		console.log('p');
    	}
    }
    
    function S (name,id){
    	P.call(this,name);
    	this.id = id;
    	this.eat = function(){
    		console.log('s');
    	}
    }
    
    var s = new S('yanghi','test');

    在子类构造方法中,借用父类的构造方法。使子类具有父类的属性和方法。

    例如以下:

    P.call(this,name);

    该句代码与例如以下效果一样:

    this.name = name;
    this.say = function(){}

    从而将父类的属性复制到子类中。从而实现对象冒充。

    那么该此种对象冒充方式。相同存在问题:

    1 无法继承原型prototype中的属性和主法。

    2 构造方法的成员方法在父类和子类中都会有一份拷贝,造成内存的添加。


    所以最好的实现方式是:

    1 对原型对象。採用原型继承

    2 构造方法中的属性和方法。採用对象冒充。

    这也是当前绝大对数的js继承库所採用的实现方式。例如以下:

    function P (name){
    	this.name = name;
    }
    
    P.prototype.say = function(){
    	console.log('say');
    }
    
    function S (name,id){
    	P.call(this,name);
    	this.id = id;
    }
    
    function Bare(){}
    Bare.prototype = P.prototype;
    S.prototype = new Bare();
    S.prototype.constructor = S;
    
    S.prototype.eat = function(){
    	console.log('eat');
    }
    
    var s = new S('yanghi','test');
    

    这里的成员属性。採用对象冒充,成员方法採用原型继承。

    注意一点。这里实现原型继承须要採用一个中间变量。例如以下:

    S.prototype = new Bare();

    假设不採用中间变量。直接new P() 的话,会出现故障。

    因为new 会依照P的prototype对象模版,创建一个对象,这一步没有问题。

    可是接下来。它会将P构造方法的成员属性也设置到这个对象中,就会导致对这个对象污染。

    这里我们仅仅须要它的prototype就能够了。其他的成员变量採用对象冒充的方式就能够了。


    第三种实现继承方式,採用ES5 Object.create实现。

    //Shape - superclass
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    Shape.prototype.move = function(x, y) {
        this.x += x;
        this.y += y;
        console.info("Shape moved.");
    };
    
    // Rectangle - subclass
    function Rectangle() {
      Shape.call(this); //call super constructor.
    }
    
    Rectangle.prototype = Object.create(Shape.prototype);
    
    var rect = new Rectangle();
    
    rect instanceof Rectangle //true.
    rect instanceof Shape //true.
    
    rect.move(1, 1); //Outputs, "Shape moved."

    只是此方式最大的问题还是兼容性,须要 IE 9 + , safari 5 +,opera 11.6 + 


    以上就是对象继承的一些问题,以记录之,谨防忘记。


  • 相关阅读:
    HDU2602:Bone Collector
    HDU5773:The All-purpose Zero
    LightOJ 1275:Internet Service Providers
    8.SpringMVC拦截器
    7.SpringMVC和Ajax技术
    Tomcat什么时候需要restart,redeploy,update classes and resources
    6.SpringMVC的JSON讲解
    5.SpringMVC数据处理
    4.SpringMVC的结果跳转方式
    3.SpringMVC的Controller 及 RestFul风格
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6881415.html
Copyright © 2020-2023  润新知