1.Object.freeze():冻结对象
首先,为什么要冻结对象呢?
在ES6中有一种变量声明方法为const,当我们使用这个命令来声明一个变量的时候,其实本意是想声明一个只读的常量,也就是说,我们并不希望在以后改变它。然而,但是,想象总是美好滴,对于复合型变量(数组,对象),变量名指向的并不是数据本身,而是数据所在的地址。这就意味着我们用const声明了一个对象,却依然能够向其添加或删除或修改属性很显然,这样的做法在一定程度上违背了我们设计这个变量的初衷了。所以,我们需要冻结一个对象,使得对其属性的增删操作无法生效,这就是Object.freeze()的作用啦!
然后呢,为了彻底冻结一个对象,单靠Object.freeze()肯定是不行的啦,我们不仅要将对象本身冻结,还要将对象的属性也冻结,这个对象属性尤指typeof类型为object的属性。
下面,贴代码:
var constantize=(obj) => { Object.freeze(obj); Object.keys(obj).forEach((key,value) => { if(typeof obj[key]==="object"){ constantize(obj[key]); } }); };
2.Object.is():比较两个值是否严格相等
首先,我们需要知道,ES6中每一个新出的特性,必定都是有其出现的充足的理由的。为啥这么说,因为看它的作用,貌似并不是很大,因为在ES5中已经有运算符是用作比较判断的了:相等==和严格相等===。那么为啥还要新增一个Object.is()呢(~~默默脑补懵逼Object.is()君内心:所以我是为谁存在的呢?),咳咳,让我来解释一下吧!
第一点是ES5的相等运算符和全等运算符有缺点。前者会自动转换数据类型,后者对NaN不友好(NaN君含泪哭诉:懂我的人终于出现了!),而且竟然认为+0跟-0是相等的!(我们明明只是双胞胎好伐?我们要独立“数”权好伐?)
第二是ES6的Object.is()弥补了上一条的缺点。首先它的比较是全等比较,其次是,它为NaN和+0、-0正名了。
哟哟哟,效果图,来一张!
所以,Object.is()君和{NaN,+0,-0}君们热情拥抱在一起了,我们就来贴代码吧!
Object.defineProperty(Object,'is',{ value:function(x,y){ if(x===y){ //针对+0等于-0的情况 return x!==0 || 1/x===1/y; } //针对NaN不等于NaN的情况 return x!==x && y!==y; }, configurable:true, enumerable:false, writable:true });
3.Object.assign(target,source):对象合并
有面试经历的人应该都知道Object.assign()有一个非常重要的作用:对象拷贝。然后针对拷贝,我需要说明一点的就是,当源对象是单层对象时,属于深拷贝,当源对象存在对象的嵌套,就是浅拷贝啦。贴上效果图:
其实Object.assign()还有很多其他的作用(Object.assign()君:我可是有十八般武艺在身的萌萌哒小能手!):为对象添加属性和方法;合并对象;为属性指定默认值等等。
4.Object实例的__proto__属性
__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。之所以要在前后加上双下划綫,是为了说明它本质上是一个内部属性,不是一个正式对外的API。那为啥ES6要把它加进来呢?(咳咳,几朝元老级人物了,不能做得太绝呀!)其实是因为得到了浏览器的广泛支持,所以标准规定了,只有浏览器必须部署这个属性,其他运行环境不一定部署。(ES6:既然爱卿们喜欢,真就成人之美,把__proto许配给你们啦!浏览器:我们就呵呵哒了。)所以,我们最好不要用这个属性,而用Object.setPrototypeOf(),Object.getPrototypeOf()以及Object.create()来代替。
在实现上,__proto__调用的是Object.prototype.__proto__,贴代码!
Object.defineProperty(Object.prototype,"__proto__",{ get(){ let _thisObj=Object(this); return Object.getPrototypeOf(_thisObj); }, set(proto){ if(this====undefined || this===null){ throw new TypeError(); } if(!isObject(this)){ return undefined; } if(!isObject(proto)){ return undefined; } let status=Reflect.setPrototypeOf(this,proto); if(!status){ throw new TypeError(); } }, }); function isObject(value){ return Object(value)===value; }