由于您在问题中提到了最佳实践,因此我已经重构了您的代码,以显示一些可能对您和其他人将来有所帮助的实践。下面将列出此重构中使用的概念。
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
's 上下文的内部仅对那些有权访问的代码是可变的。虽然标准化的 ECMAScript中还没有常量, 但这种模块模式方法提供了一个不错的解决方案,结果可预测。