Skip to content

鼓励作者:欢迎打赏犒劳

各种手写源码

防抖

节流

new

Object.create

深拷贝

instanceof

call、apply、bind

reduce

柯里化

发布订阅

async/await 实现

实现一个双向数据绑定

Array.isArray 实现

promise 实现

防抖

文章可见防抖与节流

饭都

javascript
function debounce(func, wait, flag) {
    let timer = null;
    return function (...args) {
        clearTimeout(timer);
        if (!timer && flag) {
            func.apply(this, args)
        } else {
            timer = setTimeout(() => {
            	func.apply(this, args)
        	}, wait)   
        }
    }
}

节流

javascript
function throttle(func, wait) {
    let pre,
        timer = null;
    if (Date.now() - pre > wait) {
        clearTimeout(timer);
        timer = null;
        pre = Date.now()
        func.apply(this, args)
    } else if (!timer) {
        timer = setTimeout(() => {
            func.apply(this, args)
        }, wait)
    }
}

new

文章可看new 做了什么

ES5 版本:

javascript
function new2(Constructor, ...args) {
  let obj = Object.create(null);
  obj.__proto__ = Constructor.prototype;
  let result = Constructor.apply(obj, args);
  return typeof result === 'object' ? result : obj;
}

ES3 版本:

javascript
function new3() {
    let obj = {},
    Constructor = Array.prototype.shift.call(arguments)
    var F = function(){}
    F.prototype = Constructor.prototype
    obj = new F()
    var result = Constructor.apply(obj, arguments)
    returb typeof result === 'object' ? result : obj
}

Object.create

javascript
function create(obj) {
    function F() {}
    F.prototype = obj;
    return new F()
}

深拷贝

文章可看拷贝的密码

javascript
function deepClone(source, storage = new WeakMap()) {
    // 针对基本数据类型
    if (typeof source !== 'object' || source === null) {
        return source
    }
    // 是否是日期
    if (source.constructor === Date) {
        return new Date(source)
    }
    // 是否是正则
    if (source.constructor === RegExp) {
        return new RegExp(source)
    }
    // 是否是数组
    let target = source instanceof Array ? [] : {}
    // 循环引用 返回存储的引用数据
    if (storage.has(source)) return storage.get(source)
    // 开辟存储空间设置临时存储值
    storage.set(source, target)
    // 是否包含 Symbol 类型
    let isSymbol = Object.getOwnPropertySymbols(source)
    // 包含 Symbol 类型
    if (isSymbol.length) {
        isSymbol.forEach((item) => {
            if (typeof source[item] === 'object') {
                target[item] = deepClone(source[item], storage);
                return
            }
            target[item] = source[item]
        })
    }
    // 不包含 Symbol
    for(let key in source) {
        if (source.hasOwnProperty(key)) {
            target[key] = typeof source[key] === 'object' ? deepClone(sourcep[key], storage) : source[key]
        }
    }
    return target;
}

instanceof

文章可看instanceof——找祖籍

javascript
function myInstanceof(left, right) {
    if (typeof left !== 'object' || left === null) return false;
    let proto = Object.getPrototypeOf(left);
    while (true) {
        if (proto == null) return false;
        if (proto == right.prototype) return true;
        proto = Object.getPrototypeOf(proto);
    }
}

call、apply、bind

call

javascript
function myCall(context = window, args) {
    if (this === Function.prototype) {
        return undefined;
    }
    let fn = Symbol()
    context[fn] = this;
    let result = context[fn](...args)
    delete context[fn];
    return result
}

apply

javascript
function myApply(context = window, args) {
    if (this === Function.prototype){
        return undefined
    }
    let fn = Symbol()
    context[fn] = this;
    let result;
    if (Array.isArray(arg)){
        result = context[fn](...args)
    } else {
        result = context[fn]()
    }
    delete context[fn]
    return result
}

bind

javascript
function myBind(context, ...args1) {
    if (this === Function.prototype) {
        return new TypeError('Error')
    }
    const _this = this;
    return function F(...args2) {
        if (this instance F) {
            return new _this(...args1, ...args2)
        }
        return _this.apply(context, args1.concat(args2))
    }
}

reduce

柯里化

javascript
function curry(fn) {
  return function curriedFn() {
    var _args = Array.prototype.slice.call(arguments);
    if (_args.length < fn.length) {
      return function () {
        var _args2 = Array.prototype.slice.call(arguments);
        return curriedFn.apply(null, _args.concat(_args2));
      };
    }

    return fn.apply(null, _args);
  };
}

ES6 实现

javascript
function curry(fn) {
  return function curriedFn(...args) {
    if (args.length < fn.length) {
      return function () {
        return curriedFn(...args.concat(Array.from(arguments)));
      };
    }

    return fn(...args);
  };
}

发布订阅

javascript
class eventEmitter {
    constructor() {
        this.event = {}
    }
    
    on(type, callback) {
        if (!this.event[type]) {
            this.event[type] = [callback]
        } else {
            this.event[type].push(callback)
        }
    }
    
    off(type, callback) {
        if (!this.event[type]) {
            return
        }
        this.event[type] = this.event[type].filter((item) => {
            return item !== callback
        })
    }
    
    emit(type, ...args) {
        if (!this.event[type]) {
            return
        }
        this.event[type].forEach((callback) => {
            callback.apply(this, args)
        })
    }
    
    once(type, callback) {
        function f() {
            callback()
            this.off(type, f)
        }
        this.on(type, f)
    }
}

示例:

javascript
const eventEmitter = new EventEmitter();

// 订阅事件
eventEmitter.on("公众号", (name) => {
    console.log(`我订阅了${name}`)
})

// 发布事件
eventEmitter.emit('公众号''随朱波流')