实现一个自己的bind,call,apply,instanceof,new

193 阅读1分钟

不多bb直接上代码,希望对大家伙有少许帮助

本文中涉及到的公用方法

// 原始值
const primitive = {
    'string': true,
    'number': true,
    'symbol': true,
    'boolean': true,
    'null': true,
    'undefined': true,
}
const isFn = v => typeof v === 'function';
const isBrow = () => typeof window !== 'undefined';
const isArray = v => Array.isArray(v);
const isNew = (v, c) => v instanceof c;
const isPrimitive = v => primitive[typeof v];

apply

// apply的实现
Function.prototype.apply1 = function (context) {
    // 获取需要被调用的函数
    const fn = this;
    if (!isFn(fn)) return;
    // 获取指定上下文
    const ctx = context || global;
    // 获取传递过来的参数
    let args = [...arguments]
    args = args.pop();
    if (!isArray(args)) return;
    // 将fn 作为对象的属性
    ctx.fn = fn;
    const res = ctx.fn(...args);
    delete ctx.fn
    return res;
}

call

Function.prototype.call1 = function (context) {
    // 获取需要被调用的函数
    const fn = this;
    if (!isFn(fn)) return;
    // 获取指定上下文
    const ctx = context || global;
    // 获取传递过来的参数
    const args = [...arguments]
    args.shift()
    // 将fn 作为对象的属性
    ctx.fn = fn;
    // 执行 fn
    const res = ctx.fn(...args)
    delete ctx.fn
    return res;
}

bind

// bind的实现
Function.prototype.bind1 = function (context) {
    // 获取需要被调用的函数
    const fn = this;
    if (!isFn(fn)) return;
    // 获取指定上下文
    let ctx = context || global;
    // 获取 预置入绑定函数的参数列表
    const _args = [...arguments]
    _args.shift();
    // 利于一个中转函数 来实现继承关系
    const temp = function () { };
    const f = function () {
        // 合并 bind传递的参数 和 调用函数时传递的参数
        const args = [..._args, ...arguments]
        ctx = isNew(this, f) ? this : ctx
        return fn.call1(ctx, ...args)
    }
    temp.prototype = fn.prototype;
    f.prototype = new temp();
    return f
}

instanceof

// instanceof的实现
function instanceof1(left, right) {
    if (!(left && right)) return;
    do {
        if (left.__proto__ === right.prototype) return true;
    } while (left = left.__proto__)
    return false;
}

new

// new的实现
function new1(constructor) {
    if (!isFn(constructor)) return;
    // 获取参数
    const args = [...arguments];
    args.shift()
    // 创建一个空对象
    const obj = {};
    // 将obj作为 上下文 调用 构造函数
    const res = constructor.call(obj, ...args);
    // 实现一个继承关系 让 obj 可以访问到构造函数上面的属性
    // 其实可以在 创建obj的时候 利用 Object.create() 来指定它的原型对象为constructor.prototype
    obj.__proto__ = constructor.prototype;
    return isPrimitive(res) ? obj : res;
}