Vue不兼容IE8緣由以及Object.defineProperty詳解

Vue不兼容IE8緣由以及Object.defineProperty詳解

緣由概述:

  • Vue.js使用了IE8不能模擬的ECMAScript5特性. Vue.js支持全部兼容ES5的瀏覽器.
  • Vue將遍歷此對象全部的屬性, 並使用Object.defineProperty把這些屬性所有轉爲getter/setter.
  • Object.defindProperty是僅ES5支持, 且沒法shim的特性.

接下來逐步介紹概念.vue

shim特性

指把一個庫引入一箇舊的瀏覽器, 而後用舊的API, 實現一些新的API的功能.segmentfault

Object.definePropety()

  • 語法: Object.definePropety(obj, prop, descriptor)
  • 參數:
    • obj: 操做對象
    • prop: 須要操做的屬性名稱
    • descriptor: 屬性具備的特性
  • 返回值: 傳入的對象, 即第一個參數obj
  • 針對特性描述存在兩種形式: 數據描述和存取器描述

數據描述

當修改或定義對象的時候, 給屬性添加一些特性瀏覽器

var obj = {
  test: 'hello'
}

// 對象已有的屬相添加特性描述
Object.defineProperty(obj, 'test', {
  configurable: true | false,
  enumerable: true | false,
  value: `任意類型的值`,
  writable: true | false
})

// 對象新添加的屬性描述
Object.defineProperty(obj, 'newKey', {
  configurable: true | false,
  enumerable: true | false,
  value: `任意類型的值`,
  writable: true | false
})

value

  • 屬性對應的值, 能夠爲任意類型的值.
  • 默認: undefined
// 不設置value的值
Object.defineProperty(obj, 'newKey', {

})
console.log(obj.newKey) // undefined

/*
注: 兩段代碼不能同時出現 ;
報錯: Cannot redefine property: newKey
緣由: configurable屬性默認爲false, 不能修改; writable默認fasle, 不能被重寫
*/
// 設置value值
Object.defineProperty(obj, 'newKey', {
  value: 'this is test'
})
console.log(obj.newKey) // undefined

writable

  • 屬性的是否能夠被重寫.
  • 默認false, 不能被重寫.
// writable爲false, 不可被重寫
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  writable: false
})

Object.defineProperty(obj, 'newKey', {
  value: 'change'
})
// 這種狀況下會報錯: Cannot redefine property: newKey
console.log(obj.newKey)
// 能夠被重寫
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  writable: false
})

obj.newKey = 'change'

console.log(obj.newKey) // hello

enumerable

  • 此屬性是否能夠枚舉(使用for...in或者Object.keys)
  • 默認爲false: 不可枚舉
// 不可枚舉
var obj = {}

Object.defineProperty(obj, 'newKey', {
  value: 'hello'
})

console.dir(obj) // {}
// 能夠枚舉
var obj = {}

Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  enumerable: true
})

console.dir(obj) // { newKey: 'hello' }

configurable

  • 目標屬性是否能夠被刪除
  • 目標屬性的特性是否能夠被再次修改
  • 默認false, 不可刪除與修改
// 屬性不可被刪除
var obj = {}
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  configurable: false
})
delete obj.newKey
console.log(obj.newKey) // hello
// 屬性能夠被刪除
var obj = {}
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  configurable: true
})
delete obj.newKey
console.log(obj.newKey) // undefined
// 不能修改特性
var obj = {}
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  writable: false,
  configurable: false
})

Object.defineProperty(obj, 'newKey', {
  writable: true,
})
// 報錯: Cannot redefine property: newKey
// 再次修改特性
var obj = {}
Object.defineProperty(obj, 'newKey', {
  value: 'hello',
  writable: false,
  configurable: true
})

Object.defineProperty(obj, 'newKey', {
  writable: true,
})
obj.newKey = 'change'
console.log(obj.newKey) // change

注意

  • 一旦使用Objec.defineProperty給對象添加屬性, 若是不設置屬性的話, 那麼configuable, enumerable, writable這些都是默認的false
  • 不能被枚舉, 不能被重寫, 不能被再次更改屬性

存取器描述

當使用存取器描述特性的時候, 容許使用如下特性屬性:函數

var obj = {}

Object.defineProperty(obj, 'newKey', {
  get: function() {} | undefined,
  set: function() {} | undefined,
  configurable: true | false,
  enumerable: true | false
})
  • 當使用了getter或者setter方法, 不容許使用writablevalue這兩個屬性

getter/setter

  • 當設置或獲取某個對象的屬性值的時候, 能夠提供getter/setter方法
    • getter: 是一種獲取值的方法
    • setter: 是一種設置值的方法
// 在特性中使用get/set屬性來定義對應的方法
var obj = {}
var initVlue = 'hello'
Object.defineProperty(obj, 'newKey', {
  get: function () {
    // 當獲取值的時候, 觸發這個函數
    return initVlue
  },
  set: function (value) {
    // 設置值的時候, 觸發這個函數
    initVlue = value
  }
})
// 獲取值
console.log(obj.newKey) // hello

obj.newKey = 'change'

console.log(initVlue)// change
  • get/set沒必要成對出現, 任寫其一就能夠. 若是設置不方便, 則get和set的默認值爲undeifend

兼容性

在IE8下只能對DOM對象使用, 若是對原生對象使用Object.defineProtry()會報錯this


參考: http://www.javashuo.com/article/p-qasukviu-dp.htmlcode

相關文章
相關標籤/搜索