Visual LabINTERACTIVE LEARNING
JavaScript 内核精校教程

JavaScript 手写题:从原理到实现

用 call / apply / bind、防抖节流、深拷贝和事件总线检验语言机制是否真正掌握。

手写题函数事件
专题预计 16 分钟查看源文 ↗

call、apply、bind实现

💡 提示

基本思路,使用隐式绑定,给传入的thisArg转换成一个对象,给新的对象添加一个属性fn,值为this,this即为调用者,也就是调用的函数,然后使用传入的thisArg去调用原来的函数

Function.prototype.myCall = function (thisArg, ...args) {
    thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)
    Object.defineProperty(thisArg, 'fn', {
        configurable: true,
        enumerable: false,
        value: this
      })
     //
    thisArg.fn(...args)
    delete thisArg.fn
}

手写防抖和节流

防抖

💡 提示

对于多次触发的事件,一定时间间隔内,只有最后一次事件会触发执行函数

function debounce(fn, delay, immediate = false) {
        let timer = null
        let isExc = false
        function exec(...arg) {
            // 立即执行一次
            if (!isExc && immediate) {
                fn.apply(this, arg)
                isExc = true
                return
            }
            // 清除定时器
            timer && clearTimeout(timer)
            timer = setTimeout(() => {
                fn.apply(this, arg)
                clearTimeout(timer)
                timer = null
            }, delay)
        }
        // 可取消
        exec.cancel = function () {
            console.log('cancel');
            timer && clearTimeout(timer)
        }
        return exec
    }
节流

💡 提示

多次触发的事件按一定频率执行,减少执行次数

手写深拷贝

💡 提示

注意对不同类型的数据进行不同的操作,常见的对象、数组、函数,循环引用,set map,symbol等

循环引用可以使用weakmap来解决,symbol需要判断key和value

手写事件总线