谈谈JavaScript中的this关键字

Java 语言当中也有this关键字,而 JavaScript 语言当中的this关键字因为具有运行期绑定的特性,JS 当中的这个this关键字的含义要丰富的多。现在来看看这个this到底有啥奥秘……

运行环境

this关键字指定的对象具体是指什么,这完全取决于函数的调用方式,JavaScript 中的函数的调用有以下几种方式:

  • 作为函数调用
  • 作为对象方法调用
  • 作为构造函数调用

作为函数调用

1
2
3
4
5
var n = "Hello World!";
function example(){
console.log(this.n);
}
example(); //Hello World!
1
2
3
4
5
6
var n = 'Hello World!';
function example(){
this.n=0;
}
example();
console.log(n); //0

我们通过上面的两个例子,我们可以明确知道:当函数直接调用时,该函数的this关键字指向的就是全局对象window。此时上面例子的全局变量n其实就是window.n

作为对象方法调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function getAge(){
var y = new Date().getFullYear();
return y - this.birth;
}

var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};

console.log(xiaoming.age());//27
console.log(getAge()); //NaN

var fn = xiaoming.age;
console.log(fn()); //NaN
1
2
3
4
5
6
7
8
9
10
11
12
var name = 'Akita';
var dogs = {
name:'Collie',
showName: function(){
console.log(this.name);
}
};

console.log(dogs.showName()); //Collie

var otherNmae = dogs.showName;
console.log(otherName()); //Akita

如上面所示代码,当使用obj.xxx()的形式调用函数时,里面的this关键字指向的就是对象本身。但是我们还需要注意一点就是:在对象方法内部再次定义一个方法,该方法的this关键字又会重新指向全局对象window!如下代码所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
var xiaoming = {
name: '小明',
birth: 1990,
age: function(){
function getAgeFromBirth(){
var y = new Date().getFullYear();
return y - this.birth;
}
return getAgeFromBirth();
}
};

console.log(xiaoming.age()); //NaN

由于这是 JavaScript 一个巨大的设计错误。ECMA 决定在 strict 模式下(就是开头声明'use strict';)让函数的this指向undefined。因此,在 strict 模式下你会得到的错误就不是 NaN,而是TypeError:Cannot read property 'birth' of undefined

作为构造函数调用

1
2
3
4
5
function Student(name){
this.name=name;
}
var xiaoming = new Student('小明');
console.log(xiaoming.name); //小明

上面这段代码中我们通过构造函数构造了一个新的对象xiaoming,那么this就会指向这个对象。

指定 this 指向

虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefinedwindow,不过,我们还是可以控制this的指向的!

要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。

apply修复getAge()调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}

var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};

xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25

此时利用apply()getAge()this指向了xiaoming这个对象,因此函数执行正确。

参考

  1. 方法 - 廖雪峰的官方网站

  2. Javascript 深入浅出this

本文作者:刘志宇

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!

Donate comment here