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

資訊專欄INFORMATION COLUMN

JS基礎(chǔ)-Prototype原型繼承

frolc / 1256人閱讀

摘要:如何確定原型和實(shí)例的關(guān)系第一個(gè)方法是,,用于檢測(cè)實(shí)例與原型鏈中出現(xiàn)過(guò)的構(gòu)造函數(shù)。所謂寄生組合繼承,即通過(guò)借用構(gòu)造函數(shù)方式,繼承屬性,通過(guò)原型鏈形式繼承方法。

概述

原型和閉包是JS的兩個(gè)難點(diǎn),最近碰到了原型繼承的概念,正好在這里總結(jié)一下。

既然要實(shí)現(xiàn)繼承,就一定要有一個(gè)父類。

        // 定義一個(gè)父類
        function father(name) {
            //屬性
            this.name = name;
        }
        // 原型方法
        father.prototype.getName = function () {
            return this.name;
        }
        
原型鏈繼承

基本思想就是利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法。

回顧一下原型、實(shí)例和構(gòu)造函數(shù)的關(guān)系。

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)指向原型對(duì)象內(nèi)部的指針。
        // 子類
        function son(age) {
            // 屬性
            this.age = age;
        };

        son.prototype = new father("jason");

        son.prototype.getAge = function () {
            return this.age;
        }

        let firstchild = new son("19");

        console.log(firstchild.getAge()) // 19
        

這里需要注意幾點(diǎn)的是:

默認(rèn)原型

原型鏈的最頂端是Object,所有引用類型默認(rèn)都是繼承于Object的,所以默認(rèn)也是有toString等方法的。

如何確定原型和實(shí)例的關(guān)系
第一個(gè)方法是,instanceof,用于檢測(cè)實(shí)例與原型鏈中出現(xiàn)過(guò)的構(gòu)造函數(shù)。

     console.log(firstchild instanceof Object) //true
     console.log(firstchild instanceof son) //true
     console.log(firstchild instanceof father) //true
第二個(gè)方法是,isPrototypeOf方法。
        console.log(Object.prototype.isPrototypeOf(firstchild)) //true
        console.log(son.prototype.isPrototypeOf(firstchild)) //true
        console.log(father.prototype.isPrototypeOf(firstchild)) //true

謹(jǐn)慎定義方法

子類型可能要重寫(xiě)父類型方法,或定義父類沒(méi)有的方法。不管是啥,這個(gè)方法一定要寫(xiě)在替換原型語(yǔ)句的后面。
還有原型鏈繼承的時(shí)候,不能使用對(duì)象字面量創(chuàng)建原型方法。

例如:

        son.prototype = new father("jason");

        son.prototype = {
            getAge: function() {
                return this.age
            }
        }

這樣會(huì)導(dǎo)致創(chuàng)建一個(gè)新的Object實(shí)例,而非原來(lái)的father。

共享性和傳參問(wèn)題

第一,引用類型的原型屬性會(huì)被所有實(shí)例共享。

        function father(name) {
            this.name = name;
            this.colors = ["blue", "red", "white"];
        }
        
        let firstchild = new son("19");
        let secondchild = new son("20");
        firstchild.colors.push("black");
        console.log(firstchild.colors) // ["blue", "red", "white", "black"]
        console.log(secondchild.colors) // ["blue", "red", "white", "black"]
        

第二,不能像父類型構(gòu)造函數(shù)傳參數(shù),書(shū)里準(zhǔn)確說(shuō)法是,沒(méi)有辦法在不影響所有實(shí)例的情況下,給父類構(gòu)造函數(shù)傳遞參數(shù)。

小結(jié)

優(yōu)點(diǎn):

非常純粹的繼承關(guān)系,實(shí)例是子類的實(shí)例,也是父類的實(shí)例

父類新增原型方法/原型屬性,子類都能訪問(wèn)到

簡(jiǎn)單,易于實(shí)現(xiàn)

缺點(diǎn):

要想為子類新增屬性和方法,必須要在new father()這樣的語(yǔ)句之后執(zhí)行,不能放到構(gòu)造器中

無(wú)法實(shí)現(xiàn)多繼承

來(lái)自原型對(duì)象的引用屬性是所有實(shí)例共享的

創(chuàng)建子類實(shí)例時(shí),無(wú)法向父類構(gòu)造函數(shù)傳參

借用構(gòu)造繼承

在子類型的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù),使用父類的構(gòu)造函數(shù)來(lái)增強(qiáng)子類實(shí)例,等于是復(fù)制父類的實(shí)例屬性給子類(不用原型)

        function son(age) {
            father.call(this);
            this.age = age;
        };

        son.prototype = new father("jason");
        
        son.prototype.getAge = function () {
            return this.age;
        }

        let firstchild = new son("19");
        let secondchild = new son("20");
        firstchild.colors.push("black");
        
        console.log(firstchild.colors); // ["blue", "red", "white", "black"]
        console.log(secondchild.colors); // ["blue", "red", "white"]

