JavaScript变量scope和underscore.js

时间:2012-05-30 10:52:47

标签: javascript

我有一个功能,里面有这个:

var fobj = function(){};

var my_obj = fobj.extend({
    test: function(){
        this.year = 1999;  
        my_fmagic.doMagic([
            {
                field: 'year', 
                type: 'function', 
                value: function(data_from_doMagic){

                    console.log(data_from_doMagic, this.year);

                    return data_from_doMagic == this.year;
                }
            }
        ]);
    }
});

然后,doMagic函数:

var fmagic = function(){};

var my_fmagic = fmagic.extend({
    doMagic: function( rules ) {
        var data_from_doMagic = 1999;
        _.each(rules, function(rule) { 
            switch(rule.type) {
                case "function":
                    var f = _.wrap(rule.value, function(func){
                        return func( data_from_doMagic );
                    });
                    f();
                    break;
            }
        });
    }
});

这个想法是:将一系列“规则”传递给doMagic,然后让它完成剩下的工作。

预期结果:test()应返回true(在此示例中,它不会返回任何内容,显然,因为没有返回,但规则的value字段应该是true。)

问题:结果是true它是false,因为f()中的函数doMagic不知道变量year是什么,并且所以它将“1999”与“未定义”进行比较。

如你所见,我知道问题所在,但我无法考虑任何解决方案。

想法?

此致

1 个答案:

答案 0 :(得分:1)

您发布到(原始)问题的代码 根本不同 与您最终在您的小提示中显示的代码显示问题

问题在于:

test: function(){
    this.year = 1999;  // <=== This isn't a variable, as you originally showed
    my_fmagic.doMagic([
        {
            field: 'year', 
            type: 'function', 
            value: function(data_from_doMagic){

                // *** `this` here won't be the same as `this` was above ***

                console.log(data_from_doMagic, this.year);

                return data_from_doMagic == this.year;
            }
        }
    ]);
}

快速解决方法是:

test: function(){
    var self = this;   // <=== Create a variable to close over

    this.year = 1999;

    my_fmagic.doMagic([
        {
            field: 'year', 
            type: 'function', 
            value: function(data_from_doMagic){

                console.log(data_from_doMagic, self.year); // <== And use it here

                return data_from_doMagic == self.year;     // <== And use it here
            }
        }
    ]);
}

Updated fiddle

这是因为在JavaScript中,this完全取决于函数的调用方式,而不是它定义的位置。在调用您作为value传递的函数时,this将成为浏览器上的全局对象(window),因为代码无法告诉引擎{{1}应该是。

所以要解决它,简单的答案是在调用this函数的上下文中创建一个变量,并为其赋值test;然后我们在this函数中使用该变量(self)而不是this,因为value函数会在调用value的上下文中关闭。

更多探索(披露:这些都来自我的博客)