# 函数实现

# Throttle

节流 -- 单位时间内只能触发一次,单位时间内多次调用只有一次生效

function throttle(fn, delay) {
    let flag = true, timer = null;

    return function (...args) {
        const context = this;
        if (!flag) return;
        flag = false;
        clearTimeout(timer);
        timer = setTimeout(() => {
            fn.apply(context, args);
            flag = true;
        }, delay);
    }
}

# Debounce

防抖 -- 调用n秒后执行,如果n秒内再次被调用,重新计时。

function debounce(fn, delay) {
    let timer = null;
    return function (...args) {
        const context = this;
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(() => {
            fn.apply(context, args);
        }, delay);
    }
}

# Call

Function.prototype.myCall = function(context) {
    context = context ? Object(context) : window;
    context.fn = this;
    let args = [];
    for (let i = 1; i < arguments.length; i++) {
        args.push(`arguments[${i}]`);
    }
    let res = eval(`context.fn(${args})`);
    delete context.fn;
    return res;
}

# Apply

Function.prototype.myApply = function(context, args) {
    context = context ? Object(context) : window;
    context.fn = this;
    if(!args) {
        return context.fn();
    }
    let res = eval(`context.fn(${args})`);
    delete context.fn;
    return res;
}

# Bind

Function.prototype.myBind = function(context) {
    let that = this;
    let bindArgs = Array.prototype.slice.call(arguments, 1);
    function Fn() {};
    function fBound(params) {
        return that.apply(this instanceof fBound ? this : context, [...bindArgs, ...params]]);
    }
    Fn.prototype = this.prototype;
    fBound.prototype = new Fn();
    return fBound;
}

# New

const myNew = function(constructor, ...args) {
    let obj = {};
    obj.__proto__ = constructor.prototype;
    let res = constructor.apply(obj, args);
    return res instanceof Object ? res : obj;
}

# Instanceof

const myInstanceof = function(left, right) {
    right = right.prototype;
    left = left.__proto__;

    while(true) {
        if (left === null) {
            return false;
        }
        if (left === right) {
            return true;
        }
        left = left.__proto__;
    }
}

# Object.create

创建一个新对象,使用现有的对象来提供新创建的对象的__proto__

Object.myCreate = function(proto) {
    function F() {};
    F.prototype = proto;

    return new F();
}

基于Object.create的单继承

function Super() {
    // ...
}

function Sub() {
    Super.call(this);
}

Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;

基于Object.create的多继承

function Super1() {
    // ...
}

function Super2() {
    // ...
}

function Sub() {
    Super1.call(this);
    Super2.call(this);
}

Sub.prototype = Object.create(Super1.prototype);
Object.assign(Sub.prototype, Super2.prototype);
Sub.prototype.constructor = Sub;