0,本文适合人群和主要内容
ES6初學者,通過閱讀本文可對ES6知識點有個大體的概念,強烈建議閱讀阮一峰大大的ES6入門
老司機可以直接繞路。
上一節主要是總結了ES6中和數組有關的内容。本節主要總結ES6中對象的擴充,具體内容包括以下幾個方面:
會介紹以下内容:
1.ES6對象字面量
1.1簡化對象屬性定義
驗證(1)
簡化屬性定義:
// ES5
function test(name, age) {
return {
name: name,
age: age
}
}
// 等價于
function test(name, age) {
return {
name,
age
}
}
複制
當一個對象的屬性和本地變量同名時,可以簡單地中寫屬性名。
1.2對象方法簡寫
驗證(2)
對象方法可以簡寫,去掉冒号和function關鍵字:
// ES5
var person = {
name: "Peter",
age: 26,
showAge: function () {
console.log('age is', this.age)
}
}
// 等價于
var person = {
name: "Peter",
age: 26,
showAge() {
console.log('age is', this.age)
}
}
複制
1.3同一個對象定義多個同名屬性不報錯
驗證(3)
同一個對象定義多個同名屬性不報錯
var person = {
name:'Peter',
name:'Tom'
}
console.log(person.name) // Tom
複制
ES5在嚴格模式下會去校驗是否有同名屬性,ES6則無論在嚴格模型下,還是非嚴格模式下,都不會去校驗屬性是否重複。
2.Object.is()和Object.assing()
2.1Object.is()
有些像“===”運算符,可接受兩個參數進行比較。如果兩個參數的類型一緻,并且值也相同,則傳回true。
驗證:
console.log(Object.is(1,"1")); // false
複制
Object.is()和===運算符的差別:
console.log(Object.is(+0, -0)); // false
console.log(+0 === -0); // true
console.log(Object.is(NaN, NaN)) // true
console.log(NaN === NaN) // false
複制
2.2Object.assign(target,source1,source2,...)
傳回第一個接收對象,可以接受任意個源對象,如果多個源對象有相同的屬性,則後面的會覆寫前面的。
驗證(1):
var target = {};
Object.assign(target, {
name: 'tony',
age: '24'
})
console.log(target) // {name: "tony", age: "24"}
複制
驗證(2)
如果後面的多個源對象source1,source2有同名的屬性,則後面的源對象會覆寫前面的
var target = {};
Object.assign(target, {
name: 'tony',
age: '24'
}, {
age: '28'
})
console.log(target) // {name: "tony", age: "28"}
複制
驗證(3)
var target = {};
function source() { }
source.prototype = {
constructor: source,
hello: function () { console.log('hello~~') }
}
Object.assign(target, source.prototype)
target.hello(); //hello~~
複制
驗證(4)
忽略enumerable為false的屬性,隻拷貝對象自身的可枚舉的屬性。
var target = {};
var source1 = {
age: '24'
}
function Person(name) {
this.name = name;
}
Person.prototype.hello = function () {
console.log(this.name)
}
var source2 = new Person("tony");
// 使用Object.defineProperty()為source2對象定義一個名為hobby的屬性,且設定為可枚舉的
Object.defineProperty(source2, "hobby", {
enumerable: true,
value: 'reading'
})
Object.assign(target, source1, source2)
console.log(target) // {age: "24", name: "tony", hobby: "reading"}
複制
去掉上述enumerable屬性(預設為false),再看下結果:
var target = {};
var source1 = {
age: '24'
}
function Person(name) {
this.name = name;
}
Person.prototype.hello = function () {
console.log(this.name)
}
var source2 = new Person("tony");
// 使用Object.defineProperty()為source2對象定義一個名為hobby的屬性,且設定為不可枚舉的
Object.defineProperty(source2, "hobby", {
value: 'reading'
})
Object.assign(target, source1, source2)
console.log(target) // {age: "24", name: "tony"}
複制
可以看出Object.assign()會忽略enumerable為false的屬性,隻拷貝對象自身的可枚舉的屬性。
【補充】有四個操作會忽略enumerable為false的屬性,即不可枚舉的屬性:
for...in循環:隻周遊對象自身的和繼承的可枚舉的屬性。
Object.keys():傳回對象自身的所有可枚舉的屬性的鍵名。
JSON.stringify():隻串行化對象自身的可枚舉的屬性。
Object.assign():隻拷貝對象自身的可枚舉的屬性。
3.定義了自身屬性枚舉順序
自有屬性枚舉順序的基本規則:
1,所有數字鍵按升序排序;
2,所有字元串鍵按它們被加入對象的順序排序;
3,所有symbol鍵按照它們被加入對象的順序排序;
驗證(1):
可以用Object.getOwnPropertyNames(obj)方法檢視對象自身的所有屬性(不含Symbol屬性,包含不可枚舉屬性)的鍵名。
var obj = {
2: 1,
name: 'tony',
0: 1,
age: '24',
hobby: 'reading',
1: 1
}
console.log(Object.getOwnPropertyNames(obj)) // ["0", "1", "2", "name", "age", "hobby"]
複制
可以看出,字元串鍵是跟在數值鍵之後,數值鍵按升序排序,字元串鍵按加入對象的順序排序。
【補充】:
ES6 一共有 5 種方法可以周遊對象的屬性。
(1)for...in
for...in循環周遊對象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。
(2)Object.keys(obj)
Object.keys傳回一個數組,包括對象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames傳回一個數組,包含對象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols傳回一個數組,包含對象自身的所有 Symbol 屬性的鍵名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys傳回一個數組,包含對象自身的所有鍵名,不管鍵名是 Symbol 或字元串,也不管是否可枚舉。
以上的 5 種方法周遊對象的鍵名,都遵守同樣的屬性周遊的次序規則。
4.建立對象後修改對象原型:Object.setPrototypeOf()
Object.setPrototypeOf()方法的作用:改變任意指定對象的原型,接受兩個參數:
-- 被改變原型的對象
-- 替代第一個參數原型的對象
驗證(1):
var dog = {
hello() {
console.log('a dog barks')
}
}
var person = {
hello() {
console.log('say hello')
}
}
// 以person為原型
var person1 = Object.create(person);
person1.hello(); // say hello
console.log(person.isPrototypeOf(person1)) // true
// 将person1的原型設定為dog
Object.setPrototypeOf(person1, dog)
person1.hello(); // a dog barks
console.log(person.isPrototypeOf(person1)) // false
console.log(dog.isPrototypeOf(person1)) // true
複制
說明:person1的原型原本是person,通過Object.setPrototypeOf(person1,dog)後,把person1的原型設定為了dog。
5.super關鍵字
ES5中,this關鍵字總是指向函數所在的目前對象。
ES6 中的關鍵字super,指向目前對象的原型對象。
驗證(1):
可以用super更友善地通路對象的原型,來引用對象原型上所有的方法。
ES5:
var dog = {
hello() {
return 'a dog barks'
}
}
var person = {
hello() {
return 'say hello'
}
}
var friend = {
hello() {
let msg = Object.getPrototypeOf(this).hello.call(this)
console.log(msg);
}
}
Object.setPrototypeOf(friend, dog);
friend.hello(); // a dog barks
Object.setPrototypeOf(friend, person);
friend.hello(); // say hello
複制
Object.getPrototypeOf(this)就是指向對象的原型,ES6中可以用super替換:
Object.getPrototypeOf(this).hello.call(this)
// 等價于
super.hello()
複制
var dog = {
hello() {
return 'a dog barks'
}
}
var person = {
hello() {
return 'say hello'
}
}
var friend = {
hello() {
let msg = super.hello()
console.log(msg);
}
}
Object.setPrototypeOf(friend, dog);
friend.hello(); // a dog barks
Object.setPrototypeOf(friend, person);
friend.hello(); // say hello
複制
從結果可以看出效果是一樣的。
驗證(2)
必須要在簡寫方法的對象中使用super,其他地方聲明中使用則會報文法錯誤。
Uncaught SyntaxError: 'super' keyword unexpected here
複制
還是上面的示例:
var dog = {
hello() {
return 'a dog barks'
}
}
var person = {
hello() {
return 'say hello'
}
}
var friend = {
hello: function () {
let msg = super.hello()
console.log(msg);
}
}
Object.setPrototypeOf(friend, dog);
friend.hello();
Object.setPrototypeOf(friend, person);
friend.hello(); // Uncaught SyntaxError: 'super' keyword unexpected here
複制
6.小結
本節内容主要總結了ES6中對象的一些擴充。包括對象字面量上的變更、Object.is()(注意下和===的差別)、Object.assign()方法,對象自身屬性的枚舉屬性的順序、Object.setPrototypeOf()方法可以在建立對象後改變它的原型,以及可以通過super關鍵字調用對象原型的方法。