色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

為什么我要說 JavaScript 對象字面量很酷?

瀏覽:2日期:2023-11-17 13:47:02

在 ECMAScript 2015 之前,JavaScript 里的對象字面量(也叫對象初始化器)功能很弱。它只能定義兩種屬性:

普通鍵/值對 { name1: value }Getters { get name(){..} } 以及 setters { set name(val){..} },用來設置和獲取需要計算的值。

令人心痛地,對象字面量的所有用法只用一個簡單的例子就能囊括:

Try in JS Bin

var myObject = { myString: ’value 1’, get myNumber() { return this.myNumber; }, set myNumber(value) { this.myNumber = Number(value); }};myObject.myString; // => ’value 1’ myObject.myNumber = ’15’; myObject.myNumber; // => 15

JavaScript 是一個基于原型的語言,因此一切皆是對象。當涉及到對象創建、結構和訪問原型時,語言必須提供簡單的結構。

定義一個對象并設置它的原型是一個常見的任務。我總覺得設置原型應該被對象字面量直接支持,使用單一的語法。

不幸地是,字面量的局限性使得它沒有直接的解決方案。你不得不使用 Object.create() 來結合對象字面量和設置原型:

Try in JS Bin

var myProto = { propertyExists: function(name) { return name in this; }}; var myNumbers = Object.create(myProto); myNumbers[’array’] = [1, 6, 7]; myNumbers.propertyExists(’array’); // => true myNumbers.propertyExists(’collection’); // => false

在我看來,這是一個不舒服的解決方案。JavaScript 是基于原型的,為什么從原型創建一個對象那么麻煩?

幸運地是,JavaScript 在改變。比較令人沮喪的許多問題在 JavaScript 中正在被一步一步地解決。

這篇文章解釋 ES2015 是如何解決上面所說的問題以及改進對象字面量以獲得額外的好處:

在對象構造的過程中設置原型速記方法定義調用父類方法計算屬性名稱

同時,讓我們展望未來,了解最新的提案(stage 2):對象的 rest 屬性和屬性展開操作符。

為什么我要說 JavaScript 對象字面量很酷?

1. 在對象構造時設置原型

如你已經知道得,其中一個訪問一個已存在對象的原型的方法是使用 getter 屬性 __proto__:

Try in JS Bin

var myObject = { name: ’Hello World!’ };myObject.__proto__; // => {} myObject.__proto__.isPrototypeOf(myObject); // => true

myObject.__proto__ 返回 myObject 的原型對象。

好消息是 ES2015 允許使用 字面量 __proto__ 作為屬性名來設置對象字面量的原型 { __proto__: protoObject }。

讓我們用 __proto__ 重寫一下上面那個例子,讓它看起來好一點:

Try in JS Bin

var myProto = { propertyExists: function(name) { return name in this; }}; var myNumbers = { __proto__: myProto, array: [1, 6, 7]};myNumbers.propertyExists(’array’); // => true myNumbers.propertyExists(’collection’); // => false

myNumbers 對象使用原型 myProto 創建,這可以通過特殊屬性 __proto__ 實現。

這個對象通過簡單的語句創建,而不需要額外的函數例如 Object.create()。

如你所見,使用 __proto__ 是簡單的。我偏愛簡單直接的解決方案。

有點說跑題了,回到主題來。我認為獲得簡單和可靠的解決方案需要通過大量的設計和實踐。如果一個解決方案是簡單的,你可能認為它同樣也很容易被設計出來,然而事實并不是這樣:

讓它變得簡單明了的過程是復雜的讓它變得復雜和難以理解卻很容易

如果某個東西看起來太復雜或者用起來不舒服,很可能它的設計者考慮不周。

元芳,你怎么看?(歡迎在文章底部發表評論參與討論)

2.1 使用 __proto__ 的特例

盡管 __proto__ 看似簡單,卻有一些特殊的場景你需要格外注意。

為什么我要說 JavaScript 對象字面量很酷?

在對象字面量中 __proto__ 只允許使用一次。多次使用的話 JavaScript 會拋出異常:

Try in JS Bin

var object = { __proto__: { toString: function() { return ’[object Numbers]’ } }, numbers: [1, 5, 89], __proto__: { toString: function() { return ’[object ArrayOfNumbers]’ } }};

