JavaScript中对象属性描述符的使用详解

 更新时间:2023年11月17日 15:12:50   作者:梦想是坚持  
属性描述符是 ECMAScript 5 新增的语法,它其实就是一个内部对象,用来描述对象的属性的特性,下面小编就来为大家详细介绍一下js中对象属性描述符的使用,需要的可以参考下

属性描述符是 ECMAScript 5 新增的语法,它其实就是一个内部对象,用来描述对象的属性的特性。

属性描述符的结构

在 JavaScript 中,对象的属性描述符用于描述和定义对象属性的特性。以下是常见的属性描述符及其作用:

configurable:表示属性是否可以被删除或修改特性。如果设置为 false,则不能删除或修改该属性的特性。默认为 true。

enumerable:表示属性是否可以通过 for...in 循环或 Object.keys() 方法进行枚举。如果设置为 false,则该属性不会出现在枚举中。默认为 true。

value:表示属性的值。可以是任何有效的 JavaScript 值。

writable:表示属性是否可以被赋值运算符修改。如果设置为 false,则该属性的值不能被修改。默认为 true。

get:一个函数,用于获取属性的值。当访问该属性时,会调用该函数并返回其返回值。

set:一个函数,用于设置属性的值。当给该属性赋值时,会调用该函数并传入新值作为参数。

注意这几个属性不是都可以一起设置。get 和 set 以及 value 和 writable 这两组是互斥的,设置了 get 和 set 就不能设置 value 和 writable,反之设置了 value 和 writable 也就不可以设置 get 和 set。

使用示例

示例 1

下面示例演示了使用 value 读写属性值的基本用法。

var obj = {}  //定义空对象
Object.defineProperty(obj, 'x', {value : 100})  //添加属性x,值为100
console.log(Object.getOwnPropertyDescriptor(obj, 'x').value)  //返回100

示例 2

下面示例演示了使用 writable 属性禁止修改属性 x。

var obj = {};
Object.defineProperty(obj, 'x', {
    value : 1,  // 设置属性默认值为1
    writable : false  // 禁止修改属性值
});
obj.x = 2;  //修改属性x的值
console.log(obj.x)  // 1 说明修改失败

在正常模式下,如果 writable 为 false,重写属性值不会报错,但是操作失败,而在严格模式下则会抛出异常。

示例 3

configurable 可以禁止修改属性描述符,当其值为 false 时,value、writable、enumerable 和 configurable 禁止修改,同时禁止删除属性。

在下面示例中,当设置属性 x 禁止修改配置后,下面操作都是不允许的,其中 obj.x=5; 若操作失败,则后面 4 个操作方法都将抛出异常。

var obj = Object.defineProperty({}, 'x', {
    configurable : false  // 禁止配置
})
obj.x = 5  // 试图修改其值
console.log(obj.x);  // 修改失败,返回undefined
Object.defineProperty(obj, 'x', {value : 2})  // 抛出异常
Object.defineProperty(obj, 'x', {writable: true})  // 抛出异常
Object.defineProperty(obj, 'x', {enumerable: true})  // 抛出异常
Object.defineProperty(obj, 'x', {configurable: true})  // 抛出异常

当 configurable 为 false 时,如果把 writable=true 改为 false 是允许的。只要 writable 或 configurable 有一个为 true,则 value 也允许修改。

get 和 set 函数

除了使用点语法或中括号语法访问属性的 value 外,还可以使用访问器,包括 set 和 get 两个函数。

其中,set( ) 函数可以设置 value 属性值,而 get( ) 函数可以读取 value 属性值。

借助访问器,可以为属性的 value 设计高级功能,如禁用部分特性、设计访问条件、利用内部变量或属性进行数据处理等。

示例 1

下面示例设计对象 obj 的 x 属性值必须为数字。为属性 x 定义了 get 和 set 特性,obj.x 取值时,就会调用 get;赋值时,就会调用 set。

