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

資訊專欄INFORMATION COLUMN

JavaScript面向?qū)ο蟮某绦蛟O(shè)計

GitCafe / 2180人閱讀

摘要:前言說到面向?qū)ο?,可能第一想到的是或者這樣的語言。默認(rèn)情況下,所有原型對象都會自動獲得一個構(gòu)造函數(shù)屬性會執(zhí)行屬性所在函數(shù)。相對于原型鏈而言,借用構(gòu)造函數(shù)有一個很大的優(yōu)勢,即

前言

說到面向?qū)ο?,可能第一想到的是C++或者Java這樣的語言。這些語言有都一個標(biāo)志,那就是引入了類的概念。我們可以通過類創(chuàng)建任意數(shù)量的具有相同屬性和方法的對象。ECMAScript(JavaScript分為ECMAScript、DOM和BOM)中沒有類的概念,所以它的對象相比較基于類的語言還是有所不同的。

說說對象的屬性
 var person={
        name:"張三",
        age:23,
        sex:"男",
        sayName:function () {
            alert(this.name);
        }
    }

上面我們用了對象字面量的方式建了一個非常簡單的person對象,他擁有name、age、sex、sayName這些屬性,而這些屬性在創(chuàng)建時都帶有一些特征值,JavaScript通過這些特征值就可以定義這些屬性的行為。在ECMAScript中,屬性分為兩種:數(shù)據(jù)屬性和訪問器屬性。下面我們一一學(xué)習(xí)下。

數(shù)據(jù)屬性

數(shù)據(jù)屬性有四個特征值,分別為如下四個:

configurable
表示能否delete刪除屬性,能否修改屬性的特性,默認(rèn)值是false

enumerable
表示能否通過for-in循環(huán)返回屬性,默認(rèn)值是false

writable
表示能否修改屬性的值,默認(rèn)值是false

value
表示該屬性的值,我們讀取和修改都是在這個位置,默認(rèn)值是undefined

接下來我們一一理解這四個特征值。要修改屬性默認(rèn)的特性,必須使用ECMAScript 5的Object.defineProperty()方法

configurable
1.delete無效
    var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:"張三"
    });
    console.log(person.name);//張三
    delete person.name;
    console.log(person.name);//張三
2.不能修改屬性的特性
    var person={};
    Object.defineProperty(person,"name",{
        configurable:true,
        value:"張三"
    });
    Object.defineProperty(person,"name",{
        value:"李四"
    });
    console.log(person.name);//李四
    var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:"張三"
    });
    Object.defineProperty(person,"name",{
        value:"李四"
    });
    console.log(person.name);
    
    //控制臺報錯 Uncaught TypeError: Cannot redefine property: name
enumerable
    var person={};
    Object.defineProperty(person,"name",{
        enumerable:true,
        value:"張三"
    });
    Object.defineProperty(person,"age",{
        value:"23"
    });
    Object.defineProperty(person,"sayName",{
        enumerable:true,
        value:function () {
            alert(this.name);
        }
    });
    for( var prop in person){
        console.log(prop);
    }
    //控制臺輸出 name和sayName
writable
    var person={};
    Object.defineProperty(person,"name",{
        writable:false,
        value:"張三"
    });
    console.log(person.name);//張三
    person.name="李四";
    console.log(person.name);//張三
value
    var person={};
    Object.defineProperty(person,"name",{
        writable:true,
        value:"張三"
    });
    console.log(person.name);//張三
    person.name="李四";
    console.log(person.name);//李四
訪問器屬性

訪問器屬性有四個特征值,分別為如下四個:

configurable
表示能否delete刪除屬性,能否修改屬性的特性,默認(rèn)值是false

enumerable
表示能否通過for-in循環(huán)返回屬性,默認(rèn)值是false

get
在讀取屬性調(diào)用的函數(shù),默認(rèn)值是undefined

set
在設(shè)置屬性調(diào)用的函數(shù),默認(rèn)值是undefined

