configurable:true ∈ JS原生配置
configurable: true 表示这个属性可以被修改、删除或重新定义! 🔧
🎯 基本含义
Object.defineProperty(p, 'name', {
configurable: true // 允许配置更改
})
configurable: true 的作用:
- ✅ 允许删除属性
- ✅ 允许修改属性描述符
- ✅ 允许重新定义属性
🔍 详细解释
1. 允许删除属性
const obj = {};
// 定义可配置属性
Object.defineProperty(obj, 'name', {
value: '张三',
configurable: true, // 允许删除
writable: true,
enumerable: true
});
console.log(obj.name); // "张三"
// ✅ 可以删除
delete obj.name;
console.log(obj.name); // undefined
2. 允许修改属性描述符
const obj = {};
Object.defineProperty(obj, 'age', {
value: 25,
configurable: true, // 允许重新配置
writable: false, // 初始不可写
enumerable: true
});
console.log(obj.age); // 25
obj.age = 30; // ❌ 修改失败(writable: false)
console.log(obj.age); // 25
// ✅ 重新配置属性
Object.defineProperty(obj, 'age', {
value: 30,
writable: true, // 改为可写
enumerable: true,
configurable: true
});
obj.age = 35; // ✅ 现在可以修改
console.log(obj.age); // 35
3. 与 configurable: false 对比
const obj = {};
// 不可配置的属性
Object.defineProperty(obj, 'id', {
value: '12345',
configurable: false, // 禁止配置更改
writable: true,
enumerable: true
});
// ❌ 尝试删除 - 失败(严格模式会报错)
delete obj.id;
console.log(obj.id); // "12345" - 仍然存在
// ❌ 尝试重新配置 - 报错
try {
Object.defineProperty(obj, 'id', {
value: '67890',
writable: true
});
} catch (error) {
console.error('错误:', error.message); // 无法重新定义属性
}
// ✅ 但可以修改值(因为 writable: true)
obj.id = '67890';
console.log(obj.id); // "67890"
🎯 属性描述符的完整选项
Object.defineProperty(obj, 'propertyName', {
// 值相关
value: 'some value', // 属性值
writable: true, // 是否可修改值
// 特性相关
configurable: true, // 是否可配置
enumerable: true, // 是否可枚举(for...in, Object.keys)
// 访问器(getter/setter)
get() { return this._value },
set(newValue) { this._value = newValue }
});
🔧 实际应用场景
场景1:创建可删除的常量属性
function createConfigurableConstant(obj, key, value) {
Object.defineProperty(obj, key, {
value: value,
writable: false, // 值不可修改
enumerable: true, // 可枚举
configurable: true // 但可删除
});
}
const config = {};
createConfigurableConstant(config, 'API_URL', 'https://api.example.com');
console.log(config.API_URL); // "https://api.example.com"
// ❌ 不能修改值
config.API_URL = '新的URL'; // 静默失败
console.log(config.API_URL); // 仍然是原值
// ✅ 但可以删除
delete config.API_URL;
console.log(config.API_URL); // undefined
场景2:插件系统的配置属性
class PluginSystem {
constructor() {
this.plugins = new Map();
}
registerPlugin(name, plugin) {
// 创建可配置的插件属性
Object.defineProperty(this, name, {
value: plugin,
writable: false, // 防止意外修改
enumerable: true, // 在迭代中可见
configurable: true // 允许卸载插件
});
this.plugins.set(name, plugin);
plugin.install(this);
}
unregisterPlugin(name) {
if (this.plugins.has(name)) {
// ✅ 可以删除(因为 configurable: true)
delete this[name];
this.plugins.get(name).uninstall();
this.plugins.delete(name);
}
}
}
// 使用示例
const system = new PluginSystem();
system.registerPlugin('logger', {
install(sys) { console.log('Logger 安装') },
uninstall() { console.log('Logger 卸载') }
});
console.log(system.logger); // 插件对象
system.unregisterPlugin('logger'); // ✅ 成功卸载
场景3:响应式数据绑定
function defineReactiveProperty(obj, key, value) {
let internalValue = value;
Object.defineProperty(obj, key, {
configurable: true, // 允许后续重新定义或删除
enumerable: true,
get() {
console.log(`读取 ${key}:`, internalValue);
return internalValue;
},
set(newValue) {
console.log(`设置 ${key}:`, newValue);
internalValue = newValue;
// 触发更新逻辑
if (typeof this.onChange === 'function') {
this.onChange(key, newValue);
}
}
});
}
const data = {};
defineReactiveProperty(data, 'username', '张三');
data.username = '李四'; // 控制台输出: 设置 username: 李四
console.log(data.username); // 控制台输出: 读取 username: 李四
// ✅ 以后可以重新定义为计算属性
Object.defineProperty(data, 'username', {
get() {
return this.firstName + ' ' + this.lastName;
},
configurable: true
});
⚠️ 重要注意事项
1. 默认值
// 普通属性赋值 - 默认所有特性为 true
obj.name = '张三';
// 等价于:
Object.defineProperty(obj, 'name', {
value: '张三',
writable: true,
enumerable: true,
configurable: true // 默认就是 true
});
// Object.defineProperty - 默认所有特性为 false
Object.defineProperty(obj, 'id', { value: '123' });
// 等价于:
Object.defineProperty(obj, 'id', {
value: '123',
writable: false, // 默认 false
enumerable: false, // 默认 false
configurable: false // 默认 false
});
2. 一次性操作
const obj = {};
// 第一次定义
Object.defineProperty(obj, 'key', {
value: 'initial',
configurable: true // 允许后续修改
});
// ✅ 可以重新配置
Object.defineProperty(obj, 'key', {
value: 'modified',
configurable: false // 现在设为不可配置
});
// ❌ 不能再修改了(因为 configurable: false)
try {
Object.defineProperty(obj, 'key', {
value: 'final'
});
} catch (e) {
console.error('无法重新定义不可配置的属性');
}
🎯 在 Vue 中的应用
Vue 2 的响应式系统
// Vue 2 使用 Object.defineProperty 实现响应式
function defineReactive(obj, key, val) {
const dep = new Dep(); // 依赖收集
Object.defineProperty(obj, key, {
configurable: true, // 允许 Vue 在需要时重新定义
enumerable: true,
get() {
dep.depend(); // 收集依赖
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 通知更新
}
});
}
动态添加响应式属性
// Vue 2 中动态添加响应式属性
Vue.set(obj, 'newKey', 'value');
// 内部实现类似:
if (!Object.prototype.hasOwnProperty.call(obj, 'newKey')) {
// 定义可配置的属性,便于 Vue 管理
Object.defineProperty(obj, 'newKey', {
value: 'value',
configurable: true, // 允许 Vue 后续管理
enumerable: true,
writable: true
});
}
✅ 总结
configurable: true 的含义:
| 特性 | configurable: true |
configurable: false |
|---|---|---|
| 删除属性 | ✅ 允许 delete obj.prop |
❌ 禁止删除 |
| 修改描述符 | ✅ 允许重新定义 | ❌ 禁止修改 |
| 修改类型 | ✅ 可改为访问器 | ❌ 类型固定 |
| Vue 应用 | ✅ 适合动态属性 | ❌ 适合固定属性 |
简单记忆:
configurable: true= “这个属性可以重新配置”configurable: false= “这个属性已经锁定,不能更改”
在代码中,configurable: true 让这个 name 属性变得灵活,可以被修改或删除! 🎉
