call、apply、bind都是改变this指向的方法
1、call
fn.call(fn的this关键字,参数) : 执行函数fn,并传参,同时指定函数fn的this。
函数fn通过原型链的查找机制,找到
function.prototype
上的call
方法。举例:fn.call(obj, 1, 2, 3);
1) 非严格模式
如果不传参数,或者第一个参数是
null
或nudefined
,this
都指向window
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b:undefined
fn.call(); // this:window a:undefined b:undefined
fn.call(null); // this=window a=undefined b=undefined
fn.call(undefined); // this=window a=undefined b=undefined
2)严格模式
第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined
"use strict"
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b=undefined
fn.call(); // this:undefined a:undefined b:undefined
fn.call(null); // this:null a:undefined b:undefined
fn.call(undefined); // this:undefined a:undefined b:undefined
2、apply
和call基本上一致,唯一区别在于传参方式,apply通过数组传参。
apply把需要传递给fn的参数放到一个数组(或者类数组)中传递进去,虽然写的是一个数组,但是也相当于给fn一个个的传递
fn.call(obj, 1, 2);
fn.apply(obj, [1, 2]);
3、bind
语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8。
call:改变函数的this,立即执行函数
bind:改变函数的this,返回对应函数,便于稍后调用执行
fn.call(obj, 1, 2); // 改变fn中的this,并且把fn立即执行
fn.bind(obj, 1, 2); // 改变fn中的this,fn并不执行,而是返回函数fn
使用call:this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候,fn已经执行完毕,执行的是fn的返回值undefined
document.onclick = fn.call(obj);
使用bind:会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行
document.onclick = fn.bind(obj);
4、call、apply、bind的区别
1)相同点:
- call,apply,bind的第一个参数都是this要指向的对象
2)不同点:
- bind是返回对应函数,便于稍后调用,call与apply是立即调用
- bind会产生新的函数,(把对象和函数绑定死后,产生新的函数)
- call和apply不会产生新的函数,只是在调用时,绑定一下而已
- call传递参数是按顺序传入,apply是把参数放入数组中