对象就是一组属性的集合,对象的成员可以是普通的属性、也可以是方法还可以是回调的事件。
声明一个对象,本质上就是为它的属性描述清楚以下五种性质:
在我们声明的时候,JavaScript 就已经默认配置了「Writable、Enumerable、Configurable」三种属性,所以我们一般情况下只需要指定 Name 和 Value 即可。
我们在使用对象字面量的时候,其实用的是名称和值的方式,快速定义了上述属性的一个简化版,代码如下:
obj = {
name: \\\'value\\\'
}
对象属性分为两种:数据属性和访问器属性,我们来分别阐述下。
以上面声明的代码 obj.name 举例,它的描述符如下:
{
value: \\\'value\\\',
writable: true,
enumerable: true,
configurable: true
}
首先是属性描述符和访问器属性不能同时存在,只能取其一。其次它的格式也是有区别的:
{
get: function(){...},
set: function(){...},
enumerable: true,
configurable: true,
}
在访问器属性中,wirtable 用 get、set 去代替了。
我们使用字面量风格的声明,不存在对 Enumerable 和 Configurable 的定义,因为他们总是使用默认值,为了兼容旧的对象声明语法,Writable 值需要按照语法分析来确定。
其一、当使用旧的字面量风格声明属性或添加对象属性时,JavaScript 总是会初始化一个数据属性,并包括两个性质:Value 和 Writable,其中 Writable 为 true。
//字面量风格声明
obj = {
name: \\\'value\\\'
}
//添加属性
obj.newName = \\\'value\\\'
其二、 方法的声明可以视为上述传统声明的补充形式,在属性描述符的使用上与上述规则是一致的。
//方法声明
obj = {
foo(){...}
}
//添加属性
obj.newName = \\\'value\\\'
其三、 在使用存取方法来声明属性的时候,会初始化一个访问器属性,它包括两个函数 get、set 之一,或者两个都有。
//字面量风格声明「存取属性」
obj = {
get name(){
return \\\'value\\\'
}
}
在使用类声明时,属性描述符创建规则与上述一致。不过,类静态成员声明为类的属性,而一般成员声明为类的原型的属性。
在 JavaScript 中,对象属性的赋值操作会根据属性的存在情况、属性的特性和继承关系等不同情况做出不同的处理。具体来说:
一、如果属性不存在,将会隐式创建一个数据属性,其特性为可写、可枚举和可配置(也就是 Writable、Enumerable 和 Configurable 均为 true),并将赋值操作的值填入 value 中。
二、 如果这个属性已经存在,并且是数据属性,那么赋值操作就变成了更新。在这种情况下呢,只要 Writable 不是 false,也就是允许编辑,那么值就会被写入 Value 中,否则就什么也不做。
三、如果属性是继承来的数据属性,将在当前对象上创建一个新的数据属性,其特性为可写、可枚举和可配置。
这个新的数据属性本身不会继承任何「可枚举、可配置」的性质,而是会按照一个默认的数据描述方式来初始化,即:Writable、Enumerable 和 Configurable 均为 true。
四、 如果一个属性用的是访问器属性,都不会创建新的属性描述符。如果子类中继承了这样一个属性,那么在子类中对该属性的读写,也会忠实地调用继承而来的、原型中的读写器。
即使是全局属性,也会挂载在 window 对象上,属性描述也遵循上述规则。
数据属性和访问器属性在继承属性时的初始化逻辑是不同的。
题图生成:Midjourney
内容优化:ChatGPT
内容来源:《JavaScript 语言精髓与编程实战》
原创文章,作者:小道研究,如若转载,请注明出处:https://www.sudun.com/ask/34579.html