JS 之数据属性和访问器属性的内部特性

ES5 定义了内部特性来描述属性的各种特征,这些特性可以看做是属性的属性,他们是内部值因此不能直接访问

属性分为两种: 数据属性访问器属性

数据属性

特性名称 描述 默认值
configurable 能否 delete 删除属性、修改属性特性等 true
enumerable 能否通过 for-in 循环返回属性 true
writable 是否可以修改属性的值 true
value 该属性的数据值 undefined

getOwnPropertyDescriptor 方法可以获取数据属性的特性

let obj = { a: 5 }
Object.getOwnPropertyDescriptor(obj, 'a')
// { configurable: true, enumerable: true, value: 5, writable: true }

defineProperty 方法可以修改属性默认的特性

let obj = { a: 5 }
Object.defineProperty(obj, 'a', { writable: false })
obj.a = 8
obj // {a: 5}

一旦把属性定义为不可配置的,修改除了 writable 以外的其它特性都会报错

let obj = { a: 5 }
Object.defineProperty(obj, 'a', { configurable: false })
Object.defineProperty(obj, 'a', { configurable: true }) // 报错
Object.defineProperty(obj, 'a', { enumerable: false }) // 报错
Object.defineProperty(obj, 'a', { writable: false }) // 不报错

defineProperty 方法还可以创建一个新的属性,若不指定特性,configurable、enumerable 和 writable 的特性值都为 false

Object.defineProperty(obj, 'b', { value: 6 })
// {a: 8, b: 6}
Object.getOwnPropertyDescriptor(obj,'b')
// {value: 6, writable: false, enumerable: false, configurable: false}

访问器属性

访问器属性用于读取或写入对象的某个属性值(通过属性的 getter 和 setter 函数实现),它本身不包含数据值

特性名称 描述 默认值
configurable 能否 delete 删除属性、修改属性特性等 true
enumerable 能否通过 for-in 循环返回属性 true
get 读取属性时调用的函数,非必须 undefined
set 写入属性时调用的函数,非必须 undefined

访问器属性必须通过 defineProperty 方法来定义

let obj = { _a: 5, edition: 0 }
Object.defineProperty(obj, 'a', {
    get: function () {
        return this._a
    },
    set: function (newValue) {
        this._a = newValue
        this.edition ++ 
    }
})
obj.a = 8
obj // {edition: 1, _a: 5}

注意:

  • 上面代码定义了一个访问器属性 a,实现了修改 a 的值自动将 edition 加 1 的功能
  • 修改 a 的值会导致 _a 的值发生变化,但 a 与 _a 是不同的属性
  • _a 前面的下划线只是为了标识该属性只能通过对象方法访问,没有别的含义
  • get 和 set 非必须,若只有 get 则属性为只读,若只有 set 则属性为只写

补充

defineProperty 方法只能定义一个属性,defineProperties 则可以定义多个属性

var obj = {}
Object.defineProperties(obj, {
    _a: {
        writable: true,
        value: 5
    },
    edition: {
        writable: true,
        value: 0
    },
    a: {
        get: function () {
            return this._a
        },
        set: function (newValue) {
            this._a = newValue
            this.edition ++
        }
    }
})

上面的代码为 obj 定义了两个数据属性(_a 和 edition)以及一个访问器属性 a,适用于需要一次性定义多个属性的情形

除特殊说明外本人博客均属原创,转载请注明出处:http://blog.johnhan.cn/blog_1033.html
鄂ICP备17018604号-1  鄂公网安备42060702000030号