国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

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

caoym / 617人閱讀

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

Objct 模式

工廠模式

構(gòu)造器模式

通過 Function 對象實(shí)現(xiàn)

prototype 模式

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

動態(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 對象為一個(gè)原型模板,新建一個(gè)以這個(gè)原型模板為原型的對象
//區(qū)別
var o7 = Object.create(null);//創(chuàng)建一個(gè)原型為 null 的對象

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

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

2.工廠模式
//工廠方法1 通過一個(gè)方法來創(chuàng)建對象 利用 arguments 對象獲取參數(shù)設(shè)置屬性(參數(shù)不直觀,容易出現(xiàn)問題)
function createCar(){
    var oTemp = new Object();
    oTemp.name = arguments[0];//直接給對象添加屬性,每個(gè)對象都有直接的屬性
    oTemp.age = arguments[1];
    oTemp.showName = function () {
        alert(this.name);
    };//每個(gè)對象都有一個(gè) showName 方法版本
    return oTemp;
}
createCar("tom").showName();//在 JS 中沒有傳遞的實(shí)參,實(shí)際形參值為 undefined(這里的 age 為 undefined)
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判斷對象是否 Object 類或子類
//工廠方法2 通過傳參設(shè)置屬性(參數(shù)直觀明了)
function createCar(name,age){
    var oTemp = new Object();
    oTemp.name = name;//直接給對象添加屬性,每個(gè)對象都有直接的屬性
    oTemp.age = age;
    oTemp.showName = function () {
        alert(this.name);
    };//每個(gè)對象都有一個(gè) showName 方法版本
    return oTemp;
}
createCar("tom").showName();
createCar("tim",80).showName();
alert(createCar("tom") instanceof Object);//true 判斷對象是否 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 對象都有自己的 showColor方法版本
    this.showDoor = function () {
        return this.doors;
    }
}

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

//構(gòu)造器方法2
function showDoor(){      //定義一個(gè)全局的 Function 對象
    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 對象共享同一個(gè) showDoor 方法版本(方法有自己的作用域,不用擔(dān)心變量被共享)
}

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

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

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

我們知道每聲明一個(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模式

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

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

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

方法1
function Car3(){}//用空構(gòu)造函數(shù)設(shè)置類名
Car3.prototype.color = "blue";//每個(gè)對象都共享相同屬性
Car3.prototype.doors = 3;
Car3.prototype.drivers = new Array("Mike","John");
Car3.prototype.showColor = function(){
    alert(this.color);
};//每個(gè)對象共享一個(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í)例對象的屬性,解析器會先去找實(shí)例對象是否有這個(gè)屬性(不會去找實(shí)例對象的 _proto_ 屬性內(nèi)的那些類的 prototype 屬性,而是直接查看這個(gè)實(shí)例是否有對應(yīng)的屬性(與_proto_同級))
//如果沒有則直接給這個(gè)實(shí)例對象添加該屬性,但不會修改類的prototype域的同名屬性,既實(shí)例對象的_proto_屬性內(nèi)的那些類 prototype 域?qū)傩圆粫恍薷?car3_1.color = "red";//car3_1對象內(nèi)無名為 color 的對象屬性,故將該屬性添加到該對象上

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

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

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

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

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

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

6.構(gòu)造器方式與原型方式的混合模式
//每個(gè)對象有專屬的屬性不會與其他對象共享
function Car4(sColor,iDoors){
    this._color = sColor;//私有屬性變量名稱頭加下劃線標(biāo)識
    this._doors = iDoors;
    this.drivers = new Array("Mike","John");//公有屬性標(biāo)識
}
//所有對象共享一個(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)建對象方式之一

7.動態(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)來判斷是否已給原型賦予了任何方法,保證方法永遠(yuǎn)只被創(chuàng)建并賦值一次
    if(typeof Car5._initialized == "undefined"){//因?yàn)檫@里的標(biāo)記是附加在類上,故如果后期直接對其進(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)類型語言例如 java 等語言的定義模式

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)建的對象被傳遞回變量car6,這種方式在對象方法的內(nèi)部管理方面與經(jīng)典方式(工廠方法)有著相同的問題.應(yīng)盡量避免

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86064.html

相關(guān)文章

  • 淺談node.jsstream(流)

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

    elliott_hu 評論0 收藏0
  • 2018 淺談前端面試那些事

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

    LiuRhoRamen 評論0 收藏0
  • 2018 淺談前端面試那些事

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

    stormgens 評論0 收藏0
  • 2018 淺談前端面試那些事

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

    Hujiawei 評論0 收藏0
  • js面向對象淺談(二)

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

    Yuanf 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<