前言
ES6
新增了很多属性、方法以及某些特性,本系列主要通过模拟实现的方式来重学ES6
,以便帮助自己更深入的的理解那些新增的东西。
本文目标:模拟实现对象的新增方法
模拟实现
说明:
- 只简单说明用法,然后模拟实现
- 真实实现未必是这样实现,仅实现功能,用于理解
Object.is()
用法
该方法用于优化===
的两个问题:NaN
不等于NaN
、+0
等于-o
模拟实现:_is
方法
Object._is = function (one, two) {
if (Number.isNaN(one) && Number.isNaN(two)) {
return true;
}
if (one === 0 && two === 0) {
if (1 / one < 0 && 1/two >0){
return false
}
if (1 / one > 0 && 1/two <0) {
return false
}
}
return one === two;
}
console.log(Object._is(NaN,NaN));//true
console.log(Object._is(+0, -0));//false
console.log(Object._is(-0, +0));//false
这里有个小窍门,就是判断一个数是+0
还是-0
,正常是比较难判断的,因为他们都全等于0
,但是我可以利用一个正数除以+0
为Infinity
,除以-0
为-Infinity
的规律,在通过Infinity
和-Infinity
分别跟0
比较,判断出是-0
还是+0
Object.assign()
用法
assign
用于把多个对象合并到到一个对象上,第一个参数是要把其他对象合并到的对象target
,剩下其他参数是要被合并的对象,返回target
模拟实现:_assign
方法
Object._assign = function () {
if (arguments.length == 0) {
throw new TypeError(`Cannot convert undefined or null to object`);
}
if (arguments.length == 1) {
return arguments[0];
}
if (arguments.length >= 2) {
let target = arguments[0];
for (let i = 1; i < arguments.length; i++) {
// 拿出每一个要被合并的对象,判断对象里面属性,在arguments[0]中是否已经存在,没有存在则加入,有存在就覆盖。
for(let key in arguments[i]){
//key表示每个要合并的对象的属性,直接添加到target中去就可以,有就覆盖,没有就添加
target[key] = arguments[i][key];
}
}
return target
}
}
let obj1 = { name: 'a' };
let obj2 = { name: 'b' }
console.log(Object._assign(obj1, obj2));
Object.getPrototypeOf()
用法
用于获取对象的原型
模拟实现:_getPrototypeOf
方法
Object._getPrototypeOf = function (target) {
return target.__proto__;
}
Object.setPrototypeOf()
用法
用于设置对象的原型
模拟实现:_getPrototypeOf
方法
Object._setPrototypeOf = function (target, proto) {
target.__proto__ = proto;
}
Object.create()
使用
Object.create()
用于产生指定原型的新对象,返回该对象。第一个参数可以是某个对象,也可以是null
,如果是null
表示该对象没有原型。
模拟实现:_create
方法
Object._create = function(proto){
let obj = {}
Object.setPrototypeOf(obj,proto)
return obj
}
Object.keys()、Object.values()、Object.entries()
用法
Object.keys()
是ES5新增方法,用于返回由对象的key
组成的数组
而Object.values
和Object.entries
是ES2017引入的方法,分别用于返回由对象的value
组成的数组、返回由多个key
和value
组成的键值对的数组
由于大家梳理ES6的时候都加上它,所以我们也一起来写一下
模拟实现:_keys
、_values
、_entries
- _keys实现
Object._keys = function(o){
let res = [];
for(let key in o){
res.push(key)
}
return res;
}
console.log(Object._keys(obj));//["a", "b", "c"]
- _values实现
Object._values = function(o){
let res = [];
for(let key in o){
res.push(o[key]);
}
return res;
}
let obj = {a:1,b:2,c:3};
console.log(Object._values(obj));//[1, 2, 3]
- _entries实现
Object._entries = function(o){
let res = [];
for(let key in o){
res.push([key,o[key]]);
}
return res;
}
let obj = {a:1,b:2,c:3};
console.log(Object._entries(obj));//[["a", 1], ["b", 2], ["c", 3]]
Object.fromEntries()
用法
相当于创建对象,它是将键值对的数组转成对象。
因此被传入的数组格式必须像这样子[['name','Alice'],['age',12],...]
模拟实现
Object._fromEntries = function(arr){
// 要求接受的必须是数组
if(Array.isArray(arr)){
// 里面的每一项也必须是数组,并且长度要为2
let isTwoLengthArray = arr.some(val =>{
return Array.isArray(val) && val.length == 2
});
if(isTwoLengthArray){
let obj = {}
arr.forEach(val => {
obj[val[0]] = val[1]
});
return obj
}
}
// 还有可能是map之类的数据结构,待实现
}
let person = [['name','Alice'],['age',12]]
console.log(Object._fromEntries(person))//{name: "Alice", age: 12}
Object.getOwnPropertyDescriptors()
用法
这个方法其实是ES2017引入的,用于返回传入对象的所有自身属性的描述
模拟实现:_getOwnPropertyDescriptors
方法
function _getOwnPropertyDescriptors(obj) {
const res = {};
for (let key of Reflect.ownKeys(obj)) {
res[key] = Object.getOwnPropertyDescriptor(obj, key);
}
return res;
}
__proto__属性
用法
用于返回传入对象的原型对象
模拟实现:_proto_
Object.prototype._proto_ = Object.getPrototypeOf(obj);
END
以上就是ES6对象身上新增的属性和方法的模拟实现!
我知道还有很多问题待完善,但我只要熟悉这些方法具体干了什么,也就达到了我这次学习的目的!
如有疑问或建议,希望可以留言告知,感谢你!!