手写篇

1. 手写 instenceof

console.log([] instanceof Array) // true

console.log('' instanceof Array) // false

手写myInstanceof

function myInstanceof(left,right){

    let proto = left.__proto__

    let prototype = right.prototype

    while(true){

        if(proto === null)return false

        if(proto === prototype)return true

        proto = proto.__proto__

    }
}

console.log(myInstanceof([],Array))// true

console.log(myInstanceof('',Array))// false

2. 手写 flat

原生示例:

const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

手写flatDeep:

function flatDeep( arr, dep=1 ){
    let ret = []

    for(let i=0;i<arr.length;i++){

        if(Array.isArray(arr[i])){

            dep>0 ? (ret = ret.concat(flatter(arr[i],dep-1))):(ret.push(arr[i]))

        }else{

            ret.push(arr[i])
        }
    }

    return ret
}

3. 手写 call

Function.prototype.myCall = function(context){

    context =(context === null || context === undefined) ? window : context

    context.fn = this// 其实就等价于 obj.fn = function say(){} 当指向 context.fn 时,say里面的this 指向obj [关键]
    //obj 此时变成 var obj = {name:'innerName',fn:function say(){console.log(this.name)}}

    let args = [...arguments].slice(1) //截取第二个开始的所有参数
    let result= context.fn(...args)//把执行的结果赋予result变量

    delete context.fn //删除执行上下文上的属性 (还原)由var obj = {name:'innerName',fn:function say(){console.log(this.name)}}删除fn
    return result
}
var name = 'outerName'
var obj = {
    name:'innerName'
}
function say(){
    console.log(this.name)
}
say()//outerName     等价于  window.say    this指向window
say.myCall(obj)//innerName

4. 手写 apply

Function.prototype.myApply = function(context){

    context =(context === null || context === undefined) ? window : context

    let result

    context.fn = this

    result = arguments[1] ? context.fn(...arguments[1]) : context.fn()

    delete context.fn

    return result
}

5. 手写 bind

Function.prototype.myBind = function(context){

    context =(context === null || context === undefined) ? window : context

    let o = Object.create(context)

    o.fn = this

    let args = [...arguments].slice(1)

    let fn= function(){

        o.fn(...args)
    }

    return fn
}

6. 手写 new

function myNew(func){

    //第一步 将函数的 prototype 指向 o 对象的__proto__
    let o = Object.create(func.prototype)

    //第二步 通过call改变 this的指向,使之指向 o
    let ret = func.call(o)

    //第三步 如果构造函数里面有返回对象,则返回这个对象,没有则返回 o 对象
    return typeof ret === 'object' ? ret : o

}

检测:

function M(){}

let m = myNew(M); // 等价于 new M 这里只是模拟
console.log(m instanceof M); // instanceof 检测实例
console.log(m instanceof Object);
console.log(m.__proto__.constructor === M);
06-12 10:17