首先必须要说的是,this的意义在函数定义的时候是无法确定的。 只有当函数执行时才能确定this指向谁。 其实this最终指向的是调用它的对象(这句话有点问题,后面我会解释为什么会出现问题,虽然网上大部分文章都是这么说的,虽然很多情况下如果你是这么理解的,但其实这么理解是不准确的,所以在你没有理解之前,读到这里会有一种看不懂的感觉),那么接下来我会深入讨论这个问题。
为什么要研究这个? 如果你学过面向对象编程,那么你一定知道它是用来做什么的。 如果还没有,您可以暂时跳过阅读本文。 当然,如果你有兴趣也可以阅读。 毕竟这是你在js中必须掌握的东西。
示例1:
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
a();
根据我们上面所说,this最终指向调用它的对象。 这里的函数a实际上是对象所指向的,下面的代码可以证明。
function a(){
var user = "追梦子";
console.log(this.user); //undefined
console.log(this); //Window
}
window.a();
和上面的代码是一样的,其实alert也是一个属性,也是点击出来的。
示例2:
var o = {
user:"追梦子",
fn:function(){
console.log(this.user); //追梦子
}
}
o.fn();
这里this指向对象o,因为你通过o.fn()调用了这个fn,所以自然指向的就是对象o。 同样,在创建函数时无法确定 this 的意义。 只有调用的时候才能决定,谁调用就指向谁。 你必须弄清楚这一点。
事实上,例1和例2不够准确。 下面的例子可以推翻上面的理论。
如果你想彻底理解这一点,你必须看下面的几个例子
本文来源:追逐梦想博客
示例3:
var o = {
user:"追梦子",
fn:function(){
console.log(this.user); //追梦子
}
}
window.o.fn();
这段代码和上面这段代码几乎是一样的,但是这里为什么不指向this呢,如果按照上面的理论,到底this指向的是调用它的对象,我们先说一下,它是js中的全局对象,我们创建的变量实际上是给它添加属性,所以这里我们可以使用point o对象。
我们先不解释为什么上面这段代码this没有指向它,我们再来看一段代码。
var o = {
a:10,
b:{
a:12,
fn:function(){
console.log(this.a); //12
}
}
}
o.b.fn();
这里也是对象o的要点,而且this也没有实现,那你肯定会说我一开始说的不都是错的吗? 其实不然,只是我一开始说的不准确。 接下来我补充一句。 我相信你能够充分理解这里所指出的问题。
情况一:如果函数中有this,但不是被上层的对象调用,那么this指向的是什么,这里需要说明的是,严格版本的js中,this指向的是不会,但是严格的我们就不讨论了。如果想了解更多版本,可以网上搜索一下。
情况2:如果一个函数中有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 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总是指向最后调用它的对象,也就是说,取决于它执行时是谁调用了它。 在示例4中,虽然函数fn被对象b引用,但是当fn被赋值给变量j时,它并没有被执行。 最后一点是,这与示例3不同。示例3直接执行fn。
这实际上在一般情况下是同一件事,但在不同的情况下所指向的东西是不同的。 上面的总结每个地方都有一些小错误,也不能说是错误,但是不同环境情况不同。 会有差异,所以我无法一下子解释清楚,只能慢慢体会。
其构造函数版本:
function Fn(){
this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子
函数Fn中对象a之所以能够指向用户,是因为new关键字可以改变this的方向,将this指向对象a。 为什么我说a是一个对象,因为使用new关键字就是创建一个对象实例。 要理解这句话,你可以想一下我们的例子3。这里我们使用变量a来创建Fn的实例(相当于将Fn的副本复制到对象a中)。 此时只是创建并没有执行。 函数Fn就是对象a,那么this自然就指向了对象a,那为什么对象a里面有一个用户呢,因为你已经把Fn函数复制了一份到对象a中,使用new关键字就相当于复制共享。
除了上面的之外,我们还可以自己改变这个的方向。 如果想要自己改变this的方向,请阅读本文中call、apply、bind方法的总结,里面详细解释了我们如何手动改变this的方向。
遇到这个问题更新一下
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不再是,但是。
2.新的运算符将改变函数this的方向。 虽然上面我们已经解释过了,但是我们并没有深入讨论这个问题,网上也很少提及,所以这里有必要说一下。
function fn(){
this.num = 1;
}
var a = new fn();
console.log(a.num); //1
为什么this指向a? 首先new关键字会创建一个空对象,然后自动调用一个函数apply方法,将this指向这个空对象,这样函数内部的this就会被这个空对象替换。
注意:当你创建一个空对象时,js内部实现并不一定使用apply方法来改变this指向的内容。 这里我只是打个比方。
if (this === 动态\可变) true;