apply、call和bind的区别
1、相同点:
这三个的作用就是改变他们前面的函数执行时的上下文,即改变函数运行时的this指向,第一个参数都表示是this的指向,在this为null或者为undefined的时候,this默认指向window。
2、不同点:
apply的第二个参数是函数执行时传入的参数,apply时以数组的方式传入,一次传多个参数,只传一次,且函数是立即执行。
call 的第二个参数在函数执行的时候以参数列表的形式传入,一次传多个参数,只传一次,函数时立即执行的。
bind的第二个参数是动态传递参数,可以分多次传,但不会立即执行, 且会返回一个函数。
1 2 3
| fn.bind(obj,1,2); 或者 fn.bind(obj,1)(2)
|
实现apply、call和bind
简单说一下他们的实现原理,fn.call(o) 它的实现原理就是o上定义一个新的属性m,m的值为要执行的这个函数fn,
即 :o.m=fn; 执行这个函数 fn(); 最后删除m这个属性。
那么这个函数是怎么获取呢,可以通过this来获取,this指向这个调用的函数fn
Function.prototype.apply()
1 2 3 4 5 6 7 8 9 10
| Function.protoptype.apply=function(context=window, args){ if(typeof this!='function'){ throw new TypeError('type errror'); //因为this要指向apply前面要调用的函数,所以必须是一个函数 } const fn = Symbol('fn');//保证fn作为属性时的唯一性 context[fn] =this;//this获取调用apply的函数(this会指向调用它的对象,所以会获取到到调用函数),fn是执行上下文的一个属性,这样能够保证fn的作用域是在context中的,从而实现传入context的绑定。 let result = contetx[fn](..args);//将参数传进去然后执行 delete contet[fn]; //删除新建的属性; return result;//将调用的结果返回回去 }
|
Function.prototype.call()
1 2 3 4 5 6 7 8 9 10 11 12
| //传入的参数是参数离列表 Function.prototype.call = function(context,=window, ...args){ if(typeof this !="function"){ throw TypeError('type error!'); }
const fn = Symbolp('fn');//此属性不可更改 context[fn]= this; let result = context[fn](..args); delete context[fn]; return result; }
|
Function.prototype.bind()