【筆記】再學JavaScript ES(6-10)全版本語法——反射機制及應用


Reflect

1.案例:四捨五入

{
  let price = 91.5
  // ES5
  console.log(
    price = price > 100
      ? Math.floor.apply(null, [price])
      : Math.ceil.apply(null, [price])
  )
  // ES6
  console.log(
    Reflect.apply(
      price > 100 ? Math.floor : Math.ceil, null, [price]
    )
  )
}

2.案例:獲得時間戳

{
  // ES5
  let d1 = new Date()
  console.log(
    d1.getTime(),
    d1 instanceof Date // true
  )
  // ES6
  let d2 = Reflect.construct(Date, []) // 注意:這裏必須要傳入一個空數組作爲參數列表
  console.log(
    d2.getTime(),
    d2 instanceof Date // true
  )
}

3.案例:對象操作

(1)對象增加屬性

// ES5: 對象增加屬性
const obj1 = {}
const o1 = Object.defineProperties(obj1, {
  'A': { value: 'a', writable: true },
  'B': { value: 'b' },
  'C': { value: 'c', configurable: true },
  'D': { value: 'd', configurable: true }
})
console.log(
  obj1, // {A: "a", B: "b", C: "c", D: "d"}
  o1 // {A: "a", B: "b", C: "c", D: "d"}
)
// ES6: 對象增加屬性
const obj2 = {}
const o2 = [
  Reflect.defineProperty(obj2, 'A', { value: 'a', writable: true }),
  Reflect.defineProperty(obj2, 'B', { value: 'b' }),
  Reflect.defineProperty(obj2, 'C', { value: 'c', configurable: true })
]
console.log(
  obj2, // {A: "a", B: "b", C: "c"}
  o2 // [true, true, true]
)

(2)對象刪除屬性

// ES5: 對象刪除屬性
console.log(delete obj1.C) // true
console.log(obj1) // {A: "a", B: "b", D: "d"}
console.log(delete obj1['D']) // false
console.log(obj1) // {A: "a", B: "b"}
// ES6: 對象刪除屬性
console.log(Reflect.deleteProperty(obj2, 'C')) // false
console.log(obj2) // {A: "a", B: "b"}

(3)對象讀寫屬性

// ES5: 對象讀寫屬性
console.log(obj1.A = 'aa') // aa
console.log(obj1.A) // aa
// ES6: 對象讀寫屬性
console.log(Reflect.set(obj2, 'A', 'aa')) // true
console.log(Reflect.get(obj2, 'A')) // aa

(4)獲取對象屬性描述

// ES5: 獲取對象屬性描述
console.log(Object.getOwnPropertyDescriptor(obj1, 'A')) // {value: "a", writable: false, enumerable: false, configurable: false}
// ES6: 獲取對象屬性描述
console.log(Reflect.getOwnPropertyDescriptor(obj2, 'A')) // {value: "a", writable: false, enumerable: false, configurable: false}
  • value:該屬性的值(僅針對數據屬性描述符有效)
  • writable:當且僅當屬性的值可以被改變時爲true。(僅針對數據屬性描述有效)
  • get:獲取該屬性的訪問器函數(getter)。如果沒有訪問器, 該值爲undefined。(僅針對包含訪問器或設置器的屬性描述有效)
  • set:獲取該屬性的設置器函數(setter)。 如果沒有設置器, 該值爲undefined。(僅針對包含訪問器或設置器的屬性描述有效)
  • configurable:當且僅當指定對象的屬性描述可以被改變或者屬性可被刪除時,爲true。
  • enumerable:當且僅當指定對象的屬性可以被枚舉出時,爲 true。

(5)讀寫對象原型鏈上的方法

// ES5: 讀寫對象原型鏈上的方法
console.log(Object.setPrototypeOf(obj1, String.prototype)) // String {A: "aa", B: "b"}
console.log(Object.getPrototypeOf(obj1)) // String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ…}
// ES6: 讀寫對象原型鏈上的方法
console.log(Reflect.setPrototypeOf(obj2, String.prototype)) // true
console.log(Reflect.getPrototypeOf(obj2)) // String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ…}

(6)判斷對象是否有某個屬性

// ES5: 判斷對象是否有某個屬性
console.log(obj1.E) // undefined
// ES6: 判斷對象是否有某個屬性
console.log(Reflect.has(obj2, 'E')) // false

(7)判斷對象是否可拓展(凍結、密封)

// ES5: 判斷對象是否可拓展
console.log(Object.isExtensible(obj1)) // true
// 阻止拓展
Object.preventExtensions(obj1)
console.log(Object.isExtensible(obj1)) // false
// 凍結
Object.freeze(obj1)
console.log(Object.isFrozen(obj1)) // true
// 密封
Object.seal(obj1)
console.log(Object.isSealed(obj1)) // true
// ES6: 判斷對象是否可拓展
console.log(Reflect.isExtensible(obj2)) // true
// 阻止拓展
console.log(Reflect.preventExtensions(obj2)) // true
console.log(Reflect.isExtensible(obj2)) // false

阻止對象擴展後:

  • 不能添加屬性。
  • 可以修改屬性的值。
  • 可以刪除屬性。
  • 可以修改屬性描述符。
    在這裏插入圖片描述

拓展:

拓展:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章