首頁 >web前端 >js教程 >ES6中物件的新功能與解構賦值的詳解(程式碼範例)

ES6中物件的新功能與解構賦值的詳解(程式碼範例)

不言
不言轉載
2018-10-20 16:04:522430瀏覽

這篇文章帶給大家的內容是關於ES6中物件的新功能與解構賦值的詳解(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

ES6 透過字面量語法擴展、新增方法、改進原型等多種方式加強物件的使用,並透過解構簡化物件的資料擷取過程。

字面量語法擴展

在ES6 模式下使用字面量創建物件更加簡潔,對於物件屬性來說,屬性初始值可以簡寫,並且可以使用可計算的屬性名稱。物件方法的定義消除了冒號和function 關鍵字,範例如下:

// Demo1
var value = "name", age = 18
var person = {
  age, // age: age
  ['my' + value]: 'Jenny',  // myname
  sayName () {  // sayName: function()
    console.log(this.myname)
  }
}
console.log(person.age) // 18
console.log(person.myname) // Jenny
person.sayName(); // Jenny

針對重複定義的物件字面量屬性,ES5嚴格模式下會進行重複屬性檢查從而拋出錯誤,而ES6移除了這個機制,無論嚴格模式或非嚴格模式,同名屬性都會取最後一個值

// demo2
var person = {
  ['my' + value]: 'Jenny',
  myname: 'Tom',
  myname: 'Lee',
}
console.log(person.myname) // Lee

新增方法

從 ES5 開始遵循的一個設計目標是,避免建立新的全域函數,也不在object.prototype上建立新的方法。
為了是某些任務更容易實現,ES6 在全域 Object 物件上引入一些新的方法。

Object.is( )

ES6 引入Object.is()方法來彌補全等運算子的不準確計算。

全等運算子在比較時不會觸發強制轉換類型,Object.is()運行結果也類似,但對於0 和-0(在JS 引擎中為兩個不同實體)以及特殊值NaN的比較結果不同,範例來看:

// demo3
console.log(5 == '5') // true
console.log(5 === '5') // false
console.log(Object.is(5, '5')) // false

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

console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(Object.is(NaN, NaN)) // true

總結來說,Object.is()對所有值進行了更嚴格等價判斷。當然,是否使用Object.is()來取代全等運算元(===)取決於這些特殊情況是否會影響程式碼。

Object.assign( )

ES6 加入Object.assign()來實作混合(Mixin)模式,也就是一個物件接收另一個物件的屬性和方法。注意是接收而不是繼承,例如接收demo1 中的物件:

// demo4
var friend = {}
Object.assign(friend, person)
friend.sayName() // Jenny
console.log(friend.age) // 18
console.log(Object.getPrototypeOf(friend) === person) // false

Object.assign()之前,許多JS 函式庫自訂了混合方法mixin( ) 來實作物件組合,程式碼類似:

function mixin(receiver, supplier) {
  Object.keys(supplier).forEach(function (key) {
    receiver[key] = supplier[key]
  })
  return receiver
}

可以看出mixin( ) 方法使用「=」賦值運算,並不能複製存取器屬性,同理Object.assign()也不能複製存取器屬性,只是執行了賦值操作,存取器屬性最終會轉變為接收物件的資料屬性。範例如下:

// demo5
var animal = {
  name: 'lili',
  get type () {
    return this.name + type
  },
  set type (news) {
    type = news
  }
}
animal.type = 'cat'
console.log(animal.type) // lilicat

var pet = {}
Object.assign(pet, animal)
console.log(animal) // { name: 'lili', type: [Getter/Setter] }
console.log(pet) // { name: 'lili', type: 'lilicat' }

Object.setPrototypeOf( )

正常情況下對透過建構函式或Object.create()建立時,原型是被指定的。 ES6 新增Object.setPrototypeOf() 方法來改變物件的原型。

例如建立一個繼承person 物件的coder 對象,然後改變coder 物件的原型:

// demo6
let person = {
  myname: 'Jenny',
  sayName () { 
    console.log(this.myname)
  }
}

// 创建原型为 person 的 coder 对象
let coder = Object.create(person) 
coder.sayName() // Jenny
console.log(Object.getPrototypeOf(coder) === person) // true

let hero = {
  myname: 'lee',
  sayName () {
    console.log(this.myname)
  }
}

// 改变 coder 对象的原型为 hero
Object.setPrototypeOf(coder, hero)
coder.sayName() // lee
console.log(Object.getPrototypeOf(coder) === hero) // true

物件原型被儲存在內部專有屬性[[Prototype]],呼叫Object.getPrototypeOf( )傳回儲存在其中的值,呼叫Object.setPrototypeOf()改變其值。這個方法加強了對物件原型的操作,下一節將重點放在講解其它操作原型的方式。

增強物件原型

原型是 JS 繼承的基礎,ES6 針對原型做了許多改進,目的是更靈活地方式使用原型。除了新增的Object.setPrototypeOf()改變原型外,還引入Super關鍵字簡化對原型的訪問,

#Super關鍵字

#ES6 引入Super來更便捷的訪問對象原型,上一節介紹ES5 可以使用Object.getPrototypeOf()傳回物件原型。舉例說明Super的便捷,當物件需要重複使用原型方法,重新定義自己的方法時,兩種實作方式如下:

// demo7
let coder1 = {
  getName () {
    console.log("coder1 name: ")
    Object.getPrototypeOf(this).sayName.call(this)
  }
}

// 设置 coder1 对象的原型为 hero(demo6)
Object.setPrototypeOf(coder1, hero)
coder1.getName() // coder1 name: lee

let coder2 = {
  getName () {
    console.log("coder2 name: ")
    super.sayName()
  }
}

Object.setPrototypeOf(coder2, hero)
coder2.getName() // coder2 name: lee

在coder1 物件的getName 方法還需要call(this)保證使用的是原型方法的this,比較複雜,並且在多重繼承會出現遞歸呼叫棧溢位錯誤,而直接使用Super就很簡單安全。

注意必須在簡寫方法中使用Super,要不然會報錯,例如以下程式碼執行語法錯誤:

let coder4= {
  getName: function () { // getName () 正确
    super.sayName() // SyntaxError: 'super' keyword unexpected here
  }

因為在範例中getName 成為了匿名function 定義的屬性,在目前上下問呼叫Super引用是非法的。如果不理解,可以進一步看下方法的從屬對象。

方法的從屬物件

ES6 之前「方法」是具有功能而非資料的物件屬性,ES6 正式將方法定義為有[[HomeObject]]內部屬性的函數。

[[HomeObject]]屬性儲存目前方法的從屬對象,例如:

let coder5 = {
  sayName () {
    console.log("I have HomeObject")
  }
}

function shareName () {
    console.log("No HomeObject")
}

coder5 物件的sayName( ) 方法的[[HomeObject]]屬性值為coder5,而function 定義的shareName( ) 沒有將其賦值給對象,所以沒有定義其[[HomeObject]]屬性,這在使用Super時很重要。

Super就是在[[HomeObject]]屬性上呼叫Object.getPrototypeOf()取得原型的引用,然後搜尋原型得到同名函數,最後設定 this 綁定呼叫對應方法。

解構賦值

ES6 為陣列和物件字面量提供了新特性-解構,可以簡化資料擷取的過程,減少同質化的程式碼。解構的基本語法範例如下:

let user = {
  name: 'jenny',
  id: 18
}
let {name, id} = user
console.log(name, id) // jenny 18

注意在这段代码中,user.name 存储在与对象属性名同名的 name 变量中。

默认值

如果解构时变量名称与对象属性名不同,即在对象中不存在,那么这个变量会默认为undefined:

let user = {
  name: 'jenny',
  id: 18
}
let {name, id, job} = user
console.log(name, id, job) // jenny 18 undefined

非同名变量赋值

非同名变量的默认值为undefined,但更多时候是需要为其赋值的,并且会将对象属性值赋值给非同名变量。ES6 为此提供了扩展语法,与对象字面量属性初始化程序很像:

let user = {
  name: 'jenny',
  id: 18
}
let {name, id = 16, job = 'engineer'} = user
console.log(name, id, job) // jenny 18 engineer

let {name: localName, id: localId} = user
console.log(localName, localId) // jenny 18

let {name: otherName = 'lee', job: otherJob = 'teacher'} = user
console.log(otherName, otherJob) // jenny teacher

可以看出这种语法实际与对象字面量相反,赋值名在冒号左,变量名在右,并且解构赋值时,只是更新了默认值,不能覆盖对象原有的属性值。

嵌套解构

解构嵌套对象的语法仍然类似对象字面量,使用花括号继续查找下层结构:

let user = {
  name: 'jenny',
  id: 18,
  desc: {
    pos: {
      lng: 111,
      lat: 333
    }
  }
}

let {desc: {pos}} = user
console.log(pos) // { lng: 111, lat: 333 }

let {desc: {pos: {lng}}} = user
console.log(lng) // 111

let {desc: {pos: {lng: longitude}}} = user
console.log(longitude) // 111

对象类别

ES6 规范定义了对象的类别,特别是针对浏览器这样的执行环境。

普通(Ordinary)对象
具有 JS 对象所有的默认内部行为

特异(Exotic)对象
具有某些与默认行为不符的内部行为

标准(Standard)对象
ES6 规范中定义的对象
可以是普通对象或特异对象,例如 Date、Array 等

内建对象
脚本开始执行时存在于 JS 执行环境中的对象
所有标准对象都是内建对象

以上是ES6中物件的新功能與解構賦值的詳解(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除