上面例子中的對象字面量使用了 __proto__ 屬性兩次,這是不允許的。這種情況下,會拋出一個錯誤 SyntaxError: Duplicate __proto__ fields are not allowed in object literals。

JavaScript 限制了只允許使用 object 或者 null 作為 __proto__ 屬性的值。使用其它原生類型(如字符串、數值、布爾類型)或者 undefined 會被忽略,并不能改變對象的原型。

看一個例子:

Try in JS Bin

var objUndefined = { __proto__: undefined }; Object.getPrototypeOf(objUndefined); // => {} var objNumber = { __proto__: 15 }; Object.getPrototypeOf(objNumber); // => {}

上面的例子里,對象字面量使用 undefined 和數值 15 來設置 __proto__ 值。因為只有對象或者 null 才允許被使用,objUndefined 和 objNumber 仍然是它們默認的原型:簡單 JavaScript 對象 {}。__proto__ 的賦值被忽略了。

當然,嘗試使用原生類型來設置對象的原型,這本身是很奇怪的。所以在這里做限制是符合預期的。

2. 速記方法定義

現在對象字面量中可以使用一個更短的語法來聲明方法,省略 function 關鍵字和冒號。這被叫做速記方法定義(shorthand method definition)。

讓我們用新的方式來定義一些方法:

Try in JS Bin

var collection = { items: [], add(item) { this.items.push(item); }, get(index) { return this.items[index]; }};collection.add(15); collection.add(3); collection.get(0); // => 15

add() 和 get() 是 collection 中使用快捷的方式定義的方法。

一個很好的地方是這樣聲明的方法是具名的,這對于調試有幫助。執行 collection.add.name 將返回函數名稱 ’add’。

3. 調用父類方法

一個有趣的改進是能夠使用 super 關鍵字來訪問從原型鏈繼承下來的屬性。看下面的例子:

Try in JS Bin

var calc = { sumArray (items) { return items.reduce(function(a, b) { return a + b; }); }}; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements() { return super.sumArray(this.numbers); }};numbers.sumElements(); // => 17

calc 是 numbers 對象的屬性。在 numbers 的方法 sumElements 里面,要調用原型 calc上的方法,可以使用 super 關鍵字: super.sumArray()。

所以 super 是從原型鏈訪問被繼承的屬性的一個快捷的方法。

在上一個例子里,我們也可以直接調用 cale.sumArray(),不過 super 是一個更好的選擇因為它訪問對象的原型鏈。它的存在清晰地暗示了繼承的屬性將被使用。

3.1 使用 super 的限制

在對象字面量中, super 只能用在速記方法定義中。

如果在普通的方法聲明 { name: function() {} } 中使用它,JavaScript 會拋異常:

Try in JS Bin

var calc = { sumArray (items) { return items.reduce(function(a, b) { return a + b; }); }}; var numbers = { __proto__: calc, numbers: [4, 6, 7], sumElements: function() { return super.sumArray(this.numbers); }}; // Throws SyntaxError: ’super’ keyword unexpected here numbers.sumElements();

上面的代碼里,方法 sumElements 被定義為:sumElements:function(){...}。由于 super要求在速記方法中使用,在其中調用 super 將拋出異常:SyntaxError: ’super’ keyword unexpected here。

這個限制不會對對象字面量聲明有多少影響,因為大部分情況下我們沒有理由不用速記方法定義,畢竟它語法更簡單。

4. 計算屬性名稱

在 ES2015 之前,對象初始化器的屬性名稱是字面量,大多數情況下是靜態字符串。要創建一個動態計算的屬性名,你不得不使用屬性訪問器:

Try in JS Bin

function prefix(prefStr, name) { return prefStr + ’_’ + name;} var object = {}; object[prefix(’number’, ’pi’)] = 3.14; object[prefix(’bool’, ’false’)] = false; object; // => { number_pi: 3.14, bool_false: false }

當然,這種定義屬性的方法差強人意。

計算屬性名稱能更優雅地解決這個問題。

當我們從表達式計算屬性名稱,將代碼放在方括號之間 {[expression]: value}。這個表達式計算結果將成為屬性名。

我真的很喜歡這個語法:短而簡單。

讓我們改進上面的代碼:

Try in JS Bin

function prefix(prefStr, name) { return prefStr + ’_’ + name;} var object = { [prefix(’number’, ’pi’)]: 3.14, [prefix(’bool’, ’false’)]: false };object; // => { number_pi: 3.14, bool_false: false }

