JavaScript系列:浅析apply和call

  • 白小霁
  • 10 Minutes
  • April 18, 2017

apply、call 有什么作用,什么区别?

两者都可以特殊化设置传入函数执行上下文(个人理解就是所处环境的变化,就是传入对象直接替代window的环境),这样设置this值的作用。
区别:
两者的参数设置不一样,在call中第一个参数是设置this的值,而如果该函数如含有若干个参数,就以参数列表的形式去写入,如:

1
2
3
4
5
6
7
8
9
10
var obj = {
name : "Kevin",
fn : function(name,age){
this.name = name;
this.age = age;
console.log(this);
}
}
var fn2 = obj.fn;
fn2.call(obj,"baiji",12);

如果理解了上述环境,那apply就更好理解了,apply同样的第一个参数是设置this的值,但想将参数传入的写法则是以一个参数数组的方式写入。

1
2
3
4
5
6
7
8
9
10
var obj = {
name : "Kevin",
fn : function(name,age){
this.name = name;
this.age = age;
console.log(this);
}
}
var fn2 = obj.fn;
fn2.apply(obj,["baiji",12]);

代码

1. 以下代码输出什么?

1
2
3
4
5
6
7
8
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func // Func 绑定到了john.sayHi上
john.sayHi() // 弹出"John: hi!",因为这时候this指向jhon

2. 下面代码输出什么,为什么?

1
2
3
4
func() // 弹出object window,等同于window.func();
function func() {
alert(this)
}

3. 下面代码输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function fn0(){
function fn(){
console.log(this);
}
fn();
}
fn0(); //window 还是window调用了fn0()函数
document.addEventListener('click', function(e){
console.log(this); // document DOM中谁绑定,this就是谁
setTimeout(function(){
console.log(this); // window,定时器会排队列的最后,最后还是window调用这个定时器
}, 200);
}, false);

4. 下面代码输出什么,why?

1
2
3
4
5
6
7
8
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) // alert("Jhon")

因为就想开头的解释到,call的第一个参数就是设置this的指向。

5. 代码输出?

1
2
3
4
5
6
7
8
9
10
var john = {
firstName: "John",
surname: "Smith"
}
function func(a, b) {
alert( this[a] + ' ' + this[b] )
}
func.call(john, 'firstName', 'surname')
// alert( "Jhon Smith"); 执行上下环境在john中

6. 以下代码有什么问题,如何修改?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指 $btn
this.showMsg(); // 由于$btn 没有showMsg属性,会报错
})
},
showMsg: function(){
console.log('饥人谷');
}
}
// 修改
var module= {
bind: function(){
var temp = this;
$btn.on('click', function(){
console.log(temp)
temp.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}