JavaScript 属性描述对象详解:元数据与核心 API

作者:半夏

时间:2026-10-26

浏览:152

本文详细解析 JavaScript 中的属性描述对象(attributes object),涵盖 value、writable、enumerable、configurable、get 和 set 六个元属性的含义与默认值。同时深入讲解 Object.getOwnPropertyDescriptor、Object.getOwnPropertyNames、Object.defineProperty 及 Object.defineProperties 等核心 API 的用法、参数及注意事项,帮助开发者掌握对象属性的底层控制机制。

文章目录

属性描述对象

JavaScript 是一门支持多种编程范式的语言,既包括函数式编程,也涵盖面向对象编程:

  • JavaScript 中的对象被设计为一系列无序属性的集合,类似于哈希表,由键(key)和值(value)组成;
  • 键是一个标识符名称,而值可以是任意类型的数据,也可以是其他对象或函数类型;
  • 如果值是一个函数,则我们将其称为对象的方法。

因此,属性描述对象的概念由此产生:JavaScript 提供了一个内部数据结构,用于描述对象的属性并控制其行为,例如该属性是否可写、是否可遍历等。这个内部数据结构被称为“属性描述对象”(attributes object)。每个属性都拥有自己对应的属性描述对象,用于保存该属性的一些元信息。

以下是属性描述对象的一个示例。

{
    value:123,
    writable:false,
    enumerable:true,
    configurable:false,
    get:undefined,
    set:undefined
}    

属性描述对象提供了六个元属性。

  • value:value 表示该属性的属性值,默认值为 undefined。
  • writable:writable 是一个布尔值,表示属性值(value)是否可修改(即是否可重写),默认值为 true。
  • enumerable:enumerable 是一个布尔值,表示该属性是否可遍历,默认值为 true。如果将其设置为 false,会导致某些操作(例如 for...in 循环、Object.keys())跳过该属性。
  • configurable:configurable 是一个布尔值,表示属性的可配置性,默认值为 true。如果设置为 false,将阻止某些操作改写属性,例如无法删除该属性,也不能改变该属性的属性描述对象(value 属性除外)。也就是说,configurable 属性控制了属性描述对象的可写性。
  • get:get 是一个函数,表示该属性的取值函数(getter),默认值为 undefined。
  • set:set 是一个函数,表示该属性的存值函数(setter),默认值为 undefined。

Object.getOwnPropertyDescriptor()

Object.getOwnPropertyDescriptor() 方法用于获取属性描述对象。它接受两个参数:第一个是目标对象,第二个是字符串,对应目标对象的某个属性名。

var obj = (p:'a'};

Object.getOwnPropertyDescriptor(obj,'p')
//Object{ value:"a",
//       writable:true,
//       enumerable:true,
//       configurable:true
  }        

在上述代码中,Object.getOwnPropertyDescriptor() 方法用于获取 obj.p 的属性描述对象。

需要注意的是,Object.getOwnPropertyDescriptor() 方法仅适用于对象自身的属性,不适用于继承的属性。

var obj = {p:'a');

Object.getOwnPropertyDescriptor(obj,'toStrng')
//undefined

在上述代码中,toString 是 obj 对象继承的属性,Object.getOwnPropertyDescriptor() 无法获取该属性的描述对象。

Object.getOwnPropertyNames()

Object.getOwnPropertyNames 方法返回一个数组,其成员是参数对象自身的全部属性的属性名,无论这些属性是否可遍历。

var obj = Object.defineProperties({},{
    p1:{value:1,enumerable:true},
    p2:{value:2,enumerable:false}
});

Object.getOwnPropertyNames(obj)
//["p1","p2"]

在上述代码中,obj.p1 是可遍历的,而 obj.p2 是不可遍历的。Object.getOwnPropertyNames 会将它们都返回。

这与 Object.keys 的行为不同,Object.keys 仅返回对象自身的所有可遍历属性的属性名。

