理解js中this的指向

this 的指向在函数定义的时候是肯定不了的,只有函数执行的时候才能肯定this到底指向谁,实际上 this 的最终指向的是那个调用它的对象,深刻的探讨这个问题。javascript

为何要学习this?若是你学过函数式编程,面向对象编程,那你确定知道干什么用的,若是你没有学过,那么暂时能够不用看这篇文章,固然若是你有兴趣也能够看看,毕竟这是 js 中必需要掌握的东西。html

例子 1:

function a() {
  var user = "追梦子";
  console.log(this.user); //undefined
  console.log(this); //Window
}
a();
复制代码

按照咱们上面说的 this 最终指向的是调用它的对象,这里的函数 a 实际是被 Window 对象所点出来的,下面的代码就能够证实。java

function a() {
  var user = "追梦子";
  console.log(this.user); //undefined
  console.log(this); //Window
}
window.a();
复制代码

和上面代码同样吧,其实 alert 也是 window 的一个属性,也是 window 点出来的。编程

例子 2:

var o = {
  user: "追梦子",
  fn: function() {
    console.log(this.user); //追梦子
  }
};
o.fn();
复制代码

这里的this指向的是对象o,由于你调用这个 fn 是经过o.fn()执行的,那天然指向就是对象 o,这里再次强调一点,this的指向在函数建立的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁app

其实例子 1 和例子 2 说的并不够准确,下面这个例子就能够推翻上面的理论。 若是要完全的搞懂 this 必须看接下来的几个例子函数式编程

例子 3:

var o = {
  user: "追梦子",
  fn: function() {
    console.log(this.user); //追梦子
  }
};
window.o.fn();
复制代码

window 是 js 中的全局对象,咱们建立的变量其实是给 window 添加属性,因此这里能够用 window 点 o 对象。函数

var o = {
  a: 10,
  b: {
    a: 12,
    fn: function() {
      console.log(this.a); //12
    }
  }
};
o.b.fn();
复制代码

这里一样也是对象 o 点出来的,可是一样 this 并无执行它,那你确定会说我一开始说的那些不就都是错误的吗?其实也不是,只是一开始说的不许确,接下来我将补充一句话,我相信你就能够完全的理解 this 的指向的问题。学习

状况1:若是一个函数中有 this,可是它没有被上一级的对象所调用,那么this 指向的就是 window,这里须要说明的是在 js 的严格版中 this 指向的不是 window,可是咱们这里不探讨严格版的问题,你想了解能够自行上网查找。ui

状况2:若是一个函数中有this,这个函数有被上一级的对象所调用,那么this 指向的就是上一级的对象this

状况3:若是一个函数中有 this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this 指向的也只是它上一级的对象,例子 3 能够证实,若是不相信,那么接下来咱们继续看几个例子。

var o = {
  a: 10,
  b: {
    // a:12,
    fn: function() {
      console.log(this.a); //undefined
    }
  }
};
o.b.fn();
复制代码

尽管对象 b 中没有属性 a,这个 this 指向的也是对象 b,由于 this 只会指向它的上一级对象,无论这个对象中有没有 this 要的东西。

还有一种比较特殊的状况

例子 4:

var o = {
  a: 10,
  b: {
    a: 12,
    fn: function() {
      console.log(this.a); //undefined
      console.log(this); //window
    }
  }
};
var j = o.b.fn;
j();
复制代码

这里 this 指向的是 window,是否是有些蒙了?实际上是由于你没有理解一句话,这句话一样相当重要。

this 永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用的,例子 4中虽然函数 fn 是被对象 b 所引用,可是在将 fn 赋值给变量 j 的时候并无执行因此最终指向的是 window,这和例子 3 是不同的,例子 3 是直接执行了 fn。

this 讲来说去其实就是那么一回事,只不过在不一样的状况下指向的会有些不一样,上面的总结每一个地方都有些小错误,也不能说是错误,而是在不一样环境下状况就会有不一样,因此我也没有办法一次解释清楚,只能你慢慢地的去体会。

构造函数版 this:

function Fn() {
  this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子
复制代码

这里之因此对象 a 能够点出函数 Fn 里面的 user 是由于 new 关键字能够改变 this 的指向,将这个 this 指向对象 a,为何我说 a 是对象,由于用了 new 关键字就是建立一个对象实例,理解这句话能够想一想咱们的例子 3,咱们这里用变量 a 建立了一个 Fn 的实例(至关于复制了一份Fn到对象a里面),此时仅仅只是建立,并无执行,而调用这个函数 Fn 的是对象 a,那么 this 指向的天然是对象 a,那么为何对象 Fn 中会有 user,由于你已经复制了一份 Fn 函数到对象 a 中,用了 new 关键字就等同于复制了一份。

除了上面的这些之外,咱们还能够自行改变 this 的指向,关于自行改变 this 的指向请看 JavaScript 中 call,apply,bind 方法的总结这篇文章,个人上一篇文章有提到过。

当 this 碰到 return 时

function fn() {
  this.user = "追梦子";
  return {};
}
var a = new fn();
console.log(a.user); //undefined
复制代码

再看一个

function fn() {
  this.user = "追梦子";
  return function() {};
}
var a = new fn();
console.log(a.user); //undefined
复制代码
function fn() {
  this.user = "追梦子";
  return 1;
}
var a = new fn();
console.log(a.user); //追梦子
复制代码
function fn() {
  this.user = "追梦子";
  return undefined;
}
var a = new fn();
console.log(a.user); //追梦子
复制代码

什么意思呢?

若是返回值是一个对象,那么 this 指向的就是那个返回的对象,若是返回值不是一个对象那么 this 仍是指向函数的实例。

function fn() {
  this.user = "追梦子";
  return undefined;
}
var a = new fn();
console.log(a); //fn {user: "追梦子"}
复制代码

还有一点就是虽然 null 也是对象,可是在这里 this 仍是指向那个函数的实例,由于 null 比较特殊。

function fn() {
  this.user = "追梦子";

  return null;
}
var a = new fn();
console.log(a.user); //追梦子
复制代码

知识点补充:

1.在严格版中的默认的 this 再也不是 window,而是 undefined。 2.new 操做符会改变函数 this 的指向问题,虽然咱们上面讲解过了,可是并无深刻的讨论这个问题,网上也不多说,因此在这里有必要说一下。

function fn() {
  this.num = 1;
}
var a = new fn();
console.log(a.num); //1
复制代码

为何this会指向a?首先new关键字会建立一个空的对象,而后会自动调用一个函数apply方法,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。

转载自:追梦子

相关文章
相关标签/搜索