JavaScript对象的增强、属性描述符介绍

导读:本篇文章讲解 JavaScript对象的增强、属性描述符介绍,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

1.对属性操作的控制

在前面我们的属性都是直接定义在对象内部,或者直接添加到对象内部的:

  • 但是这样来做的时候我们就不能对这个属性进行一些限制:比如这个属性是否是可以通过delete删除的?这个属性是否在forin遍历的时候被遍历出来呢?

如果我们想要对一个属性进行比较精准的操作控制,那么我们就可以使用属性描述符

  • 通过属性描述符可以精准的添加或修改对象的属性
  • 属性描述符需要使用 Object.defineProperty 来对属性进行添加或者修改;

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

Object.defineProperty(obj, prop, descriptor)

可接收三个参数

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

返回值

  • 被传递给函数的对象。

2.属性描述符分类

属性描述符的类型有两种:

  • 数据属性(Data Properties)描述符(Descriptor);

  • 存取属性(Accessor访问器 Properties)描述符(Descriptor);

    在这里插入图片描述

2.1 数据属性描述符

数据数据描述符有如下四个特性:

[[Configurable]]:表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;

  • 当我们直接在一个对象上定义某个属性时,这个属性的[[Configurable]]默认为true

  • 当我们通过属性描述符定义一个属性时,这个属性的[[Configurable]]默认为false

    // 直接在一个对象上定义某个属性, 这个属性的Configurable默认为true
    var obj = {
      name: "why",
      age: 18,
    };
    
    Object.defineProperty(obj, "name", {
      configurable: false,
    });
    
    delete obj.name;
    console.log(obj); // {name: 'why', age: 18}
    
    // 通过属性描述符定义一个属性, 这个属性的Configurable默认为false
    Object.defineProperty(obj, "address", {});
    delete obj.address;
    console.log(obj); // {name: 'why', age: 18, address: undefined}
    

[[Enumerable]]:表示属性是否可以通过for-in或者Object.keys()返回该属性

  • 当我们直接在一个对象上定义某个属性时,这个属性的[[Enumerable]]默认为true

  • 当我们通过属性描述符定义一个属性时,这个属性的[[Enumerable]]默认为false

    // 直接在一个对象上定义某个属性, 这个属性的Configurable默认为true
    var obj = {
      name: "why",
      age: 18,
    };
    
    // 告诉JS引擎,obj的name属性不可枚举
    Object.defineProperty(obj, "name", {
      enumerable: false,
    });
    
    // 通过属性描述符定义一个属性, 这个属性的Enumerable默认为false
    Object.defineProperty(obj, "address", {});
    // 枚举obj
    console.log(Object.keys(obj)); // ['age']
    

[[Writable]]:表示是否可以修改属性的值

  • 当我们直接在一个对象上定义某个属性时,这个属性的[[Writable]]默认为true

  • 当我们通过属性描述符定义一个属性时,这个属性的[[Writable]]默认为false

    // 直接在一个对象上定义某个属性, 这个属性的Writable默认为true
    var obj = {
      name: "why",
      age: 18,
    };
    
    // 告诉JS引擎obj的name属性是不可修改的, 不可写入(只读)
    Object.defineProperty(obj, "name", {
      writable: false,
    });
    
    // 通过属性描述符定义一个属性, 这个属性的Writable默认为false
    Object.defineProperty(obj, "address", {});
    
    obj.name = "kaisa";
    console.log(obj.name); // why
    obj.address = "成都市";
    console.log(obj.address); // undefined
    

[[value]]:属性的value值,读取属性时会返回该值,修改属性时,会对其进行

  • 默认情况下这个值是undefined;

    var obj = {
      name: "why",
      age: 18,
    };
    
    // 告诉JS引擎, 读取obj的name属性会返回kaisa这个值
    Object.defineProperty(obj, "name", {
      value: "kaisa",
    });
    
    console.log(obj.name); // kaisa
    

2.2 存取属性描述符

