javascript类中的范围问题

时间:2010-09-28 15:21:46

标签: javascript class callback scope

我的经典程序员爱上了OO的公共/私人范例,我发现很难放弃。这导致我遇到了一个我希望你可以帮助我的问题。

我有一个名为map的单例对象。只可以有一个人。此地图包含名为Star的对象(它是一个游戏)。明星看起来像这样:

var Star = function(id, x, y) {
    this.id_ = parseInt(id);
    this.x_ = parseInt(x);
    this.y_ = parseInt(y);
};

实际上有更多的论点和属性。这只是一个例子。

地图的定义如下:

var map = (function() {
    // public interface
    return {
        init: function() {
            getStars();         
        },
        stars: {} // works but publicly accessible
    };

    var stars = new Array(); // fail

    function getStars() {
        $.getJSON("ps.php?jsoncallback=?", addStars);
    }

    function addStars(data) {
        for (var x=0, xx=data.stars.length; x<xx; x++) {
            map.stars[data.stars[x].id] = new Star(
                data.stars[x].id,
                data.stars[x].xpos, 
                data.stars[x].ypos
            );
        }
    }
})();

我认为由于addStars的范围是$.getJSON的回调函数,它无法将新创建的星添加到星号的私有变量中(FireBug表示它未定义且jQuery调用尝试添加后abort)。但是,如果我将星星制作成公众可见的物体,那么它确实有效,但是从界面可以看到星星,这不是我想要的。

如何将星标保密并让其可以通过JSON回调访问?

3 个答案:

答案 0 :(得分:2)

您可以在stars前面引用map

var map = (function() { 

    var stars = new Array(); 

    function getStars() { 
        $.getJSON("ps.php?jsoncallback=?", addStars); 
    } 

    function addStars(data) { 
        for (var x=0, xx=data.stars.length; x<xx; x++) { 
            stars[data.stars[x].id] = new Star( 
                data.stars[x].id, 
                data.stars[x].xpos,  
                data.stars[x].ypos 
            ); 
        } 
    } 

    // this should be at the bottom.

    // public interface 
    return { 
        init: function() { 
            getStars();          
        }
    }; 

})(); 

在与addStars相同的范围上下文中定义stars会创建一个闭包,只要调用该函数,stars就可用。

答案 1 :(得分:2)

您在返回后定义了星标。它永远不会被创建,确定它将是未定义的。

[See is in action]

var map = (function() {     

    var stars = new Array(); // define before return!

    function getStars() {
        $.getJSON("ps.php?jsoncallback=?", addStars);
    }

    function addStars(data) {
        for (var x=0, xx=data.stars.length; x<xx; x++) {
            stars[data.stars[x].id] = new Star( // use private stars
                data.stars[x].id,
                data.stars[x].xpos, 
                data.stars[x].ypos
            );
        }
    }

    // public interface
    return {
        init: function() {
            getStars();         
        }
    };
})();​

答案 2 :(得分:0)

虽然stars可以被视为私有成员,但它实际上只存在于定义map的自调用函数的范围内。因此,您无法通过map.stars访问它,但您可以在回调函数中只访问stars

var map = (function() {

    var stars = [];

    function getStars() {
        $.getJSON("ps.php?jsoncallback=?", function(data) {
            for (var x=0, xx=data.stars.length; x<xx; x++) {
                stars[data.stars[x].id] = new Star(
                    data.stars[x].id,
                    data.stars[x].xpos, 
                    data.stars[x].ypos
                );
            }
        });
    }

    // public interface
    return {
        init: function() {
            getStars();         
        }
    };
})();