下面我們一一了解一下訪問器屬性的特征值,其中configurable和enumerable與上面數(shù)據(jù)類型一樣,這里我們就不多做介紹,主要我們說一下get和set。

 var person={
        name:"張三",
        age:32
    };
    Object.defineProperty(person,"sayAge",{
        get:function () {
            return this.name+":"+this.age+"歲";
        },
        set:function (newAge) {
            console.log("想要重返"+newAge+"歲?不存在的!");
        }
    });
    console.log(person.sayAge);//張三:32歲
    person.sayAge=18;//想要重返18歲?不存在的!
    console.log(person.sayAge);//張三:32歲

get和set并非需要同時都要指定。如果只指定get,那么這個屬性就是不可寫的;如果只指定set,那么這個屬性就是不可讀的。

 var person1={
        name:"張三",
        age:32
    };
    Object.defineProperty(person1,"sayAge",{
        get:function () {
            return this.name+":"+this.age+"歲";
        }
    });
    console.log(person1.sayAge);//張三:32歲
    person1.sayAge=18;
    console.log(person1.sayAge);//張三:32歲

    var person2={
        name:"李四",
        age:46
    };
    Object.defineProperty(person2,"sayAge",{
        set:function () {
            console.log("想要重返18歲?不存在的!");
        }
    });
    console.log(person2.sayAge);//undefined
    person2.sayAge=18;//想要重返18歲?不存在的!
    console.log(person2.sayAge);//undefined
定義多個屬性

這個里我們就要說一個Object.defineProperties()方法,具體用下看如下示例:

    var person = {};
    Object.defineProperties(person, {
        name: {
            writable: true,
            value: "張三"
        },
        age: {
            enumerable: true,
            value: 23,
        },
        sayName: {
            get: function () {
                return this.name;
            },
            set: function (newName) {
                console.log("名字修改完成");
                this.name=newName+"(修改)";
            }
        }
    });
讀取屬性的特性

這里我們可以正好驗(yàn)證我們前面所有默認(rèn)值。

    var person={};
    Object.defineProperty(person,"name",{
        value:"張三"
    });
    var descriptor=Object.getOwnPropertyDescriptor(person,"name");
    console.log("configurable:"+descriptor.configurable);
    //configurable:false
    console.log("enumerable:"+descriptor.enumerable);
    //enumerable:false
    console.log("writable:"+descriptor.writable);
    //writable:false
    console.log("value:"+descriptor.value);
    //張三
創(chuàng)建對象 字面量模式
    var person={};
    person.name="張三";
    person.age=22;
    person.sex="男";
    person.sayName=function () {
        alert(this.name);
    }

優(yōu)點(diǎn):創(chuàng)建單個對象簡單方便
缺點(diǎn):創(chuàng)建多個相似對象會產(chǎn)生大量代碼

工廠模式
    function createPerson(name, age, sex) {
        var person = new Object();
        person.name = name;
        person.age = age;
        person.sex = sex;
        person.sayName = function () {
            alert(this.name);
        };
        return person;
    }
    var person=createPerson("張三",22,"男");

優(yōu)點(diǎn):可以快速創(chuàng)建多個相似對象
缺點(diǎn):無法進(jìn)行對象的識別

構(gòu)造函數(shù)模式
     function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.sayName = function () {
            alert(this.name);
        };
    }
    var person=new Person("張三",22,"男");

以構(gòu)造函數(shù)的方式創(chuàng)建對象要經(jīng)歷下面四個步驟:

創(chuàng)建一個新對象

將構(gòu)造函數(shù)的作用域賦給新對象(因此this指向這個新對象)

執(zhí)行構(gòu)造函數(shù)中的代碼,為這個新對象添加屬性

返回新對象

這里person有一個constructor(構(gòu)造函數(shù))屬性指向Person,我們可以驗(yàn)證一下。

    alert(person.constructor===Person);//true

鑒于這個特性我們可以用constructor來驗(yàn)證對象的類型。除了這個,我們還可以利用instanceof。

    alert(person instanceof Person);//true

