前言
我们都知道这三种方法都用于绑定this,但没有区分好,很容易踩坑。继多次踩坑之后我又踩坑了,所以决定再次学习这种三种方法,并写下这篇文章,希望大家看了有所帮助,不再踩坑!
一.用法
我们先来简单看看三种方法的用法
-
call:
function a(arg){ console.log(arg) } a.call('this',1) //输出1
用法说明:fn.call(this,任何类型的参数),参数可为任何类型,数组非数组均可
ps:你是否知道如果我直接调用函数:a(参数),其实就等于a.call(window对象,参数),就是说所有函数调用我们平时写成:
fn(参数)
但其实是:
fn.call(this,参数),而this往往就是fn的调用对象,即a.fn()的this就是对象a,直接fn()默认就是window全局对象
-
apply:
function a(arg){ console.log(arg) } a.apply('this',[1,2]) //输出结果为1
用法说明:fn.apply(this,数组or类数组对象)
-
bind:
function a(arg){ console.log(arg) } var returnFn=a.bind('this',1); returnFn() //输出1
用法说明:fn.bind(this,任何类型的参数),不立即调用函数fn,返回一个已经绑定this(传入参数)的函数fn
三者区别,踩坑时刻!
重头戏来了!!!三者区别我们可以用call作为一个桥梁,依次与其它两者比较,至于为什么待会儿你就明白了;
踩坑时刻一:
- call与apply区别:从上述已说明的用法两者的直接区别就是:前者传入任何形式参数,后者传入数组或者类数组对象
你知道apply参数传入数组或类数组对象,那你知道它是怎么处理这些参数的吗,请看例子:
var b=[1,2]
function a(a,c){
console.log(a,c)
}
a.apply('this',b) //输出1 2 ,数组依次对应参数
var b=[1,2]
function a(a){
console.log(a)
}
a.apply('this',b) //输出1 数组被展开了,传入第一个值
function a(a){
console.log(a)
}
a.call('this',b) //输出[1,2]
- 说明:apply调用的时候会把数组or类数组展开,实参依次传入函数的形参,如果数目不一致,后面的实参就没有了!!!不过可以用函数的arguments对象来获得其余实参
踩坑时刻二:
-
call与bind区别:bind与call的参数是一样的,都可以是任何类型的参数,bind与call的直接区别就是bind绑定this之后不会立即调用函数,而是返回一个绑定了this的函数等待被调用,注意!此刻你需要一个变量去接受这个函数,否则就是下面的坑,这个坑就是我今天踩的!!!
var _this='bindthis' function a(a){ console.log(this) console.log(a) } var c=a.bind(_this,1) //定义变量c来接受这个返回的函数,并且等待被调用 c() //输出bindthis,1 //踩坑,错误范例 var _this='bindthis' function a(a){ console.log(this) console.log(a) } a.bind(_this,1) a() //window,undefined 调用的依然是全局变量中的函数a,而不是bind绑定this后返回的新函数
说明:怎么样,看完我踩的这个坑你是恍然大悟,哦~原来如此,还是觉得我很2很天真,233333。不管怎么样,这样的坑我们以后不要再踩了,call与bind的直接区别就是是立即执行还是返回一个函数等待执行?如果是后者记得用个变量接受一下
总结
1.函数这样调用a.fn(参数),其实是fn.call(a,参数),a就是this
2.call与apply:绑定this后都是立即执行,就是参数的区别,前者是任何形式的参数,后者是数组或类数组对象,你要注意apply对参数的处理,这个往往不太引起注意;
3.call与bind:参数都是一样的,区别就是是立即执行还是返回一个函数等待执行?如果是后者你要注意记得用个变量接受一下,不然一不小心容易从错
4.bind与apply:通过上面的比较,我们可以看出前者返回一个函数等待执行,后者立即执行;前者参数可以是任何形式,后者只能是数组或类数组对象