可以傳遞參數(shù)

方法都在構(gòu)造函數(shù)中定義,函數(shù)復(fù)用性丟失

總結(jié)

優(yōu)點(diǎn):

由例子可見(jiàn),解決了1中子類實(shí)例共享父類引用屬性的問(wèn)題

創(chuàng)建子類實(shí)例時(shí),可以向父類傳遞參數(shù)

可以實(shí)現(xiàn)多繼承(call多個(gè)父類對(duì)象)

缺點(diǎn):

實(shí)例并不是父類的實(shí)例,只是子類的實(shí)例

只能繼承父類的實(shí)例屬性和方法,不能繼承原型屬性/方法

無(wú)法實(shí)現(xiàn)函數(shù)復(fù)用,每個(gè)子類都有父類實(shí)例函數(shù)的副本,影響性能

組合繼承

也就是將原型鏈繼承和構(gòu)造函數(shù)繼承融合,原型鏈實(shí)現(xiàn)對(duì)原型屬性和方法的繼承,構(gòu)造函數(shù)實(shí)現(xiàn)對(duì)實(shí)例屬性的繼承。
這樣既保證了原型上函數(shù)的復(fù)用,也保證了每個(gè)實(shí)例有自己的屬性。

         function son(name, age) {
            father.call(this, name);
            this.age = age;
        };

        son.prototype = new father();
        
        son.prototype.getAge = function () {
            return this.age;
        }


        let firstchild = new son("jason", "19");
        let secondchild = new son("jason junior", "18");
        firstchild.colors.push("black");
        
        
        console.log(firstchild.colors); // ["blue", "red", "white", "black"]
        console.log(secondchild.colors); //["blue", "red", "white"]
        console.log(firstchild.getName()); // jason
        console.log(secondchild.getName()); // jason junior
        console.log(firstchild.getAge()); //19
        console.log(secondchild.getAge()); //18

特點(diǎn):

可以繼承實(shí)例屬性/方法,也可以繼承原型屬性/方法

既是子類的實(shí)例,也是父類的實(shí)例

不存在引用屬性共享問(wèn)題

可傳參

函數(shù)可復(fù)用

缺點(diǎn):

調(diào)用了兩次父類構(gòu)造函數(shù),生成了兩份實(shí)例(子類實(shí)例將子類原型上的那份屏蔽了)

原型式繼承

為父類實(shí)例添加新特性,作為子類實(shí)例返回

        let p = {
            name: "jason",
            colors: ["white", "black", "red"]
        }
        function object (o) {
            function F() {};
            F.prototype = o;
            return new F();
        }

        let firstchild = object(p)
        let secondchild = object(p)

        firstchild.name = "jason1"
        firstchild.colors.push("blue")

        secondchild.name = "jason2"
        secondchild.colors.push("green")

        console.log(p.colors) //?["white", "black", "red", "blue", "green"]

ECMAScript 5新增Object.create()方法規(guī)范原型式繼承。兩個(gè)參數(shù),一個(gè)參數(shù)是新對(duì)象原型的對(duì)象,一個(gè)參數(shù)是對(duì)象定義額外屬性的對(duì)象,第二個(gè)可忽略,就等于上述object函數(shù)了

寄生式繼承

創(chuàng)造一個(gè)用于封裝繼承過(guò)程的函數(shù),該函數(shù)內(nèi)部以某種方式增強(qiáng)對(duì)象。

        function create(o) {
            let clone = object(o);
            o.sayHi = function () {
                console.log("Hi")
            }
            return o;
        }
寄生組合繼承

組合繼承雖然好用,但是也有缺陷,就是會(huì)調(diào)用兩次構(gòu)造函數(shù),一次在創(chuàng)建時(shí)候,一次在內(nèi)部,那個(gè)call方法。

所謂寄生組合繼承,即通過(guò)借用構(gòu)造函數(shù)方式,繼承屬性,通過(guò)原型鏈形式繼承方法。

沿用寄生方式:

        function inheritPrototype (sub, sup) {
            let prototype = object(sup.prototype);
            prototype.constructor = sub;
            sub.prototype = prototype;
        }
        function father(name) {
            this.name = name;
            this.colors = ["blue", "red", "white"];
        }

        father.prototype.getName = function () {
            return this.name;
        }

        function son(name, age) {
            father.call(this, name);
            this.age = age;
        };

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

        function inheritPrototype (sub, super) {
            let prototype = object(super.prototype);
            prototype.constructor = sub;
            sub.prototype = prototype;
        }

        inheritPrototype(son, father);

        son.prototype.getAge = function () {
            return this.age;
        }
總結(jié)

優(yōu)點(diǎn):

堪稱完美

缺點(diǎn):

實(shí)現(xiàn)較為復(fù)雜

