首页 > 代码库 > javascript的this到底指向谁

javascript的this到底指向谁

新手对this最困惑。 

因为javascript的面向对象比较诡异。

我们说, 通常的面向对象, 分为对象和消息。 

由于一些课本的讲解问题, 大家通常认为消息就是方法, 就是函数

这个呢, 有的时候也不能说错啦。消息是抽象概念, 方法是具体实现。

而且对于像C#这类的语言来说, 基本上就是用方法来发消息。

 

可是对于javascript来说问题就大了。 

因为对于javascript来说, 方法, 也是对象!

这下麻烦了。 那javascript还有消息么?

这个仁者见仁了。 你认为那个能发消息哪个就是消息好了。 这是题外话不再继续聊。 

 

话说Function成了对象, 最大的问题就是, this是谁?

这个能搞晕一片人,即使不考虑with这种不推荐的情况

永远记住一点:this指向调用者。 

*当没有调用者的时候, 指向全局变量(浏览器里是window)

没有调用者, 这个有点反直觉。 实际上这就是javascript不太面向对象的一点。 

这里不谈大量空洞的理论, 只给出一个最简单的判断方式:

“当你把方法调用改成apply调用的时候, 你自然就知道如何填写this了”

 

这个技巧是我自己创造的。 所以不保证权威。 但是很有效。 

请注意:该方法不会让你加深任何对this的理解, 只能让你理清整个代码的关系。 

 

这里需要前置知识:apply方法。 

MDN描述如下:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

The apply() method calls a function with a given this value and arguments provided as an array (or an array-like object).

用法:

fun.apply(thisArg[, argsArray]

 

OK, 举个例子:

var a = function(){  alert(this);}var b = "test";a.apply(b);

  

运行结果, 弹出test

那么这里, 这个函数就很好理解了。 apply的第一个参数是this, 就这么简单。 

现在再做一些迷惑人的题就容易多了。 

比如这种:

(function(){var a = {  name:‘Lina‘,  test:function(){    alert(this.name);  }}var b = {name:‘arthas‘};b.test = a.test;b.test();})();

  

最简单的this替换问题。 

可能即使你不用我的技巧也能看得出。 

我们调用b.test的时候, b就是this。

那么alert(this.name);相当于alert(b.name);, 所以会弹出arthas

换个理解则是:

a.test.apply(b);

因为我们传入了b, 所以b就是this。 弹出就是arthas

换个稍稍复杂点的:

(function(){var a = {  name:‘Lina‘,  test:function(){    alert(this.name);  }}var b = {name:‘arthas‘};var test = a.test;test();})();

  

经验丰富的会说, 哦, 

由于test是单独调用的, 所以this指向window对象。 

那么我们要如何理解刚刚的代码呢?

改成这样:

test.apply();

没错, apply里面什么都不填。 在这个情况下, 似乎按照js的逻辑, 不传参数默认给undefined啊?

注意, apply的说明里有:

thisArgThe value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.

 

看到了吧, apply的第一个参数, 如果什么都不提供,也就是提供undefined, 那么会被替换为global object

在浏览器里, global object就是window了。 

 但是注意, 这仅仅是在non-strict模式下。 

等以后用了use strict会如何呢?

话说这个我还真没研究过。 不过看文档, 估计应该是null吧。 

 

紧接着是面试题最爱搞的:setTimeout

比如:

(function(){  var a = {    name:‘arthas‘,    test:function(){      setTimeout(function(){        alert(this.name);      },100);    },    test2:function(){      alert(this.name);    }  }  a.test2();  a.test();})();

  

跑下来, test2给出的this.name是arthas, 这毫无疑问。 

那么setTimeout呢?

setTimeout哪里, 开了一块新的区域来跑, 所以相当于这么个调用:

(function(){        alert(this.name);}).apply();

  

this是window, 所以show了个window.name

刚好是个空字串。 

javascript的this到底指向谁