call、apply、bind 的用法和区别
首先:call、apply、bind的作用是改变函数运行时的this的指向
var zr = {
a: 1,
fn: function () {
console.log(this.a); //1
}
}
zr.fn();
//相当于zr.fn.call(zr)或者zr.fn.apply(zr);
var zr = {
a: 1,
b: {
a: 2,
fn: function () {
console.log(this.a);
}
}
}
//this指向zr对象中的b,所以打印的是this上一级对象,所以输出2
zr.b.fn(); //2
//此处使用call或者apply函数 把this从指向b改变为指向zr
console.log(zr.b.fn.call(zr)) //1
console.log(zr.b.fn.apply(zr)) //1
//也就相当于是变成了
var zr = {
a: 1,
fn: function () {
console.log(this.a); //1
}
}
//由于普通函数(没有父级对象)没有任何调用,所以其this就指向window;
function zr() {
var username = "睿睿";
console.log(this.username); //undefined
console.log(this); //Window
}
zr();
//相当于zr.call(undefined)
所以setTimeout作为一个普通的回调函数,其this是指向window;这就是setTimeout()丢失this的原因;所以在使用setTimeout()的时候:var _this=this;
接下来进入正题
call()可以传n个参数,但是第一个参数是this将要指向的对象 当第一个参数为null或者undefined的时候,this默认指向window;之后的参数相当于普通传参一样自定义使用;
apply()只可以传俩个参数,第一个参数和call()的第一个参数一样,是this将要指向的对象;当第一个参数为null或者undefined的时候,this默认指向window;;第二个参数是一个数组,相当于把call()除第一个参数外的所有参数放到一个数组中;
var zr = {
a: 1,
b: {
a: 2,
c: {
a: 3,
fn: function (x , y) {
console.log(this.a);
console.log(x+y);
}
}
}
}
//此处使用call或者apply函数 把this从指向c改变为指向b
zr.b.c.fn.call(zr.b ,1 , 2) //2 3
zr.b.c.fn.apply(zr.b ,[1 , 2] ) //2 3
//此处使用call或者apply函数 把this从指向c改变为指向zr
zr.b.c.fn.call(zr ,1 , 2) //1 3
zr.b.c.fn.apply(zr ,[1 , 2] ) //1 3
//此处使用call或者apply函数 第一个参数传null,this默认指向window
zr.b.c.fn.call(null ,1 , 2) //undefined 3
zr.b.c.fn.apply(null ,[1 , 2] ) //undefined 3
其实apply() 和 call() 的用法基本上相同, 唯一的差别就是:当函数需要传递>1个变量时, apply() 可以接受一个数组作为参数, call() 必须接受>1个的单独变量。
bind()的传参方式和call()很相似,第一个参数是this将要指向的对象,第一个传null得话不改变this指向,并且可以在后续的调用中去传入参数
//后续的调用中去传入参数
function zr(a, b, c) {
return a * b * c;
}
var fn = zr.bind(null, 2);
//相当于
//function fn(2, b, c) {
//return 2 * b * c;
//}
console.log(fn(3, 4));//24
//相当于
//function fn(2, 3, 4) {
//return 2 * 3 * 4;
//}
//bind()返回的一个改变了 this 之后的新函数;原函数zr中的this并没有改变;
var obj = {
username:'睿睿'
}
function zr () {
console.log(this.username)
}
var bindfn =zr.bind(obj)
bindfn()//睿睿
//zr () {
//console.log(this.username)
//}