摘要:用對(duì)象字面量形式創(chuàng)建的對(duì)象,直接賦值給函數(shù)的原型對(duì)象,本質(zhì)上完全重寫(xiě)了其對(duì)象,因此屬性也就變成了新對(duì)象的屬性指向構(gòu)造函數(shù),不再指向函數(shù)。
【上一篇】:JavaScript對(duì)象內(nèi)部屬性及其特性總結(jié)
工廠模式(★★)先在內(nèi)部顯示地創(chuàng)建一個(gè)臨時(shí)對(duì)象,根據(jù)接收的參數(shù)來(lái)構(gòu)建(賦值屬性和方法)該對(duì)象,并返回該對(duì)象。
缺點(diǎn):沒(méi)有解決對(duì)象識(shí)別的問(wèn)題(即無(wú)法確認(rèn)一個(gè)對(duì)象的類型)。
function PersonFactory (name, age){ var o = new Object(); o.name = name; o.age = age; o.sayName = function(){ console.log(this.name) } return o; } var p1 = PersonFactory(); var p2 = PersonFactory(); p1 instanceof Object; // true p2 instanceof Object; // true p1 instanceof PersonFactory; // false 無(wú)法識(shí)別具體對(duì)象類型 p2 instanceof PersonFactory; // false構(gòu)造函數(shù)模式(★★★)
調(diào)用構(gòu)造函數(shù)實(shí)際經(jīng)歷4個(gè)步驟函數(shù)名首字母一般大寫(xiě)(如:Person,借鑒OO語(yǔ)言命名習(xí)慣)區(qū)別于其他函數(shù);
構(gòu)造函數(shù)本身也是函數(shù),只不過(guò)可以用來(lái)參加對(duì)象而已;
每個(gè)新建的實(shí)例對(duì)象都有一個(gè)constructor屬性,該屬性指向構(gòu)造函數(shù)自身Person;
構(gòu)造函數(shù)也可以被當(dāng)做普通函數(shù)來(lái)調(diào)用;
在全局作用域中調(diào)用一個(gè)函數(shù)時(shí),this對(duì)象總是指向Global對(duì)象(瀏覽器中即window對(duì)象)
【優(yōu)點(diǎn)】自定義構(gòu)造函數(shù)可以將它的實(shí)例標(biāo)識(shí)為一種特定的類型;
【缺點(diǎn)】構(gòu)造函數(shù)的主要問(wèn)題是,每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍;
與工廠模式比較創(chuàng)建(隱式地)一個(gè)新對(duì)象;
將構(gòu)造函數(shù)的新對(duì)象賦值給新對(duì)象(此時(shí)this指向這個(gè)新對(duì)象);
執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性);
返回新對(duì)象(該構(gòu)造函數(shù)的實(shí)例);
沒(méi)有顯示地創(chuàng)建對(duì)象;
直接將屬性和方法賦值給this對(duì)象;
沒(méi)有return語(yǔ)句;
優(yōu)點(diǎn):可以確認(rèn)具體對(duì)象類型;
function Person (name, age){ this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); } } // 當(dāng)做普通函數(shù) var p1 = new Person("Tom", 20); var p2 = new Person("Greg", 30); p1 instanceof Object; // true p2 instanceof Object; // true p1 instanceof PersonFactory; // true 可以確認(rèn)具體對(duì)象類型 p2 instanceof PersonFactory; // true // 作為普通函數(shù)調(diào)用 Person("Green", 30); // 屬性和方法都被添加到window對(duì)象了 window.sayName(); // "Green" // 在另一個(gè)對(duì)象的作用域中調(diào)用 var obj = new Object(); Person.call(obj , "Jim", 23); obj .sayName(); // "Jim"原型模式(★★★)
與構(gòu)造函數(shù)模式比較構(gòu)造函數(shù)變?yōu)榭蘸瘮?shù);
將所有屬性和方法都添加到了構(gòu)造函數(shù)的prototype屬性中;
不同:新對(duì)象的屬性和方法由所有實(shí)例共享(p1和p2訪問(wèn)的都是同一組屬性和同一個(gè)函數(shù));
function Person(){} Person.prototype.name = "Tom"; Person.prototype.age = 24; Person.prototype.sayName = function(){ console.log(this.name); } var p1 = new Person(), p2 = new Person(); p1.sayName();// "Tom" p2.sayName();// "Tom" console.log(p1.sayName === p2.sayName);// true利用更簡(jiǎn)單的原型語(yǔ)法
每創(chuàng)建一個(gè)函數(shù),就會(huì)同時(shí)創(chuàng)建它的prototype對(duì)象,該prototype對(duì)象也會(huì)自動(dòng)獲得constructor屬性。
用對(duì)象字面量形式創(chuàng)建的對(duì)象,直接賦值給函數(shù)的原型對(duì)象(Person.prototype),本質(zhì)上完全重寫(xiě)了其prototype對(duì)象,
因此constructor屬性也就變成了新對(duì)象的constructor屬性(指向Object構(gòu)造函數(shù)),不再指向Person函數(shù)。
此時(shí)instanceof操作符可以返回正確結(jié)果,但通過(guò)constructor已經(jīng)無(wú)法確定對(duì)象類型了。
function Person(){} Person.prototype = { // construtor : Person, // 需要重新指設(shè)constructor屬性 name : "Tom", age : 24, sayName : function(){ console.log(this.name); } } var p = new Person(); console.log(p instanceof Object); // ture console.log(p instanceof Person); // ture console.log(p.construtor == Object); // ture console.log(p.construtor == Person); // false安全地重設(shè)constructor
以上述方式重設(shè)constructor屬性會(huì)導(dǎo)致它的[[Enumerable]]特性被設(shè)置為true;
默認(rèn)情況下,原生的constructor屬性是不可枚舉的;
因此可利用Object.defineProperty()重設(shè);
Object.defineProperty(Person.prototype, "constructor", { enumerable : false, value : Person });組合模式(構(gòu)造函數(shù)模式和原型模式)(★★★★)
定義
組合使用構(gòu)造函數(shù)模式和原型模式;
構(gòu)造函數(shù)模式用于定義實(shí)例屬性,原型模式用于定義方法和共享的屬性;
優(yōu)點(diǎn):
每個(gè)實(shí)例都會(huì)有自己的一份實(shí)例屬性的副本,同時(shí)又共享著對(duì)方方法的引用,最大限度節(jié)省了內(nèi)存;
這種混成模式支持向構(gòu)造函數(shù)傳遞參數(shù);
目前使用最廣泛、認(rèn)同度最高的一種自定義類型的方法,可以說(shuō)是用來(lái)定義引用類型的一種默認(rèn)模式;
// 實(shí)例屬性均在構(gòu)造函數(shù)中定義 function Person(name, age){ this.name = name; this.age = age; this.friends = ["Nicholas", "Jim"]; } // 由所有實(shí)例共享屬性constructor和方法則是在原型中定義的 Person.prototype = { construtor: Person, sayName: function(){ console.log(this.name); } } var p1 = new Person("Tom", 25); var p2 = new Person("Greg", 26); p1.friends.push("Tony"); console.log(p1.friends); // ["Nicholas", "Jim", "Tony"] console.log(p2.friends); // ["Nicholas", "Jim"] console.log(p1.friends === p2.friends); // false console.log(p1.sayName === p2.sayName); // true動(dòng)態(tài)原型模式(★★★★★)
注意點(diǎn):
定義:
動(dòng)態(tài)原型模式把所有信息都封裝在了構(gòu)造函數(shù)中;
通過(guò)在構(gòu)造函數(shù)中初始化原型(僅在必要的情況下,比如第一次新建實(shí)例時(shí));
通過(guò)檢查某個(gè)應(yīng)該存在(原型中)的方法是否有效,來(lái)決定是否需要初始化原型;
優(yōu)點(diǎn):保持了同時(shí)使用構(gòu)造函數(shù)和原型的特點(diǎn);
下段代碼中只會(huì)在初次調(diào)用構(gòu)造函數(shù)時(shí)才會(huì)執(zhí)行,此后原型已經(jīng)完成初始化,無(wú)需再做修改;
這里對(duì)原型所做對(duì)修改,能夠立即在所有實(shí)例中得到反映;
if語(yǔ)句檢查的可以是初始化之后應(yīng)該存在的任何屬性或方法,檢查其中一個(gè)即可;
function Person(name, age){ // 屬性 this.name = name; this.age = age; // 方法 if(typeof this.sayName != "function"){ Person.prototype.sayName = function(){ console.log(this.name); } } }寄生構(gòu)造函數(shù)模式(★★)
與工廠模式的比較【定義】: 基本思想是創(chuàng)建一個(gè)函數(shù),該函數(shù)的作用僅僅是封裝創(chuàng)建對(duì)象的代碼,然后再返回新創(chuàng)建的對(duì)象。
【特點(diǎn)】:
返回的對(duì)象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性之間沒(méi)有關(guān)系;
寄生構(gòu)造函數(shù)返回的對(duì)象與在寄生構(gòu)造函數(shù)外部創(chuàng)建的對(duì)象沒(méi)有什么不同;
不能依賴instanceof操作符來(lái)確定對(duì)象類型;
與構(gòu)造函數(shù)模式的比較除了使用new操作符并把使用的包裝函數(shù)叫做構(gòu)造函數(shù)之外,該模式和工廠模式其實(shí)是一模一樣的;
從表面上看,很像典型的構(gòu)造函數(shù);
構(gòu)造函數(shù)在不返回值的情況下,默認(rèn)會(huì)返回新對(duì)象實(shí)例;
而寄生構(gòu)造函數(shù)通過(guò)在構(gòu)造函數(shù)的末尾加一個(gè)return語(yǔ)句,重寫(xiě)了調(diào)用構(gòu)造函數(shù)時(shí)返回的值;
此時(shí)返回的對(duì)象的__proto__屬性指向Object;
function Person(name, age){ // 創(chuàng)建臨時(shí)新對(duì)象 var o = new Object(); // 初始化該對(duì)象 o.name = name; o.age = age; o.sayName = function(){ console.log(this.name); } // 返回該臨時(shí)新對(duì)象 return o; } var p1 = new Person("Tom", 25); var p2 = new Person("Greg",30); console.log(p1 instanceof Object); // true console.log(p1 instanceof Person); // false console.log(p1.sayName == p2.sayName); // false console.log(p1.constructor == Object); //true穩(wěn)妥構(gòu)造函數(shù)模式(★★)
所謂穩(wěn)妥對(duì)象,就是指沒(méi)有公共屬性,而且其方法也不引用this的對(duì)象。與寄生構(gòu)造函數(shù)模式的比較
穩(wěn)妥對(duì)象最適合在一些安全的環(huán)境中(這些環(huán)境會(huì)禁用this和new),或者防止數(shù)據(jù)被其他應(yīng)用程序改動(dòng)時(shí)調(diào)用。
與寄生構(gòu)造函數(shù)類似,但又不同:
一是新創(chuàng)建的對(duì)象實(shí)例方法不引用this;
二是不使用new操作符調(diào)用構(gòu)造函數(shù);
function Person (name, age){ var o = new Object(); // 可定義私有變量和函數(shù) // ... // 新創(chuàng)建的對(duì)象實(shí)例方法未引用this; o.sayName = function(){ console.log(name) } return o; } var p = Person("Tom", 23); p.sayName(); // "Tom" console.log(p instanceof Person); // false
除了sayName()方法外,沒(méi)有別的方法可以訪問(wèn)其數(shù)據(jù)成員;
即使有其他代碼給這個(gè)對(duì)象添加方法或數(shù)據(jù)成員,也不可能有別的辦法訪問(wèn)傳入到構(gòu)造函數(shù)中的原始數(shù)據(jù);
與寄生構(gòu)造函數(shù)模式類似,使用穩(wěn)妥構(gòu)造函數(shù)模式創(chuàng)建的對(duì)象與構(gòu)造函數(shù)之間也沒(méi)有關(guān)系(故instanceof操作符對(duì)這種對(duì)象也無(wú)意義);
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/99379.html
摘要:函數(shù)類型檢測(cè)是的子類型,其屬性為參數(shù)個(gè)數(shù),但是判斷結(jié)果有內(nèi)建函數(shù)原生函數(shù)常見(jiàn)的有,可能被當(dāng)作構(gòu)造函數(shù)來(lái)使用,創(chuàng)建出來(lái)的是封裝了的基本類型值。構(gòu)造函數(shù)可以不帶關(guān)鍵字。建議使用和來(lái)進(jìn)行顯示強(qiáng)制轉(zhuǎn)換。 前言 此篇小結(jié)來(lái)源與《你不知道的JavaScript》和《JavaScript高級(jí)程序設(shè)計(jì)》的結(jié)合??或許是的,龜速總結(jié)中... 七種內(nèi)置類型 null undefined boolean ...
摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來(lái)有點(diǎn)混亂所以將前端主流技術(shù)做了一個(gè)書(shū)簽整理不求最多最全但求最實(shí)用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來(lái)有點(diǎn)混亂; 所以將前端主流技術(shù)做了一個(gè)書(shū)簽整理,不求最多最全,但求最實(shí)用。 書(shū)簽源碼 書(shū)簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...
摘要:繼承的是超類型中構(gòu)造函數(shù)中的屬性,如上繼承了屬性,但沒(méi)有繼承原型中的方法。上述造成的結(jié)果是子類型實(shí)例中有兩組超類型的構(gòu)造函數(shù)中定義的屬性,一組在子類型的實(shí)例中,一組在子類型實(shí)例的原型中。 ECMAScript只支持實(shí)現(xiàn)繼承,主要依靠原型鏈來(lái)實(shí)現(xiàn)。與實(shí)現(xiàn)繼承對(duì)應(yīng)的是接口繼承,由于script中函數(shù)沒(méi)有簽名,所以無(wú)法實(shí)現(xiàn)接口繼承。 一、原型鏈 基本思想:利用原型讓一個(gè)引用類型繼承另一個(gè)引用...
摘要:創(chuàng)建對(duì)象中,創(chuàng)建對(duì)象的基本模式有三種。因此,在設(shè)計(jì)構(gòu)造函數(shù)時(shí),需要進(jìn)行慎重考慮。因此在中,這種問(wèn)題被稱作繼承破壞封裝。靜態(tài)成員每個(gè)只有一份,直接通過(guò)類對(duì)象進(jìn)行訪問(wèn)。 什么是封裝 找工作時(shí)一些公司給了offer后我就想知道真正拿到手的是多少,畢竟賦稅繁重。但各種稅也好,五險(xiǎn)一金也好我實(shí)在是弄不清楚,于是我就會(huì)在網(wǎng)上的一些稅后收入計(jì)算器上進(jìn)行計(jì)算,只需要填寫(xiě)一些基本信息,比如稅前收入,所...
閱讀 1849·2023-04-26 01:58
閱讀 1982·2019-08-30 11:26
閱讀 2730·2019-08-29 12:51
閱讀 3495·2019-08-29 11:11
閱讀 1183·2019-08-26 11:54
閱讀 2096·2019-08-26 11:48
閱讀 3478·2019-08-26 10:23
閱讀 2384·2019-08-23 18:30