Skip to content

思路

  1. 模拟this调用
  2. 解析剩余参数
  3. 参数如何传到函数中
  4. context为null时处理
  5. 处理函数非法的情况
  6. 删除额外新增的变量,最好采用symbol
js
const getFunctionArgs = (funcArgs, startIndex = 0) => {
    const result = []
    for(let i = startIndex, len = funcArgs.length; i < len; i++) {
        result.push(funcArgs[i])
    }

    return result;
}

const checkFunction = (fn) => {
    return typeof fn === 'function'
}

Function.prototype.myCall = function(context) {
    if(!(checkFunction(this))) {
        throw new Error('not function');
    }

    const restArgs = getFunctionArgs(arguments, 1);
    context = context || globalThis;
    context.__fn = this;
    const result = eval(`context.__fn(${restArgs})`)
    delete context.__fn
    return result
}

Function.prototype.myApply = function(context, args = []) {
    if(!checkFunction(this)) throw new Error('not function');
    context = context || globalThis;
    context.__fn = this;
    const result = eval(`context.__fn(${args})`)
    delete context.__fn
    return result
}

Function.prototype.myBind = function (context, ...initArgs) {
    if(!checkFunction(this)) throw new Error('not function');
    const fn = this;

    const temp = function () {}
    temp.prototype = this.prototype;

    const fbind = function (...args) {
        return fn.myCall(this instanceof fn ? this : context, ...initArgs, ...args)
    }

    fbind.prototype = new temp()

    return fbind
}

function newFn(constructor, ...args) {
    const obj = Object.create(null);
    obj.__proto__ = constructor.prototype;
    constructor.myApply(obj, args)

    return obj
}