javascript中的this指向问题

    很多学java的同学在接触js之后使用this的时候都是懵逼的,这特么怎么回事,怎么老是给我报“Cannot read property 'xxx' of undefined”,我的this.xxx.xxx明明已经有值啊,为什么会出现这种情况。

    面对上面的问题,很多js的初学者都会很懵,不知道js的this为什么就不指向自己想要的那个this了。

  我以前也遇见过这种疑惑,直到我后来学习了一个大佬的博客(至于是谁的我还真忘了),我彻底弄懂了js的this为什么这么调皮了。

  在js中,函数的调用有三种方式:

  1. 直接调用:例如a(...params)

  2. 对象调用:例如obj.a(...params)

  3. new 函数调用:例如new A(...params)

  但其实这些都是语法糖。

  直接调用其实写完整就是:

a.call(undefined,...params)

  对象调用写完整是:

obj.a.call(obj,...params)

  而使用 new 调用函数的时候,例如

var a = new A(...params)

  其实写完整是:

  var a = {}

  a.call(a, ...params)

  a.__proto__ = A.prototype

  这就是this为什么会乱跳的根本原因所在。

  在js中,根据函数的调用方式不同,this的指向变化也不同:

  1. 直接调用函数,this指向全局:

  这里会因为环境不同而产生不同的结果:

   在严格模式下,this是undefined,但是我们大部分代码都是在非严格模式下写的,所以不探讨这个情况。

   在非严格模式下,浏览器环境下this会指向window,node环境中会指向global。

     以浏览器代码为例:

 function a(){
    console.log(this)
 }
 a() 

 显示结果是:

  

 这里出现的问题是最多的,因为很多时候函数都是直接调用的,所以this会直接指向window,导致取值错误。

 

 2.对象调用函数,this指向调用对象:

  先看代码:

const obj = {
    a:1,
    b: function (){
        console.log(this.a)
    }
}
obj.b()

  这个打印出来结果是1,毋庸置疑。因为这个this指向调用对象obj,所以this.a就是obj.a。

  再看一个代码:

const obj = {
    a:1,
    b:{
       a:2,
       b:function (){
           console.log(this.a)
       }
    } 
}
obj.b.b()

  这里打印的是多少呢。把代码在浏览器中运行一下:

   

  是2,因为obj.b.b()就相当于obj.b.b.call(obj.b),所以this指向obj.b,那么打印出来的自然是obj.b.a。

  再看一段代码:

var a = 'This is brower'
const obj = { a:1, b:function(){ console.log(this.a) } } const fn = obj.b fn()

  这里打印的是多少呢。把代码在浏览器中运行一下:

  这是为什么?

  这是因为fn = obj.b = function(){...},在这里的fn被赋值  function(){...},跟obj.b没有关系了,所以直接调用fn其中的this指向window,而window.a则是 'This is brower'。

  

 3. 使用构造函数调用,this 指向创建的对象:

  照例,先看代码:

function A(){
   this.a = 1
   this.b = 2  
}
var a = new A()
console.log(a.a)
console.log(a.b)

  这里打印出来的自然是1和2,因为new A()过程中将this指向了a。

  但是在这里有个坑,就是构造函数的返回值如果是引用类型的值就会引发错误,会直接将this指向返回的对象。

function A(){
  this.a = 1
  return {
     a:2
  }    
}
var a = new A()
console.log(a.a)

  在浏览器中运行查看结果:

  上图中可以看出,a指向的是A返回的对象,所以a.a打印出的是2。

  返回的如果是一个数组的话,a也会指向返回的数组,a.a就会打印出 undefined。

 

 在es6中出现了箭头函数,箭头函数中的this始终指向函数所处的块级作用域的this。

  看代码:

var a = 'This is window'
const obj = { a: 1, b: () => { console.log(this.a) } } obj.b()

  上答案:

  是不是又懵了,明明是obj调用的,但是this却指向了window。

  这就是箭头函数的优点,因为它的this指向是固定的,永远指向所处的块级作用域内部的this。

  在这里obj.b所处的块级作用域就是全局,所以其中的this指向window。

  再来一段代码:

function a(){
  this.a = 10
  return {
    a:1,
    b:()=>{
      console.log(this.a)
    }
  }  
}    

const obj = a()
obj.b()

  继续直接上答案:

  这次差不多懂了吧,这个箭头函数创建的时候是处于方法 a 的作用域内部的,所以箭头函数内部的this始终指向方法 a 中的this。

 

 上述就是我在学习js中的this时遇到的所有关于this的调用的问题,估计应该可能大概差不多maybe是有没有涉及到的,但是关于this的这些差不多够了。

posted @ 2018-10-22 17:41  行骗艺术家  阅读(273)  评论(1编辑  收藏  举报