JavaScript对象属性
外观
JavaScript对象属性[编辑 | 编辑源代码]
JavaScript对象属性是构成对象的基本单元,用于描述对象的特征或存储数据。在JavaScript中,对象是键值对的集合,其中键是字符串(或Symbol),值可以是任意数据类型(包括其他对象或函数)。理解对象属性是掌握JavaScript面向对象编程的关键。
属性类型[编辑 | 编辑源代码]
JavaScript对象属性主要分为两种类型:
1. 数据属性(Data Properties)[编辑 | 编辑源代码]
存储实际值的标准属性,包含以下特性:
- value:属性的值
- writable:是否可修改(默认为true)
- enumerable:是否可枚举(for...in循环中可见,默认为true)
- configurable:是否可删除或修改特性(默认为true)
2. 访问器属性(Accessor Properties)[编辑 | 编辑源代码]
通过getter和setter函数控制访问的特性:
- get:获取属性值时调用的函数
- set:设置属性值时调用的函数
- enumerable 和 configurable:同数据属性
定义属性[编辑 | 编辑源代码]
对象字面量语法[编辑 | 编辑源代码]
最常用的属性定义方式:
const person = {
firstName: "John", // 数据属性
lastName: "Doe",
get fullName() { // 访问器属性
return `${this.firstName} ${this.lastName}`;
},
set fullName(name) {
[this.firstName, this.lastName] = name.split(" ");
}
};
使用Object.defineProperty()[编辑 | 编辑源代码]
可以精确控制属性特性:
const obj = {};
Object.defineProperty(obj, 'readOnlyProp', {
value: 42,
writable: false,
enumerable: true
});
属性特性操作[编辑 | 编辑源代码]
获取属性描述符[编辑 | 编辑源代码]
const descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log(descriptor);
/* 输出:
{
value: "John",
writable: true,
enumerable: true,
configurable: true
}
*/
修改属性特性[编辑 | 编辑源代码]
Object.defineProperty(person, 'firstName', {
writable: false // 使属性变为只读
});
属性枚举与检测[编辑 | 编辑源代码]
检测属性存在性[编辑 | 编辑源代码]
// 检查自身属性
console.log(person.hasOwnProperty('firstName')); // true
// 检查原型链属性
console.log('toString' in person); // true
遍历属性[编辑 | 编辑源代码]
// 只遍历可枚举的自身属性
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key, person[key]);
}
}
// 获取所有自身属性名(包括不可枚举)
console.log(Object.getOwnPropertyNames(person));
// ES6: 获取可枚举的自身属性名
console.log(Object.keys(person));
计算属性名[编辑 | 编辑源代码]
ES6引入的计算属性名允许使用表达式作为属性名:
const dynamicKey = 'id';
const obj = {
[dynamicKey + '_value']: 123,
[`get_${dynamicKey}`]() {
return this[dynamicKey + '_value'];
}
};
属性顺序[编辑 | 编辑源代码]
ES6规范定义了对象属性的枚举顺序: 1. 所有数字键按数值升序 2. 所有字符串键按添加顺序 3. 所有Symbol键按添加顺序
实际应用案例[编辑 | 编辑源代码]
表单验证对象[编辑 | 编辑源代码]
const validator = {
errors: [],
get isValid() {
return this.errors.length === 0;
},
validateEmail(email) {
const re = /\S+@\S+\.\S+/;
if (!re.test(email)) {
this.errors.push('Invalid email');
}
}
};
validator.validateEmail('test@example');
console.log(validator.isValid); // false
配置对象[编辑 | 编辑源代码]
const config = {};
Object.defineProperties(config, {
'apiUrl': {
value: 'https://api.example.com',
writable: false,
configurable: false
},
'maxRetries': {
value: 3,
writable: true
}
});
高级主题[编辑 | 编辑源代码]
属性代理[编辑 | 编辑源代码]
使用Proxy对象拦截属性操作:
const target = {};
const handler = {
get(obj, prop) {
return prop in obj ? obj[prop] : `Property ${prop} not found`;
}
};
const proxy = new Proxy(target, handler);
proxy.test = 1;
console.log(proxy.test); // 1
console.log(proxy.unknown); // "Property unknown not found"
属性与原型链[编辑 | 编辑源代码]
当访问对象属性时,JavaScript会沿着原型链查找,直到找到该属性或到达null。
性能考虑[编辑 | 编辑源代码]
- 频繁添加/删除属性会影响V8引擎的隐藏类优化
- 使用Object.freeze()可以阻止属性修改,提高某些情况下的性能
- 访问器属性比数据属性有轻微的性能开销
数学表示[编辑 | 编辑源代码]
属性访问可以表示为函数映射: 其中K是属性键集合,V是属性值集合。
总结[编辑 | 编辑源代码]
JavaScript对象属性是构建复杂数据结构的基础,理解其工作机制对于编写高效、可维护的代码至关重要。从简单的数据存储到高级的访问控制,属性系统提供了丰富的功能来满足各种编程需求。