JavaScript数据属性和访问器属性

228 阅读2分钟

《用得上的前端知识》系列 - 你我都很忙,能用100字说清楚,绝不写万字长文

对象属性的分类

ES5 规范中,JavaScript 对象的属性可以分为数据属性访问器属性。数据属性一般用于存储数据,而访问器属性一般用于进行 set/get 操作,但不能直接存储数据。

注:在 ECMA-262 中定义了一些用两对方括号括起来的内部属性(如:[[configurable]]、[[writable]]),用于实现JavaScript 引擎,这些属性是写给引擎看的,在编码中无法直接访问。

数据属性

数据属性有 4 个行为特性:

  • [[configurable]]
    • 表示能否通过 delete 删除属性,从而重新定义属性;
    • 能否修改属性的特性;
    • 能否把属性修改为访问器属性。
    • 默认值为 true。
  • [[enumerable]]
    • 表示能否通过 for-in 循环遍历属性;
    • 默认值为 true。
  • [[writable]]
    • 表示能否修改属性的值;
    • 默认值为 true。
  • [[value]]
    • 包含这个属性的数据值;
    • 读取属性值的时候,从这个位置读取;
    • 写入属性值的时候,把新值保存在这个位置;
    • 默认值为 undefined。

访问器属性

访问器属性最大的作用就是通过 set 方法修改属性的值,通过 get 方法获取属性的值,它有 4 个特性:

  • [[configurable]]
    • 表示能否通过 delete 删除属性,从而重新定义属性;
    • 能否修改属性的特性;
    • 或者能否把属性修改为数据属性;
    • 对于直接在对象上定义的属性,这个特性的默认值为 true。
  • [[enumerable]]
    • 表示能否通过 for-in 循环遍历属性;
    • 对于直接在对象上定义的属性,这个特性的默认值为 true。
  • [[get]]
    • 在读取属性时调用的函数;
    • 默认值为 undefined。
  • [[set]]
    • 写入属性时调用的函数;
    • 默认值为 undefined。

注意:一个属性不可能同时属于“数据属性”和“访问器属性”,也就是说,如果为属性指定了 [[value]] 特性的值,原则上就不能为其设置 [[get]] 特性和 [[set]] 特性的值。

访问器属性不能直接定义,必须使用Object.defineProperty()来定义。

let obj = {
    name : 'xq'
}

Object.defineProperty(obj, 'name', {
    set(){
        console.log('有人设置为 name 属性赋值!');
    },

    get(){
        console.log('有人读取 name 属性!');
    }
});

obj.name = 'cool';
console.log( obj.name );

// output:
// 有人设置为 name 属性赋值!
// 有人读取 name 属性!

// 应用场景:数据双向绑定

参考资料