Appearance
Object.defineProperty 详解
基本概念
Object.defineProperty() 是 JavaScript 中一个强大的方法,它允许我们精确地添加或修改对象的属性。通过这个方法,我们可以定义属性的各种特性,如属性是否可写、可枚举、可配置等。
javascript
Object.defineProperty(obj, prop, descriptor)参数说明:
obj:要定义属性的对象prop:要定义或修改的属性名称descriptor:属性描述符对象
属性描述符
属性描述符分为数据描述符和访问器描述符两种。
数据描述符
数据描述符包含以下可选键值:
value:属性的值,默认为 undefinedwritable:属性值是否可以被修改,默认为 falseenumerable:属性是否可以被枚举(如在 for...in 循环中),默认为 falseconfigurable:属性是否可以被删除或修改特性,默认为 false
访问器描述符
访问器描述符包含以下可选键值:
get:获取属性值的函数,默认为 undefinedset:设置属性值的函数,默认为 undefinedenumerable:同数据描述符configurable:同数据描述符
为对象添加不可修改、不可删除的方法
在实际开发中,我们经常需要为对象添加一些核心方法,并确保这些方法不会被意外修改或删除。这时,Object.defineProperty 就派上用场了。
示例代码
javascript
Object.defineProperty(uni.$componentsRows, 'get', {
value: function (name) {
let item = this.find((item) => item.name === name)
if (!item) return {}
return cloneDeep(item)
},
writable: false, // 不允许修改
configurable: false, // 不允许删除
})在这个示例中:
- 我们为
uni.$componentsRows对象添加了一个名为get的方法 - 该方法接收一个
name参数,查找并返回匹配的项目的深拷贝 writable: false确保该方法不能被重新赋值configurable: false确保该方法不能被删除,也不能修改其描述符
属性特性的作用
writable: false
当 writable 设置为 false 时,尝试修改属性值会失败(在严格模式下会抛出错误):
javascript
uni.$componentsRows.get = function () {
return 'hacked'
} // 无效操作
console.log(uni.$componentsRows.get('test')) // 仍然执行原来的函数configurable: false
当 configurable 设置为 false 时:
- 不能删除该属性
- 不能修改该属性的描述符(除了 writable 可以从 true 改为 false)
javascript
delete uni.$componentsRows.get // 无效操作
Object.defineProperty(uni.$componentsRows, 'get', { enumerable: true }) // 抛出错误实际应用场景
1. 创建常量属性
javascript
const config = {}
Object.defineProperty(config, 'API_URL', {
value: 'https://api.example.com',
writable: false,
configurable: false,
})2. 保护核心方法
javascript
const api = {
data: [],
}
Object.defineProperty(api, 'fetch', {
value: async function () {
// 实现获取数据的逻辑
this.data = await fetchData()
return this.data
},
writable: false,
configurable: false,
})3. 实现私有属性
javascript
function createUser(name) {
const user = {}
Object.defineProperty(user, '_password', {
value: '',
writable: true,
enumerable: false, // 不可枚举,在遍历对象时不会出现
})
Object.defineProperty(user, 'name', {
value: name,
writable: false,
})
Object.defineProperty(user, 'setPassword', {
value: function (pwd) {
this._password = pwd
},
writable: false,
configurable: false,
})
return user
}注意事项
- 默认值:如果不指定
writable、enumerable和configurable,它们的默认值都是false - 不可逆性:一旦属性被设置为不可配置(
configurable: false),就无法再将其改回可配置 - 严格模式:在严格模式下,尝试违反这些限制会抛出错误;非严格模式下只会静默失败
- 性能考虑:大量使用
Object.defineProperty可能会影响性能,特别是在频繁创建对象的场景
总结
Object.defineProperty 是 JavaScript 中一个强大的工具,它允许我们精确控制对象属性的行为。通过设置 writable: false 和 configurable: false,我们可以创建不可修改、不可删除的方法或属性,从而提高代码的健壮性和安全性。
在实际开发中,合理使用这一特性可以帮助我们创建更可靠的 API,防止关键方法被意外覆盖或删除,同时也能更好地实现封装和信息隐藏的设计原则。