ES6語法(三) 物件

Godfrey1995發表於2019-03-23

首先,在JavaScript中物件是個很重要的概念,因為在JavaScript中一切都是物件,無論是函式,還是陣列。同樣,ES6這次也帶來了一些新特性。能夠幫助我們更加輕鬆與準確的完成想要完成的目標。

物件字面量語法擴充

物件字面量屬性簡寫

在ES6之前。我們使用字面量建立屬性,會寫一個屬性名,後面跟一個":",最後跟著屬性值。看起來一切都是很簡潔的,但是在屬性值與屬性名同名時,這就很痛苦了,每次都要寫兩個同樣的文字。我們看個例子:

    let Person = function(name,age){
        return {
            name : name,
            age : age,
        }
    }
複製程式碼

一個兩個這種程式碼沒問題,但是當類似的程式碼量一旦多起來,那便是很痛苦的一件事了。但是,在ES5中,這個問題將得到解決。它為我們提供了簡寫方式。

    let Person = function(name,age){
        return {
            name,
            age,
        }
    }
複製程式碼

在使用字面量的時候,我們只需寫一個變數名就好,剩下的工作由JavaScript引擎幫我們去做。JavaScript引擎回去可訪問作用域查詢同名屬性,找到便會將該變數的值賦值給字面量物件的同名屬性。如果沒找到,這個屬性的值為undefined。

物件字面量的可計算屬性名

在ES6之前,我們可以在物件建立之後,使用可計算屬性名,但是無法在物件字面量中使用可計算屬性名。現在ES6將可計算屬性名帶到了物件字面量中。

    // ES6之前
    
    let param1 = 'name';
    let person = {};
    person[param1] = 'kidd';
    console.log(person[name]);       // kidd
    
    //不允許
    let dog = {
        [param]:'Snoopy',
    }
    
    // ES6
    
    let firstName = 'first Name';
    
    let cat = {
        [firsName]:'tom'
    }
    console.log(cat[firstName]);        // tom
    
複製程式碼

物件方法的簡寫

這不是一個重大的改進。但是能幫助我們書寫起來更容易。

    // ES6之前按
    let person= {
        getName:function(){
            return : this.name
        }
    }
    
    // ES6
    let person = {
        getName(){
            return this.name;
        }
    }
    
複製程式碼

重複的物件字面量屬性

在ES5及之前,我們如果在物件字面量中宣告瞭兩個同名屬性,嚴格模式下便會報錯。而ES6中將這個特性改變了,無論是否在嚴格模式下,物件字面量中宣告瞭兩個同名屬性,之後後面的屬性會生效。

    let person = {
        getName(){
            return 'tom';
        },
        
        getName(){
            return 'jure';
        }
    }
    
    person.getName();       // jure
複製程式碼

物件自有屬性的列舉順序

在ES6之前自由屬性的列舉順序基本都是百家爭鳴,不同的JavaScript引擎,都會有不同的列舉順序,這次ES6算是將自由屬性的列舉順序給出了官方說法

  • 所有數字鍵按照升序排列
  • 所有字串鍵按照它們被加入物件的順序排列
  • 所有symbol鍵按照它們被加入物件的順序排列

物件新增方法

在ES6也給物件新增了一些方法,下面讓我們來看看

Object.is()

Object.is()很想一個完整版的 “===”,因為它大部分情況下與 “===” 相同,只有兩種情況與 “===” 有一些差別。就是下面兩種情況

    console.log(-0 === +0);             //true
    console.log(Object.is(+0,-0));      //false
    console.log(NaN === NaN);           //false
    console.log(NaN,NaN);               //true

複製程式碼

除了上面兩種情況,與 “===”是一樣的。

Object.assign()

因為很多JavaScript第三方庫有混合模式,這次ES6便將它們直接引入進來。assign方法的主要作用是將一個物件的方法、屬性複製給另一個物件。注意,這裡的複製其實是淺複製,如果被複制物件的屬性值是一個物件的話,那麼便只是將這個物件的引用複製給被複制物件。

    function EventTarget(){ doSomething };
    
    EventTarget.prototype = {
        constructor : EventTarget,
        emit : function(){ doSomething },
        on : function(){ doSomething }
    }
    
    var obj = {},
    Object.assign(obj,EventTarget.prototype);
    
    obj.on();

複製程式碼

這樣的話,新建立的物件就會擁有之前物件的屬性。而且assign是可以接受任意數量的源物件的。如果不同的源物件中有同名屬性,最後被複制物件中會採用最有一個擁有此屬性的物件的屬性值。 還有一個很重要的點。assign是不能複製訪問器屬性的。如果源物件中有訪問器屬性,會在新的物件中變為數值屬性。

增強物件原型

我們都知道,JavaScript最特別的地方就是使用了原型繼承的方式。而現在,ES6對物件原型又進行了增強。

Super引用

super引用其實就是儲存了當前物件的原型物件的引用,在ES6之前,我們要獲得物件的原型只有通過Object.getPrototypeOf(this)的方法去返回原型物件。但是這個方法在某些情況的時候會發生某些錯誤,比如


    let person = {
        getGreeting(){
            return 'Hello';
        }
    };
    
    let friend = {
        getGreeting(){
            return Object.getPrototypeOf(this).getGreeting.call(this) + ", Hi!";
        }
    }
    
    Object.setPrototypeOf(friend,person);
    
    let relative = Object.create(friend);
    
    console.log(person.getGreeting());          // Hello
    console.log(friend.getGreeting());          // Hello, Hi!
    console.log(relative.getGreeting());        // error

複製程式碼

這裡的問題是陷入了一個呼叫死迴圈,this是relative時Object.getPrototypeOf(this)返回的物件是friend。而Object.getPrototypeOf(this).getGreeting會呼叫friend的getGreeting()方法。後面的call(this)又會去改變當前的函式作用域,因此,陷入了一個遞迴呼叫的死迴圈,最後棧溢位報錯,但是在ES6中使用super就會解決這個問題

    let person = {
        getGreeting(){
            return 'Hello';
        }
    };
    
    let friend = {
        getGreeting(){
            return super.getGreeting() + ", Hi!";
        }
    }
    
    Object.setPrototypeOf(friend,person);
    
    let relative = Object.create(friend);
    
    console.log(person.getGreeting());          // Hello
    console.log(friend.getGreeting());          // Hello, Hi!
    console.log(relative.getGreeting());        // Hello, Hi!
    
複製程式碼

這是因為super引用不是動態變化的,它總是指向正確的物件。

改變物件原型的方法

在ES6之前我們要改變物件的原型很麻煩,現在ES6有了setPrototypeOf(),可以輕而易舉的改變物件的原型。

   
   let person = {
        getGreeting(){
            return 'Hello';
        }
    };
    
    let dog = {
        getGreeting(){
            return 'Woof';
        }
    };
    
    let friend = Object.create(person);
    console.log(friend.getGreeting());      // Hello
    console.log(Object,getPrototypeOf(friend) === person);  //true
    
    Object.setPrototype(friend,dog);
    console.log(friend.getGreeting());      // Woof
    console.log(Object,getPrototypeOf(friend) === dog);  //true
    
複製程式碼

以上便是ES6有關物件的內容,如果您有不同的見解或者是本文哪裡有錯誤,你都可以在下面留言給我!!!

相關文章