天天看點

小結ES6基本知識點(五):對象的擴充1.ES6對象字面量2.Object.is()和Object.assing()3.定義了自身屬性枚舉順序4.建立對象後修改對象原型:Object.setPrototypeOf()5.super關鍵字6.小結

0,本文适合人群和主要内容

ES6初學者,通過閱讀本文可對ES6知識點有個大體的概念,強烈建議閱讀阮一峰大大的ES6入門

老司機可以直接繞路。

小結ES6基本知識點(五):對象的擴充1.ES6對象字面量2.Object.is()和Object.assing()3.定義了自身屬性枚舉順序4.建立對象後修改對象原型:Object.setPrototypeOf()5.super關鍵字6.小結

上一節主要是總結了ES6中和數組有關的内容。本節主要總結ES6中對象的擴充,具體内容包括以下幾個方面:

會介紹以下内容:

小結ES6基本知識點(五):對象的擴充1.ES6對象字面量2.Object.is()和Object.assing()3.定義了自身屬性枚舉順序4.建立對象後修改對象原型:Object.setPrototypeOf()5.super關鍵字6.小結

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關鍵字調用對象原型的方法。