ES6 學習筆記之四 對象的擴展

ES6 爲對象字面量添加了幾個實用的功能,雖然這幾個新功能基本上都是語法糖,但確實方便。瀏覽器

1、屬性的簡潔表示法安全

當定義一個對象時,容許直接寫入一個變量,做爲對象的屬性,變量名就是屬性名。函數

例1:spa

var x = 2, y = 3,
o = {
    x,
    y
}

與例2:prototype

var x = 2, y = 3,
o = {
    x: x,
    y: y
}

是相同的。code

2、方法的簡潔表示法對象

下面的例子是方法的簡潔表示法(例3)blog

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)這種使用命名函數定義方法,並做自我調用的狀況,是不能使用方法的簡潔表示法的:ip

let o = {
    factorial: function factorial (x) {\
        if (x > 1) {
            return x * factorial(x - 1)
        } else {
            return 1;
        }
    }
}
console.log(o.factorial(5));

3、 屬性名錶達式

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] };

4、操做[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 屬性的值。

5、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();

6、 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' } } ,你可要失望了。

相關文章
相關標籤/搜索