浅谈Object.defineProperty()

206 阅读3分钟

前言

学习前端的小伙伴一定对前端三大框架不陌生,其中在国内Vue使用的企业可以说是最多的。如果去面试前端相关岗位,一定为问你框架相关的知识。其中Vue的响应式原理一定会问的,那么在Vue2.x中,实现响应式的原理可以说Object.defineProperty()这个ES5的API是核心。

1.Object.defineProperty()简介

在JS代码中,我们经常使用到Object对象,通常我们给对象设置属性时,一般通过对象的.操作符或者[]操作符直接赋值的,或者直接使用对象字面量的方式赋值。

比如Obj.a=1,Obj['b']=4等等。

这样赋值后,属性值是可以在后续更改的,而且该对象可以枚举,即通过循环等方式获取到该对象的属性值。

但是在有些时候我们只想定义了对象之后,在后续无法更改其属性值或者无法枚举,这个时候Object.defineProperty()就派上了用场。

静态方法Object.defineProperty(obj, prop, descriptor),其可以通过定义属性的元数据信息精确地控制属性的行为。

方法详细操作:

**方法名:**Object.defineProperty(obj, prop, descriptor)

参数:

  • obj
    Object,Required,要在其上定义属性的对象。
  • prop
    String|Symbol,Required,要定义或修改的属性的名称。
  • descriptor
    Object,Required,将被定义或修改的属性描述符。

**返回值:**Object,返回被传递给函数的对象obj。

2.属性描述符

Object.defineProperty(obj, prop, descriptor)接收3个参数,其中descriptor就是属性描述符,它就是可以定义属性行为的元数据信息。属性描述符又有两种表现形式:数据描述符和存取描述符,这两种描述符不能够同时存在。

(1)数据描述符和存取描述符均有以下键值:

configurable

当且仅当该属性的 configurable 为 true 时,才能够再次修改该属性的属性描述符,同时该属性也能从对应的对象上被删除。默认为 false。

enumerable

当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。

(2)数据描述符可选键值:

value

该属性的初始值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。

writable:

当且仅当该属性的writable为true时,该属性才能被写入值。默认为 false。

(3)存取描述符可选键值:

get:

一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。默认为 undefined。

set:

一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。默认为 undefined。

3.代码示例

(1)创建属性

<script>
    const Obj = {};
    // 向对象Obj中添加一个属性a,并设置数据描述符
    Object.defineProperty(Obj, "a", {
        value: 100, // 默认值1
        writable: true, // 可写
        enumerable: true, // 可枚举
        configurable: true // 可以再次修改属性描述符
    });
    // 对象Obj有了属性a,其值为1
    console.log(Obj.a) // 输出: 1
</script>

(2)get、set存取描述符

const Obj = {};
let v = null;
Object.defineProperty(Obj, 'a', {
    get: function () {
        return v;
    },
    set: function (newValue) {
        v = newValue;
    }
});
Obj.a = 1000;
console.log(Obj.a); // 输出: 1,表示属性a的getter和setter均生效

总结

一句话来说,Object.defineProperty()就是用来操作对象属性的,赋予属性生命,Vue2.x就是一个使用Object.defineProperty()的典范。