[prefix(’number’, ’pi’)] 通過計算 prefix(’number’, ’pi’) 表達式來設置屬性名稱, 得到的結果是 ’number_pi’。

相應地, [prefix(’bool’, ’false’)] 將第二個屬性名稱設為 ’bool_false’。

4.1 Symbol 作為屬性名

Symbols 也可以被用來計算屬性名稱,只需要將它包含在方括號中:{ [Symbol(’name’)]: ’Prop value’ }。

例如,使用特殊屬性 Symbol.iterator 來迭代遍歷一個對象的自有屬性名,代碼如下:

Try in JS Bin

var object = { number1: 14, number2: 15, string1: ’hello’, string2: ’world’, [Symbol.iterator]: function *() { var own = Object.getOwnPropertyNames(this), prop; while(prop = own.pop()) { yield prop; } }}[...object]; // => [’number1’, ’number2’, ’string1’, ’string2’]

[Symbol.iterator]: function *() { } 定義一個屬性來用于迭代遍歷對象自有屬性。展開操作符 [...object] 使用迭代器并返回自有屬性列表。

5. 展望未來:rest 和屬性展開

對象字面量的 Rest 和屬性展開 是新的標準草案中的一個提案(stage 2),意味著這一特性是新版本 JavaScript 的規范的候選。

數組的 展開和 rest 操作符 已經被實現了。

Rest 屬性 允許我們從解構賦值左側使用對象來收集屬性,看下面的例子:

Try in JS Bin

var object = { propA: 1, propB: 2, propC: 3 }; let {propA, ...restObject} = object; propA; // => 1 restObject; // => { propB: 2, propC: 3 }

屬性展開 允許將源對象的自有屬性拷進對象字面量內部。在上面的例子中,對象字面量從 souce對象中收集額外的屬性。

Try in JS Bin

var source = { propB: 2, propC: 3 }; var object = { propA: 1, ...source}object; // => { propA: 1, propB: 2, propC: 3 }6. 結論

JavaScript 在快速進步。

即使是相對小的結構比如對象字面量在 ES2015 中都有相當大的改進,更別說還有一大堆新特性在草案中。

你可以從初始化器中使用 __proto__ 屬性直接設置對象的原型,這比使用 Object.create() 要更方便。

方法聲明可以寫成更簡短的形式,這樣你就不用寫 function 關鍵字了。然后在速記方法中可以使用 super 關鍵字,它能提供方便的對被繼承原型鏈上屬性的訪問。

如果一個屬性名在運行時計算,現在你可以使用計算屬性名稱 [表達式] 來初始化對象。

的確,對象字面量現在很酷!

你覺得呢?歡迎在下方發表評論參與討論。

來自:http://www.zcfy.cc/article/why-object-literals-in-javascript-are-cool-948.html

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 伊人色综合7777 | 成年人午夜网站 | 日本男人的天堂 | 最新理论三级中文在线观看 | 香港国产特级一级毛片 | 成人精品一区二区激情 | 日韩中文字幕在线观看 | 99久久免费看国产精品 | 国产精品九九视频 | 草草久| 视频二区国产 | 香港台湾经典三级a视频 | 亚洲人成网国产最新在线 | xo欧美性另类| 欧美三级在线看 | 久久精品国产91久久综合麻豆自制 | 99精品高清不卡在线观看 | 92午夜国产福利视频1000 | 日本xxxxx黄区免费看动漫 | 亚洲欧美一区二区三区孕妇 | 男人的天堂欧美 | 99久久精品免费看国产一区二区三区 | 真实国产普通话对白乱子子伦视频 | 成a人v | 美女擦逼 | 欧美日韩亚洲精品一区 | 日本一级特黄aa毛片免费观看 | 久热精品男人的天堂在线视频 | 午夜专区 | 精品一区二区三区在线播放 | 就草草在线观看视频 | 99国产精品热久久久久久夜夜嗨 | 视色4setv.com | 波多野结衣视频免费观看 | 日韩午夜在线视频不卡片 | 波多野结衣在线免费观看视频 | 9191精品国产费久久 | 国产成人高清一区二区私人 | 手机在线观看毛片 | 欧美一区二区不卡视频 | 国产三级做爰在线观看 |