前端面试题javascript篇——call-apply-bind

264 阅读2分钟

call-apply-bind三者的作用,区别以及内部实现

1. call-apply-bind三者的作用

在JavaScript中,call-apply-bind是Function对象自带的三种方法,它们的作用都是用来改变函数内的this指向,传递的第一个参数都是this所要指向的对象,而且它们三个都可以传递参数(后续传值)。

2. call-apply-bind三者的区别

  • call:调用一个对象的一个方法,用另一个对象替换当前对象,在传递参数的时候需要一个一个进行传递,而且定义完立即执行,返回值为调用方法的返回值,如果调用的方法没有返回值,则返回undefined

    obj.call(obj1,arg1,arg2,arg3....);

  • apply:和call很类似,都是立即执行,返回值为调用方法的返回值,如果调用方法没有返回值,则返回undefined,唯一不同的是,apply在传递参数的时候需要以数组的形式

    obj.apply(obj1,[arg1,arg2,arg3.....]);

  • bind:除了返回值是函数以外,它在传递参数的时候和call一样,都是一个一个传递,它在调用之后返回一个新的函数,不会立即执行

    obj.bind(obj1,arg1,arg2,arg3...)();

3. call-apply-bind三者的内部实现

在内部实现的时候,需要把函数绑定在Function原型上,是原型上面的方法
  • call

    Function.prototype.myCall = function(context = window, ...args) { if (this === Function.prototype) { return undefined; //判断当前this是否为函数,用于防止Function.prototype.myCall()直接调用 } context = context || window; //context为可选参数,如果不传的话,默认指向window const fn = Symbol(); //利用symbol进行定义,可以保证不会重名 context[fn] = this; //将当前函数赋给这个属性,这样之后执行context[fn]的时候,fn里面的this指向就为context了 const result = contextfn; delete context[fn]; //调用完后立即删除symbol属性 return result; }

    //调用 let person1 = { name:'王', age:18, say(...args){ console.log(名字为${this.name},年龄为${this.age},参数为${args}); } } let person2 = { name:'李', age:20 } person1.say.myCall(person2,1,2,3);

    //输出 名字为李,年龄为20,参数为1,2,3

  • apply

    Function.prototype.myApply = function(context = window,args){ if(this === Function.prototype){ return undefined; } context = context || window; const fn = Symbol(); context[fn] = this; let result; if(Array.isArray(args)){ result = contextfn; }else{ result = contextfn; } delete context[fn]; return result; }

    //调用 let person1 = { name:'王', age:18, say(...args){ console.log(名字为${this.name},年龄为${this.age},参数为${args}); } } let person2 = { name:'李', age:20 } person1.say.myApply(person2,[1,2,3]);

    //输出 名字为李,年龄为20,参数为1,2,3

  • bind

    Function.prototype.myBind = function(obj,...args){ let self = this; return function(){ let newArgs = args.concat(...arguments); self.call(obj,newArgs); } }

    //调用 let person1 = { name:'王', age:18, say(...args){ console.log(名字为${this.name},年龄为${this.age},参数为${args}); } } let person2 = { name:'李', age:20 } person1.say.myBind(person2,1,2,3)(4,5);

    //输出 名字为李,年龄为20,参数为1,2,3,4,5