# 数组去重

let arr = [1,21,3,4,5,1,3,1];

# 利用 Set 数据结构

function unique(arr){
    // 利用 es6 的 set 数据结构
    return [...new Set(arr)];
}

# 利用 Array.prototype.filter 函数

function unique(arr){
    return arr.filter((item,index) => {
        // 判断是否有出现索引号不一致情况,若有则说明有重复
        return arr.indexOf(item) === index;
    });
}

# 利用 Array.prototype.includes 函数

function unique(arr){
    const newArr = [];
    
    arr.forEach(item => {
    // 判断新数组里是否有该 item
        if(newArr.includes(item)) return;
        newArr.push(item);
    })
    
    return newArr;
}

# 利用 Array.prototype.indexOf 函数

function unique(arr){
    const newArr = [];
    
    arr.forEach(item => {
        // 若 item 从未出现在新数组里,将 item 加入新数组
        if(newArr.indexOf(item) === -1) newArr.push(item)
        // if(!newArr.includes(item)) newArr.push(item)
    })
    
    return newArr;
}

# 数组扁平化

let arr = [[1], [2, 3], [4, 5, 6, [7, 8, [9, 10, [11]]]], 12];
// 原生
arr.flat(Infinity);

# 利用字符串转换

function flat(arr){
    let arrStr = arr.toString();
    let newArr = arrStr.split(',');
    return newArr.map(item => Number(item));
}

# 完美版本,不改变变量类型

function flat(arr,maxDepth = 1){    
    let counter = 0;    
	// 利用迭代
    while(arr.some(item => Array.isArray(item))){
        if(counter < maxDepth){
            ++counter;
            arr = [].concat(...arr);
        }        
    }
    return arr;
}

# 柯里化

function curring(fn,...argsOne){
    // 若参数不够则继续返回函数,继续接收参数
    if(argsOne.length<fn.length){
        return (...argsTwo)=>{
            return curring(fn,...argsOne.concat(argsTwo));
        }
    }else{
        // 若参数足够则直接返回函数调用结果
        return fn.call(this,...argsOne);
    }
}
function add(a,b,c,d,e){
    return a + b + c + d + e;
}
let fn = curring(add);
console.log(fn(1,2,3,4,5))
console.log(fn(1,2,3,4)(5))
console.log(fn(1,2)(3,4,5))
console.log(fn(1)(2)(3)(4)(5))

# new

new 操作符做的事情

  • 判断操作对象是否为函数,若是则创建一个空对象。若不是则抛出类型错误
  • 将该空对象的原型指向构造函数的原型
  • 执行构造函数,将 this 指向该空对象
  • 判断构造函数执行结果,若为对象则返回对象,若不是则返回开始时创建的对象
function myNew(Constructor,...args){
   if(Constructor instanceof Function){
       const obj = Object.create(Constructor.prototype);
       const res = Constructor.call(obj,...args);
       return res instanceof Object ? res : obj;
   }else{
       // 值不是函数类型,抛出错误
       throw new Error(`TypeError:${Constructor} is not a Constructor`);
   }
}

# instanceof

instanceof 就是根据构造函数的原型链网上查找,找到即返回 true ,找不到则返回 false

  • 判断右操作数是否为函数类型,是则继续。否则返回类型错误
  • 左操作数的原型不是则继续获取该原型的原型
  • 若最终找到 Object.prototype__proto 则返回 false,查找失败。否则返回 true
function myInstanceof(left,right){
    if(typeof right === 'function'){
        let Lproto = Object.getPrototypeOf(left);
        while(true){
            // 找到终点 null 时,直接返回 false
            if(!Lproto) return false;
            if(Lproto === right.prototype) return true;
            Lproto = Object.getPrototypeOf(Lproto);
        }
    }else{
        throw new Error(`Right-hand side of 'instanceof' is not callable`)
    }
}