目录
前言
JavaScript中this关键字是一个非常重要的语法点,在面向对象语言中this表示当前对象的一个引用,但在JavaScript中this不是固定不变的,它会随着执行环境的改变而改变。也就是说,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁。
this的使用
方法中的this
在对象方法中,this指向调用它所在方法的对象。
例:
var obj = {
a: 3,
b: 4,
fn: function(){
return this.a+this.b;
}
}
console.log(obj.fn()); //7
在上述实例中,this指向obj对象,fn方法所属的对象就是obj。
单独使用this
单独使用this,则它指向全局对象。在浏览器中,Window就是全局对象。
例:
var a = this;
console.log(a); //Window
函数中this(默认)
在函数中,函数的所属者默认绑定到this上;在浏览器中,Window就是全局对象。
例:
function fn(){
return this;
}
console.log(fn()); //Window
函数中使用this(严格模式)
严格模式下函数是没有绑定到this上的,这时this是undefined。
例:
"use strict"
function fn(){
return this;
}
console.log(fn()); //undefined
事件绑定中的this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素。
例:
<button onclick="this.style.display='none'">点击消失</button>
对象方法中绑定this
例:
var obj = {
a: 3,
b: 4,
fn: function(){
return this;
}
}
console.log(obj.fn()); //obj
上面实例中,this指向obj对象,obj对象是函数fn的所有者。
构造函数中的this
无论函数是否做了绑定, 都要创建一个新的对象, 然后函数中的 this 引用这个对象。
例:
function fn(){
this.bar = 2;
}
var a = new fn();
console.log(a.bar); //2
为什么这里的this会指向a呢?这是因为new操作符会改变this的指向,将这个this指向对象a。那又为什么是对象a呢?因为用了new关键字就是创建一个对象实例,这里我们用变量a创建了一个fn实例,也就相当于复制了一份fn到对象a里面,此时仅仅只是创建,并没有执行,而调用这个函数fn的是对象a,那么this指向的自然就是对象a。
显式函数绑定this
在JavaScript中,函数也是对象,是对象就说明有方法,apply、call、bind就是函数对象的方法,这几个方法可以手动更改this的指向。
foo.call(obj, ...)
foo.apply(obj,[...])
foo.bind(obj,...)
之后会单独详细讲一下这几个方法。
理解this的原理
先来看下面几个例子。
例1:
function fn(){
var bar = 2;
console.log(this.bar);
console.log(this);
}
fn(); //undefined Window
window.fn(); //undefined Window
从例1可以看出,这里的函数fn是被Window对象所点出来的,this指向的是Window对象。
例2:
var obj = {
bar: 1,
fn: function(){
console.log(this.bar);
}
}
var fn = obj.fn;
var bar = 2;
obj.fn(); //1
fn(); //2
从例2代码中可以看到,this指向的是对象obj,并且obj.fn和fn都指向同一函数,fn函数被调用了两次,但是这两次的执行结果并不一样。这是因为obj.fn()是通过obj对象找到fn函数,所以就在obj环境下执行。一旦var fn = obj.fn,变量fn就会直接指向函数本身,所以fn()就变成在全局环境下执行。
例3:
var obj = {
bar: 1,
fn: function(){
console.log(this.bar);
}
}
var fn = obj.fn;
var bar = 2;
window.obj.fn(); //1
window.fn(); //2
例3和例2代码几乎一样,但是为什么这里的this不是指向window呢?不急,我们先来看看例4再进行理解。
例4:
var obj = {
bar: 1,
obj2:{
bar: 2,
fn: function(){
console.log(this.bar);
console.log(this);
}
}
}
obj.obj2.fn(); //2 obj2
在例4中,除了打印this.bar外,还添加了打印this,this指向的是obj2对象,这说明这里this指的是上一级的对象,当然,这是有前提的——含有this的函数在有被上一级对象所调用的前提下。
总结
1、如果一个函数中有this,但是它没有被上一级的对象所调用,那么this指向的就是Window,这里需要说明的是在js的严格模式中this指向的不是Window,而是undefined。
2、如果一个函数中有this,这个函数有被上一级的对象所调用,那么this指向的就是上一级的对象。
3、如果一个函数中有this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象。也就是说,this永远指向的是最后调用它的对象,要看它执行的时候是谁调用的。