一、前言
-
"Javascript 中万物都是对象",这是错误的(我是这么理解的)。对象是7个基础类型(string, number,boolean, null, undefined,object, symbol).
对象有包含function在内的子类型,不同子类型具有不同的行为。通过Object.prototype.toString.call() 可以看属于对象中的那个子类型;[object Array]
表示这是对象子类型数组
-
对象就是键/值得集合,可以通过 . 或者__[ ]__ 语法来获取对象的属性
-
访问对象属性是会执行默认__[[Get]]操作, 设置属性是会默认执行[[Put]]__
-
__[[Get]]__获取这个对象的属性是,会检查这个对象是否包含这个属性,如果没有就会通过__原型链__查找。
-
属性的特性 可以通过属性描述符来控制。
二、属性控制符
从ES5 开始,所有的属性都有了属性描述符
let obj = {
a:2
}
console.log(Object.getOwnPropertyDescriptor(obj,'a'))
// value: 2, writable: true, enumerable: true, configurable: true }
1、属性描述符 包含:writable, enumerable, configurable 三个特性
let obj = {}
Object.defineProperty(obj,"a",{
value:12,
writable: false,
enumerable:false,
configurable: false
})
console.log(obj.a)
console.log(Object.getOwnPropertyDescriptor(obj,'a'))
// 12
// { value: 12, writable: false, enumerable: false, configurable: false }
2、在创建一个对象的属性时,属性描述符会使用默认值。同时也可以使用Object.defineProperty 来添加属性或者修改属性
-
1、writable: 决定是否可以修改属性的值
"use strict" let obj = {} Object.defineProperty(obj,"a",{ value:12, writable: false, enumerable:true, configurable: true }) console.log(obj.a) obj.a = 13 console.log(obj.a) // 12 // obj.a = 13 TypeError: Cannot assign to read only property 'a' of object '#<Object>' // 非严格模式下 第二个 obj.a = 12 数据不可改变你可以把writable: false 看做属性不可改变,相当于你定义了一个空操作的setter
-
2、configurable: 只要设置为false,defineProperty() 就不可修改obj 中的属性,把configurable 修改成false 是单向操作,无法撤销
- 但是可以将writable的状态由true改为false,但是不能由false改为true
- 不能操作delete 方法,删除对象属性
let obj = {} Object.defineProperty(obj,"a",{ value:12, writable: true, enumerable:true, configurable: false }) console.log(obj.a) obj.a = 13 console.log(obj.a) delete obj.a // TypeError: Cannot delete property 'a' of #<Object> Object.defineProperty(obj,"a",{ value:12, writable: true, enumerable:true, configurable: true }) console.log(Object.getOwnPropertyDescriptor(obj,'a')) // 12 // 13 // TypeError: Cannot redefine property: a-
3、enumable:如果设为false,这个属性就不会在枚举中出现,但是可以正常访问他。
- 当对象的enumable:false 用for-in 遍历不出这个属性
let obj = {} Object.defineProperty(obj,"a",{ value:12, writable: true, enumerable:true, configurable: true }) Object.defineProperty(obj,"b",{ value:13, writable: true, enumerable:false, configurable: true }) console.log(obj) // { a: 12, b: 13 } for (let c in obj) { console.log(c) } // a
总结:
-
1、通过设置writable和configurable 值 来创建一个真正的常量属性,不可修改,不可重新定义,不可删除
-
2、若禁止向一个对象中添加新属性,可以使用
Object.preventExtensions() -
3、
Object.seal()会创建“密封对象”,实际上是对对象上调用Object.preventExtensions(),并把对象上的所有属性都标记为configurable:false -
4、Object.freeze() 会创建一个冻结对象,实际上是调用
Object.seal(),并把设置对象writable:false,这样就无法修改他们的值。是最高级别的不可变性
参考《你不知道的JavaScript 上卷》