雖然我們使用構(gòu)造函數(shù)模式可以進(jìn)行對象的識別,但是構(gòu)造函數(shù)模式卻有一個缺點(diǎn),就是每個方法都要在每個實(shí)例上重新創(chuàng)建一遍。下面我們舉個例子說明一下。

    function Person(name, age, sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.sayName = function () {
            alert(this.name);
        };
    }
    var person1=new Person("張三",22,"男");
    var person2=new Person("李四",25,"男");
    alert(person1.sayName===person2.sayName);//false

從上面的例子我們看出來,person1和person2的sayName函數(shù)并非共用同一個。

優(yōu)點(diǎn):可以進(jìn)行對象的識別
缺點(diǎn):構(gòu)造函數(shù)里面的函數(shù)在實(shí)例化的時候都需要每次都創(chuàng)建一遍,導(dǎo)致不同作用域鏈和標(biāo)識符解析。

原型模式
   function Person() {

   }
   Person.prototype.name="張三";
   Person.prototype.age=22;
   Person.prototype.sex="男";
   Person.prototype.sayName=function () {
       alert(this.name);
   };
   var person=new Person();

任何時候我們只要創(chuàng)建一個新函數(shù),就會根據(jù)一組特定的規(guī)則為該函數(shù)創(chuàng)建一個prototype屬性這個屬性指向函數(shù)的原型對象。默認(rèn)情況下,所有原型對象都會自動獲得一個constructor(構(gòu)造函數(shù))屬性會執(zhí)行prototype屬性所在函數(shù)。以上面這個例子為例,即:

Person.prototype.constructor===Person//true

另外我們的實(shí)例對象都會有一個__proto__屬性指向構(gòu)造函數(shù)的原型對象。即:

person.__proto__===Person.prototype //true

接下來我們要說的一點(diǎn)是我們可以通過對象實(shí)例訪問保存在原型中的值,但是不能通過對象實(shí)例重寫原型中的值。下面我們看個例子:

   function Person() {

   }
   Person.prototype.name="張三";
   Person.prototype.age=22;
   Person.prototype.sex="男";
   Person.prototype.sayName=function () {
       alert(this.name);
   };
   var person1=new Person();
   var person2=new Person();
   person1.name="李四";
   alert(person1.name);//李四
   alert(person2.name);//張三

從上面的例子我們可以看出,我們修改了person1的name屬性實(shí)際是實(shí)例對象person1中的屬性,而不是Person.prototype原型對象。如果我們想要person1.name指向Person.prototype.name則需要刪除實(shí)例對象person1中name屬性,如下所示:

   delete person1.name;
   alert(person1.name);//張三

說到這里我們遇到一個一個問題,就是如何判斷一個屬性在原型上還是在實(shí)例對象上?這個是有方法可以做到的,那就是hasOwnProperty()方法,接著上面的代碼,我們可以用這個hasOwnProperty()方法去驗(yàn)證一下。

   alert(person1.hasOwnProperty("name"));//false

上面我們刪除實(shí)例對象person1中name屬性之后,name應(yīng)該不屬于實(shí)例對象person1的屬性,所以hasOwnProperty()返回false.
如果只是想知道person1能否訪問name屬性,不論在實(shí)例對象上還是原型上的話,我們可以用in操作符。如下所示:

   alert("name" in person1);//true

相對上面的原型語法,我們有一個相對簡單的原型語法。

    function Person() {

    }
    Person.prototype = {
        constructor:Person,
        name: "張三",
        age: 22,
        sex:"男",
        sayName: function () {
            alert(this.name);
        }
    };

這里注意的是,需要重新設(shè)置constructor為Person,否則constructor指向Object而不是Person。但是這樣有一個缺點(diǎn),就是constructor的enumerable特性被設(shè)為true。導(dǎo)致constructor屬性由原本不可枚舉變成可枚舉。如果想解決這個問題可以嘗試這種寫法:

    function Person() {

    }
    Person.prototype = {
        name: "張三",
        age: 22,
        sex:"男",
        sayName: function () {
            alert(this.name);
        }
    };
    Object.defineProperty(Person.prototype,"constructor",{
        enumerable:false,
        value:Person
    });

