call() , apply() 与 bind() 详解
我们知道可以用call()
, apply()
和 bind()
这三个函数都是用来完成函数调用,并且设置this指向。 call()
和apply()
是 ECMAScript3 标准引入,而bind()
函数则是在 ECMAScript 5 引入。 这边文章会用几个小例子来回忆一下他们之间有什么不一样。
用法
call()
和apply()
会立即调用函数, 而bind()
只会返回一个函数引用,当后面真正调用返回的函数的时候,函数里面的this将会指向给bind()
函数传入的参数,并在调用新函数时,将给定参数列表作为原函数的参数序列的前若干项, 所以 bind()
函数非常适合在事件回调的时候修改this 指向, 有React 经验的朋友应该会有更深的感受。
call()
var dist = 'Beijing';
function greet(name, hometown) {
var word = `Welcome ${name} from ${hometown} to ${this.dist}!`
console.log(word);
}
var obj1 = {
dist: 'Chengdu'
};
greet.call(obj1, "Tom", "Dallas"); // Welcome Tom from Dallas to Chengdu!
greet("Jerry", "Houston"); // Welcome Jerry from Houston to Beijing!
因为greet.call(obj)
传入了obj1作为第一个参数,所以在 greet()
函数执行时, this指向 obj1
。其余的参数就将作为参数传给greet()
函数。
当没有使用call()
而直接调用greet()
时, this指向 window
对象.
apply()
var dist = 'Beijing';
function greet(name, hometown) {
var word = `Welcome ${name} from ${hometown} to ${this.dist}!`
console.log(word);
}
var obj1 = {
dist: 'Chengdu'
};
var args = ["Tom", "Dallas"];
greet.apply(obj1, args); // Welcome Tom from Dallas to Chengdu!
greet("Jerry", "Houston"); // Welcome Jerry from Houston to Beijing!
apply()
函数和call()
函数非常的相似,第一个参数都用来设置目标函数运行时的this指向。 唯一的区别就是 apply()
的第二个参数接受一个数组, 其他表现则一样。
bind()
var dist = 'Beijing';
function greet(name, hometown) {
var word = `Welcome ${name} from ${hometown} to ${this.dist}!`;
console.log(word);
}
var obj1 = {
dist: 'Chengdu',
};
var obj2 = {
dist: 'Chongqing',
};
var greet1 = greet.bind(obj1, 'Tom', 'Dallas');
var greet2 = greet.bind(obj2, 'Spike', 'San Antonio');
greet('Jerry', 'Houston');
greet1();
setTimeout(function() {
greet2();
}, 1000);
这个例子会更加复杂一点, 输出结果如下:
Welcome Jerry from Houston to Beijing!
Welcome Tom,Dallas from undefined to Chengdu!
Welcome Spike,San Antonio from undefined to Chongqing!
在上面例子中, bind()
函数并不会立即执行目标函数, 而是返回了一个函数的拷贝,但this会指向bind()
的第一个参数,其余传给bind()
的参数都会按顺序传给返回的函数。我们就可以异步调用这个函数返回值了。但是需要注意的是,bind()
方法返回的函数拷贝在使用 new 操作时, 第一个参数是会被忽略的。
那么新的问题又来了, 如果在调用返回的函数拷贝的时候, 又传入了新的参数, 会发生什么呢, 只有再写一个例子试试了。
var obj1 = {
dist: 'Chengdu',
};
function greet(name, hometown) {
console.log(Array.prototype.slice.call(arguments));
var word = `Welcome ${name} from ${hometown} to ${this.dist}!`;
console.log(word);
}
var greet1 = greet.bind(obj1, 'Tom', 'Dallas');
greet1('Jerry', 'Houston');
输出的结果为:
[ "Tom", "Dallas", "Jerry", "Houston" ]
Welcome Tom from Dallas to Chengdu!
结果证明两个地方传入的参数都会被传给目标函数,函数拷贝调用时传入的参数会追加在bind()
函数调用时传入的参数后面。
以上就是所有关于 call()
, apply()
和 bind()
三个函数的实例了。大家有什么疑问建议留言讨论。
网友评论