JavaScript 的函数调用与 this
JavaScript 函数有多种调用方式,每种方式的不同在于函数内 this
的初始化。对 this
关键字有解释:* 一般而言,在 JavaScript 中,this
指向函数执行时的当前对象。* 注意 this
是保留关键字,你不能修改 this
的值。
作为一个函数调用
先看一个最简单的实例,在浏览器中:1
2
3
4function myFunction() {
return this;
}
alert(myFunction()); // [object Window]
而当函数没有被自身的对象调用时,this
的值就会变成全局对象。在 Web 浏览器中全局对象是浏览器窗口(window
对象)。该实例返回 this
的值是 window
对象。也就是此函数即为 window
对象的函数,myFunction()
等同于 window.myFunction()
。但是此处在使用内部函数时存在一个 this
指向的问题,看下面的例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22// 注意此处在Node环境和浏览器环境下值不同,
// Node环境下必须去掉var使value成为全局变量。
value = 4;
var myObject = {
value: 1,
double: function() {
//var that = this;
var helper = function() {
this.value = add(this.value, this.value);
};
helper();
}
};
function add(a, b) {
return a + b;
}
myObject.double();
alert(value); // 8
alert(myObject.value); // 1
在这里的 myObject
对象中,我们在 double
这个函数中使用了内部函数并赋值给 helper
,但是此处的 this.value
的 this
指向了全局对象,所以在执行这个函数后全局变量 value
的值变了但 Object
中的 value
属性值仍然是 1,这不是我们想要的结果。《JavaScript 语言精粹》中指出这里是语言设计上的一个错误,this
应该仍然绑定到外部函数的 this
变量中。这个设计错误的后果就是方法不能利用内部函数来帮助它工作,因为内部函数的 this
被绑定了错误的值,所以不能共享该方法对对象的访问权。但是我们可以有一个很容易的解决方案去解决这个问题,对 myObject
进行修改:1
2
3
4
5
6
7
8
9
10
11
12
13
14var myObject = {
value: 1,
double: function() {
var that = this;
var helper = function() {
that.value = add(that.value, that.value);
};
helper();
}
};
myObject.double();
alert(value); // 4
alert(myObject.value); // 2
这里使用了一个 that
变量来指向 double
方法中 this
的值即 myObject
本身,这样就可以对 myObject
对象的属性 value
进行修改。
函数作为方法调用
这种方式即为,一个函数被保存为一个对象的属性,在此时此函数被成为一个方法。调用时 this
关键字被绑定到该对象,即:函数作为对象方法调用,会使得 this
的值成为对象本身。实例如下:1
2
3
4
5
6
7
8var myObject = {
firstName: "John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName(); //返回 "John Doe"
另一个例子:1
2
3
4
5
6
7
8
9
10
11
12var myObject = {
value: 0,
increment: function (inc) {
this.value += typeof inc === 'number' ? inc : 1;
}
};
myObject.increment();
console.log(myObject.value); // 1
myObject.increment(2);
console.log(myObject.value); // 3
在此例中,increment
方法对 myObject
对象中的 value
属性进行增加操作,increment
函数中的 this
即指向 myObject
对象本身。