說完這個之后,我們來說一下原型的動態(tài)性。由于在原型中查找值的過程是一次搜索,因此我們對原型對象所做的任何修改都能夠立即從實(shí)例上反映出來。我們看一下下面的例子:

   function Person() {

   }
   var person=new Person();
   person.name="張三";
   person.sayName=function () {
     alert(this.name);
   };
   person.sayName();//張三

但是在重寫整個原型對象的時候情況就不一樣了,我們看一下下面這個例子:

    function Person() {

    }
    var person = new Person();
    Person.prototype = {
        constructor:Person,
        name: "張三",
        age: 22,
        sayName: function () {
            alert(this.name);
        }
    };
    person.sayName();
    //Uncaught TypeError: person.sayName is not a function

重寫原型對象會切斷現(xiàn)有原型與任何之前已經(jīng)存在的對象實(shí)例之間的聯(lián)系,引用的仍然是最初的原型,上面的例子由于最初的原型的沒有sayName()方法,所以會報錯。

優(yōu)點(diǎn):可以進(jìn)行對象的識別,以及實(shí)例對象的函數(shù)不會被重復(fù)創(chuàng)建,從而不會導(dǎo)致不同的作用域鏈。
缺點(diǎn):省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),所有實(shí)例在默認(rèn)情況都取相同的值。

組合使用構(gòu)造函數(shù)模式和原型模式
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype = {
        constructor:Person,
        sayName: function () {
            alert(this.name);
        }
    };
    var person1 = new Person("張三", 22);
    var person2 = new Person("李四", 23);
    alert(person1.sayName===person2.sayName);//true

優(yōu)點(diǎn):結(jié)合構(gòu)造函數(shù)模式和原型模式的優(yōu)點(diǎn),是目前使用最廣泛、認(rèn)同度最高的一種創(chuàng)建自定義類型的方法。

動態(tài)原型模式
    function Person(name,age,sex) {
        this.name=name;
        this.age=age;
        this.sex=sex;
        if(typeof this.sayName!="function"){
            Person.prototype.sayName=function () {
              alert(this.name);
            };
        }
    }
    var person=new Person("張三",22,"男");
    person.sayName();//張三

上面代碼中if語句只有在初次調(diào)用構(gòu)造函數(shù)時才會執(zhí)行。此后,原型已經(jīng)初始化,不需要再做什么修改了。
優(yōu)點(diǎn):保留了構(gòu)造函數(shù)模式和原型模式的優(yōu)點(diǎn),又將所有信息封裝信息封裝在了構(gòu)造函數(shù)中。

寄生構(gòu)造函數(shù)模式(了解即可)
    function Person(name,age,sex) {
        var object=new Object();
        object.name=name;
        object.age=age;
        object.sex=sex;
        object.sayName=function () {
            alert(this.name);
        };
        return object;
    }
    var person=new Person("張三",22,"男");
    person.sayName();//張三

由于我們可以重寫調(diào)用構(gòu)造函數(shù)時的返回值,所以我們可以在特殊情況下為對象創(chuàng)建構(gòu)造函數(shù)。例如我們想創(chuàng)建一個具有特殊方法的數(shù)組,由于我們不能修改Array構(gòu)造函數(shù),因此可以使用這種方式。

    function SpecialArray() {
        var values=new Array();
        values.push.apply(values,arguments);
        values.toPipedString=function () {
            return this.join("|");
        };
        return values;
    }
    var colors=new SpecialArray("red","yellow","white");
    alert(colors.toPipedString());//"red|yellow|white"

