理解JavaScript中call()、apply()、bind()的方法

前言

首先,值得一提的是js中call()、apply()和bind()这三种方法是继承于Function.prototype中的实例方法,它们的作用都可以改变函数的调用对象(改变函数运行时上下文),也就是可改变函数体内this的指向,而this的指向只有当函数被调用时才可被确定指向谁(此处若不了解js中this指向问题,可自行百度查询),最后的返回值是调用方法的返回值,若没有返回值,则返回undefined,这三种实例方法同时也可简化代码的调用。


先来看看下面的几个例子:

例 1:

var name = '李四';
function one() {
	var name = '张三';
	console.log(this); // Window
    console.log(this.name); // 李四
}
one();

从上面代码可以看出此时的this指向是Window对象(严格模式),Window是js中的全局对象,this.name指向的是全局变量。

例 2:

var a = {
	name: '张三',
	fn: function() {
		console.log(this.name); // undefined
	}
}
var b = a.fn;
b();

例 3:

var a = {
	name: '张三',
	fn: function() {
		console.log(this.name); // 张三
	}
}
a.fn();

从例2和例3可以看出,我们只能通过a.fn()方式达到所预期的效果,因为在例3中this的指向是函数a,a中存在name属性,而在例2中this的指向是函数b,此时函数b中并没有this.name,所以例2中会出现undefined的结果。但有时我们也需要将对象赋值于一个变量,此时我们就可以通过以下的call()、apply()、bind()方法来改变this的指向,从而达到预期的结果。

  • call()方法

call()方法可以用来调用函数,改变this的指向,实现继承,调用其他对象中的方法,并会立即执行当前函数,call()方法中第一个参数是this的指向对象,第二个第三个或第n个参数用逗号隔开指函数中需传递的参数。

/* call() 方法-无参实例 */
var name = '小小';
var age = 10;
var test = {
	name: '张三',
	age: 18,
	foo: function() {
		console.log(this.name + ' ' + this.age);
	}	
}
var result = {
	name: '李四',
	age: 19
}

test.foo();                // 张三 18
test.foo.call(result);     // 李四 19
test.foo.call(null);       // 小小 10
test.foo.call(undefined);  // 小小 10
test.foo.call({});         // undefined undefined

var way = test.foo;
way();                     // 小小 10
way.call(result);          // 李四 19
way.call(test);            // 张三 18
/* call() 方法-有参实例 */
var person = {
	name: '张三',
	age: '18',
	foo: function(a, b, c) {
		console.log(a,b,c);
	}
}

var student = {
	name: '李四',
	age: 19
};

person.foo();                       // undefined undefined undefined
person.foo.call(student, 1, 2, 3);  // 1 2 3

var foo = person.foo;
foo.call(student, 1, 2, 3);         // 1 2 3

从上述实例中可看出call中若不传参或传入null、undefined时(非严格模式下),this指向window,若传入空对象时,返回undefined,同时call方法在接受参数时可接受参数列表,并立即执行第一个参数指向的函数。

  • apply()方法

apply()方法和call()方法作用类似,可改变this指向,可继承其他对象的方法,被调用的方法函数会被立即执行,只是call()方法接收的参数是列表,而apply()方法接收的参数是数组。

/* apply() 方法-无参实例 */
var name = '小小';
var age = 10;
var test = {
	name: '张三',
	age: 18,
	foo: function() {
		console.log(this.name + ' ' + this.age);
	}	
}
var result = {
	name: '李四',
	age: 19
}

test.foo();                 // 张三 18
test.foo.apply(result);     // 李四 19
test.foo.apply(null);       // 小小 10
test.foo.apply(undefined);  // 小小 10
test.foo.apply({});         // undefined undefined

var way = test.foo;
way();                     // 小小 10
way.call(result);          // 李四 19
way.call(test);            // 张三 18
/* apply() 方法-有参实例 */
var person = {
	name: '张三',
	age: '18',
	foo: function(a, b, c) {
		console.log(a,b,c);
	}
}

var student = {
	name: '李四',
	age: 19
};

person.foo();                       // undefined undefined undefined
person.foo.apply(student, [1, 2, 3]);  // 1 2 3

var foo = person.foo;
foo.apply(student, [1, 2, 3]);         // 1 2 3

从上面代码可以看出apply()方法在不传参时和call()方法类似,当传参时则需传入一个数组。

  • bind()方法

bind()方法可以改变函数内部的this指向,但会返回一个新函数,函数不会被立即执行,需再次调用才能被执行。

/* bind() 方法-无参实例 */
var name = '小小';
var age = 10;
var test = {
	name: '张三',
	age: 18,
	foo: function() {
		console.log(this.name + ' ' + this.age);
	}	
}
var result = {
	name: '李四',
	age: 19
}

test.foo();                  // 张三 18
test.foo.bind(result)();     // 李四 19
test.foo.bind(null)();       // 小小 10
test.foo.bind(undefined)();  // 小小 10
test.foo.bind({})();         // undefined undefined

var way = test.foo;
way();                       // 小小 10
way.bind(test)();            // 张三 18

var outcome = way.bind(result);     
outcome();                   // 李四 19
/* bind() 方法-有参实例 */
var person = {
	name: '张三',
	age: '18',
	foo: function(a, b, c) {
		console.log(a,b,c);
	}
}

var student = {
	name: '李四',
	age: 19
};

person.foo();                         // undefined undefined undefined
person.foo.bind(student, 1, 2, 3)();  // 1 2 3

var foo = person.foo;
var result = foo.bind(student, 1);      
result(2, 3);                         // 1 2 3

从上面代码可以看出bind 不会像call()和apply()方法一样调用后立即执行,它需要单独再调用bind()()方法才可被执行。


总结

call、apply、bind三者的区别:

  1. call、apply、bind三者都可以改变函数(函数执行时所在的作用域)的this指向。
  2. call、apply、bind三者都可传递参数,其第一个参数都是this所指向的对象,call和bind的第二个第三个或第n个参数需用逗号隔开依次直接传递,而apply后面的参数需要放入一个数组中进行传递。
  3. apply和call会立即执行调用的函数,而bind会返回一个新函数,需再次调用才会被执行。
  4. 当确定函数中传递参数个数时,可选用call()方法;当不确定函数中传入的参数个数时,可选用apply();当不需要立即调用函数时,可选择bind()方法。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值