模拟实现对象新增10个的方法

1,961 阅读1分钟

前言

ES6新增了很多属性、方法以及某些特性,本系列主要通过模拟实现的方式来重学ES6,以便帮助自己更深入的的理解那些新增的东西。

本文目标:模拟实现对象的新增方法

image.png

模拟实现

说明:

  1. 只简单说明用法,然后模拟实现
  2. 真实实现未必是这样实现,仅实现功能,用于理解

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,但是我可以利用一个正数除以+0Infinity,除以-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组成的数组、返回由多个keyvalue组成的键值对的数组

由于大家梳理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对象身上新增的属性和方法的模拟实现!

我知道还有很多问题待完善,但我只要熟悉这些方法具体干了什么,也就达到了我这次学习的目的!

如有疑问或建议,希望可以留言告知,感谢你!!