JS 僞繼承 prototype

衆所周知JS中沒有類的概念,但是要想實現類的功能可以同過function模擬。如:

第一種繼承 (屬性繼承)


    //該函數相當於是一個構造器,也是一個僞類
    function Fn(){

        this.a = 4;
        this.b = 5;

        this.log = function(){
            console.log(this.a,this.b);
        }
    }

    function Fn1(){
        Fn.call(this);//調用父類的構造函數
    }

    Fn1.prototype = Fn.prototype;

    var fn = new Fn();
    var fn1 = new Fn1();

    //由此可見Fn1 是fn1的子類。
    fn1 instanceof Fn; // true
    fn  instanceof Fn1; // true

    fn.a = 5;

    //由此可見Fn1 繼承了 Fn得所有屬性和方法
    //而是是複製了一份Fn的屬性和方法,並不是對象的引用。
    console.log(fn.a); // 5
    console.log(fn1.a); // 4
    this.log(); // 4 5

總結: 這種繼承,是重新拷貝一份放入內存中,他們的值互相獨立,修改一個不會改變另一個。

第二種繼承 原型繼承(prototype)


    function Fn(){}

    Fn.prototype.data = {
        name: 'zhangsan'
    }
    Fn.prototype.getName = function(){

        return this.data.name;
    }

    function Fn1(){}

    //原型鏈繼承
    Fn1.prototype = Fn.prototype;

    var fn = new Fn();
    var fn1 = new Fn1();

    //所用Fn1 繼承了 Fn
    fn1 instanceof Fn;//true
    console.log(fn1.getName()); // zhangsan
    console.log(fn.getName()); // zhangsan

    //修改了fn的name屬性值
    fn.data.name = 'lisi';

    // 由此我們可看出 原型鏈繼承 是 引用繼承
    //不會重新拷貝一份變量。就像對象的引用一樣。
    console.log(fn.getName()); // lisi
    console.log(fn1.getName()); // lisi

兩種類的寫法造成示例的區別


    //第一種
    function Fn(){

        this.a = 4;
        this.b = 5;

        this.log = function(){
            console.log(this.a,this.b);
        }
    }

    var fn1 = new Fn();
    var fn2 = new Fn();
    fn1.a = 1;

    //由此可以看出兩個對象互不影響
    //說明每個對象裏都存在一份a和b
    fn1.log(); // 1 5
    fn2.log(); // 4 5


    //第二種
    function Fn(){}
    fn.prototype.name = 'zhangsan';
    fn.prototype.data = {
        a: 4,
        b: 5
    }
    fn.prototype.log = function(){
        console.log(this.data.a,this.data.b);
    }

    var fn1 = new Fn();
    var fn2 = new Fn();
    fn1.a = 1;

    //由此可見就算是不同的示例他們他們所指向的值是同一個。
    fn1.log();//1 5
    fn2.log();//1 5

    fn2.name = 'lisi';

    //這裏fn1.name並沒有被修改
    console.log(fn1.name); //zhangan
    console.log(fn2.name); // lisi

總結

  1. 類中直接this. 出來的屬性和方法都會直接複製一份給子類或者實例對象。個子類或實例對象之間互不影響。
  2. 使用prototype增加的屬性和方法,對象類型的只有一份,值類型的這會被複制。

收穫

由於函數都是通用的,所以比較上面兩種方法,第二種明顯比第一種性能要好的多,因爲避免了沒有必要的複製,肯定會比較節省內存。所以以後寫類的時候,儘量使用第二種方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章