前言
最近参加若川的源码共度活动,第 24 期 vue2 源码工具函数,最开始:
var emptyObject = Object.freeze({});
之前知道 Object.freeze() 是冻结,可是具体是什么呢,错过了就错过了,要不看看吧,那就看看吧,嗯,我这种读源码的方式比较低效,但是还是得看看,不然后面的都不易于理解,就暂且打打基础。
然后就看了MDN Web Docs Object.freeze()
Object.freeze()
Try it
Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
可枚举型、可配置性、可写性,啥意思,要不搜搜?嗯,搜搜。
然后找到了这个js 对象中什么是可枚举性(enumerable)?
看完了这篇,懂了 enumerable,那可配置性呢,继续搜。
找到了这篇JavaScript 属性的可迭代、可修改和可配置特性。
看了一半,有原文链接Javascript properties are enumerable, writable and configurable也看看。
看过中文,英文看着还可以理解。
由于看过第一篇,所以第二篇的标题写错了,加上原文链接是 enumerable,所以,enumerable 是可枚举型,并不是可迭代性 iterable。
所以引用 MDN Web Docs 里的名字,JavaScript 的可枚举性、可配置性、可写性是什么意思呢?
现总结如下。
阅读《js 对象中什么是可枚举性(enumerable)?》有感
读后感
-
讲 JS 对象的属性的可枚举性(属性的 enumerable):
如果为 false,(for..in 循环、Object.keys 方法、JSON.stringify 方法)这三个操作不会取到该属性。
- 我的示例
// 1. 一个没隐式原型的对象a,没有继承性,因为对象a太美了。a自己有 aa aaa aaaa 三个属性 let a = Object.create(null); a.aa = 1; a.aaa = 2; a.aaaa = 3; // 2. 弄一个对象b,b继承了a的美貌。b自己也有 b bb bbb 仨属性。 let b = Object.create(a); b; b.b = "b1"; b.bb = "b2"; b.bbb = 333; // 3. for...in 循环,发现了对象 b 拥有 b bb bbb 和 a aa aaa 一共六个属性的值,属性就是什么方面美,值就是什么方面具体到多少,a4腰,1.8米大长腿。 for (let key in b) { console.log(b[key]); } // for...in 循环 // b1 // b2 // 333 // 1 // 2 // 3 // 4. Object.keys() 列出 对象的 属性什么方面美。 Object.keys(b); // ['b', 'bb', 'bbb'] // 5. JSON.stringify() 列出了 对象b 拥有 的属性和值,{腰:a4,腿:1.8m} JSON.stringify(b); // '{"b":"b1","bb":"b2","bbb":333}' // 6. enumerable 是枚举的,列出,上面 3 4 5 都罗列了 对象b 的属性及其值,所以是可枚举性。 // 7. Object.getOwnPropertyNames() 罗列 对象b 所有属性(包括 可枚举性属性 & 不可枚举性属性),发现:b bb bbb 都是可枚举属性,因为是[.key]的方式定义的嘛。 Object.getOwnPropertyNames(b); // ['b', 'bb', 'bbb'] // 8. Object.defineProperty() 新建 | 修改属性。因为 b 没有 属性 bbbb,所以给对象b定义新属性bbbb,值34,设置属性bbbb具有不可枚举性。 Object.defineProperty(b, "bbbb", { value: 34, enumerable: false }); // {b: 'b1', bb: 'b2', bbb: 333, bbbb: 34} // 9. 罗列b的属性key,发现没有bbbb,因为上面设置了enumerable为false Object.keys(b); // (3) ['b', 'bb', 'bbb'] // 10. 获取 对象b 的 光明正大定义的属性 和悄悄定义的属性。 Object.getOwnPropertyNames(b); // (4) ['b', 'bb', 'bbb', 'bbbb']
收获
-
Object.freeze 对象后,对象属性不能添加,不能删除,不能给对象以.key 方式修改值,不能给对象以 Object.defineProperty(obj,key9,{value:val9,enumerable:false})方式修改值。
-
for...in 循环的 key 是自己的属性和原型链上的属性们,所以深拷贝的时候 for...in 循环里要判断 if(obj.hasOwnProperty(key)){ result[key] = deepClone(obj[key])}。
-
Object.keys 方法:得到对象自己的属性数组,不包含原型链上的属性。
-
Object.getOwnPropertyNames 方法得到对象 b 的自己及原型链上的属性。
-
JSON.stringify 方法将 obj 序列化为 JSON 字符串,也是自己的属性,跟 Object.keys 一样,不包括原型链上的属性。
-
上面 2、3、5 :
都得不到不可枚举性(使用 Object.defineProperty 方法给对象赋值并设置可枚举型 enumerable 为 false)的属性。 -
上面 4 :
Object.getOwnPropertyNames 方法可以得到不可枚举性的属性的数组。 -
上面 6、7 即:
for...in 循环、Object.keys 方法、JSON.stringify 方法 这仨只能得到枚举性属性,得不到不可枚举性的属性(悄悄的属性得不到);
Object.getOwnPropertyNames 方法 可以得到不可枚举型(悄悄的属性可得)
-
上面所有的意思(对于 Object.freeze 来说):Object.freeze 冻结对象后,增加属性、删除属性、光明正大修改属性、悄悄修改属性,都不可以!
参考链接
Javascript properties are enumerable, writable and configurable