但這種方式缺點(diǎn)也是很明顯,由于構(gòu)造函數(shù)返回的對象與構(gòu)造函數(shù)外部創(chuàng)建的對象沒有什么不同。所以,instanceof操作符不能確定對象類型。因此這種模式優(yōu)先級很低,不推薦優(yōu)先使用。
優(yōu)點(diǎn):可以重寫構(gòu)造函數(shù)函數(shù)的返回值,特殊情況下比較好用。
缺點(diǎn):instanceof操作符不能確定對象類型。

穩(wěn)妥構(gòu)造函數(shù)模式
    function Person(name) {
        var object=new Object();
        var name=name;
        object.sayName=function () {
            alert(name);
        };
        return object;
    }
    var person=new Person("張三",22,"男");
    person.sayName();//張三
    alert(person.name);//undefined

在這種模式下,想訪問name這個數(shù)據(jù)成員時,除了調(diào)用sayName()方法,沒有其他方法可以訪問傳入構(gòu)造函數(shù)中的原始數(shù)據(jù)。這種模式的安全性就很高。
優(yōu)點(diǎn):安全性高。
缺點(diǎn):instanceof操作符不能確定對象類型。

繼承 原型鏈
    function SuperType() {
        this.property=true;
    }
    SuperType.prototype.getSuperValue=function () {
        return this.property;
    };
    function SubType() {
        this.subproperty=false;
    }
    //繼承SuperType
    SubType.prototype=new SuperType();
    SubType.prototype.getSubValue=function () {
        return this.subproperty;
    };
    var instance=new SubType();
    alert(instance.getSuperValue());

上面代碼中,我們沒有使用SubType默認(rèn)提供的原型,而是給它換了一個新原型(SuperType實(shí)例)。于是,新原型不僅具有作為SuperType的實(shí)例所擁有的全部屬性和方法,而且其內(nèi)部還擁有一個指針,指向了SuperType的原型。最終結(jié)果如下:

根據(jù)上面,需要說明一點(diǎn)的是所有函數(shù)的默認(rèn)原型都是Object的實(shí)例,因此默認(rèn)原型都會包含一個內(nèi)部指針指向Object.prototype。

在我們使用原型鏈的過程會有一個問題就是確定原型和實(shí)例之間的關(guān)系。這里我們有兩種方式,我們接著上面代碼繼續(xù)看。

第一種:instanceof操作符,測試實(shí)例與原型中出現(xiàn)過的構(gòu)造函數(shù)

    alert(instance instanceof Object);//true
    alert(instance instanceof SuperType);//true
    alert(instance instanceof SubType);//true

第二種:方法isPrototypeOf(),測試原型鏈中出現(xiàn)過的原型

   alert(Object.prototype.isPrototypeOf(instance));//true
   alert(SuperType.prototype.isPrototypeOf(instance));//true
   alert(SubType.prototype.isPrototypeOf(instance));//true

如果子類型需要覆蓋超類型中的某個方法,或者需要添加超類型中不存在的某個方法,我們要遵循一個原則,給原型添加方法的代碼一定要放在替換原型的語句之后。如下所示:

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

另外我們還需要注意在添加方法時候,不能使用對象字面量創(chuàng)建原型方法。如下所示:

    function SuperType() {
        this.property=true;
    }
    SuperType.prototype.getSuperValue=function () {
        return this.property;
    };
    function SubType() {
        this.subproperty=false;
    }
    //繼承SuperType
    SubType.prototype=new SuperType();
    //使用字面量添加新方法,會導(dǎo)致上一行代碼無效
    SubType.prototype={
        getSubValue:function () {
            return this.subproperty;
        }
    };
    var instance=new SubType();
    alert(instance.getSuperValue());
    //Uncaught TypeError: instance.getSuperValue is not a function

說到這里我們,我來總結(jié)一下原型鏈的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):功能很強(qiáng)大,可以連續(xù)繼承多個原型的全部屬性和方法。
缺點(diǎn):

