深入理解ES6 --- 物件

漓漾li發表於2019-03-30

物件字面量語法擴充套件

(1) 屬性初始值簡寫

物件字面量屬性賦值為同名的區域性變數時,不必再寫: 和值,只寫屬性名即可。這種寫法不僅簡潔,而且也有助於消除命名錯誤,

let name = '漓漾li'
let age = 18
// es5
let es5Info = {
    name: name,
    age: age,
}
// es6
let es6Info = {
    name,
    age,
}
複製程式碼

(2) 物件方法簡寫

為物件字面量新增方法時,不用再寫:function。兩個函式唯一的區別就是簡寫函式可以使用super.

// es5
let es5Person = {
    sayName: function(){
        console.log('漓漾li')
    },
}
// es6
let es6Person = {
    sayName () {
        console.log('漓漾li')
    },
}
複製程式碼

(3) 可計算屬性名

es5中,如果一個物件的屬性名稱來源於變數或者計算結果,在初始化這個變數時,就必須使用[]代替.;es6中則可以直接在字面量中使用[]

let keyName = 'name'
// es5
let es5Info = {}
es5[keyName] = '漓漾li'

// es6
let es6Info = {
    [keyName]: '漓漾li'
}
複製程式碼

字面量中使用[],表示屬性名稱是可計算的,所以中括號內可以使用表示式

新增方法

(1) Object.is()

引入Object.is()主要是為了彌補全等運算子===的一些不準確運算,其餘的遠算結果基本一致。

NaN === NaN  // false  應該是相等的
+0 === -0  // true   應該是不相等的

Object.is(NaN, NaN)   // true
Object.is(+0, -0)  // false
複製程式碼

(2) Object.assign

概念不在贅述。

Object.assign不能將提供者的訪問器屬性複製到接受物件中

let obj = {
  get name(){
    return 'val'
  }
}
let a = Object.assign({}, obj)

Object.getOwnPropertyDescriptor(obj,'name').get   //  [Function: get name]
Object.getOwnPropertyDescriptor(a,'name').get   //   undefined
複製程式碼

(3) Object.setPrototypeOf

Object.setPrototypeOf可以修改指定物件的原型

物件原型的儲存在內部專用屬性[Prototype]中,呼叫Object.getPrototypeOf可以返回其中的值,呼叫Object.setPrototypeOf可以改變其中的值

(4) super

假設例項與原型中有同名的方法,想要呼叫原型中的同名方法,在es5中:

let person = {
  name: 'person',
  sayName(){
    return this.name
  }
}
let xiaoli = {
  name:'xiaoli',
  sayName(){
    // 呼叫原型中的同名方法,並自定義
    // 如果不自定義函式,那也就不需要在例項中重新定義這個函式
    return Object.getPrototypeOf(this).sayName.call(this) + ' hi'
  }
}
Object.setPrototypeOf(xiaoli, person)
console.log(xiaoli.sayName())   // xiaoli hi
複製程式碼
  1. Object.getPrototypeOf(this)用來獲取xiaoli的原型(即person);
  2. sayName.call(this)是為了讓sayNamexiaoli的上下文中執行,如果不繫結this,則會輸出person hi

而是用es6中的super,就可以實現上述兩點:呼叫原型的同名方法;並繫結this到當前作用域

let person = {
  name: 'person',
  sayName(){
    return this.name
  }
}
let xiaoli = {
  name:'xiaoli',
  sayName(){
    return super.sayName() + ' hi'
  }
}
Object.setPrototypeOf(xiaoli, person)
console.log(xiaoli.sayName())  // xiaoli hi
複製程式碼

super必須在簡寫方法的物件中使用,否則會語法錯誤

物件屬性的遍歷

  • 物件的每一個屬性都會有一個描述物件,來控制這個屬性的行為。Object.getOwnPropertyDescriptor可以獲取到物件屬性的描述物件。
  • 描述物件中的enumerable屬性,稱為可列舉性如果enumerablefalse,則某些物件屬性遍歷的操作,就會忽略該屬性
  • enumerable屬性引入的目的就是讓一些內部屬性和方法避免被遍歷到。比如物件原型的toString方法,和陣列的length屬性
方法\是否能遍歷特殊屬性 不可列舉屬性 繼承的可列舉屬性 Symbol屬性 備註
for...in 大多情況只關心物件自身的屬性,謹慎使用
Object.keys(obj)
Object.getOwnPropertyNames(obj)
Object.getOwnPropertySymbols(obj) 只返回symbol屬性
Reflect.ownKeys(obj)

遍歷順序規則:

  1. 首先遍歷所有數值鍵,按照數值升序排列;
  2. 其次遍歷所有字串鍵,按照加入時間升序排列;
  3. 最後遍歷所有 Symbol 鍵,按照加入時間升序排列。

相關文章