SOURCE

// 手写深拷贝实现
// 判断类型,正则和日期直接返回新对象
// 空或者非对象类型,直接返回原值
// 考虑循环引用,判断如果hash中含有直接返回hash中的值
// 新建一个相应的 new obj.contructor 加入hash
// 遍历对象递归(普通key 和 key 是 symbol 的情况)

// 浅拷贝 Object.creat()   [...arr]

function deepClone(obj, hash = new WeakMap()) {
    if(obj instanceof RegExp) {
        return new RegExp(obj);
    }
    if(obj instanceof Date) {
        return new Date(obj);
    }
    if(obj === null || typeof obj !== 'object') {
        return obj;
    }

    // 循环引用情况
    if(hash.has(obj)) {
        return hash.get(obj);
    }

    // new 一个相应对象
    // obj 为Array 相当于 new Array()
    // obj 为 Object 相当于 new Object()
    let constr = new obj.constructor();
    hash.set(obj, constr);
    for(let key in obj) {
        if(obj.hasOwnProperty(key)) {
            constr[key] = deepClone(obj[key], hash);
        }
    }
    // 考虑symbol 的情况
    let symbolObj = Object.getOwnPropertySymbols(obj);
    for(let i = 0; i < symbolObj.length; i++) {
        if(obj.hasOwnProperty(symbolObj[i])) {
            constr[symbolObj[i]] = deepClone(obj[symbolObj[i]], hash);
        }
    }

    return constr;
}

// let obj = { a:1, arr: [2,3]};
// let deepObj = deepClone(obj);

// console.log(deepObj);

// deepObj.arr.push(5);
// console.log(deepObj);
// console.log(obj);



// 函数柯里化
// 概念:把接收多个参数的函数变换成接受一个单一参数的函数,并且返回余下参数的
// 新函数的技术

function sum(a, b, c) {
    return a + b + c;
}

function curry(fn) {
    return function currify() {
        const args = Array.prototype.slice.call(arguments);
        return args.length >= fn.length
            ? fn.apply(null, args)
            : currify.bind(null, ...args);
    }
}

let currySum = curry(sum);

// console.log(currySum(1)(2)(3));
// console.log(currySum(1, 2)(3));
// console.log(currySum(1)(2, 3));

// 对象数组去重
// 把对象中的key 排序,然后再转为字符串
function objSort(obj) {
    let newObj = {};
    // 遍历对象,将key进行排序
    Object.keys(obj).sort().map(key => {
        newObj[key] = obj[key];
    })
    // 将排好序的数组转成字符串
    return JSON.stringify(newObj);
}

const obj = [{a:1,b:2,c:3},{b:2,c:3,a:1},{d:2,c:2}];
// const res = objSort(obj);
// console.log(res);

function unique(arr) {
    let set = new Set();
    for(let i = 0; i < arr.length; i++) {
        let str = objSort(arr[i]);
        set.add(str);
        // console.log(str);
    }
    // 将数组中的字符串转回对象
    arr = [...set].map(item => {
        return JSON.parse(item);
    })

    return arr;
}

let res = unique(obj);
// console.log(res);



// instanceof的实现
// 实现:遍历左边变量的原型链,直到找到右边变量的prototype
function myInstanceof(left, right) {
    // 获取对象原型
    let proto = Object.getPrototypeOf(left);
    // 获取构造函数的prototype 对象
    let prototype = right.prototype;
    // 判断构造函数的prototype 对象是否在对象的原型链上
    while(true) {
        if(!proto) {
            return false;
        }
        if(proto === prototype) {
            return true;
        }
        proto = Object.getPrototypeOf(proto);
    }
}

let Obj1 = function() {

}

let test1 = {};

res = myInstanceof(test1, Obj1);
// console.log(res);


// new的实现
function Ctor() {
    // 
}

function myNew(ctor, ...args) {
    if(typeof ctor !== 'function') {
        throw 'mynew function the first param must be a function';
    }
    // 创建一个继承自ctor.prototype 的新对象
    let newObj = Object.create(ctor.prototype);
    // 将构造函数ctor 的this 绑定到newObj中
    let ctorReturnResult = ctor.apply(newObj, args);
    let isObj = typeof ctorReturnResult === 'object'
        && ctorReturnResult !== null;
    let isFunction = typeof ctorReturnResult === 'function';
    if(isObj || isFunction) {
        return ctorReturnResult;
    }
    return newObj;
}

let c = myNew(Ctor);

console 命令行工具 X clear

                    
>
console