如下所示,我制作了一个简单的高分数组,该数组保存到本地存储并添加到用户提示中。
作为一个独立的文件本身就很有效。或者至少它似乎是。
但是,当我尝试将其集成到我的大型应用程序中时,我似乎对我的全局变量allScores存在范围问题。数组的长度保持为0.我检查是否有任何变量重复,我没有。
我一直在尝试阅读有关功能提升和范围的信息。我不确定的是为什么下面的代码作为一个独立的文件工作,但是当我将它集成到我的大型应用程序中时,我有范围问题。
我应该如何做到这一点?由于我是JavaScript的新手,我最好的做法很可能是关闭的。感谢您的指导。感谢。
var allScores = [];
function saveScore() {
if (allScores.length === 0) {
allScores[0]= prompt('enter score', '');
localStorage ['allScores'] = JSON.stringify(allScores);
}
else if (allScores.length < 3) {
var storedScores = JSON.parse(localStorage ['allScores']);
storedScores = allScores;
var injectScore = prompt('enter score', '');
allScores.push(injectScore);
allScores.sort(function(a, b) {return b-a});
localStorage ['allScores'] = JSON.stringify(allScores);
}
else {
var storedScores = JSON.parse(localStorage ['allScores']);
storedScores = allScores;
var injectScore = prompt('enter score', '');
allScores.pop();
allScores.push(injectScore);
allScores.sort(function(a, b) {return b-a});
localStorage ['allScores'] = JSON.stringify(allScores);
}
document.getElementById('readScores').innerHTML = allScores;
}**
答案 0 :(得分:1)
您是否考虑过JS关闭? 这是一些给你一个想法的作品..
var scoreboard = (function () {
var _privateVar = "some value"; //this is never exposed globally
var _allScores = [];
return {
getAllScores: function() { //public
return _allScores;
},
saveScore: function(value) { //public
_allScores.push(value);
}
};
})();
alert(scoreboard.getAllScores().length); //0
scoreboard.saveScore(1);
alert(scoreboard.getAllScores().length); //1
alert(scoreboard._privateVar); //undefined
alert(scoreboard._allScores); //undefined
这样,您的变量和函数永远不会暴露给窗口对象,您无需担心重复或范围。唯一必须唯一的变量是闭包函数的名称(在此示例中为scoreboard
)。
答案 1 :(得分:1)
我已经重构了您的代码,以便展示一些可能对您和其他人有帮助的做法,因为您提到了问题中的最佳做法。此重构中使用的概念列表如下所示。
var saveScore = (function () { /* Begin IIFE */
/*
The variables here are scoped to this function only.
They are essentially private properties.
*/
var MAX_ENTRIES = 3;
/*
Move the sorting function out of the scope of saveScore,
since it does not need any of the variables inside,
and possibly prevent a closure from being created every time
that saveScore is executed, depending upon your interpreter.
*/
function sorter(a, b) {
return b - a;
}
/*
As far as your example code shows, you don't appear to need the
allScores variable around all the time, since you persist it
to localStorage, so we have this loadScore function which
pulls it from storage or returns a blank array.
*/
function getScores() {
var scores = localStorage.getItem('scores');
return scores ? JSON.parse(scores) : [];
/*
Please note that JSON.parse *could* throw if "scores" is invalid JSON.
This should only happen if a user alters their localStorage.
*/
}
function saveScore(score) {
/* Implicitly load the scores from localStorage, if available. */
var scores = getScores();
/*
Coerce the score into a number, if it isn't one already.
There are a few ways of doing this, among them, Number(),
parseInt(), and parseFloat(), each with their own behaviors.
Using Number() will return NaN if the score does not explicitly
conform to a textually-represented numeral.
I.e., "300pt" is invalid.
You could use parseInt(score, 10) to accept patterns
such as "300pt" but not anything with
leading non-numeric characters.
*/
score = Number(score);
/* If the score did not conform to specifications ... */
if (isNaN(score)) {
/*
You could throw an error here or return false to indicate
invalid input, depending on how critical the error may be
and how it will be handled by the rest of the program.
If this function will accept user input,
it would be best to return a true or false value,
but if a non-numeric value is a big problem in your
program, an exception may be more appropriate.
*/
// throw new Error('Score input was not a number.');
// return false;
}
scores.push(score);
scores.sort(sorter);
/*
From your code, it looks like you don't want more than 3 scores
recorded, so we simplify the conditional here and move
"magic numbers" to the header of the IIFE.
*/
if (scores.length >= MAX_ENTRIES) {
scores.length = MAX_ENTRIES;
}
/* Limiting an array is as simple as decreasing its length. */
/* Save the scores at the end. */
localStorage.setItem('scores', JSON.stringify(scores));
/* Return true here, if you are using that style of error detection. */
// return true;
}
/* Provide this inner function to the outer scope. */
return saveScore;
}()); /* End IIFE */
/* Usage */
saveScore(prompt('Enter score.', ''));
正如您所看到的,在您的分数处理逻辑封装在此功能上下文中,几乎没有任何东西可以在不使用界面的情况下篡改内部。从理论上讲,你的saveScore
函数可以被其他代码所取代,但IIFE
的上下文只能对那些有访问权限的内容进行修改。虽然no constants中有standardized ECMAScript ,但这种模块模式的方法提供了一个具有可预测结果的体面解决方案。
IIFE
,一个立即调用的函数表达式,用于创建我们的模块DRY
,不要重复自己:代码重用答案 2 :(得分:0)
无法访问您的环境,您可以做的最好的事情是使用firefox开发工具(或获取firebug)在您的saveScore
函数中放置断点。您可以逐行执行并检查值,甚至可以在控制台窗口(REPL)中评估当前作用域内的表达式。
https://developer.mozilla.org/en-US/docs/Tools/Debugger - 使用firefox
http://getfirebug.com/javascript - 使用firebug(firefox插件)
如果你正在进行网络开发,这些都是无价的资源,所以要花些时间学习如何使用它们。(它们将为你节省更多的时间!)