我的经典程序员爱上了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回调访问?
答案 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)
您在返回后定义了星标。它永远不会被创建,确定它将是未定义的。
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();
}
};
})();