全局执行

  1. console.log(this)
  2. //window

在浏览器中直接打印this, this指向的是window。

函数中执行

在纯函数中调用

  1. function foo(){
  2. console.log(this)
  3. }
  4. foo() //window

调用foo函数,this指向的是window,因为foo函数是在全局作用域中被调用的,所以this指向window。

严格模式下 ‘use strict’

  1. 'use strict'
  2. function foo(){
  3. console.log(this)
  4. }
  5. foo() //undefined

在严格模式下,this指向的是undefined,而不是全局,这是因为在严格模式下,会消除一些js的不严谨的行为。

作为对象的方法被用

  1. var obj = {
  2. name: 'zhang',
  3. foo: function(){
  4. console.log(this)
  5. }
  6. }
  7. obj.foo() //obj

代码执行完毕,我们发现 this指向的是obj,当一个函数被一个对象当做方法来调用的时候,this指向当前的这个对象。

下面我们把上面的例子稍微修改一下

  1. function test(){
  2. console.log(this)
  3. }
  4. var obj = {
  5. name: 'zhang',
  6. foo: test
  7. }
  8. obj.foo() //obj

代码执行我们会得到相同的结果,因为js中一切皆是对象,这里的test函数也是一个对象,对于test它只是一个函数名,foo引用了test函数,foo指向test函数的地址。

下面我们把对象的方法赋值给一个变量,看看会发生什么?

  1. var obj = {
  2. name: 'zhang',
  3. foo: function(){
  4. console.log(this)
  5. }
  6. }
  7. var test = obj.foo
  8. test() //window

代码执行显示this指向window, 我们定义的变量test指向obj.foo函数,因为test是全局下的,所以会指向this。

好,到这里,我们发现了this的指向永远都是最后调用它的那个对象

下面来看在回调函数中遇到的一些坑

  1. var obj = {
  2. name: 'zhang',
  3. foo: function(){
  4. console.log(this)
  5. },
  6. foo2: function(){
  7. console.log(this)
  8. setTimeout(this.foo,1000)
  9. }
  10. }
  11. obj.foo2() // obj window

代码执行的结果是:第一个是obj, 第二个是window;下面主要分析一下window是怎么回事?
setTimeout作为函数需要参数this.foo,this.foo作为参数在传参的时候,是把this.foo的引用给到了此处的函数参数,这个引用跟obj就没有关系了,只是作为一个存函数在执行,因此调用的是全局对象this。

要解决这个问题,可以如下操作

  1. var obj = {
  2. name: 'zhang',
  3. foo: function(){
  4. console.log(this)
  5. },
  6. foo2: function(){
  7. console.log(this)
  8. var _this = this
  9. setTimeout(function(){
  10. console.log(this)
  11. console.log(_this)
  12. },1000)
  13. }
  14. }
  15. obj.foo2() // obj window obj

我们可以看到setTimeout中的this依然指向window, 在foo2中的我们定义一个_this来储存this,此时this指向obj, 当我们在setTimeout中的_this就指向obj了。

用箭头函数我们也可以解决这个问题,看代码,这里我就只写foo2函数了

  1. foo2:function(){
  2. console.log(this)
  3. setTimeout(() => {
  4. console.log(this)
  5. },1000)
  6. }
  7. obj.foo2() //obj obj

通过使用箭头函数我们也可以得到setTimeout中的this指向obj了。
关于箭头函数中的this只和他定义时候的作用域的this有关,与在哪里一级如何调用无关,同时它this的指向是不变的。

箭头函数中的this

我们看下箭头函数中的this可以更改吗?

  1. var afoo = a => {
  2. console.log(a)
  3. console.log(this)
  4. }
  5. afoo(1) //1 obj
  6. var obj = {
  7. name: 'zhang'
  8. }
  9. afoo.call(obj,2) //2 window
  10. afoo.apply(obj,[3])//3 window
  11. afoo.bind(obj,4)() //4 window

通过例子我们可以发现,箭头函数中的this只跟它定义时候所在的作用域的相关,跟在哪里调用一级如何调用无关,同时call、apply、bind也无法改变this的指向。