首页 > javascript运行上下文 问题

javascript运行上下文 问题

var element = document.getElementById('element');
 
var user = {
 firstname: 'Wilson',
 greeting: function(){
   alert('My name is ' + this.firstname);
 }
};
 
// Attach user.greeting as a callback
element.addEventListener('click', user.greeting);
// alert => 'My name is undefined'

为什么运行的时候,拿不到上下文的值firstname的值


<div class="box box-widget">
                            <div style="display: block;" class="box-body">

                                <p>邀请了微软office负责人演示[拜拜]</p>
                                
                                <div>
                                    <span class="text-muted">Thu Sep 10 17:03:57 CST 2015</span>
                                    <span class="text-muted">0转发</span>
                                    <div class="pull-right">
                                        <input type="hidden" name="weibo_id" value="3885571242155022">
                                        <button class="btn btn-box-tool dbtn"><i class="fa fa-times"></i></button>
                                        <button class="btn btn-danger btn-flat btn-xs bbtn "><i class="fa-hand-stop-o"></i>拉黑</button>
                                        <button class="btn btn-success btn-flat btn-xs cbtn "><i class="fa fa-comments-o margin-r-5"></i>0评论</button>
                                    </div>
                                </div>

                            </div>
                            <div style="display: block;" class="box-body box-comments">
                        <!--  ajax从后台取回来的部分 -->
                            <div class="box-comment">
                                    <!-- User image -->
                                    <img class="img-circle img-sm" src="http://tp2.sinaimg.cn/3888714809/180/5727878850/1" alt="user image">
                                    <div class="comment-text">
                                        <span class="username">有人说刘伟楠这个<span class="text-muted pull-right">Sat Sep 12 16:41:23 CST 2015</span>
                                        </span>
                                        <!-- /.username -->
                                        测试测试测试
                                        <span class="text-muted pull-right">
                                            <input type="hidden" name="comment_id" value="3886290342368683">
                                            <a href="#" class="link-black text-sm rbtn"><i class="fa fa-share margin-r-5"></i>回复</a>
                                        </span>
                                    </div>
                                    <!-- /.comment-text -->
                                </div>

                        <!--  通过开关控制打开关闭,同时后台获取<div style="display: none;" class="box-body box-comments"> -->
                                
                                <form class="form-inline" action="#" method="post">
                                    <div class="input-group">
                                        <input type="hidden" name="weibo_id" value="3885571242155022">
                                        <input name="message" placeholder="Type Message ..." class="form-control" type="text"> <span class="input-group-btn">
                                        <button type="button" class="btn btn-primary btn-flat sbtn">发送</button>
                                    </span>
                                    </div>
                                </form>

                    <!--  /ajax从后台取回来的部分 -->
                            </div>

                        </div>

为什么对<a href="#" class="link-black text-sm rbtn"><i class="fa fa-share margin-r-5"></i>回复</a>绑定的时间会失效了?单纯静态网页的时候是可以触发动作,使用了动态刷新就会失效。这是什么原因?jquery只对页面载入的部分元素进行选择?


这不是上下文件的问题,是 this 的问题。

像下面这么改下就对了:

element.addEventListener('click', user.greeting.bind(user));

@边城狂人 已经把问题解释清楚了,只是做点补充说明。

问题是怎么出现的

JS中的this只与函数调用方式有关,与定义时的上下文,函数作用域,都无关。有如下情况:

user.greeting()      // this --> user

var handler = user.greeting;
handler()            // this --> window

当程序执行到

element.addEventListener('click', user.greeting);

user.greeting作为addEventListener的第二个参数,假设这个参数就叫handler。可以想象,在addEventListener的内部,进行了类似

var handler = user.greeting;   // 这步在传递参数时完成
handler()            // this --> window

的过程,this的指向就发生了改变。

如何修复

this的指向只与函数调用方式有关,函数调用方式一共四种:

func();

obj.func();

func.apply/call();

new func();

要修复这个问题,需要用到apply/call这种调用方式。我们可以想象bind是这样一个函数:

function bind ( func, target ) {
    return function () {
        func.apply( target, arguments );
    }
}

Function.prototype['bind'] = function ( target ) {
    return bind( this, target );
}

这样,就可以使用element.addEventListener('click', user.greeting.bind(user));来解决这个问题了。当然,这里的bind是非常简化、不可用的,比如可以看到bindreturn的函数已经不是原函数了,为了保持一致性应该绑定原型链。这一系列完整的操作在MDN文档中都可以看到。

【热门文章】
【热门文章】