最近在看ES6的入门教程,分类很细,知识点也很多,然后脑壳一抽,觉得是不是应该做点什么呢?哈哈,然后就更了此文,若有不当,欢迎指正!
此文会不定时更新,毕竟是边看边总结,随时会有补充哒!
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;
}
5.实现一个对象继承另一个对象的方法总结:
(1)浏览器特有的__proto__属性:
var prot={a:1,b:2,c:3};
const obj1={
__proto__:proto,
foo:123, //ES6特别说明,对象最后一个属性结束是可以带逗号哒,为了动态添加属性方便
}
(2)Object.create()
var prot={a:1,b:2,c:3};
const obj2=Object.create(prot);
obj2.foo=123;
(3)Object.assign()+Object.create()
var prot={a:1,b:2,c:3};
const obj3=Object.assign(Object.create(prot),{foo:123,});
(4)Object.create()+Object.getOwnPropertyDescriptors()
var prot={a:1,b:2,c:3};
const obj4=Object.create(
prot,
Object.getOwnPropertyDescriptors({foo:123,})
)
6.Object.setPrototypeOf
Object.setPrototypeOf=function(obj,proto){
obj.__proto__=proto;
return obj;
}