手写实现一个系列

125 阅读2分钟

instanceof

function myInstanceof(child,parent) {
    let left = child.__proto__
    let right = parent.prototype
    while (true) {
        if (left === null) {
            return false
        }else if (left !== right) {
            left = left.__proto__
        }else {
            return true
        }
    }
}

节流防抖

// 只执行新来的
function debounce(fn, delay) {
    let isFirstTime = true
    let timer = null
    return (...args)=>{
        if (isFirstTime) {
            fn()
            isFirstTime = false
        } else { // 只执行最新的
            if (timer) clearTimeout(timer)
            timer = setTimeout(()=>{
                console.log("执行最新一次", this)
                fn.apply(this,args)
                clearTimeout(timer)
                timer = null
            },delay)

        }
        
        
    }
}

function throttle(fn, delay) {
    let isFirstTime = true
    let timer = null 
    return (...args) => {
        if (isFirstTime) {
            fn.apply(this,args)
            isFirstTime = false
            return
        }
        if (timer) return // 根据标识决定是否执行,上一次执行完才允许下一次
        timer = setTimeout(() => {
            fn.apply(this,args)
            clearTimeout(timer)
            timer = null
        },delay)
    }
}
  

深拷贝

function deepClone(target, map = new Map()) {
  
  if (typeof target === 'object') {
    let cloneTarget = Array.isArray(target) ? [] : {}
    if (map.get(target)) {
        return map.get(target);
    }
      map.set(target, cloneTarget);
      for (let key in target) {
        cloneTarget[key] = deepClone(target[key], map)
      }
        return cloneTarget
  } else {
    return target
  }
}

call

Function.prototype.myCall = function(context){
    if (typeof this !== "function") throw new Error("Type error");
    let fun = this  // 获取函数
    let myArgs = [...arguments].slice(1)
    let myThis = context || window // 获取当前执行this
    let key = Symbol // 绑定的key
    let res = ''
    // 绑定函数
    myThis[key] = fun 
    res = myThis[key](...myArgs) // 函数执行结果
    delete myThis[key] // 删除函数防止污染对象
    return res
}

// 执行例子 (亲测有效)
function consoleAll(arr){
    for(let i = 0; i<arr.length; i++) {
        console.log(arr[i])
    }

}
consoleAll.myCall({a:'1'},1,2,3)

apply

Function.prototype.myApply = function(context) {
    if (typeof this !== 'function') throw new Error("Type error")
    let myFun = this 
    let myArgs = [...arguments].slice(1)
    console.log("myArgs:",myArgs)
    let myThis = context || window
    let myKey = Symbol()
    let myResult = undefined
    myThis[myKey] = myFun
    myResult = myThis[myKey](...myArgs)
    delete myThis[myKey]
    return myResult
}

// 执行例子 (亲测有效)
function myFun() {
    console.log("你好世界")
    console.log("我是a",this.a)
}
myFun.myCall({a:'1'})

bind

Function.prototype.myBind = function(context) {
    if (typeof this !== 'function') throw new Error("Type error ")
    let myFun = this    
    return (...args)=>{
        myFun.call(context,...args)
    }
}

//执行例子
function fun(arg1, arg2) {
    console.log(this.name) 
    console.log(arg1 + arg2) 
} 
const _this = { name: 'YIYING' } // 只变更fun中的this指向,返回新function对象 

const newFun = fun.myBind(_this)
newFun(1, 2)

function myNew(fun,...args){
    if(typeof fun !== 'function') throw new Error('Type Error')
    let myObj = Object.create(fun.prototype)// 获取对象
    let res = fun.apply(myObj,[...args]) // 执行结果
    return res === "object" ? res : myObj
}

快速排序

function quickSort(arr) {
    if (arr.length <= 1 )  return arr
    let baseValue = arr[0]
    let resArr = []
    let leftArr = []
    let rightArr = []
    arr.forEach((item, index)=> {
        if (item === baseValue) {
            resArr.push(item)
        } else if (item < baseValue){
            leftArr.push(item)
        } else {
            rightArr.push(item)
        }
    })
    return quickSort(leftArr).concat(resArr).concat(quickSort(rightArr))
}
let arr =[51,2,5,3,8,4,100,0,19]
quickSort(arr)

数组扁平化

/*
    1.判断是不是一个数组
    2.添加数组容器
    3.遍历数组,该项是数组?
        是 => 连接当前函数的返回值。
        不是 => 直接往当前函数添加元素
    4.返回数组

*/

function flatten(arr) {
    if (Array.isArray) throw new Error('Type error')
    let resArr = []
    arr.forEach(item => {
        if(Array.isArray(item)){
            arr.concat(flatten(item))
        } else {
            arr.push(item)
        }
    })
    return arr
}

reduce手写

Array.prototype.myReduce = function(cb,initValue){
    let arr = this
    initValue = initValue || arr[0]
    for (let i = 1; i < arr.length; i++){
        initValue = cb(initValue,arr[i],i,arr)
    }
    return initValue
}

new实现

当我们使用`new`时,做了些什么?

1.  创建一个全新对象,并将其`__proto__`属性指向构造函数的`prototype`属性。
(ps: let newObj = Object.create(xxx.prototype) 
则 newObj.__proto__ === xxx.prototype === Object.prototype)
2.  将构造函数调用的this指向这个新对象,并执行构造函数,参数绑定。
(ps: let res = xxx.apply(this,args)
3.  如果构造函数返回对象类型Object(比如Functoin, Array, Date, RegExg, Error等),则正常返回,否则返回这个新的对象。
(ps: return res instanceof Object ? res : newObj
完整代码:
function myNew(fn,...args) {
    let newObj = Object.create(fn.prototype)
    let fnRes = fn.apply(newObj,args)
    console.log(fnRes instanceof Object)
    return FnRes instanceof Object ? FnRes : newObj
}