var obj = Object.create(Object.prototype, {
    _x : {  //数据属性
        value : 1,  //初始值
        writable : true
    },
    x : {  //访问器属性
        get : function () {  //getter
            return this._x;  //返回_x属性值
        },
        set : function (value) {  //setter
            if (typeof value != "number"){
              throw new Error('请输入数字');
            }
            this._x = value;  //赋值
        }
    }
});
console.log(obj.x);  //1
obj.x = "2";  //抛出异常

示例 2

JavaScript 也支持一种简写方法。针对示例 1,通过以下方式可以快速定义属性。

var obj = {
    _x : 1,  // 定义 _x 属性
    get x() { return this._x },  //定义 x 属性的 getter
    set x(value) {  //定义 x 属性的 setter
        if (typeof value != "number"){
          throw new Error('请输入数字');
        }
        this._x = value;  // 赋值
    }
};
console.log(obj.x);  //1
obj.x = 2;
console.log(obj.x);  //2

取值函数 get( ) 不能接收参数,存值函数 set( ) 只能接收一个参数,用于设置属性的值。

操作属性描述符

属性描述符是一个内部对象,无法直接读写,可以通过下面几个函数进行操作。

Object.getOwnPropertyDescriptor( ):可以读出指定对象私有属性的属性描述符。

Object.defineProperty( ):通过定义属性描述符来定义或修改一个属性,然后返回修改后的描述符。

Object.defineProperties( ):可以同时定义多个属性描述符。

Object.getOwnPropertyNames( ):获取对象的所有私有属性。

Object.keys( ):获取对象的所有本地可枚举的属性。

propertyIsEnumerable( ):对象实例方法,直接调用,判断指定的属性是否可枚举。

示例 1

在下面示例中,定义 obj 的 x 属性允许配置特性,然后使用 Object.getOwnPropertyDescriptor( ) 函数获取对象 obj 的 x 属性的属性描述符。修改属性描述符的 set 函数,重设检测条件,允许非数值型数字赋值。

var obj = Object.create(Object.prototype, {
    _x: {  //数据属性
        value: 1,  //初始值
        writable: true
    },
    x: {  //访问器属性
        configurable: true,  //允许修改配置
        get: function () {  //getter
            return this._x;  //返回_x属性值
        },
        set: function (value) {
            if (typeof value != "number") {
                throw new Error('请输入数字');
            }
            this._x = value;  //赋值
        }
    }
});
var des = Object.getOwnPropertyDescriptor(obj, "x");  //获取属性x的属性描述符
des.set = function (value) {
    //修改属性x的属性描述符set函数
    //允许非数值型的数字,也可以进行赋值
    if (typeof value != "number" && isNaN(value * 1)) {
        throw new Error('请输入数字');
    }
    this._x = value;
}
obj = Object.defineProperty(obj, "x", des);
console.log(obj.x);  //1
obj.x = "2";  //把一个给数值型数字赋值给属性x
console.log(obj.x);  //2

示例 2

下面示例先定义一个扩展函数,使用它可以把一个对象包含的属性以及丰富的信息复制给另一个对象。

【实现代码】

function extend (toObj, fromObj) {  //扩展对象
    for (var property in fromObj) {  //遍历对象属性
        if (!fromObj.hasOwnProperty(property)) continue;  //过滤掉继承属性
        Object.defineProperty(  //复制完整的属性信息
            toObj,  //目标对象
            property,  //私有属性
            Object.getOwnPropertyDescriptor(fromObj, property)  //获取属性描述符
        );
    }
    return toObj;  //返回目标对象
}

【应用代码】

var obj = {};  //新建对象
obj.x = 1;  //定义对象属性
extend(obj, { get y() { return 2} })  //定义读取器对象
console.log(obj.y);  //2

控制对象状态

JavaScript 提供了 3 种方法,用来精确控制一个对象的读写状态,防止对象被改变。

  • Object.preventExtensions:阻止为对象添加新的属性。
  • Object.seal:阻止为对象添加新的属性,同时也无法删除旧属性。等价于属性描述符的 configurable 属性设为 false。注意,该方法不影响修改某个属性的值。
  • Object.freeze:阻止为一个对象添加新属性、删除旧属性、修改属性值。

