1. 程式人生 > >ES6的getter和setter

ES6的getter和setter

  • 基本用法
// get和set語法將物件屬性繫結到函式,訪問/賦值時函式會被呼叫
let nums = {
  all: [],
  get curr () {
    let len = this.all.length
    return this.all[len - 1]
  },
  set curr (val) {
    this.all.push(val)
  }
}

nums.curr   // undefined,呼叫getter
nums.curr = 1   // 呼叫setter
nums.curr   // 1

// 相當於建立了一個偽屬性(pseudo-property),可以使用delete刪除
delete nums.curr
  • 屬性名要求是number/string/symbol
let s = Symbol('foo')

let nums = {
  getter 1 () {return 1},
  getter ['a' + 'b'] () {return 2},
  getter [s] () {return 3}
}

Object.getOwnPropertyNames(nums)    // ['1', 'ab'],屬性'1'會提到最前面
Object.getOwnPropertySymbols(nums)  // [Symbol(foo)]
  • getter沒有引數,setter有一個引數
let nums = {
  all: [],
  // SyntaxError: getter must not have any formal parameters.
  get curr (x) {
    let len = this.all.length
    return this.all[len - 1]
  },
  // SyntaxError: setter must have exactly one formal parameter.
  set curr (val, x) {
    this.all.push(val)
  }
}
  • 不能存在同名屬性

It must not appear in an object literal with another get/set or with a data entry for the same property.
(1)同名屬性在getter/setter前面

// 存在同名屬性並沒有報錯
let nums = {
  all: [],
  curr: 2, // 在getter/setter前面
  get curr () {
    let len = this.all.length
    return this.all[len - 1]
  },
  set curr (val) {
    this.all.push(val)
  }
}

curr, all   // undefined, []
nums.curr = 4
// getter/setter都正常執行
curr, all   // 4, [4]

(2)同名屬性在getter/setter後面

let nums = {
  all: [],
  get curr () {
    let len = this.all.length
    return this.all[len - 1]
  },
  set curr (val) {
    this.all.push(val)
  },
  curr: 2, // 在getter/setter後面
}

curr, all   // undefined, []
nums.curr = 4
// 沒有執行setter,返回了getter
curr, all   // undefined, []

(3)存在同名getter/setter

let nums = {
  all: [],
  get curr () {
    let len = this.all.length
    return this.all[len - 1]
  },
  get curr () {
    return 3
  },
  set curr (val) {
    this.all.push(val)
  },
  set curr (val) {
    this.all.push(val + 1)
  }
}

// 後面的getter/setter生效
curr, all   // 3, []
nums.curr = 4
curr, all   // 3, [5]
  • 已存在的物件新增getter/setter
Object.definedProperty(nums, 'curr', {
  configurable: true, // 預設false
  enumerable: true, // 預設false
  get curr () {
    let len = this.all.length
    return this.all[len - 1]
  },
  set curr (val) {
    this.all.push(val)
  }
})

// 物件字面量中定義的getter/setter的屬性描述符(property descriptor)
Object.getOwnPropertyDescriptor(nums, 'curr')
{  
  configurable: true,
  enumerable: true,
  get: [Function get],
  set: [Function set]
}
  • get Vs. definedProperty
class Nums {
  get curr () { 
    return 1
  }
}

let n = new Nums()
Object.definedProperty(n, 'foo', {
  configurable: true, 
  enumerable: true,
  get () {return 1}
})

n.hasOwnProperty('foo') // true
Object.getPropertyOf(n).hasOwnProperty('curr')  // true
  • getter的懶求值和快取

某些屬性計算的代價比較高,如花費大量記憶體和CPU時間的操作;
屬性值不是立即需要,甚至是不需要的,延遲計算;
計算多次且屬性值沒有改變時,不應該重新計算。

let o = {
  get foo () {
    return 1 + 2
  }
}

o.foo // 3, 此時才會計算(1 + 2)