天天看點

JavaScript原型prototypeprototype繼承

版權聲明:本文為部落客原創文章,轉載請注明出處。 https://blog.csdn.net/twilight_karl/article/details/59700099

prototype

聽說prototype是JavaScript中最難的部分,最近學習了相關知識,感覺确實挺複雜,主要是比較難了解。為了避免遺忘,将最近的學習做一個簡單的總結。

prototype類似java中的靜态方法和靜态變量。可以實作共享。對象中的proto指針指向prototype,prototype儲存着該類的“靜态屬性和方法和constructor”。constructor 可以擷取構造函數本身。

構造函數中的方法分為執行個體方法和原型方法,構造函數中定義的方法是執行個體方法。prototype指向的方法是原型方法。

//定義原型方法和原型屬性
            function Person(){}
            Person.prototype.height = 180;
            Person.prototype.sex = "man";
            Person.prototype.fun = function (){
                return this.height+this.sex;
            };           

直接輸出constructor會輸出構造函數的函數體。

alert(tom.__proto__.constructor);           

使用時的執行流程: 現在執行個體對象中找,如果找不到再到原型對象中找。(通路–>執行個體對象–>原型對象)

删除原型屬性:

delete Person.prototype.name;

isPrototypeOf()

判斷一個屬性是否指向自己的原型

Box.prototype.isPrototypeOf(屬性);

var tom = new Person();
    var jerry = new Person();
    var obj = new Object();

    var flag = Person.prototype.isPrototypeOf(tom);  // true
    var flag = Person.prototype.isPrototypeOf(obj);  // true
    var flag = Object.prototype.isPrototypeOf(tom);  // false           

是以,所有對象都指向Object的原型。如果改變object對象指向的原型,就改變了所有對象的原型。但是原型是單向的,所有對象都指向Object,但是Object不會指向其他對象

Object.prototype.name = "zhangsan";           

hasOwnProperty(屬性名) // ???

判斷是否存在指定的執行個體屬性。

in

查找執行個體和原型中的屬性,隻要存在就傳回

屬性名 in 對象名

隻判斷原型中的屬性(自定義函數)

hasOwnProperty傳回false && in傳回true 時滿足要求

封裝

對象的屬性分為執行個體屬性和原型屬性,為了将類封裝成一個整體,可以把原型屬性寫在構造函數内,但是這種方式每次建立對象時都會建立原型屬性,比較浪費資源:

function Fun(name , age){
            this.name = name ;
            this.age = age;

            Fun.prototype.run = function (){
                return this.name+this.age+"#";
            };
        }           

可以采取這種優化的方法,判斷原型對象是否被建立過,隻在第一次使用時建立原型屬性:

function Fun2(name , age){
            this.name = name ;
            this.age = age;

            if(typeof Fun2.prototype.run != 'function'){  alert("#");
                Fun2.prototype.run = function(){
                    return this.name + this.age+"#";
                }
            }
        }           

繼承

原型鍊繼承

被繼承叫做超類型,繼承的函數叫做子類型,繼承的對象可以使用父類的執行個體和原型屬性。

所有對象都是繼承自Object對象

// 繼承
        function A(){
            this.name = "a";
            this.age = 20;
        }
        A.prototype.name = "prototype_a";   // 原型屬性
        function B(){
            this.name = "b";
        }
        B.prototype = new A();              // 使 B 繼承 A

        var obj = new B();
        alert(obj.age);     // 20
        alert(obj.name);    // b 本地屬性覆寫父類屬性           

對象冒充

對象冒充無法繼承父類的prototype屬性,隻能冒充構造函數中的資訊。冒充的對象類型不變

function C(name){
        this.name = name;
        this.age = 100;
        this.sss = new Array(1,2,3,4,5);
    }
    C.prototype.family = "family";

    function D(name ,age ){
        C.call(this,name);
    }

    var d = new D("zhangsan",20);
    alert(d.name);          //zhangsan
    alert(d.age);           //100
    alert(d.family);        //1,2,3,4,5
    alert(d instanceof D);  //true
           

組合模式

在冒充的基礎上使用繼承,這樣就可以繼承原型方法

function E(name){
        this.name = name;
        this.sss = [1,2,3,4,5];
    }
    E.prototype.family = "prototype_family";

    function F(name , age){
        E.apply(this,[name]);
    }
    F.prototype = new E();

    var f = new F("lisi",40);
    alert(f.family);            // 1,2,3,4,5           

原型式繼承

對象時采用引用的關系。

// 原型式繼承
    function G(obj){
        var Temp = function (){}
        Temp.prototype = obj;
        return new Temp();
    }

    var data = {
        name:"zhangsanG",
        age:20,
        family:[1,2,3,4,5]
    };
    var g = new G(data);
    g.family.push(6);
    alert(data.family); //1,2,3,4,5,6

    var gg = new G(data);
    alert(gg.family);   // 1,2,3,4,5,6