【手写】call方法

67 阅读1分钟

手写系列文章

手写算法,要想实现和原生的功能一致,则弄懂原生的都支持些什么功能是很重要的。

原生.call方法

作用

套用MDN上的解释为:

call()方法使用一个指定的this值和单独给出的一个或多个参数来调用函数

语法

调用原生call的语法为:

functionA.call(thisArg, arg1, arg2, ...)

参数含义:

thisArg: 在function函数运行时使用的this值。如果是在非严格模式下,thisArg指定为null或undefined时会自动替换为指向全局对象。

arg1, arg2, ...: 指定的参数列表

返回值

使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined。

示例

const a = {
    name: 'xiao a',
    b() {
        console.log('my name is: ', this.name);
    }
}

c = {name: 'xiao c'};
a.b.call(c); // 打印的内容为: my name is:  xiao c

手写call方法

手写call方法需要注意几个点:

  1. 调用call的参数中第一个是调用者提供的this值,具体的参数是从第二个位置开始的
  2. 在非严格模式下,如果没有提供this值,或者this值为null、undefined,则this会被自动替换为全局对象,在浏览器中指向的是window
  3. call是Function原型对象上的一个方法

具体的代码如下:

Function.prototype.myCall = function(context, ...args) { 
    if (typeof this !== 'function') { 
        throw Error(`typeError: ${this} not function.`); 
    } 
    const ctx = context || window; 
    const func = Symbol(); 
    ctx[func] = this; 
    const result = args.length ? ctx[func](...args) : ctx[func](); 
    delete ctx[func]; 
    return result;
}

测试

const a = {
    name: 'xiao a',
    b() {
        console.log('my name is: ', this.name);
    }
}

c = {name: 'xiao c'};
a.b.myCall(c); // 打印的内容为: my name is:  xiao c

// 不提供this
a.b.myCall() // 打印的内容为: my name is:
// 在window对象上增加属性: window.name = 'window';
a.c.myCall() // 打印的内容为: my name is: window