成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

基礎(chǔ)二:javascript面向?qū)ο蟆?chuàng)建對(duì)象、原型和繼承總結(jié)(下)

617035918 / 463人閱讀

摘要:當(dāng)調(diào)用的構(gòu)造函數(shù)時(shí),在函數(shù)內(nèi)部又會(huì)調(diào)用的構(gòu)造函數(shù),又在新對(duì)象上創(chuàng)建了實(shí)例屬性和,于是這兩個(gè)屬性就屏蔽了原型中的同名屬性。

前言:這次對(duì)上篇收個(gè)尾,主要總結(jié)一下javascript的繼承。

1.原型鏈

js中原型鏈?zhǔn)菍?shí)現(xiàn)繼承的主要方法?;舅枷胧牵豪迷妥屢粋€(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。我們來簡(jiǎn)單回顧一下以前的內(nèi)容:

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象

每個(gè)原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針:(constructor)

而實(shí)例和構(gòu)造函數(shù)都有一個(gè)prototype屬性指針指向原型對(duì)象。

假如現(xiàn)在我們讓原型對(duì)象(A)等于另一個(gè)類型的實(shí)例(b),此時(shí)相當(dāng)于這個(gè)原型對(duì)象(A)整體作為一個(gè)實(shí)例指向另一個(gè)實(shí)例的原型對(duì)象(b的原型對(duì)象B)。

以上就實(shí)現(xiàn)了繼承。

看下面代碼實(shí)例:

    function SuperType(){
        this.property = true;    //property是SuperType的實(shí)例屬性
    };
    
    SuperType.prototype.getSuperValue = function(){  //getSuperValue是SuperType的原型方法
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    //讓SuperType繼承SubType
    SubType.prototype = new SuperType();
    
    SubType.prototype.getSubValue = function(){
        return this.subproperty;
    };
    
    var instance = new SubType();
    alert(instance.getSuperValue());      //true

在上面的代碼中,定義了兩個(gè)類型:SuperType和SubType。每個(gè)類型分別有一個(gè)屬性和方法。

通過創(chuàng)建SuperType的實(shí)例,并賦值給了SubType.prototype,從而實(shí)現(xiàn)SubType繼承了這個(gè)的實(shí)例,

原來存在于SuperType的實(shí)例中的所有的屬性和方法,現(xiàn)在也存在于SubType.prototype中了。

既然現(xiàn)在SubType的原型對(duì)象SubType.prototype是SuperType的實(shí)例化對(duì)象,那么SuperType的實(shí)例屬性property就位于SubType.prototype。如下圖:

現(xiàn)在instance.constructor現(xiàn)在指向的是SuperType,圖中可以看出來。也可以在進(jìn)行繼承之后,再進(jìn)行如下步驟:
SubType.prototype.constructor = Subtype;

2.完整原型鏈

所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,所以下圖是上面例子的完整原型鏈。

3.重寫或添加方法到超類型

(1)重寫和添加方法必須在用超類型的實(shí)例(new SuperType())替換原型(SubType.prototype)之后。

    function SuperType(){
        this.property = true;    
    };
    
    SuperType.prototype.getSuperValue = function(){  
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    //讓SuperType繼承SubType
    SubType.prototype = new SuperType();
    //添加新方法
    SubType.prototype.getSubValue = function(){
        return this.subproperty;
    };
    //重寫超類型中的方法
    SubType.prototype.getSuperValue = function(){
        return false;
    };

    var instance = new SubType();
    alert(instance.getSuperValue());      //false
    alert((new SuperType()).getSuperValue());   //我仿照java這么寫,居然返回true

重寫超類型中的方法之后,通過SuperType的實(shí)例調(diào)用getSuperValue()時(shí),調(diào)用的就是這個(gè)重新定義的方法。

通過SuperType的實(shí)例調(diào)用getSuperValue()時(shí),調(diào)用的就是超類型中的方法,返回true

(2)通過原型鏈實(shí)現(xiàn)繼承時(shí),不能使用對(duì)象字面量創(chuàng)建原型方法,這樣會(huì)重寫原型鏈

    function SuperType(){
        this.property = true;    
    };
    
    SuperType.prototype.getSuperValue = function(){  
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    //讓SuperType繼承SubType
    SubType.prototype = new SuperType();
    
    SubType.prototype = {
        getSubValue: function(){
            return this.subproperty;
        },
        someOtherMethod: function(){
            return false;
        }
    };

    var instance = new SubType();
    alert(instance.getSuperValue());      //error

(3)原型鏈的問題

在通過原型鏈進(jìn)行繼承時(shí),原型實(shí)際上會(huì)變成另一個(gè)類型的實(shí)例,所以原先的實(shí)例屬性也就變成了現(xiàn)在的原型屬性了。

現(xiàn)在假如原型實(shí)例的屬性是引用類型的,那么它會(huì)直接被添加成現(xiàn)在的對(duì)象原型的屬性,那么通過這個(gè)創(chuàng)建的實(shí)例對(duì)這個(gè)引用類型的屬性進(jìn)行更改時(shí),會(huì)立即反映在所有的實(shí)例對(duì)象上。

看下面代碼:

    function SuperType(){
        this.colors = ["red","blue","green"];    
    };
    
    function SubType(){
    }
    
    //讓SubType繼承SuperType
    SubType.prototype = new SuperType();
    
    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);       //["red","blue","green","black"]
    
    var instance2 = new SubType();
    alert(instance2.colors);        //["red","blue","green","black"]

當(dāng)SubType通過原型鏈繼承了SuperType之后,SubType.prototype就變成了SuperType的一個(gè)實(shí)例

此時(shí)SubType擁有一個(gè)自己的colors屬性,就像專門創(chuàng)建了一個(gè)SubType.prototype.colors屬性一樣

此時(shí)SubType所有的實(shí)例話對(duì)象都會(huì)共享這個(gè)colors屬性,修改instances1的colors屬性會(huì)立即在instances2中顯示出來。

原型鏈還有一個(gè)問題:在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(shù),實(shí)際上是沒有辦法在不影響所有對(duì)象實(shí)例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù)。

4.實(shí)現(xiàn)繼承的其它方法 (1)借用構(gòu)造函數(shù)

基本思想:

在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型的構(gòu)造函數(shù),通過使用call()方法或者apply()方法。

例子:

    function SuperType(name){
        this.name = name;
        this.colors = ["red","blue","green"];
    }
    
    function SubType(name,age){
        //繼承了SuperType,同時(shí)還傳遞了參數(shù)
        SuperType.call(this,name);
        //再為子類型定義屬性
        this.age = age;
    }
    
    var instance1 = new SubType("Jack");
    alert(instance1.name);
    instance1.colors.push("black");
    alert(instance1.colors);       //"red,blue,green,black"
    
    var instance2 = new SubType();
    alert(instance2.colors);        //"red,blue,green"

上述代碼中解決了一個(gè)問題,就是引用類型的屬性問題,每個(gè)實(shí)例化的子類型都有自己的特有的屬性

還存在一個(gè)問題,如果方法都定義在構(gòu)造函數(shù)中,那么方法的就不能復(fù)用。

(2)組合繼承-最常用的繼承模式

組合繼承的思路是:

使用原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,通過借用構(gòu)造函數(shù)來實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承

這樣既通過在原型上定義方法實(shí)現(xiàn)了函數(shù)復(fù)用,又能夠保證每個(gè)實(shí)例都有它自己的屬性。

例子:

    function SuperType(name){
        this.name = name;
        this.colors = ["red","blue","green"];
    }
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    function SubType(name,age){
        //繼承SuperType的屬性
        SuperType.call(this,name);
        this.age = age;
    }
    
    //繼承SuperType的方法
    SubType.prototype = new SuperType();
    //定義子類型自己的方法
    SubType.prototype.sayAge = function(){
        alert(this.age);
    };
    
    var instance1 = new SubType("Jack",26);
    instance1.colors.push("black");
    alert(instance1.colors);       //"red,blue,green,black"
    instance1.sayName();          //Jack
    instance1.sayAge();          //26
    
    var instance2 = new SubType("Rose",23);
    alert(instance2.colors);      //"red,blue,green"
    instance2.sayName();          //Rose
    instance2.sayAge();           //23
(3)原型式繼承

思路:借助原型可以基于已有的對(duì)象創(chuàng)建新對(duì)象,還不必因此創(chuàng)建自己的自定義類型
如下:

    function object(o){
        function F(){};
        F.prototype = o;
        return new F();
    }

object()函數(shù)內(nèi)部先創(chuàng)建一個(gè)臨時(shí)性的函數(shù)。

然后將傳入的對(duì)象作為這個(gè)構(gòu)造函數(shù)的原型。

最后返回這個(gè)臨時(shí)類型的餓新實(shí)例。

如下:

    var person = {
        name:"Jack",
        friends:["路人甲","路人乙"]
    };
    var anotherPerson = object(person);   //此處調(diào)用上方的object方法
    anotherPerson.name = "Rose";
    anotherPerson.friends.push("路人丙");
    
    var yetPerson = object(person);
    yetPerson.name = "Rick";
    yetPerson.friends.push("路人丁");
    
    alert(person.friends);      //["路人甲","路人乙","路人丙","路人丁"]

上述person.friends不僅屬于person所有,而且會(huì)被anotherPerson和yetPerson共享。
還有Object.create()方法,前面已經(jīng)總結(jié)過了。

(4)寄生式繼承

思路:創(chuàng)建一個(gè)僅用于封裝繼承過程的函數(shù)。

    function createAnother(original){
        var clone = object(original);    //調(diào)用前面的object()方法
        clone.sayHi = function(){
            alert("hi");
        };
        return clone;
    }
    
    //使用
    var person = {
        name:"Jack",
        friends:["路人甲","路人乙","路人丙"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi();       //"Hi"
    
5.寄生組合式繼承 (1)組合繼承存在的問題

組合繼承是js最常用的繼承模式,不過它有自己的不足,組合繼承最大的問題在于要調(diào)用兩次超類型的構(gòu)造函數(shù)一次是創(chuàng)建超類型的實(shí)例賦值給子類型的原型對(duì)象時(shí),一次是子類型構(gòu)造函數(shù)內(nèi)部
最終子類型會(huì)包含超類型對(duì)象的全部實(shí)例屬性,但是我們不得不在調(diào)用子類型構(gòu)造函數(shù)時(shí)重寫這些屬性。

看下面例子:

    function SuperType(name){
        this.name = name;
        this.colors = ["red","blue","green"];
    }
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    
    function SubType(name,age){
        SuperType.call(this,name);           //第二次調(diào)用
        this.age = age;
    }
    
    SubType.prototype = new SuperType();        //第一次調(diào)用
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function(){
        alert(this.age);
    };

第一次調(diào)用SuperType構(gòu)造函數(shù)時(shí),SubType.prototype會(huì)得到兩個(gè)屬性:name和colors,它們都是SuperType的實(shí)例屬性,只不過位于SubType的原型中。

當(dāng)調(diào)用SubType的構(gòu)造函數(shù)時(shí),在函數(shù)內(nèi)部又會(huì)調(diào)用SuperType的構(gòu)造函數(shù),又在新對(duì)象上創(chuàng)建了實(shí)例屬性name和colors,于是這兩個(gè)屬性就屏蔽了原型中的同名屬性。

(2)解決方法

寄生組合式繼承的思想是:不必為了子類型的原型而調(diào)用超類型的構(gòu)造函數(shù),我們所需要的無非就是超類型的一個(gè)副本而已,本質(zhì)上就是使用寄生式繼承來繼承超類型的原型,把返回的結(jié)果賦值給子類型的原型。

大家一定還記得上面說的原型式繼承吧吧,將一個(gè)對(duì)象淺賦值給另一個(gè)對(duì)象,現(xiàn)在也可以把一個(gè)超類型的原型賦值給另一個(gè)子類型原型

1.回憶一下object()函數(shù)的代碼

    function object(o){
        function F(){}
        F.prototype = 0;
        return new F();
    }

2.創(chuàng)建一個(gè)函數(shù),它接收兩個(gè)參數(shù):子類型構(gòu)造函數(shù)和超類型構(gòu)造函數(shù)。

    function inheritPrototype(subType,superType){
        var prototype = object(superType.prototype);
        prototype.constructor = subType;
        subType.prototype = prototype;
    }

上面的代碼第一步創(chuàng)建超類型原型的一個(gè)副本

為創(chuàng)建的副本添加constructor屬性,彌補(bǔ)因重寫原型而失去默認(rèn)的constructor屬性
此處的重寫發(fā)生在object()函數(shù)里面,超類型的原型superType.prototype直接賦給了F.prototype,然后object()函數(shù)又返回了F的新實(shí)例。

把創(chuàng)建新的對(duì)象賦值給子類型的原型

3.那么現(xiàn)在來使用一下

    function SuperType(name){
        this.name = name;
        this.colors = ["red","blue","green"];
    }
    SuperType.prototype.sayName = function(){
        alert(this.name);
    };
    function SubType(name,age){
        SuperType.call(this,name);
        this.age = age;
    }
    inheritPrototype(subType,SuperType);
    SubType.prototype.sayAge = function(){
        alert(this.age);
    };
    

上述代碼高效率,因?yàn)樗徽{(diào)用了一次SuperType的構(gòu)造函數(shù),因此避免了在SubType.prototype上面創(chuàng)建不必要的、多余的屬性,

此時(shí)原型鏈還能保持不變。

以上~~~~~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/79980.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評(píng)論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對(duì)象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對(duì)象。對(duì)象就是數(shù)據(jù),對(duì)象本身不包含方法。類是相似對(duì)象的描述,稱為類的定義,是該類對(duì)象的藍(lán)圖或原型。在中,對(duì)象通過對(duì)類的實(shí)體化形成的對(duì)象。一類的對(duì)象抽取出來。注意中,對(duì)象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評(píng)論0 收藏0
  • 基礎(chǔ)javascript面向對(duì)象、創(chuàng)建對(duì)象原型繼承總結(jié)(上)

    摘要:創(chuàng)建對(duì)象兩個(gè)基本方法創(chuàng)建對(duì)象最基本的兩個(gè)方法是構(gòu)造函數(shù)和對(duì)象字面量。當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建一個(gè)新的實(shí)例對(duì)象后,該實(shí)例內(nèi)部會(huì)有一個(gè)指針指向構(gòu)造函數(shù)的原型對(duì)象。碼農(nóng)構(gòu)造函數(shù)在不返回值的情況下,默認(rèn)會(huì)返回新對(duì)象實(shí)例。 前言:本文主要總結(jié)一下javascript創(chuàng)建對(duì)象的方法、原型、原型鏈和繼承,但是先從創(chuàng)建對(duì)象的幾種方法開始,延伸到原型模式創(chuàng)建對(duì)象以及其它模式。繼承本來想一塊寫了,發(fā)現(xiàn)太多內(nèi)容了...

    fevin 評(píng)論0 收藏0
  • JS前端面試總結(jié)

    摘要:春招季如何橫掃面試核心考點(diǎn)基礎(chǔ)版前端面試之路二基礎(chǔ)整理的繼承和的繼承有什么區(qū)別的繼承時(shí)通過或構(gòu)造函數(shù)機(jī)制來實(shí)現(xiàn)。作用創(chuàng)建私有變量,減少全局變量,防止變量名污染。異步瀏覽器訪問服務(wù)器請(qǐng)求,用戶正常操作,瀏覽器后端進(jìn)行請(qǐng)求。 春招季如何橫掃 Javascript 面試核心考點(diǎn)(基礎(chǔ)版)?前端面試之路二(javaScript基礎(chǔ)整理) ES5的繼承和ES6的繼承有什么區(qū)別 ES5的繼承時(shí)通過...

    ThinkSNS 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<