• 构造函数的继承


    1.构造函数其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。

     
    function Cat(name,color){
        this.name=name;
        this.color=color;
          this.type = "猫科动物";
          this.eat = function(){console.log("吃老鼠");};
      }
      var cat1 = new Cat("大毛","黄色");
      var cat2 = new Cat("二毛","黑色");
      console.log(cat1.name); // 大毛
      console.log(cat1.color); // 黄色
        //这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。
        console.log(cat1.constructor == Cat); //true
        console.log(cat2.constructor == Cat); //true
        //instanceof运算符,验证原型对象与实例对象之间的关系。
        console.log(cat1 instanceof Cat); //true
        console.log(cat2 instanceof Cat); //true

        console.log(cat1.type); // 猫科动物
        cat1.eat(); // 吃老鼠

    这样写的弊端:对于每一个实例对象,type属性和eat()方法都是一模一样的内容,每一次生成一个实例,都必须为重复的内容,多占用一些内存。这样既不环保,也缺乏效率。

    
    
    console.log(cat1.eat == cat2.eat); //false

    所以对于相同的属性和方法等,要用prototype去定义。上面的那两个公共部分应该如下写:

    
    
      Cat.prototype.type = "猫科动物";
      Cat.prototype.eat = function(){console.log("吃老鼠")};

    此时:

    
    
    console.log(cat1.eat == cat2.eat); //true

    其实这也是JavaScript继承机制的设计思想,所有实例对象需要共享的属性和方法,都放在prototype对象里面;那些不需要共享的属性和方法,就放在构造函数里面。

    一些常用属性:

    
    
       console.log(Cat.prototype.isPrototypeOf(cat1)); //true
      console.log(Cat.prototype.isPrototypeOf(cat2)); //true

        //本地属性才为true,prototype继承的属性为false
      console.log(cat1.hasOwnProperty("name")); // true
      console.log(cat1.hasOwnProperty("type")); // false

      console.log("name" in cat1); // true
      console.log("type" in cat1); // true
        for(var prop in cat1) { //遍历属性,包括继承的
            console.log("cat1[" + prop + "]=" + cat1[prop]); 
        }
    
    

     

    2.构造函数的继承

    一、 构造函数绑定。使用call或apply方法,将父对象的构造函数绑定在子对象上。

    
    
        function Animal(){
        this.species = "动物";
      }
      function Cat(name,color){
        Animal.apply(thisarguments);
        this.name = name;
        this.color = color;
      }
      var cat1 = new Cat("大毛","黄色");
      console.log(cat1.species); // 动物

    二、 prototype模式

     
     function Animal(){
        this.species = "动物";
      }
      function Cat(name,color){
        this.name = name;
        this.color = color;
      }
        console.log(Cat.prototype); //Object
        Cat.prototype = new Animal();
        console.log(Cat.prototype); //Animal

        //Cat的prototype对象指向一个Animal的实例,所以Cat也拥有constructor属性
        console.log(Cat.prototype.constructor);//function Animal(){this.species = "动物";}
        console.log(Cat.prototype.constructor == Animal);//true
        Cat.prototype.constructor=Cat;//如果没有这一句,cat1的构造函数就是上面的Animal,所以要把它更正为Cat
        console.log(Cat.prototype.constructor);//function Cat(name,color){this.name = name;this.color = color;}

      var cat1 = new Cat("大毛","黄色");
        console.log(cat1.species); // 动物
       console.log(cat1.constructor); //function Cat(name,color){this.name = name;this.color = color;}


        //也就是说,当替换了prototype对象
        //o.prototype = {};
        //必须要修正constructor
        //o.prototype.constructor = o;
    
    

     

    前面两种方法是把属性直接定义在构造函数里,一般公共属性的话一般放在prototype,继承的方式如下

    三、 直接继承prototype(不够完善)

    
    
     function Animal(){}
        Animal.prototype.species = "动物";
        function Cat(name,color){
        this.name = name;
        this.color = color;
      }
      Cat.prototype = Animal.prototype;
      Cat.prototype.constructor = Cat;
      var cat1 = new Cat("大毛","黄色");
      console.log(cat1.species); // 动物
        console.log(Cat.prototype.constructor);//function Cat(name,color){this.name = name;this.color = color;}
        console.log(Animal.prototype.constructor);//function Cat(name,color){this.name = name;this.color = color;}这样很混乱
        //与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。
        //缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,Cat.prototype与Animal.prototype永远保持一致,属性也是。

    四、 利用空对象作为中介

    
    
        function Animal(){}
        Animal.prototype.species = "动物";
        function Cat(name,color){
        this.name = name;
        this.color = color;
      }
      function extend(ChildParent) {  //封装好
        var F = function(){};
        F.prototype = Parent.prototype;
        Child.prototype = new F();  //用空对象作为中介,避免了直接继承的弊端
        Child.prototype.constructor = Child;
        //Child.uber = Parent.prototype;//使之可以调用父对象的方法,实现继承的完备性
      }
        extend(Cat,Animal);
      var cat1 = new Cat("大毛","黄色");
      console.log(cat1.species); // 动物

    五、 拷贝继承

    
    
       function Animal(){}
        Animal.prototype.species = "动物";
        function Cat(name,color){
        this.name = name;
        this.color = color;
      }
      function extend2(ChildParent) {//封装好
        var p = Parent.prototype;
        var c = Child.prototype;
        for (var i in p) {
                console.log(i);
                console.log(p[i]);
          c[i] = p[i];
        }
        //c.uber = p;
      }
       extend2(CatAnimal);
      var cat1 = new Cat("大毛","黄色");
      console.log(cat1.species); // 动物

     

  • 相关阅读:
    Servlet3.0-使用注解定义Servlet
    poj 1256 Anagram—next_permutation的神奇应用
    poj 1664 放苹果 (划分数)
    poj 1011 Sticks
    poj和hdu部分基础算法分类及难度排序
    Notepad++支持jQuery、html5、css3
    Codeforces Round #395 (Div. 2) C. Timofey and a tree
    Codeforces Round #390 (Div. 2) D. Fedor and coupons
    bazel-编译动态库
    bazel-编译多目标
  • 原文地址:https://www.cnblogs.com/shen076/p/6556868.html
Copyright © 2020-2023  润新知