数据数据描述符有如下四个特性:

  1. [[Configurable]]:表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符;

    • 和数据属性描述符是一致的
    • 当我们直接在一个对象上定义某个属性时,这个属性的[[Configurable]]默认为true
    • 当我们通过属性描述符定义一个属性时,这个属性的[[Configurable]]默认为false
  2. [[Enumerable]]:表示属性是否可以通过for-in或者Object.keys()枚举返回该属性;

    • 和数据属性描述符是一致的;
    • 当我们直接在一个对象上定义某个属性时,这个属性的[[Enumerable]]默认为true
    • 当我们通过属性描述符定义一个属性时,这个属性的[[Enumerable]]默认为false
  3. [[set]]:设置属性时就会执行的函数。默认为undefined

    • 当获取属性时, 就会执行set函数

      var obj = {
        name: "why",
        age: 18,
      };
      
      // 当设置name属性的时候, 就会调用set函数
      Object.defineProperty(obj, "name", {
        set: function (value) {
          console.log("set方法被调用了", value);
        },
      });
      
      obj.name = "kaisa"; // set方法被调用了 kaisa
      obj.name = "vn"; // set方法被调用了 vn
      
  4. [[get]]:获取属性时就会执行的函数。默认为undefined

    • 当获取属性时, 就会执行get函数

      var obj = {
        name: "why",
        age: 18,
      };
      
      var _name = "";
      // 当设置name属性的时候, 就会调用set函数
      Object.defineProperty(obj, "name", {
        set: function (value) {
          console.log("set函数被调用了", value);
          _name = value;
        },
        get: function () {
          console.log("get函数被调用了");
          return _name;
        },
      });
      
      obj.name = "kaisa"; // set方法被调用了 kaisa
      console.log(obj.name); // get函数被调用了 kaisa
      obj.name = "vn"; // set方法被调用了 vn
      console.log(obj.name); // get函数被调用了 vn
      

3.同时定义多个属性

Object.defineProperties() 方法直接在一个对象上定义多个新的属性描述符或修改现有属性,并且返回该对象

var obj = {
  name: "why",
  age: 18,
  height: 1.88,
};

Object.defineProperties(obj, {
  name: {
    configurable: true,
  },
  age: {
    configurable: false,
    writable: false,
  },
  height: {
    set: function (value) {
      console.log("set函数被调用", value);
    },
  },
});

4.对象方法补充

获取对象的属性描述符:

  • getOwnPropertyDescriptor

    var obj = {
      name: "why",
      age: 18,
      height: 1.88,
    };
    
    // 获取obj对象name属性的属性描述符
    console.log(Object.getOwnPropertyDescriptor(obj, "name"));
    
  • getOwnPropertyDescriptors

    var obj = {
      name: "why",
      age: 18,
      height: 1.88,
    };
    
    // 获取obj对象中所有属性的属性描述符
    console.log(Object.getOwnPropertyDescriptors(obj));
    

禁止对象扩展新属性:preventExtensions

  • 给一个对象添加新的属性会失败(在严格模式下会报错);

    var obj = {
      name: "why",
      age: 18,
      height: 1.88,
    };
    
    // 阻止obj对象扩展属性
    Object.preventExtensions(obj)
    obj.address = "广州市"
    console.log(obj) // {name: 'why', age: 18, height: 1.88}
    

密封对象,不允许配置和删除属性:seal

  • 实际是调用preventExtensions

  • 并且将现有属性的configurable:false

    var obj = {
      name: "why",
      age: 18,
      height: 1.88,
    };
    
    // 将obj对象密封起来(不能进行配置)
    Object.seal(obj)
    // obj对象中所有属性都无法删除
    delete obj.name
    delete obj.age
    console.log(obj) // {name: 'why', age: 18, height: 1.88}
    

冻结对象,不允许修改现有属性: freeze

  • 实际上是调用seal

  • 并且将现有属性的writable: false

    var obj = {
      name: "why",
      age: 18,
      height: 1.88,
    };
    
    // 将obj对象冰冻起来(所有属性不允许修改)
    Object.freeze(obj)
    // obj对象中所有属性都变成只读
    obj.name = "kaisa"
    obj.age = 20
    console.log(obj) // {name: 'why', age: 18, height: 1.88}
    

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120140.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!