关于JavaScript中的this
this关键字是JavaScript中最复杂的机制之一。他是一个很特别的关键字,被自动定义在所有函数的作用域中。但是即使是非常有经验的JavaScript开发者来说也是很难说清楚它到底指向什么。
常见误区
- this指向函数本身
- this指向函数的作用域
首先我们来先看一段代码:
function foo(num){
console.log("foo:"+num);
this.count++;
}
foo.count=0;
for(var i=0;i<10;i++){
if(i>5){
foo(i);
}
}
//foo:6
//foo:7
//foo:8
//foo:9
console.log(foo.count);
//0
通过代码和输出的结果就可以看出来,foo()函数已经调用的4次,如果按照this指向函数本身的说法,foo.count++已经给对象foo添加了一个count属性,那foo.count的输出值就应该是4。显然foo.count的值并不是4。所以this指向函数本身的说法是错误的。
再来看下面的一段代码
function foo(num){
var count=0;
console.log("foo:"+num);
this.count++;
console.log(this.count)
}
for(var i=0;i<10;i++){
if(i>5){
foo(i);
}
}
//foo:6
//NAN
//foo:7
//NAN
//foo:8
//NAN
//foo:9
//NAN
console.log(count);
//NAN
如果this指向的是函数的作用域,那么this.count++,输出的结果应该是1,2,3,4而不是NAN。所以可以看出这里的this指向的并不是foo()的作用域。但是不得不说,这种说法会在某些情况下它是正确的,但是在有些情况它是错误。
那this到底是什么
this是在运行的时候进行绑定的,并不是在编写时绑定的,他的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。
当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息。this就是这个记录的一个属性,会在函数执行的过程中用到。
综上,this实际上是在函数被调用时发生的绑定,它的指向完全取决于函数在哪里被调用。
还是上面代码的例子,现在我们把var count=0,放在foo()的外面,在来看结果。
var count=0;
function foo(num){
console.log("foo:"+num);
this.count++;
console.log(this.count)
}
for(var i=0;i<10;i++){
if(i>5){
foo(i);
}
}
//foo:6
//1
//foo:7
//2
//foo:8
//3
//foo:9
//4
console.log(count);
//4
其实可以看出来this.count++,他所作用的就是window作用域下定义的count。window也就是调用foo的位置,显然这里的this指向的就是调用foo的位置。所以,就认证了“this实际上是在函数被调用时发生的绑定,它的指向完全取决于函数在哪里被调用。”。
//如果想了解函数执行过程中调用位置如何决定this的绑定对象,请看本人下面的文章。
//本人是一个前端菜鸟,是看了《你不知道的JavaScript》一书之后的个人理解,有些说的不对的地方,或是理解不到的地方,还请各位大佬指出。