一、基本用法简介
声明一个简单的对象,如下
var obj = { name: 'ldld' }
我们可以用Object.defineProperty来声明这个对象
var obj = {} Object.defineProperty(obj,'name',{ value:'ldld', writable:true, enumerable: true, configurable: true })
下列就这四个基本的配置简单介绍一下
- value:初始值
-
writable:是否可以修改该属性的值
var obj = {} Object.defineProperty(obj,'name',{ value:'ldld', writable:false, enumerable: true, configurable: true }) obj.name // 'ldld' obj.name = 'LLLL'; // 这里会修改失败,严格模式下会报错 TypeError console.log(obj.name) // 'ldld'
- enumerable:是否可枚举,这个是否能遍历到该属性(for)
-
configurable : 这个得重点讲一下
var obj = {} // 第一次设置操作configurable配置,设置为false Object.defineProperty(obj,'name',{ value:'ldld', writable:true, enumerable: true, configurable: false }) obj.name // 'ldld' obj.name = 'LLLL'; // configurable: false 不影响writable属性,这里可以设置成功 console.log(obj.name) // 'LLLL' // 第二次设置操作configurable配置,在第一步false基础上改回true Object.defineProperty(obj,'name',{ value:'ldld', writable:true, enumerable: true, configurable: true // 现在我们想改回来,但是很遗憾,不能。不管是严格模式还是非严格模式都会报错 })
此外,configurable会影响该对象属性是否可以被删除
Object.defineProperty(obj,'name',{ value:'ldld', writable:true, enumerable: true, configurable: true }) delete obj.name; console.log(obj.name) // undefined ,说明删除成功 Object.defineProperty(obj,'name',{ value:'ldld', writable:true, enumerable: true, configurable: false }) delete obj.name; console.log(obj.name) // ldld, 说明name属性没有被删除
二、对象常量
const str = 'abc'; str = 'def'; // 报错Uncaught TypeError: Assignment to constant variable. const obj = {name:'ldld'}; obj.name = { name:'ldld1234' // 这里会修改成功 }
const声明的对象不可变,实际上是可以理解为指针的不可变。
const str = 'abc'; 表示str指针指向栈中一个地址,值'abc';
str = 'def';表示str又指到另一个地址,值为'def',违反了不可变的规则,报错了。
const obj = {name:'ldld'};表示obj 对象指向一个堆 内存堆的obj的引用,不管怎么改变obj里面的值,在内存堆中地方始终不变,因此不会报错。
那么问题来了,我们想声明一个不可变的对象,那怎么办?可以参考如下:
var obj = {} Object.defineProperty(obj,'name',{ value:'ldld', writable:false, configurable: false }) // 此时问obj的name属性不可改变了。
但是问题来来,name是不能再改变,但是我们可以给对象扩展其他属性。。。
三、防止对象扩展Object.preventExtensions
var obj = {} Object.defineProperty(obj,'name',{ value:'ldld', writable:false, configurable: false }) // 此时问obj的name属性不可改变了。但是可以扩展obj属性 obj.age = 100; console.log(obj.age) // 100 Object.preventExtensions(obj); obj.sex = 'male'; console.log(obj.sex) // undefined,说明扩展失败
四、密封Object.seal
顾名思义,密封一个对象,这个对象不能配置,不能扩展属性,不能删除属性。但是可以可以修改熟悉过的值
Object.seal(obj)// 等同于如下:代码1 + 代码2 // 代码1 Object.defineProperty(obj,'[该对象所有的属性]',{ configurable: false // writable:true, // 此时默认为true,可以修改 }) // 代码2 Object.preventExtensions(obj);
四、冻结Object.freeze(obj)
Object.freeze(obj)// 等同于如下:代码1 + 代码2 // 代码1 Object.seal(obj) // 代码2 Object.defineProperty(obj,'[该对象所有的属性]',{ writable:false })
由此可见,冻结,就是定一个对象常量的终极大法。