所有函数或方法原型都是Function()函数的实例化对象;call()和apply(),bind()都是Function()上的方法,所以实例化的函数或方法都可以调用;他们都是用来改变this指向的;(在函数内部保存this指针,在需要的地方调用或者箭头函数都可以改变this的指向)
apply(),call()是函数调用的时候就立马改变this指向;而 bind方法会把要改变的this对象和参数值准备好,用到的时候再调用一下才行(在定时器中使用call、apply会首先调用一次,所以应该使用bind);apply的参数只能有两个第二个是要传的参数的数组,会默认一个一个展开传给函数;call有多个参数的时候只能一个一个 传进去,bind也要一个一个传
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//apply() var obj = { name:666, fn:function(a,b,c){ console.log(a,b,c,this) } } obj.fn.apply(window,[2,3,4]); //call() var obj = { name:666, fn:function(a,b,c){ console.log(a,b,c,this) } } obj.fn.call(window,2,3,4); //bind() var obj = { name:666, fn:function(a,b,c){ console.log(a,b,c,this) } } var ss = obj.fn.bind(window,2,3,4); ss() |
applay实现改变对象this指针的原理,就是改变对象的执行上下文环境位置。具体代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Function.prototype.myApply = function(context, argsArray) { context = context || window; const uniqueID = Symbol(); // 为context创建一个独一无二的属性名,以避免覆盖用户原有属性 context[uniqueID] = this; // 将当前函数赋值给context的这个属性;这里是核心。我们创建一个临时属性uniqueID用来接收当前执行上下文,这样当前对象的执行上下文就被强制改变成context上了 const result = context[uniqueID](...argsArray); // 调用函数 delete context[uniqueID]; // 删除临时属性 return result; }; // 示例 function greet(name) { console.log('Hello ' + name); } var person = { name: 'John' }; greet.myApply(person, ['Alice']); |