同时提供了 3 个对应的辅助检查函数,简单说明如下:

  • Object.isExtensible:检查一个对象是否允许添加新的属性。
  • Object.isSealed:检查一个对象是否使用了 Object.seal 方法。
  • Object.isFrozen:检查一个对象是否使用了 Object.freeze 方法。

示例

下面代码分别使用 Object.preventExtensions、Object.seal 和 Object.freeze 函数控制对象的状态,然后再使用 Object.isExtensible、Object.isSealed 和 Object.isFrozen 函数检测对象的状态。

var obj1 = {};
console.log(Object.isExtensible(obj1));  //true
Object.preventExtensions(obj1);
console.log(Object.isExtensible(obj1));  //false
var obj2 = {};
console.log(Object.isSealed(obj2));  //true
Object.seal(obj2);
console.log(Object.isSealed(obj2));  //false
var obj3 = {};
console.log(Object.isFrozen(obj3));  //true
Object.freeze(obj3);
console.log(Object.isFrozen(obj3));  //false

总结

这些描述符可以通过 Object.defineProperty() 方法来定义或修改对象的属性特性。通过使用这些描述符,我们可以灵活地控制和定义对象的属性行为,例如限制某些属性只读、隐藏某些不需要枚举的属性等。

总的来说,对象的属性描述符提供了对对象属性行为进行详细控制和定义的能力,包括可配置性、可枚举性、可写性、获取和设置方法等。这使得我们能够更好地管理和操作对象中的各个属性。

到此这篇关于JavaScript中对象属性描述符的使用详解的文章就介绍到这了,更多相关JavaScript属性描述符内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别

    关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别

    mouseover ,mouseout ,mouseenter,mouseleave,都是鼠标点击而触发的事件,各自代表什么意思,有哪些区别呢?下面跟着脚本之家小编一起看看吧
    2015-10-10
  • JavaScript prototype属性使用说明

    JavaScript prototype属性使用说明

    prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,而且特殊的地方便在于:它是一个给类的对象添加方法的方法!
    2010-05-05
  • html5+CSS 实现禁止IOS长按复制粘贴功能

    html5+CSS 实现禁止IOS长按复制粘贴功能

    因为在移动端APP需要实现长按执行别的事件,但是在iOS系统有默认的长按选择复制粘贴。禁止在网上找了很多资料,下面小编给大家分享解决方案,一起看看吧
    2016-12-12
  • javascript深拷贝和浅拷贝详解

    javascript深拷贝和浅拷贝详解

    本文主要介绍了javascript深拷贝和浅拷贝的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • javascript中的变量是传值还是传址的?

    javascript中的变量是传值还是传址的?

    一门编程语言的核心是数据结构,粗略来讲,可以把数据结构分成不可变类型(immutable)和可变类型(mutable)。
    2010-04-04
  • 结合 ES6 类编写JavaScript 创建型模式

    结合 ES6 类编写JavaScript 创建型模式

    这篇文章主要介绍了结合ES6类编写JavaScript创建型模式,本文开始系统性的对20多种JavaScript 设计模式进行简单概述,然后结合ES6类的方式来编写实例代码展示其使用方式,需要的朋友可以参考一下
    2022-07-07
  • Javascript中classList的基本使用方法

    Javascript中classList的基本使用方法

    classList 是一个非常实用的工具,可以让我们轻松地操作元素的类名,在使用 classList 时,我们可以通过 add、remove、toggle 和 contains 等方法来添加、删除、切换和检查类名,接下来我们详细学习一下classList的使用方法以及相关方法,感兴趣的朋友一起看看吧
    2023-10-10
  • javascript的理解及经典案例分析

    javascript的理解及经典案例分析

    下面小编就为大家带来一篇javascript的理解及经典案例分析。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • 微信小程序实现弹出菜单功能

    微信小程序实现弹出菜单功能

    最近做项目需要这样的需求,当用户点击标签栏按钮,向下弹出菜单,再次点击,收回菜单。接下来通过本文给大家介绍微信小程序实现弹出菜单功能,感兴趣的朋友一起看看吧
    2018-06-06
  • 详解webpack多页面配置记录

    详解webpack多页面配置记录

    本篇文章主要介绍了详解webpack多页面配置记录,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01

最新评论