美文网首页
深入理解 Object.defineProperty

深入理解 Object.defineProperty

作者: DavyJones1 | 来源:发表于2021-01-21 18:45 被阅读0次

    Object.defineProperty() 可以用来给对象添加属性,并控制对属性的访问操作。在我们访问或者修改某个对象的某个属性的时候,可以然后进行额外的操作。

    Object.defineProperty 总览

    首先,一个普通的对象是由多个名/值对组成的无序集合。对象中每个属性对于任意类型的值。例如:

    const obj = {
        name: '孩子',
        age: 10,
        run: function() {
            console.log('Run');
        }
    };
    

    Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

    基本语法:

    Object.defineProperty(obj, prop, descriptor);
    

    实例:

    const object1 = {};
    
    Object.defineProperty(object1, 'property1', {
      value: 42,
      writable: false
    });
    
    object1.property1 = 77;
    // throws an error in strict mode
    
    console.log(object1.property1);
    // expected output: 42
    

    参数

    • obj: 要定义属性的对象。
    • prop: 要定义或修改的属性的名称或。
    • descriptor: 要定义或修改的属性描述符。。

    第一个参数obj 和 prop参数很容易理解,重点说第三个参数
    descriptor由两部分组成,数据描述符和访问器描述符,

    • 数据描述符的含义是:它是一个包含属性的值,并说明这个属性值是可读或不可读的对象。
    • 访问器描述符的含义是:包含该属性的一对 getter/setter方法的对象。
      描述符可拥有的键值
      数据描述符 configurable enumerable value writable
      存取描述符 configurable enumerable get set

    描述符默认值

    • 拥有布尔值的键 configurableenumerablewritable 的默认值都是 false
    • 属性值和函数的键 valuegetset 字段的默认值为 undefined

    返回值

    被传递给函数的对象。

    描述

    该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...in 或 [Object.keys])方,可以改变这些属性的值,也可以[删除]这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改(immutable)的。

    对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

    使用

    添加普通属性

    const obj = {};
    
    let initValue = 'init';
    
    Object.defineProperty(obj, 'name', {
        // 当我们使用 obj.name 获取该值的时候,会自动调用 get 函数
        get: function() {
            console.log("custom-get")
            return initValue;
        },
        set: function(value) {
            console.log("custom-set " + value)
            initValue = value;
        }
    });
    console.log(obj.name); //获取值, 会调用get方法
    obj.name = 'changeValue'; // 设置值,会调用set方法。
    console.log(obj.name); // 获取值, 会调用get方法
    

    添加数组属性

    const obj = {};
    let initValue = [];
    Object.defineProperty(obj, 'array', {
        set: function(value) {
            console.log('set called' + JSON.stringify(value));
            initValue = value;
        },
        get: function() {
            return initValue;
        }
    });
    
    console.log(obj.array); //执行get方法
    obj.name = []; // 执行set方法
    obj.name = [1, 2, 3]; // 执行set方法
    obj.name[0] = 11;//  【对数组中的某一项进行改变值,不执行set方法】
    console.log(obj.array);  // 执行get方法
    obj.name.push(4); // 【使用push方法对 obj.name数组添加属性 不执行set方法】
    obj.name.length = 5; // 不会执行set方法
    

    参考:
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

    相关文章

      网友评论

          本文标题:深入理解 Object.defineProperty

          本文链接:https://www.haomeiwen.com/subject/jfudzktx.html