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

資訊專欄INFORMATION COLUMN

淺談 JS 創(chuàng)建對(duì)象的 8 種模式

caoym / 625人閱讀

摘要:模式工廠模式構(gòu)造器模式通過(guò)對(duì)象實(shí)現(xiàn)模式構(gòu)造器與原型方式的混合模式動(dòng)態(tài)原型模式混合工廠模式模式字面量的表現(xiàn)形式等價(jià)于即以對(duì)象為一個(gè)原型模板新建一個(gè)以這個(gè)原型模板為原型的對(duì)象區(qū)別創(chuàng)建一個(gè)原型為的對(duì)象在里查看各個(gè)新建對(duì)象的區(qū)別可以看出前種模式創(chuàng)建

Objct 模式

工廠模式

構(gòu)造器模式

通過(guò) Function 對(duì)象實(shí)現(xiàn)

prototype 模式

構(gòu)造器與原型方式的混合模式

動(dòng)態(tài)原型模式

混合工廠模式

1.Object 模式
var o1 = {};//字面量的表現(xiàn)形式
var o2 = new Object;
var o3 = new Object();
var o4 = new Object(null);
var o5 = new Object(undefined);
var o6 = Object.create(Object.prototype);//等價(jià)于 var o = {};//即以 Object.prototype 對(duì)象為一個(gè)原型模板,新建一個(gè)以這個(gè)原型模板為原型的對(duì)象
//區(qū)別
var o7 = Object.create(null);//創(chuàng)建一個(gè)原型為 null 的對(duì)象

在 chrome 里查看各個(gè)新建對(duì)象的區(qū)別:

可以看出前6種模式創(chuàng)建出來(lái)的對(duì)象都是一樣的,第七種不同點(diǎn)在于其雖然也為 Object 對(duì)象但其無(wú)任何屬性(包括沒(méi)有任何可以繼承的屬性,因?yàn)閯?chuàng)建的時(shí)候沒(méi)有指定其原型)

