面试时被问:如何用js自己实现一个Function.prototype.call来修改function中this

509 阅读2分钟

前言

面试时被问:如何用js自己实现一个Function.prototype.call来修改function中this?

call的基本概念

注意: 该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组

call的基本用法

function zz(name) {
    console.log(this);
    console.log(name, this.name)
};
let a = {
    name: 234
}
zz.call(a, ["abc", "2332"]);
//打印值 {name, 234}, 
// ["abc", "2332"], 234
zz();
//打印值 window
//underfined  underfined

手写call

Function.prototype.myCall = function(context,...args){
    let cxt = context || window;
    //将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
    //新建一个唯一的Symbol变量避免重复
    let func = Symbol() 
    cxt[func] = this;
    args = args ? args : []
    //以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
    const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
    //删除该方法,不然会对传入对象造成污染(添加该方法)
    delete cxt[func];
    return res;
}

apply的基本概念

call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组

apply的用法

function zz(name, age) {
    console.log(this);
    console.log(name,age, this.name)
};
let a = {
    name: 234
}
zz.apply(a, ["abc", "2332"]);

apply 常见的案例

const arr = [10, 16, 23, 6, 16];
const max = Math.max.apply(Math, arr); // 23
const min = Math.min.apply(Math, arr); // 6

手写apply

Function.prototype.myApply = function(context,args = []){
    let cxt = context || window;
    //将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
    //新建一个唯一的Symbol变量避免重复
    let func = Symbol()
    cxt[func] = this;
    //以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
    const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
    delete cxt[func];
    return res;
}

bind的基本概念

bind的基础用法

const module = {
  x: 42,
  getX: function() {
    return this.x;
  }
};

const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42

bind的实现

Function.prototype.myBind = function (context, ...args) {
    //新建一个变量赋值为this,表示当前函数
    const fn = this
    //判断有没有传参进来,若为空则赋值[]
    args = args ? args : []
    //返回一个newFn函数,在里面调用fn
    return function newFn(...newFnArgs) {
        if (this instanceof newFn) {
            return new fn(...args, ...newFnArgs)
        }
        return fn.apply(context, [...args,...newFnArgs])
    }
}