关于 Object.defineProperty()

这个东东其实没那么难,先来看看它的功能和使用方式:

Object.defineProperty(obj, prop, descriptor)

  • obj: 需要定义属性的对象。

  • prop: 需定义或修改的属性的名字。

  • descriptor: 将被定义或修改的属性的描述符。

  • 返回值:返回传入函数的对象,即第一个参数obj。

三个参数都是必填的

关于描述符 descriptor

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个拥有可写或不可写值的属性。存取描述符是由一对 getter-setter 函数功能来描述的属性。描述符必须是两种形式之一;不能同时是两者。

数据描述符和存取描述符均具有以下可选键值:

  • configurable
    当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。

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

数据描述符同时具有以下可选键值:

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

  • writable
    当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。

存取描述符同时具有以下可选键值:

  • get
    一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。

  • set
    一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

具体示例:

var o = {};
// o.mm = 'lyt'
Object.defineProperty(o, 'mm', {
    value: 'lyt',
    configurable: true,
    enumerable: true,
    writable: true
});
// 这种写法和上面的是一个意思。

如果configurable为默认值false,那么再去修改除writeable以外的属性都会抛出异常,也就是说这个属性是个总开关。

var o = {};

Object.defineProperty(o, 'mm', {
    value: 'lyt'
});

Object.defineProperty(o, 'mm', {  // 报错
    configurable: true
});

如果enumerable为默认值false,则该属性不能被for-in循环所遍历。

var o = {};

Object.defineProperty(o, 'mm', {
    value: 'Tina',
    enumerable: true
});

Object.defineProperty(o, 'name', {
    value: 'lyt'
});

for(var key in o){
    console.log(o[key]); // Tina
}

如果writable为默认值false,那么属性将不可写,只能读。

var o = {};

Object.defineProperty(o, 'mm', {
    value: 'Tina'
});

o.mm = 'lmm';

console.log(o.mm)  // Tina

关于 get 和 set 函数

通过Object.defineProperty()来设置存储描述符的时候,当对对应的数据进行读取操作的时候会触发get函数,对数据进行写入操作的时候会触发set函数,下面这个例子就会让你搞清楚它们的作用:

var o = {};

Object.defineProperty(o, 'mm', {
    get:function (){
        console.log('卢雨婷大美妞取了我的值');
        return 'Tina'  // 返回值即使读取的值
    },
    set:function (value){  // 这个参数的名字随便
        console.log(`我的值被卢小妞设置成了${value}`);
        // 这里使用this.mm = value赋值要注意,会形成递归。
    }
});

o.mm;
o.mm = '白痴';

至于取值和赋值的时候的行为,就随需求而定了。

应用:MVVM框架的基本原理

<div>
    <p>你好: <span id="name">111</span></p>
    <div id="intname">222</div>
</div>
<script>
    var userInfo = {};  // 模拟后台数据
    
    // 当对数据取值和赋值的时候对DOM进行相应的更新
    Object.defineProperty(userInfo,'name', { 
      get:function () {
        return document.getElementById('name').innerHTML;
      },
      set:function (value) {
        document.getElementById('name').innerHTML = value;
      }
    })
    
    Object.defineProperty(userInfo,'intname', {
      get:function () {
        return document.getElementById('intname').innerHTML;
      },
      set:function (value) {
        document.getElementById('intname').innerHTML = value;
      }
    })
    
    console.log(userInfo.name);
    
    userInfo.name = 'lyt';
    userInfo.intname = 'Tina';
    
    console.log(userInfo.name);
</script>

总结:以上,你没看错,就这么简单。

原文地址:https://www.cnblogs.com/copperhaze/p/6240939.html