參考 <>總結(jié)

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

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

相關(guān)文章

  • JS基礎(chǔ)(對(duì)象創(chuàng)建,構(gòu)造函數(shù)、原型、實(shí)例之間關(guān)系,繼承方式)

    摘要:對(duì)象創(chuàng)建的三種方式字面量創(chuàng)建方式系統(tǒng)內(nèi)置構(gòu)造函數(shù)方式自定義構(gòu)造函數(shù)構(gòu)造函數(shù)原型實(shí)例之間的關(guān)系實(shí)例是由構(gòu)造函數(shù)實(shí)例化創(chuàng)建的,每個(gè)函數(shù)在被創(chuàng)建的時(shí)候,都會(huì)默認(rèn)有一個(gè)對(duì)象。 JS 對(duì)象創(chuàng)建的三種方式 //字面量創(chuàng)建方式 var person= { name:jack } //系統(tǒng)內(nèi)置構(gòu)造函數(shù)方式 var person= new Object(); person.name = jack; ...

    PAMPANG 評(píng)論0 收藏0
  • 重溫JS基礎(chǔ)--繼承

    摘要:繼承了如上,我們通過(guò)方法借調(diào)了超類的構(gòu)造函數(shù),實(shí)際上是在新創(chuàng)建的實(shí)力環(huán)境下調(diào)用了構(gòu)造函數(shù)。組合繼承組合繼承的基本思想將原型鏈和借用構(gòu)造函數(shù)的技術(shù)組合到一塊,從而發(fā)揮二者之長(zhǎng)的一種繼承模式。繼承方法在上面這個(gè)例子中,構(gòu)造函數(shù)定義了兩個(gè)屬性和。 在ECMAScript中只支持實(shí)現(xiàn)繼承,而且實(shí)現(xiàn)繼承主要是依靠原型鏈來(lái)實(shí)現(xiàn)的。 1. 什么是原型鏈 繼承基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)...

    sixleaves 評(píng)論0 收藏0
  • js組合模式和寄生組合模式的區(qū)別研究

    摘要:組合模式繼承結(jié)合了構(gòu)造函數(shù)繼承時(shí)可以為每個(gè)屬性重新初始化,構(gòu)造一個(gè)副本的優(yōu)點(diǎn),以及原型鏈繼承時(shí)一次定義處處共享的優(yōu)點(diǎn)。但令我百思不得其解的是,從上面給出的例子來(lái)看,組合繼承并沒(méi)有調(diào)用兩次超類型構(gòu)造函數(shù)。 最近在閱讀《js權(quán)威指南》的繼承這一章,對(duì)于組合模式和寄生組合模式的區(qū)別有點(diǎn)混淆,在多次重讀以及嘗試之后,得到一些心得。 組合模式繼承 結(jié)合了構(gòu)造函數(shù)繼承時(shí)可以為每個(gè)屬性重新初始化,構(gòu)...

    tolerious 評(píng)論0 收藏0
  • javascript基礎(chǔ)篇:關(guān)于js面向?qū)ο蟮睦斫?/b>

    摘要:關(guān)于中面向?qū)ο蟮睦斫饷嫦驅(qū)ο缶幊趟且环N編程思想我們的編程或者學(xué)習(xí)其實(shí)是按照類實(shí)例來(lái)完成的學(xué)習(xí)類的繼承封裝多態(tài)封裝把實(shí)現(xiàn)一個(gè)功能的代碼封裝到一個(gè)函數(shù)中一個(gè)類中以后再想實(shí)現(xiàn)這個(gè)功能,只需要執(zhí)行這個(gè)函數(shù)方法即可,不需要再重復(fù)的編寫(xiě)代碼。 關(guān)于js中面向?qū)ο蟮睦斫?面向?qū)ο缶幊?oop) 它是一種編程思想 (object-oriented programming ), 我們的編程或者學(xué)習(xí)其...

    roadtogeek 評(píng)論0 收藏0
  • javascript基礎(chǔ)篇:關(guān)于js面向?qū)ο蟮睦斫?/b>

    摘要:關(guān)于中面向?qū)ο蟮睦斫饷嫦驅(qū)ο缶幊趟且环N編程思想我們的編程或者學(xué)習(xí)其實(shí)是按照類實(shí)例來(lái)完成的學(xué)習(xí)類的繼承封裝多態(tài)封裝把實(shí)現(xiàn)一個(gè)功能的代碼封裝到一個(gè)函數(shù)中一個(gè)類中以后再想實(shí)現(xiàn)這個(gè)功能,只需要執(zhí)行這個(gè)函數(shù)方法即可,不需要再重復(fù)的編寫(xiě)代碼。 關(guān)于js中面向?qū)ο蟮睦斫?面向?qū)ο缶幊?oop) 它是一種編程思想 (object-oriented programming ), 我們的編程或者學(xué)習(xí)其...

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

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

0條評(píng)論

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