摘要:要添加到新對(duì)象的可枚舉新添加的屬性是其自身的屬性,而不是其原型鏈上的屬性的屬性。大家可能會(huì)注意到,第一個(gè)參數(shù)使用了。也就是說(shuō)將設(shè)置成了新創(chuàng)建對(duì)象的原型,自然就不會(huì)有原型鏈上的屬性。至此,我相信大家已經(jīng)對(duì)兩者的區(qū)別十分清楚了。
在Vue和Vuex的源碼中,作者都使用了Object.create(null)來(lái)初始化一個(gè)新對(duì)象。為什么不用更簡(jiǎn)潔的{}呢?Object.create()的定義在SegmentFault和Stack Overflow等開(kāi)發(fā)者社區(qū)中也有很多人展開(kāi)了討論,在這里總結(jié)成文,溫故知新。
照搬一下MDN上的定義:
Object.create(proto,[propertiesObject])
proto:新創(chuàng)建對(duì)象的原型對(duì)象
propertiesObject:可選。要添加到新對(duì)象的可枚舉(新添加的屬性是其自身的屬性,而不是其原型鏈上的屬性)的屬性。
舉個(gè)例子(惡改了一下MDN的官方例子,看懂的點(diǎn)贊):
const car = { isSportsCar: false, introduction: function () { console.log(`Hi girl, this is a ${this.name}. Do you like to have a drink with me ? ${this.isSportsCar}`); } }; const porsche = Object.create(car,{ //color成為porsche的數(shù)據(jù)屬性 //顏色不喜歡,可以改色或貼膜,所以可修改 color:{ writable:true, configurable:true, value:"yellow" }, //type成為porsche的訪問(wèn)器屬性 type:{ // writable、configurable等屬性,不顯式設(shè)置則默認(rèn)為false // 想把普通車(chē)改成敞篷,成本有點(diǎn)大了,所以就設(shè)成不可配置吧 get:function(){return "convertible"}, set:function(value){"change this car to",value} } }); porsche.name = "Porsche 911"; // "name"是"porsche"的屬性, 而不是"car"的 porsche.isSportsCar = true; // 繼承的屬性可以被覆寫(xiě) porsche.introduction(); // expected output: "Hi girl, this is a Porsche 911. Do you like to have a drink with me ? true"
Object.create()的定義其實(shí)很簡(jiǎn)單,弄清楚上面這個(gè)例子就可以了。
Object.create()、{...}的區(qū)別先看看我們經(jīng)常使用的{}創(chuàng)建的對(duì)象是什么樣子的:
var o = {a:1}; console.log(o)
在chrome控制臺(tái)打印如下:
從上圖可以看到,新創(chuàng)建的對(duì)象繼承了Object自身的方法,如hasOwnProperty、toString等,在新對(duì)象上可以直接使用。
再看看使用Object.create()創(chuàng)建對(duì)象:
var o = Object.create(null,{ a:{ writable:true, configurable:true, value:"1" } }) console.log(o)
在chrome控制臺(tái)打印如下:
可以看到,新創(chuàng)建的對(duì)象除了自身屬性a之外,原型鏈上沒(méi)有任何屬性,也就是沒(méi)有繼承Object的任何東西,此時(shí)如果我們調(diào)用o.toString()會(huì)報(bào)Uncaught TypeError的錯(cuò)誤。
大家可能會(huì)注意到,第一個(gè)參數(shù)使用了null。也就是說(shuō)將null設(shè)置成了新創(chuàng)建對(duì)象的原型,自然就不會(huì)有原型鏈上的屬性。我們?cè)侔焉厦娴睦痈囊桓模?/p>
var o = Object.create({},{ a:{ writable:true, configurable:true, value:"1" } }) console.log(o)
將null改為{},結(jié)果是怎樣的?在chrome控制臺(tái)打印如下:
我們看到,這樣創(chuàng)建的對(duì)象和使用{}創(chuàng)建對(duì)象已經(jīng)很相近了,但是還是有一點(diǎn)區(qū)別:多了一層proto嵌套。
我們最后再來(lái)改一下:
var o = Object.create(Object.prototype,{ a:{ writable:true, configurable:true, value:"1" } }) console.log(o)
chrome控制臺(tái)打印如下:
這次就和使用{}創(chuàng)建的對(duì)象一模一樣了。至此,我相信大家已經(jīng)對(duì)兩者的區(qū)別十分清楚了。
Object.create(null)的使用場(chǎng)景再回到文章開(kāi)頭的問(wèn)題,為什么很多源碼作者會(huì)使用Object.create(null)來(lái)初始化一個(gè)新對(duì)象呢?這是作者的習(xí)慣,還是一個(gè)最佳實(shí)踐?
其實(shí)都不是,這并不是作者不經(jīng)思考隨便用的,也不是javascript編程中的最佳實(shí)踐,而是需要因地制宜,具體問(wèn)題具體分析。
我們進(jìn)一步比較一下Object.create(null)和{}創(chuàng)建控對(duì)象的區(qū)別:
在chrome打印如下:
從上圖可以看到,使用create創(chuàng)建的對(duì)象,沒(méi)有任何屬性,顯示No properties,我們可以把它當(dāng)作一個(gè)非常純凈的map來(lái)使用,我們可以自己定義hasOwnProperty、toString方法,不管是有意還是不小心,我們完全不必?fù)?dān)心會(huì)將原型鏈上的同名方法覆蓋掉。舉個(gè)例子:
//Demo1: var a= {...省略很多屬性和方法...}; //如果想要檢查a是否存在一個(gè)名為toString的屬性,你必須像下面這樣進(jìn)行檢查: if(Object.prototype.hasOwnProperty.call(a,"toString")){ ... } //為什么不能直接用a.hasOwnProperty("toString")?因?yàn)槟憧赡芙oa添加了一個(gè)自定義的hasOwnProperty //你無(wú)法使用下面這種方式來(lái)進(jìn)行判斷,因?yàn)樵蜕系膖oString方法是存在的: if(a.toString){} //Demo2: var a=Object.create(null) //你可以直接使用下面這種方式判斷,因?yàn)榇嬖诘膶傩裕紝⒍x在a上面,除非手動(dòng)指定原型: if(a.toString){}
另一個(gè)使用create(null)的理由是,在我們使用for..in循環(huán)的時(shí)候會(huì)遍歷對(duì)象原型鏈上的屬性,使用create(null)就不必再對(duì)屬性進(jìn)行檢查了,當(dāng)然,我們也可以直接使用Object.keys[]。
總結(jié)一下:
你需要一個(gè)非常干凈且高度可定制的對(duì)象當(dāng)作數(shù)據(jù)字典的時(shí)候;
想節(jié)省hasOwnProperty帶來(lái)的一丟丟性能損失并且可以偷懶少些一點(diǎn)代碼的時(shí)候
用Object.create(null)吧!
其他時(shí)候,請(qǐng)用{}。
以上
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/94135.html
摘要:使用操作符,創(chuàng)建一個(gè)對(duì)象,并且執(zhí)行構(gòu)造函數(shù)方法。使用可以返回一個(gè)字典型對(duì)象對(duì)象原型每一個(gè)對(duì)象都有一個(gè)內(nèi)置的屬性指向構(gòu)造它的函數(shù)屬性而構(gòu)造函數(shù)的則指向構(gòu)造函數(shù)本生。 對(duì)象概念 在 javascript 中, 一切引用類(lèi)型均為對(duì)象。 如 function Foo () {} 中,F(xiàn)oo本身就是一個(gè)對(duì)象的引用。 創(chuàng)建對(duì)象方式 字面量方式 new 構(gòu)造函數(shù) 函數(shù)聲明 Object.creat...
摘要:原文地址詳解的類(lèi)博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語(yǔ)言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類(lèi)又該怎么定義呢在面向?qū)ο缶幊讨?,?lèi)是對(duì)象的模板,定義了同一組對(duì)象又稱(chēng)實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類(lèi) 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語(yǔ)言,一...
摘要:原文地址詳解的類(lèi)博主博客地址的個(gè)人博客從當(dāng)初的一個(gè)彈窗語(yǔ)言,一步步發(fā)展成為現(xiàn)在前后端通吃的龐然大物。那么,的類(lèi)又該怎么定義呢在面向?qū)ο缶幊讨?,?lèi)是對(duì)象的模板,定義了同一組對(duì)象又稱(chēng)實(shí)例共有的屬性和方法。這個(gè)等同于的屬性現(xiàn)已棄用。。 前言 生活有度,人生添壽。 原文地址:詳解javascript的類(lèi) 博主博客地址:Damonare的個(gè)人博客 ??Javascript從當(dāng)初的一個(gè)彈窗語(yǔ)言,一...
介紹 在創(chuàng)建對(duì)象的時(shí)候,我們有2種常用方法 一個(gè)是文本標(biāo)記法(var obj = {}),一種是運(yùn)用Object函數(shù)進(jìn)行對(duì)象的創(chuàng)建(new Object()). 但是這兩種方式并不是創(chuàng)建的一個(gè)完完全全干干凈凈的對(duì)象,這里的干凈只得是沒(méi)有繼承鏈. 幸運(yùn)的是,ES5為我們提供了一種創(chuàng)建完全干凈的對(duì)象的方法,Object.create函數(shù),接下我將向大家介紹Obje...
閱讀 2403·2021-09-22 16:01
閱讀 3167·2021-09-22 15:41
閱讀 1182·2021-08-30 09:48
閱讀 501·2019-08-30 15:52
閱讀 3337·2019-08-30 13:57
閱讀 1725·2019-08-30 13:55
閱讀 3676·2019-08-30 11:25
閱讀 771·2019-08-29 17:25