zoukankan      html  css  js  c++  java
  • JavaScript继承

    1)原型链

      ①原型链示例

    function Shape() {
        this.name = 'shape';
        this.toString = function(){
            return this.name;
        }
    }
    
    function TwoDshape () {
        this.name = '2D shape';
    }
    
    function Triangle (side,height) {
        this.name = 'Triangle';
        this.side = side;
        this.height = height;
        this.getArea = function () {
            return this.side * this.height / 2;
        }
    }
    
    TwoDshape.prototype = new Shape();
    Triangle.prototype = new TwoDshape();   //用new新建对象实体,并赋值覆盖该对象的原型
    TwoDshape.prototype.constructor = TwoDshape;
    Triangle.prototype.constructor = Triangle; 
    
    var my = new Triangle(5,10); 
    my.getArea();       //25
    console.log(my.toString());//继承的方法,具体步骤(遍历my对象属性没有找到,接着查看my.__proto__所指向的对象,即new TwoDshape()创建的实体,
    //依然没找到,又继续查找该实体的__proto__所指向的对象,即new Shape()所创建的实体,找到toString方法,并在my对象中被调用,this指向my)
    
    
    //通过instanceof操作符,我们可以验证my对象同时是上面三个构造器的实例
    my instanceof Shape;          //true
    my instanceof  TwoDShape;     //true
    my instanceof Triangle;      //true
    
    //我们也可以用其他两个构造器来创建对象,用new TwoDshape()所创建的对象也可以获得继承自Shape()的toString()方法
    var td = new TwoDshape();
    td.constructor === TwoDshape;   //true;
    td.toString();          // 2D shape
    
    var s = new Shape();
    s.constructor === shape;    // true;
    

      

     ②将共享属性迁移到原型中去

    function Shape(){this.name='shape'}//使用new Shape()新建对象,每个实体都有全新的属性并占用独立空间
    function Shape(){};Shape.prototype.name='shape';//属性移到原型后,使用new新建对象时,不再含自己独立的这个属性
    

      

    2)只继承于原型

    Triangle.prototype=Shape.prototype;//减少继承方法的查询步骤
    Triangle.prototype.name='Triangle';//修改子对象原型后父对象原型也随即被改,即再new Shape()新建对象时,新对象name为‘Triangl
    

      

      ②临时构造器——new F()

    function Shape() {}
    Shape.prototype.name = "shape";
    Shape.prototype.toString = function () {
        return this.name;
    }
    
    
    function TwoDshape() {}
    var F = function () {};
    F.prototype = Shape.prototype;
    TwoDshape.prototype = new F();
    TwoDshape.prototype.constructor = TwoDshape;
    TwoDshape.prototype.name = '2D shape';
    
    
    function Triangle(side, height) {
        this.side = side;
        this.height = height;
    }
    var F = function () {};
    F.prototype = TwoDshape.prototype;
    Triangle.prototype = new F();
    Triangle.prototype.constructor = Triangle;
    Triangle.prototype.name = 'Triangle';
    Triangle.prototype.getArea = function () {
        return this.side * this.height / 2;
    }
    
    
    var my = new Triangle (5,10);
    alert(my.getArea());
    
    //通过这种方法,我们仍然能保持住原型链
    my._proto_ === Triangle.prototype;              //true
    my._proto_.constructor === Triangle;            //true
    my._proto_._proto_ === TwoDshape.prototypr;        //true
    my._proto_._proto_._proto_.constructor === Shape;_    //true
    
    //并且父对象的属性不会被子对象覆盖:
    var s = new Shape();
    s.name;    // shape
    
    //calling toString()
    "I am a" + new TwoDshape();     //I am a 2D shape   
                             
    

      

     3)uber—子对象访问父对象的方式

    function Shape(){}
    Shape.prototype.name='shape';
    Shape.prototype.toString=function(){
      var const = this.constructor;
      return const.uber
         ? this.const.uber.toString() + ',' + this.name
         : this.name;
    }
    function TwoDShape(){
    var F=function(){}
    F.prototype=Shape.prototype;
    TwoDShape.prototype=new F();
    TwoDShape.prototype.constructor=TwoDShape;
    TwoDShape.uber=Shape.prototype;
    TwoDShape.prototype.name='2D shape';
    function Triangle(side,height){
      this.side=side;
      this.height=height;
    }
    var F=function(){}
    F.prototype=TwoDShape.prototype;
    Triangle.prototype=new F();
    Triangle.prototype.constructor=Triangle;
    Triangle.uber=TwoDShape.prototype;
    Triangle.prototype.name='triangle';
    Triangle.prototype.getArea=function(){return this.side*this.height/2};
    var my=new Triangle(5,10)
    console.log(my.toString());//shape,2D shape,triangle
    

      

     4)将继承部分封装成函数

    function extend (Child,Parent) {
        var F = function () {};
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.prototype.constructor = Child;
        Child.uber = Parent.prototype;
    }
    
    
    extend(TwoDsgape,Shape);
    extend(Triangle,TwoDshape);
    

      

    5)属性拷贝

    /*属性拷贝执行的是对象原型的逐一拷贝,而非简单的原型链查询。
      所以需要特别注意的是:
        这种方法仅适用于包含基本数据类型的对象,
        所有的对象类型(包括函数和数组)都是不可复制的,
        因为他们只支持引用传递      
    */
    
    function extend2(Child,Parent){
        var p = Parent.prototype;
        var c = Child.prototype;
        for(var i in p){
            c[i] = p[i];
        }
        c.uber = p ;
    }
    

      

    6)小心处理引用拷贝

    var A=function(){},B=function(){};
    A.prototype.stuff=[1,2,3];
    A.prototype.name='a';
    extend2(B,A);//让B继承A使用方法二
    B.prototype.name+='b';//ab,A.prototype.name依然为a,因为拷贝的是值
    B.prototype.stuff.push(4);//此时A和B原型上的stuff同时被修改,因为拷贝的是应用
    B.prototype.stuff=['a','b','c']//如果完全重写事情就不一样了,A为原来,B为新的
    

      

    7)对象之间的继承(不使用构造器)

    function extendCopy (p) {
        var c = {};
        for (var i in p){
            c[i] = p[i];
        }
        c.uber = p;
        return c;
    }
    
    var shape ={
        name = 'shape',
        toString :function () {
            return this.name;
        }
    }
    
    var twoDee = extendCopy(shape);
    twoDee.name = '2D shape';
    twoDee.toString = function () {
        return this.uber.toString() + ',' + this.name;
    }
    
    //下面我们让triangle对象继承一个2D图形对象
    var triangle = extendCopy(twoDee);
    triangle.name = 'Triangle'
    triangle.getArea = function () {
        return this.side * this.height / 2;
    }
    
    
    //使用triangle
    triangle.side = 5;
    triangle.height = 10;
    triangle.getArea();          //25
    
    triangle.toString();        // shape,2D shape,Triangle
    

      

    8)深拷贝(当遇到对象类型时,再次调用拷贝)

    function deepCopy(p,c){
        c = c || {};
        for (var i in p){
            if(p.hasOwnProperty(i)){
                if(typeof p[i] === 'object'){
                    c[i] = Array.isArray(p[i]?[]:{});
                    deepCopy(p[i],c[i]);
                }else{
                    c[i] = p[i]
                }
            }
        }
        return c;
    }
    
    var parent = {
        numbers:[1,2,3],
        letters:['a','b','c'],
        obj:{
            prop : 1
        },
        bool : true
    };
    
    //我们分别用深拷贝和浅拷贝测试一下,就会发现两者的不同。
    //在深拷贝中,对对象的numbers属性进行更新不会对原对象产生影响。
    
    var mydeep = deepCopy(parent);
    var myshallow = extendCopy(parent);
    
    mydeep.numbers.push(4,5,6);
    mydeep.numbers     //[1,2,3,4,5,6]
    parent.numbers     //[1,2,3]
    
    myshallow.numbers.push(10);
    myshallow.numbers   //[1,2,3,10]
    parent.numbers      //[1,2,3,10]
    

      

    9)object()(用object函数来接受父对象,并返回一个以该对象为原型的新对象)

    function object(o){
      var n;
      function F(){}
      F.prototype=o;
      n=new F();
      n.uber=o;
      return n;
    }//这个函数与extendcopy基本相同
    

      

    10)原型继承与属性拷贝的混合应用

    function objectplus(o,stuff){
      var n;
      function F(){}
      F.prototype=o;
      n=new F();
      n.uber=o;
      for(var i in stuff){n[i]=stuff[i]}
      return n;
    }//两对象o用于继承,stuff用于拷贝方法与属性
    

      

    11)多重继承(一个对象中有不至一个父对象的继承)

    function multi(){
      var n={},stuff,j=0,len=arguments.length;
      for(j=0;i<len;j++){
        stuff=arguments[j];
        for(var i in stuff){n[i]=stuff[i]}
      }
      return n;
    }//内层循环用于拷贝属性,外层循环用于遍历多个父对象参数,若有相同属性后面替代之前
    

      

    12) 寄生式继承

    13)构造器借用

    待续...

  • 相关阅读:
    ExtJs系列教程
    linux 服务器时间 timedatectl命令时间时区操作详解
    aws CloudWatch Events
    AWS Shield
    aws ssm指令
    failed to set bridge addr: "cni0" already has an IP address different from 10.244.0.1/24
    AWS Systems Manager
    Amazon Inspector
    AWS 安全培训
    Amazon Inspector
  • 原文地址:https://www.cnblogs.com/yechanglv/p/6937966.html
Copyright © 2011-2022 走看看