1.原型的通用問題就是屬性被共用,修改原型的屬性將會動態(tài)映射到所有指向該原型的實(shí)例。
2.鑒于屬性是共用的,我們無法給超類型的構(gòu)造函數(shù)傳遞參數(shù)。
借用構(gòu)造函數(shù)
    function SuperType() {
        this.colors=["red","blue","green"];
    }
    function SubType() {
        //繼承了SuperType
        SuperType.call(this);
    }
    var instance1=new SubType();
    instance1.colors.push("black");
    console.log(instance1.colors);//["red", "blue", "green", "black"]
    var instance2=new SubType();
    console.log(instance2.colors);//["red", "blue", "green"]

通過使用call()方法(或apply()方法),在新建的SubType實(shí)例的環(huán)境下條用了SuperType構(gòu)造函數(shù)。這樣一來,就會在新的SubType對象上執(zhí)行SuperType()函數(shù)中定義的所有對象初始化代碼。結(jié)果,SubType的每個實(shí)例就都會具有自己的colors屬性的副本了。

相對于原型鏈而言,借用構(gòu)造函數(shù)有一個很大的優(yōu)勢,即可以在子類型構(gòu)造函數(shù)中向超類型構(gòu)造函數(shù)傳遞參數(shù)。如下所示:

    function SuperType(name) {
        this.name=name;
    }
    function SubType() {
        //繼承了SuperType,同時還傳遞了參數(shù)
        SuperType.call(this,"張三");
        //實(shí)例屬性
        this.age=22;
    }
    var instance=new SubType();
    alert(instance.name);//張三
    alert(instance.age);//22

優(yōu)點(diǎn):彌補(bǔ)原型鏈的共用屬性和不能傳遞參數(shù)的缺點(diǎn)。
缺點(diǎn):函數(shù)不能復(fù)用,超類型的原型中定義的方法在子類型中是不可見的。

組合繼承
    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)用SuperType()
        this.age=age;
    }
    //繼承方法
    SubType.prototype=new SuperType();
    SubType.prototype.constructor=SubType;
    SubType.prototype.sayAge=function () {
      alert(this.age);
    };
    var instance1=new SubType("張三",22);//第一次調(diào)用SuperType()
    instance1.colors.push("black");
    console.log(instance1.colors);//["red", "blue", "green", "black"]
    instance1.sayName();//張三
    instance1.sayAge();//22


    var instance2=new SubType("李四",25);
    console.log(instance2.colors);//["red", "blue", "green"]
    instance2.sayName();//李四
    instance2.sayAge();//25
    

缺點(diǎn):創(chuàng)建對象時都會調(diào)用兩次超類型構(gòu)造函數(shù)。
優(yōu)點(diǎn):融合了原型鏈和借助構(gòu)造函數(shù)的優(yōu)點(diǎn),避免了他們的缺陷。Javascript中最常用的繼承模式。

原型式繼承
    var person={
        name:"張三",
        friends:["李四","王五"]
    };
    var person1=Object(person);//或者Object.create(person)
    person1.name="趙六";
    person1.friends.push("孫七");
    var person2=Object.create(person);
    person2.name="周八";
    person2.friends.push("吳九");
    console.log(person.friends);//["李四", "王五", "孫七", "吳九"]

原型式繼承實(shí)際上是把實(shí)例的__proto__屬性指向了person。

優(yōu)點(diǎn):只想讓一個對象跟另一個對象保持相似的情況下,代碼變得很簡單。
缺點(diǎn):共享了相應(yīng)的值,原型的通病。

寄生式繼承
    function createPerson(obj) {
        var clone=Object(obj);
        clone.sayMyfriends=function () {
            console.log(this.friends);
        };
        return clone;
    }
    var person={
        name:"張三",
        friends:["李四","王五","趙六"]
    };
    var anotherPerson= createPerson(person);
    anotherPerson.sayMyfriends();//["李四", "王五", "趙六"]