2.工廠模式
//工廠方法1 通過(guò)一個(gè)方法來(lái)創(chuàng)建對(duì)象 利用 arguments 對(duì)象獲取參數(shù)設(shè)置屬性(參數(shù)不直觀,容易出現(xiàn)問(wèn)題)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接給對(duì)象添加屬性,每個(gè)對(duì)象都有直接的屬性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每個(gè)對(duì)象都有一個(gè) showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中沒(méi)有傳遞的實(shí)參,實(shí)際形參值為 undefined(這里的 age 為 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判斷對(duì)象是否 Object 類或子類
//工廠方法2 通過(guò)傳參設(shè)置屬性(參數(shù)直觀明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接給對(duì)象添加屬性,每個(gè)對(duì)象都有直接的屬性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每個(gè)對(duì)象都有一個(gè) showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判斷對(duì)象是否 Object 類或子類
3.構(gòu)造器模式
//構(gòu)造器方法1
function Car(sColor,iDoors){  //聲明為構(gòu)造器時(shí)需要將函數(shù)名首字母大寫
    this.color = sColor;      //構(gòu)造器內(nèi)直接聲明屬性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };//每個(gè) Car 對(duì)象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}

使用方法1的問(wèn)題很明顯,沒(méi)辦法是 showDoor 方法重用,每次新建一個(gè)對(duì)象就要在堆里新開辟一篇空間.改進(jìn)如下

//構(gòu)造器方法2
function showDoor(){      //定義一個(gè)全局的 Function 對(duì)象
    return this.doors;
}

function Car(sColor,iDoors){//構(gòu)造器
    this.color = sColor;      //構(gòu)造器內(nèi)直接聲明屬性
    this.doors = iDoors;
    this.showColor = function(){
        return this.color;
    };
    this.showDoor = showDoor();//每個(gè) Car 對(duì)象共享同一個(gè) showDoor 方法版本(方法有自己的作用域,不用擔(dān)心變量被共享)
}

alert(new Car("red",2).showColor());//通過(guò)構(gòu)造器創(chuàng)建一個(gè)對(duì)象并調(diào)用其對(duì)象方法

上面出現(xiàn)的問(wèn)題就是語(yǔ)義不夠清除,體現(xiàn)不出類的封裝性,改進(jìn)為 prototype 模式

4.通過(guò)Function對(duì)象實(shí)現(xiàn)創(chuàng)建對(duì)象

我們知道每聲明一個(gè)函數(shù)實(shí)際是創(chuàng)建了一個(gè)Function 實(shí)例 JS 函數(shù).

function function_name(param1,param2){alert(param1);}
//等價(jià)于
var function_name = new Function("param1","pram2","alert(param1);");
var Car2 = new Function("sColor","iDoors",
         "this.color = sColor;"+
         "this.doors = iDoors;"+
         "this.showColor = function(){ return this.color; }"
);
alert(new Car2("blue",3).showColor());
5.prototype模式

類通過(guò) prototype 屬性添加的屬性與方法都是綁定在這個(gè)類的 prototype 域(實(shí)際為一個(gè) Prototype 對(duì)象)中,綁定到這個(gè)域中的屬性與方法只有一個(gè)版本,只會(huì)創(chuàng)建一次.

類的實(shí)例對(duì)象可以直接像調(diào)用自己的屬性一樣調(diào)用該類的 prototype 域中的屬性與方法,類可以通過(guò)調(diào)用 prototype 屬性來(lái)間接調(diào)用prototype 域內(nèi)的屬性與方法.

注意:通過(guò)類實(shí)例化出對(duì)象后對(duì)象內(nèi)無(wú) prototype 屬性,但對(duì)象可直接像訪問(wèn)屬性一樣的訪問(wèn)類的 prototype 域的內(nèi)容,實(shí)例對(duì)象有個(gè)私有屬性__proto__,__proto__屬性內(nèi)含有類的 prototype 域內(nèi)的屬性與方法

方法1
function Car3(){}//用空構(gòu)造函數(shù)設(shè)置類名
Car3.prototype.color = "blue";//每個(gè)對(duì)象都共享相同屬性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每個(gè)對(duì)象共享一個(gè)方法版本,省內(nèi)存。

var car3_1 = new Car3();
var car3_2 = new Car3();

alert(car3_1.color);//blue
alert(car3_2.color);//blue
alert(Car3.prototype.color);//blue

car3_1.drivers.push("Bill");
alert(car3_1.drivers);//"Mike","John","Bill"
alert(car3_2.drivers);//"Mike","John","Bill"
alert(Car3.prototype.drivers);//"Mike","John","Bill"

//直接修改實(shí)例對(duì)象的屬性,解析器會(huì)先去找實(shí)例對(duì)象是否有這個(gè)屬性(不會(huì)去找實(shí)例對(duì)象的 _proto_ 屬性內(nèi)的那些類的 prototype 屬性,而是直接查看這個(gè)實(shí)例是否有對(duì)應(yīng)的屬性(與_proto_同級(jí)))
//如果沒(méi)有則直接給這個(gè)實(shí)例對(duì)象添加該屬性,但不會(huì)修改類的prototype域的同名屬性,既實(shí)例對(duì)象的_proto_屬性內(nèi)的那些類 prototype 域?qū)傩圆粫?huì)被修改
car3_1.color = "red";//car3_1對(duì)象內(nèi)無(wú)名為 color 的對(duì)象屬性,故將該屬性添加到該對(duì)象上

//解析器對(duì)實(shí)例對(duì)象讀取屬性值的時(shí)候會(huì)先查找該實(shí)例有無(wú)同名的直接屬性
//如果沒(méi)有,則查找__proto__屬性內(nèi)保存的那些 當(dāng)前類的 prototype 域的屬性
//有就返回,無(wú)則繼續(xù)查找是否有原型鏈中的對(duì)應(yīng)的方法屬性
//有就返回,無(wú)則返回undefined
alert(car3_1.color);//red
alert(car3_2.color);//blue
alert(car3_2.color2);//undefined

//直接修改類的 prototype 域內(nèi)的屬性,不會(huì)影響該類的實(shí)例對(duì)象的對(duì)象屬性,但會(huì)影響實(shí)例對(duì)象的_proto_屬性(_proto_屬性內(nèi)存放的是類的 prototype 域的內(nèi)容)
Car3.prototype.color = "black";
alert(car3_1.color);//red 該對(duì)象有同名的直接屬性,故不會(huì)去_proto_屬性內(nèi)查找類的 prototype 域的屬性
alert(car3_2.color);//black 受影響

//直接修改實(shí)例對(duì)象的方法,解析器會(huì)先去找實(shí)例對(duì)象是否有這個(gè)方法(不會(huì)去找實(shí)例對(duì)象的 _proto_ 屬性內(nèi)的那些類的 prototype 域的方法,而是直接查看這個(gè)實(shí)例是否有對(duì)應(yīng)的方法(與_proto_同級(jí)))
//如果沒(méi)有則直接給這個(gè)實(shí)例對(duì)象添加該方法,但不會(huì)修改類的prototype域的同名方法,既實(shí)例對(duì)象的_proto_屬性內(nèi)的那些類 prototype 域方法不會(huì)被修改
//car3_1對(duì)象內(nèi)無(wú)名為 showColor 的對(duì)象方法屬性,故將該方法屬性添加到該對(duì)象上
car3_1.showColor = function () {
    alert("new function");
}
//解析器對(duì)實(shí)例對(duì)象調(diào)用方法屬性的時(shí)候會(huì)先查找該實(shí)例有無(wú)同名的直接方法屬性
//如果沒(méi)有,則查找_proto_屬性內(nèi)保存的那些 當(dāng)前類的 prototype 域的方法屬性
//有就返回,無(wú)則繼續(xù)查找是否有原型鏈中的對(duì)應(yīng)的方法屬性
//找到就返回,無(wú)則報(bào)錯(cuò)

car3_1.showColor();//new function
car3_2.showColor();//blue
car3_1.abcd();//直接報(bào)錯(cuò)

//直接修改類的 prototype 域內(nèi)的方法屬性,不會(huì)影響該類的實(shí)例對(duì)象的方法屬性,但會(huì)影響實(shí)例對(duì)象的_proto_屬性(_proto_屬性內(nèi)存放的是類的 prototype 域的內(nèi)容)
Car3.prototype.showColor = function () {
    alert("second function");
}
car3_1.showColor();//new function 該對(duì)象有同名的方法屬性,故不會(huì)去_proto_屬性內(nèi)查找類的 prototype 域的方法屬性
car3_2.showColor();//second function 受影響

可以看出使用該方法雖然說(shuō)打打減少了內(nèi)存的浪費(fèi),但依舊有問(wèn)題,某個(gè)對(duì)象的屬性一旦改變,所有由該類實(shí)例化得到的對(duì)象的__proto__內(nèi)屬性值也會(huì)跟著變(實(shí)為引用),改進(jìn)如下

6.構(gòu)造器方式與原型方式的混合模式
//每個(gè)對(duì)象有專屬的屬性不會(huì)與其他對(duì)象共享
function Car4(sColor,iDoors){
    this._color = sColor;//私有屬性變量名稱頭加下劃線標(biāo)識(shí)
    this._doors = iDoors;
    this.drivers = new Array("Mike","John");//公有屬性標(biāo)識(shí)
}
//所有對(duì)象共享一個(gè)方法版本,減少內(nèi)存浪費(fèi)
Car4.prototype.showColor = function () {
    alert(this._color);
};

var car4_1 = new Car4("red",4);
var car4_2 = new Car4("blue",3);

car4_1.drivers.push("Bill");

alert(car4_1.drivers);//"Mike","John","Bill"
alert(car4_2.drivers);//"Mike","John"

這也是常用的創(chuàng)建對(duì)象方式之一

7.動(dòng)態(tài)原型模式
function Car5(sColor,iDoors,iMpg){
    this.color = sColor;
    this.doors = iDoors;
    this.mpg = iMpg;
    this.drivers = new Array("Mike","John");

    //使用標(biāo)志(_initialized)來(lái)判斷是否已給原型賦予了任何方法,保證方法永遠(yuǎn)只被創(chuàng)建并賦值一次
    if(typeof Car5._initialized == "undefined"){//因?yàn)檫@里的標(biāo)記是附加在類上,故如果后期直接對(duì)其進(jìn)行修改,還是有可能出現(xiàn)再次創(chuàng)建的情況
        Car5.prototype.showColor = function () {//為Car5添加一個(gè)存放在 prototype 域的方法
            alert(this.color);
        };
        Car5._initialized = true;//設(shè)置一個(gè)靜態(tài)屬性
    }
}
var car5_1 = new Car5("red",3,25);
var car5_2 = new Car5("red",3,25);

這種模式使得定義類像強(qiáng)類型語(yǔ)言例如 java 等語(yǔ)言的定義模式

8.混合工廠模式
function Car6(){
    var oTempCar = new Object;
    oTempCar.color = "blue";
    oTempCar.doors = 4;
    oTempCar.showColor = function () {
        alert(this.color);
    };
    return oTempCar;
}
var car6 = new Car6();

由于在 Car6()構(gòu)造函數(shù)內(nèi)部調(diào)用了 new 運(yùn)算符,所以將忽略第二個(gè) new 運(yùn)算符(位于構(gòu)造函數(shù)之外),
在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對(duì)象被傳遞回變量car6,這種方式在對(duì)象方法的內(nèi)部管理方面與經(jīng)典方式(工廠方法)有著相同的問(wèn)題.應(yīng)盡量避免

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

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

相關(guān)文章

  • 淺談node.jsstream(流)

    摘要:在可讀流事件里我們就必須調(diào)用方法。當(dāng)一個(gè)對(duì)象就意味著我們想發(fā)出信號(hào)這個(gè)流沒(méi)有更多數(shù)據(jù)了自定義可寫流為了實(shí)現(xiàn)可寫流,我們需要使用流模塊中的構(gòu)造函數(shù)。我們只需給構(gòu)造函數(shù)傳遞一些選項(xiàng)并創(chuàng)建一個(gè)對(duì)象。 前言 什么是流呢?看字面意思,我們可能會(huì)想起生活中的水流,電流。但是流不是水也不是電,它只是描述水和電的流動(dòng);所以說(shuō)流是抽象的。在node.js中流是一個(gè)抽象接口,它不關(guān)心文件內(nèi)容,只關(guān)注是否從...

    elliott_hu 評(píng)論0 收藏0
  • 2018 淺談前端面試那些事

    摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...

    LiuRhoRamen 評(píng)論0 收藏0
  • 2018 淺談前端面試那些事

    摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...

    stormgens 評(píng)論0 收藏0
  • 2018 淺談前端面試那些事

    摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒(méi)有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...

    Hujiawei 評(píng)論0 收藏0
  • js面向對(duì)象淺談(二)

    摘要:我們通過(guò)這個(gè)構(gòu)造函數(shù)為原型對(duì)象添加其他方法和屬性。這個(gè)屬性存在與實(shí)例與構(gòu)造函數(shù)的原型對(duì)象上直接,而不存在于實(shí)例與構(gòu)造函數(shù)之間。李小花班花張全蛋張全蛋李小花李小花我們?cè)诒闅v對(duì)象的的屬性的時(shí)候,經(jīng)常需要判斷屬性是否來(lái)自于對(duì)象的原型還是屬性。 引言 上面說(shuō)了創(chuàng)建對(duì)象有字面量方式和工廠模式還有構(gòu)造函數(shù)模式,結(jié)果發(fā)現(xiàn)他們都各自有缺點(diǎn),所以下面再給大家介紹幾種創(chuàng)建對(duì)象的方式,爭(zhēng)取能找到一種無(wú)痛的模...

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

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

0條評(píng)論

閱讀需要支付1元查看
<