在javascript里面,this是一个特殊的对象,它不像其他编程语言那样,是存储在实例中的值,直接指向此实例。
而是作为一个单独的指针,在不同的情况之下,指向不同的位置,这也是为什么我们会将它搞混的原因。
下面我们来看下,它在不同情况下分别是怎样一种形态
1.在全局作用域时:
这个是最好理解的,即在全局作用域下this指向window,也就是在全局作用域下,this与window是等价的:
1
|
console.log( this === window); //true |
另外,由于在此时,this等价于window,所以我们在全局作用域声明的变量也会指向this:
1
2
3
|
var x = 1; console.log( this .x); //1 console.log(window.x); //1 |
当然,我们还有另一种声明变量的方法:
1
2
3
4
5
6
7
|
x = 0; function setNum(){ x = 1; }; console.log( this .x); //0 setNum(); console.log( this .x); //1 |
当声明变量时不使用 var 或者 let的话 此时相当于给全局的this添加或者改变属性值
看起来还是很简单的,不就是个等价于window的对象么。
当然,如果仅仅是这样,this或许根本就没有存在的必要了。
而this最让人头疼的部分就是它在不同的作用域下,它的形态也是截然不同的
2.当在函数中时:
到这里时,this的陷阱已经渐渐显露出来了
这里为什么说是当在函数中而不是局部作用域时,要讲这个,首先我们要清楚function是什么
在javascript中,function作为js中的一个特殊对象:函数,是有着不同的形态的
我们通常看到的:
1
2
3
|
function set(){ var x = 0; }; |
在这一形态下,其内部的this是与全局作用域时一样,直接指向window,所以其形态 依然等价于window。
1
2
3
4
5
6
7
|
var x = 0; function num(){ this .x = 1; } console.log( this .x); //0 num(); console.log( this .x); //1 |
这里就是经常容易犯得错误,很多人觉得,当this已经在一个function之中时,其目前所处位置为当前的局部作用域,所以目前指向的应该是此函数
但是,如果你将这个函数实例化(new)之后,此函数将生成一个全新的环境,此时在此实例中的this也会随之发生变化,它将指向所在实例。
1
2
3
4
5
6
7
8
|
num = "0" ; function setThis(){ this .num = "1" ; } console.log( this .num); //"0" new setThis(); console.log( this .num); //"0" console.log( new setThis().num); //1 |
这是因为,当实例化之后,此函数变成了一个实例对象,而其内部的this也自然而然的指向了此实例对象,如同一开始的this是指向window的对象一样指向了它所在的实例
另外,在我们写javascript的时候,我们通常还会有一种调用函数的方法,即为元素绑定事件,比如button.addEventListener(‘click',
fn, false)等,如果在fn里面需要使用到this的话,那么此时this指向事件处理元素,也就是button
注意:this作为关键字,你是无法复写它的。
3.总结:
1. 在全局作用域中(所有函数外)出现的this,指全局对象。
在浏览器中就是window对象。
2. 在函数内部出现的this,指什么要看这个this所在的函数的被调用方式。
不论这个this出现在什么样的函数中,层次有多深,结构多复杂,只要看直接包含它的函数即可。例如:
func();
new func();
A.func();
func.apply(B, [m, n, ...]);
func.call(B, m, n, ...);