无处不在的this(setTimeout)

原创 和尚 随笔 javascript学习笔记 1711阅读 2014-08-31 10:46:24 举报

昨天晚上在知乎上看到了一道题

要求: 修改一下代码,alert出sayHello()里边的this.hello(也就“hello world”)。

代码如下:

[code]
var foo = function(){
this.hello="hello world";
};
foo.prototype.sayHello=function(){
alert(this.hello);
};
foo.prototype.bar=function(){
setTimeout(this.sayHello,1000);
};

    var f = new foo();
    f.bar();

[/code]

解题过程:

问题:在 setTimeout(this.sayHello,1000) 中this指向的是window(window.setTimeout()),所以alert出undefined。

方案一:
         然后我就改成:setTimeout(this.sayHello(),1000),咦……出来“hello world”了!!!但是为什么呢?我一开始出现在脑海的问题是:this是怎么找到sayHello的?不合理啊!
         但是我想错了,原来,setTimeout(this.sayHello(),1000)的话sayHello()就直接执行了,他是不经过setTimeout里this的。【失败】

方案二:
     于是我又改成了: 
        foo.prototype.bar=function(){
             var _this=this;
                 setTimeout(_this.sayHello,1000);
            };
     嘿嘿……这下总可以了吧?可是还是高兴的太早了,alert出的还是undefined。什么?undefined?!怎么会这样?怎么可以这样……【又告失败】

方案三:
    于是又不停的求招……终于得了一招:
        foo.prototype.bar=function(){
             var _this=this;
                 setTimeout(function(){_this.sayHello.call(_this)},1000);
            };
    真的出“hello world”了,这看起来合理多了。

终结:

在方案二中,虽然_this是当前对象的,但是_this.sayHello放在setTimeout里面,而在sayHello里边还有一个this.hello,那么这个this指向哪呢?当然是window了,
所以alert出来的还是undefined;所以在方案三中对sayHello使用call()转换sayHello里的this。

最后非常感谢给我帮助的各位前辈。
评论 ( 5 )
最新评论
移花香 1F 2014-09-04 10:13:45 5F

好吧,确实

放了学别在 1F 2014-09-04 09:47:03 4F

我给出的写法,此时调用者为me也就是保存起来的this 指向的是foo。

foo.prototype.bar = function () {
            var me = this;
            setTimeout(function () { me.sayHello(); }, 1000);
        };

放了学别在 1F 2014-09-04 09:46:23 3F

我试了一下 方法2弹窗undefined, _this.sayHello 在此时是作为函数直接调用,他的this肯定指向window啊

移花香 2014-09-04 07:47:34 2F

为什么这么好的文章没人欣赏

移花香 2014-09-04 07:47:10 1F

经测试,方案二中弹出正确结果