Object.keys([])//[]
Object.getOwnPropertyNmaes([])//['length']

Object.keys(Object.prototype)// []
Object.getOwnPropertyNames(Object.prototype)
//['hasOwmProperty'
//   'valueOf',
//   'constructor',
//   'toLocaleString',
//   'isPrototypeOf',
//   'propertyIsEnumerable',
//   'toString']

在上述代码中,数组自身的 length 属性是不可遍历的,Object.keys 不会返回该属性。第二个例子中 Object.prototype 也是一个对象,所有实例对象都会继承它,其自身的属性都是不可遍历的。

Object.defineProperty(),Object.defineProperties()

Object.defineProperty() 方法允许通过属性描述对象来定义或修改一个属性,并返回修改后的对象,其用法如下。

Object.defineProperty(object,propertyName,attributesObject)

Object.defineProperty 方法接受三个参数,依次如下。

  • object:属性所在的对象
  • propertyName:字符串,表示属性名
  • attributesObject:属性描述对象

举例来说,定义 obj.p 可以写成下面这样。

var obj = Object.defineProperty({},'p',{
    value:123,
    writable:false,
    enumerable:true,
    configurable:false
});

obj.p //123

obj.p = 246;
obj.p //123

在上述代码中,Object.defineProperty() 方法定义了 obj.p 属性。由于属性描述对象中的 writable 属性为 false,因此 obj.p 属性不可写。注意,这里的 Object.defineProperty 方法的第一个参数是 {}(一个新建的空对象),p 属性直接定义在这个空对象上面,然后返回这个对象,这是 Object.defineProperty() 的常见用法。

如果属性已经存在,Object.defineProperty() 方法相当于更新该属性的属性描述对象。

如果一次性定义或修改多个属性,可以使用 Object.defineProperties() 方法。

var obj = Object.defineProperties({},{
    p1:{value:123,enumerable:true},
    p2:{value:'abc',enumerable:true},
    p3:{get:function(){return this.p1 + this.p2},
       enumerable:true,
       configurable:true
      }
  });
  
  obj.p1 //123
  obj.p2 //"abc"
  obj.p3 //"123abc"

在上述代码中,Object.defineProperties() 同时定义了 obj 对象的三个属性。其中,p3 属性定义了取值函数 get,即每次读取该属性时,都会调用这个取值函数。

注意,一旦定义了取值函数 get(或存值函数 set),就不能将 writable 属性设为 true,或者同时定义 value 属性,否则会报错。

var obj = {};

Object.defineProperty(obj,'p',{
    value:123,
    get:function(){return 456;}
});
//TypeError: Invalid property.
// A property cannot both have accessors and be writable or have a value

Object.defineProperty(obj,'p'{
    writable:true,
    get:function(){return 456;}
});
// TypeError: Invalid property descriptor.
// Cannot both specify accessors and a value or writable attribute

在上述代码中,同时定义了 get 属性和 value 属性,以及将 writable 属性设为 true,就会报错。

在 Object.defineProperty() 和 Object.defineProperties() 参数里面的属性描述对象中,writable、configurable、enumerable 这三个属性的默认值都为 false。

var obj = {};
Object.defineProperty(obj,'foo',{});
Object.getOwnPropertyDescriptor(obj,'foo')
//{
//    value:undefined,
//    writable:false,
//    enumerable:false,
//    configurable:false
//}

在上述代码中,定义 obj.foo 时用了一个空的属性描述对象,这样就可以看到各个元属性的默认值。

Object.prototype.propertyIsEnumerable()

实例对象的 propertyIsEnumerable() 方法返回一个布尔值,用于判断某个属性是否可遍历。注意,这个方法只能用于判断对象自身的属性,对于继承的属性一律返回 false。

var obj = {};
obj.p = 123;

obj.propertyIsEnumerable('p') //true
obj.propertyIsEnumerable('toString') //false

在上述代码中,obj.p 是可遍历的,而 obj.toString 是继承的属性。

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

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章