JS—創(chuàng)建自定義對象

對象在js中的定義即為:無序?qū)傩缘募希鋵傩钥梢园局?、對象或者函?shù)。
每個對象都是基于一個引用類型創(chuàng)建的,這個引用類型可以是原生類型,也可以是開發(fā)人員定義的類型。

  • 創(chuàng)建對象最簡單的方式這里也已經(jīng)介紹。
    var person=new Object();

new操作符
1、Object()是一個構(gòu)造函數(shù),平常我們使用函數(shù)時,一個是直接調(diào)用Object(),另一種是通過對象的方法。其函數(shù)內(nèi)部的this值指的是其所處的環(huán)境對象。
2、在函數(shù)前面加上new,可以改變函數(shù)的this值,還可以共享函數(shù)的原型。

  • new操作符具體干了什么?參照
    var obj = new Base();
    這是一個基本的使用new操作符的代碼。然而一個new操作符卻悄悄的干了這些事。
    var obj = {};//第一行創(chuàng)建了一個空對象obj
    obj.proto = Base.prototype;
    //proto是每個新建對象的內(nèi)部屬性,指向該實例對象的構(gòu)造函數(shù)的原型對象。
    //第二行、將這個空對象的proto成員指向了Base函數(shù)對象prototype成員對象
    Base.call(obj);//我們將Base函數(shù)對象的this指針替換成obj,然后再調(diào)用Base函數(shù)

  • 原始創(chuàng)建對象的方式存在許多不足的地方
    使用new操作符,Object構(gòu)造函數(shù),或是對象字面量。
    問題1、導(dǎo)致一個接口創(chuàng)建很多個對象,以至于使得產(chǎn)生大量的重復(fù)代碼。
    問題2、函數(shù)作為特殊的對象,每一次創(chuàng)建對象都會實例化一個同功能的function對象,浪費。
    var person1={
    name:"xiaoming",
    age:16,
    sayname:function(){
    alert(this.name);
    }
    }
    var person2={
    name:"xiaohong",
    age:18,
    sayname:function(){
    alert(this.name);
    }
    }
    person1.sayname();
    person2.sayname();

  • 如何解決以上存在的問題
    解決問題的道路不是馬到成功,也是在提供解決方案后,又進行完善改進的過程。

  • 方案1:解決了重復(fù)代碼的問題——工廠模式
    function createPerson(name,age,job)
    {
    var obj=new Object();
    obj.name=name;
    obj.age=age;
    obj.job=job;
    obj.saynaName=function(){
    alert(this.name);
    };
    return obj;
    }
    var person1=createPerson("dudu",22,"Painter");
    person1.saynaName();
    優(yōu)點:通過傳遞參數(shù),來使用同一個function實例createPerson,達到節(jié)省代碼的效果。
    缺點:1、無法知道person是一個怎樣的對象類型。(即對象識別)2、同功能的sayName函數(shù)對象需要被重復(fù)創(chuàng)立。

  • 方案2:解決了對象識別問題以及函數(shù)對象重復(fù)創(chuàng)立問題——構(gòu)造函數(shù)模式
    function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.sayName=sayname;
    }
    function sayname(){
    alert(this.name);
    }
    var person1=new Person("dudu",22,"Painter");
    person1.sayName();
    解釋:采用構(gòu)造函數(shù)模式,函數(shù)名即為對象名,且首字母大寫,配合new操作符使用。對象的方法的定義轉(zhuǎn)移到了構(gòu)造函數(shù)外部,每次實例化對象時,該對象的方法不用在進行實例,而是共享全局作用域中的sayname函數(shù)。
    缺點:1、全局作用域的函數(shù)僅被某個對象調(diào)用,不合乎全局對象的設(shè)置效果。2、違背了對象的封裝特性。

  • 方案3:解決了對象方法定義的封裝問題——原型模式
    function Person(){}
    Person.prototype.name="Nicholas";
    Person.prototype.age=29;
    Person.prototype.job="Softwar Enginear"
    Person.prototype.sayName=function(){
    alert(this.name);
    };
    var person1=new Person();
    person1.sayName();

js高級程序設(shè)計里的截圖

根據(jù)上圖,
解釋:創(chuàng)建一個新的函數(shù)對象后,該函數(shù)對象就會擁有一個prototype屬性,這個屬性是一個指針,指向一個對象,該對象的用途是包含可以由特定類型的所有實例共享的屬性和方法。包括一個構(gòu)造函數(shù)(constructor)屬性,這個屬性包含一個指向prototype屬性所在函數(shù)的指針。其他屬性都是用戶自己建立的。
另外,由該構(gòu)造函數(shù)實例的對象,也包含一個指針[[prototype]],指向構(gòu)造函數(shù)的原型對象。在FF、Safari、Chrome在每個對象上都支持一個屬性_proto_。需要知道這個連接存在的是實例與構(gòu)造函數(shù)的原型對象之間,而你不是存在于實例與構(gòu)造函數(shù)之間。
缺點:1、原型對象的屬性與方法的添加不夠封裝。2、由于原型對象的共享,導(dǎo)致所有實例共享相同的屬性值。

  • 方案3.1:解決了原來原型模式的問題1——封裝的原型模式
    function Person(){}
    var friend=new Person();
    Person.prototype={
    constructor:Person,
    name:"Nichoas",
    age:29,
    job:"software ENgineer",
    sayName:function(){
    alert(this.name);
    }
    };
    friend.sayName();//error

    上面為重寫前,下面為重寫后

    以上的代碼實際上重寫了原型對象,導(dǎo)致切斷了構(gòu)造函數(shù)與最初原型之間的關(guān)系,需要constructor:Person,進行重新指定。
    缺點:重寫原型對象切斷了現(xiàn)有原型對象與任何之前已經(jīng)存在的對象實例之間的聯(lián)系,他們?nèi)砸玫氖亲畛醯脑汀?p>

  • 方案4:解決了原型模式的問題——構(gòu)造函數(shù)與原型混成的模式
    function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["bobo","xixi"];
    }
    Person.prototype={
    constructor:Person,
    asyName:function(){
    alert(this.name);
    }
    };
    var person1=new Person("du",22,"painter");
    var person2=new Person("susu",22,"singer");

          person1.friends.push("wawa");
          alert(person1.friends);//bobo,xixi,wawa
          alert(person2.friends);//bobo,xixi
    

解釋:對比兩次alert結(jié)果,發(fā)現(xiàn)構(gòu)造函數(shù)內(nèi)部的內(nèi)容不被對象實例共享。這也達到了對象之間個性化的設(shè)置。
缺點:還是不夠封裝啊!

  • 方案4.1:彌補不夠封裝
    function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["bobo","xixi"];
    //
    if(typeof this.sayName!= "function")
    {
    Person.prototype.sayNmae=function(){
    alert(this.name);
    };
    }
    }
    只有在sayName方法不存在的情況下,才會將他添加在原型中。這段代碼只會在初次調(diào)用構(gòu)造函數(shù)的時候才會執(zhí)行。

好吧!這樣就很完美啦。

一不小心又寫多啦,估計沒人愛看啦
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容