ES6 為對象字面量添加了幾個實用的功能,雖然這幾個新功能基本上都是語法糖,但確實方便。 一、屬性的簡潔表示法 當定義一個對象時,允許直接寫入一個變數,作為對象的屬性,變數名就是屬性名。 例1: 與例2: 是相同的。 二、方法的簡潔表示法 下麵的例子是方法的簡潔表示法(例3) 和下例是完全等同的(例 ...
ES6 為對象字面量添加了幾個實用的功能,雖然這幾個新功能基本上都是語法糖,但確實方便。
一、屬性的簡潔表示法
當定義一個對象時,允許直接寫入一個變數,作為對象的屬性,變數名就是屬性名。
例1:
var x = 2, y = 3, o = { x, y }
與例2:
var x = 2, y = 3, o = { x: x, y: y }
是相同的。
二、方法的簡潔表示法
下麵的例子是方法的簡潔表示法(例3)
let o = {
m (x) {
console.log(x);
}
}
o.m("Hello!");
和下例是完全等同的(例4)
let o = { m: function (x) { console.log(x); } } o.m("Hello!");
由於例3和例4完全相同,也就是說例3中的函數也是匿名函數,不能在函數內部使用函數名調用自身,因此下例(例5)這種使用命名函數定義方法,並作自我調用的情況,是不能使用方法的簡潔表示法的:
let o = { factorial: function factorial (x) {\ if (x > 1) { return x * factorial(x - 1) } else { return 1; } } } console.log(o.factorial(5));
三、 屬性名錶達式
ES6 允許在字面量定義對象時,使用表達式做屬性名和方法名,示例如下(例6):
1 let firstName = 'first'; 2 let secondFrontName = 'se'; 3 let secondBehandName = 'cond'; 4 let funcName = function () { 5 return 'func'; 6 } 7 let methodName1 = 'sayHello'; 8 let methodName2 = 'sayBye'; 9 let obj = { 10 [firstName]: 'hello', 11 [secondFrontName + secondBehandName]: 'world', 12 [funcName()]: 'bye', 13 [methodName1]() { 14 console.log('Hello, world!'); 15 }, 16 [methodName2]: function () { 17 console.log('Goodbye!'); 18 } 19 } 20 console.log(obj[firstName]); 21 console.log(obj[secondFrontName + secondBehandName]); 22 console.log(obj[funcName()]); 23 obj.sayHello(); 24 obj.sayBye();
註意,在第13行時,同時使用了屬性名錶達式和方法的簡潔表示法,這是沒問題的。
但是不能同時使用屬性名錶達式和屬性的簡潔表示法,會報錯(例7):
let foo = 'bar';
let bar = 'abc';
let baz = { [foo] };
四、操作[Prototype]
作為原型繼承語言,在JavaScript中,prototype屬性是非常重要的。在前ES6中,瀏覽器提供了擴展的屬性__proto__,來獲取和設置它。
ES6 將這個屬性放在了標準的附錄部分,並且說明僅要求瀏覽器實現這個屬性,也就是說只有在瀏覽器中的腳本使用這個屬性才是安全可信賴的。
為保持對特定環境的非依賴,不應該在代碼中使用這個屬性。而應該使用 Object.setPrototypeOf(...) 和 Object.getPrototypeOf(...) 方法設置和獲取,這兩個方法是全環境安全的。
例8:
1 let proto = {}; 2 proto.y = 20; 3 let obj = {x : 10}; 4 console.log(Object.getPrototypeOf(obj)); 5 console.log(obj.y); 6 Object.setPrototypeOf(obj, proto); 7 console.log(Object.getPrototypeOf(obj)); 8 console.log(obj.y);
第四行的結果顯示,obj 的 [prototype] 是 Object,並且第五行獲得的 y 屬性為 undefined。
經過第6行的設置,obj 的 [prototype] 就是proto對象了,並且第8行 obj 的 y 屬性是循著原型鏈獲取到的 proto 對象的 y 屬性的值。
五、super
super 可以用來調用原型鏈上的方法,如下例(例9):
let proto = { foo () { console.log("I'm proto foo."); } } let parent = { } let obj = { foo () { super.foo(); console.log("I'm obj foo."); } } Object.setPrototypeOf(parent, proto) Object.setPrototypeOf(obj, parent); obj.foo(); // I'm proto foo.
// I'm obj foo.
super 只能出現在方法的簡潔表示法定義中,如下例(例10)這樣是會報錯的:
let proto = { foo () { console.log("I'm proto foo."); } } let parent = { } let obj = { foo: function () { super.foo(); console.log("I'm obj foo."); } } Object.setPrototypeOf(parent, proto) Object.setPrototypeOf(obj, parent); obj.foo();
對於要調用的方法是不是用簡潔表示法定義的,則沒有限制,如下例(例11):
let proto = { foo: function () { console.log("I'm proto foo."); } } let parent = { } let obj = { foo () { super.foo(); console.log("I'm obj foo."); } } Object.setPrototypeOf(parent, proto) Object.setPrototypeOf(obj, parent); obj.foo();
六、 Object.is()方法和Object.assign()方法
Object.is() 方法用來比較兩個對象是否嚴格相等,它的行為與 === 極為相似,不同點有二:
1. +0 和 -0
對於 === 運算符,+0 和 -0 是相等的,而 Object.is()則認為這兩個值不同。
+0 === -0; // true Object.is(+0, -0); // false
2. NaN 和 NaN
對於 === 運算符,NaN 和 NaN 是不等的,Object.is() 則認為這是相同的。
NaN == NaN; // false Object.is(NaN, NaN); // true
Object.assign() 方法用來將一個至多個對象的可枚舉屬性拷貝到目標對象中。
Object.assign()方法的第一個參數是目標對象,後續的參數為源對象(參數必須是對象)。如果對象中有相同名稱的屬性,則排列在後的對象的屬性會覆蓋排在前面的對象的同名屬性。(這個方法,有點像 JQuery 中的 extend 方法)
例12:
let obj1 = {}; let obj2 = { prop: "I'm property", func () { return "I'm function."; } } Object.assign(obj1, obj2); console.log(obj1); console.log(obj1.func());
這一方法的限制是:它只複製自身的可枚舉屬性,繼承來的屬性不複製,不可枚舉屬性也不複製;另外它的複製是淺拷貝,即只處理一級屬性的添加和替換,嵌套屬性不處理。
如下例(例13)
let target = { a: { b: 'c', d: 'e' } }; let source = { a: { b: 'hello' } }; Object.assign(target, source); // { a: { b: 'hello' } }
註意此例的結果,target 的 a 屬性被 source 的 a 屬性完全替換,而不是 source 中 a 屬性的 b 嵌套屬性替換了 target 中 a 屬性的 b 嵌套屬性。如果你期望的結果是 { a: { b: 'hello', d: 'e' } } ,你可要失望了。