優(yōu)點(diǎn):可以為任意對象添加指定屬性,代碼量很少。
缺點(diǎn): 在為對象添加函數(shù),由于函數(shù)不能復(fù)用。每次添加都會新建一個函數(shù)對象,降低了效率。這一點(diǎn)與構(gòu)造函數(shù)模式類似。

寄生組合式繼承
    function inheritPrototype(subType,superType) {
        var prototype=Object(superType.prototype);//創(chuàng)建對象
        prototype.constructor=subType;//增強(qiáng)對象
        subType.prototype=prototype;//指定對象
    }
    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);
    };
    var instance1=new SubType("張三",22);
    instance1.colors.push("yellow");
    instance1.sayName();//張三
    instance1.sayAge();//22

    var instance2=new SubType("李四",25);
    console.log(instance2.colors);// ["red", "blue", "green"]
    instance2.sayName();//李四
    instance2.sayAge();//25

上面的inheritPrototype()函數(shù)接收兩個參數(shù):子類型構(gòu)造函數(shù)和超類型構(gòu)造函數(shù)。在函數(shù)內(nèi)部,第一部是創(chuàng)建超類型原型的一個副本。第二步是為創(chuàng)建的副本添加constructor屬性,從而彌補(bǔ)因重寫原型而失去的默認(rèn)的constructor屬性。最后一步,將新創(chuàng)建的對象(即副本)賦值給子類型的原型。這樣,我們就可以用調(diào)用inheritPrototype()函數(shù)的語句,去替換前面例子中為子類型原型賦值的語句。
優(yōu)點(diǎn):集寄生式繼承和組合繼承的優(yōu)點(diǎn)于一身,是實(shí)現(xiàn)基于類型繼承的最有效方式。

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

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

相關(guān)文章

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

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

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

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

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

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

    AaronYuan 評論0 收藏0
  • 面向對象 JavaScript

    摘要:是完全的面向?qū)ο笳Z言,它們通過類的形式組織函數(shù)和變量,使之不能脫離對象存在。而在基于原型的面向?qū)ο蠓绞街?,對象則是依靠構(gòu)造器利用原型構(gòu)造出來的。 JavaScript 函數(shù)式腳本語言特性以及其看似隨意的編寫風(fēng)格,導(dǎo)致長期以來人們對這一門語言的誤解,即認(rèn)為 JavaScript 不是一門面向?qū)ο蟮恼Z言,或者只是部分具備一些面向?qū)ο蟮奶卣?。本文將回歸面向?qū)ο蟊疽?,從對語言感悟的角度闡述為什...

    novo 評論0 收藏0
  • javascript 面向對象版塊之理解對象

    摘要:用代碼可以這樣描述安全到達(dá)國外面向過程既然說了面向?qū)ο?,那么與之對應(yīng)的就是面向過程。小結(jié)在這篇文章中,介紹了什么是面向?qū)ο蠛兔嫦蜻^程,以及中對象的含義。 這是 javascript 面向?qū)ο蟀鎵K的第一篇文章,主要講解對面向?qū)ο笏枷氲囊粋€理解。先說說什么是對象,其實(shí)這個還真的不好說。我們可以把自己當(dāng)成一個對象,或者過年的時候相親,找對象,那么你未來的老婆也是一個對象。我們就要一些屬性,比...

    lovXin 評論0 收藏0
  • JS對象(1)重新認(rèn)識面向對象

    摘要:對象重新認(rèn)識面向?qū)ο竺嫦驅(qū)ο髲脑O(shè)計模式上看,對象是計算機(jī)抽象現(xiàn)實(shí)世界的一種方式。除了字面式聲明方式之外,允許通過構(gòu)造器創(chuàng)建對象。每個構(gòu)造器實(shí)際上是一個函數(shù)對象該函數(shù)對象含有一個屬性用于實(shí)現(xiàn)基于原型的繼承和共享屬性。 title: JS對象(1)重新認(rèn)識面向?qū)ο? date: 2016-10-05 tags: JavaScript 0x00 面向?qū)ο?從設(shè)計模式上看,對象是...

    superw 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<