tes*_*est 30 javascript optimization
有没有办法只运行一段JavaScript代码ONCE,而不使用布尔标志变量来记住它是否已经运行过?
特别是不是这样的:
var alreadyRan = false;
function runOnce() {
if (alreadyRan) {
return;
}
alreadyRan = true;
/* do stuff here */
}
Run Code Online (Sandbox Code Playgroud)
我将有很多这些类型的功能,并保持所有布尔将是凌乱的......
Lek*_*eyn 75
在执行时覆盖函数的另一种方法,它只执行一次.
function useThisFunctionOnce(){
// overwrite this function, so it will be executed only once
useThisFunctionOnce = Function("");
// real code below
alert("Hi!");
}
// displays "Hi!"
useThisFunctionOnce();
// does nothing
useThisFunctionOnce();
Run Code Online (Sandbox Code Playgroud)
'有用'的例子:
var preferences = {};
function read_preferences(){
// read preferences once
read_preferences = Function("");
// load preferences from storage and save it in 'preferences'
}
function readPreference(pref_name){
read_prefences();
return preferences.hasOwnProperty(pref_name) ? preferences[pref_name] : '';
}
if(readPreference('like_javascript') != 'yes'){
alert("What's wrong wth you?!");
}
alert(readPreference('is_stupid') ? "Stupid!" : ":)");
Run Code Online (Sandbox Code Playgroud)
编辑:正如CMS指出的那样,只需覆盖旧函数function(){}将创建一个旧变量仍然存在的闭包.要解决这个问题,请function(){}替换为Function("").这将在全局范围内创建一个空函数,从而避免闭包.
我喜欢Lekensteyn的实现,但你也可以只有一个变量来存储运行的函数.下面的代码应该一次运行"runOnce"和"runAgain".它仍然是布尔值,但听起来你只是不想要很多变量.
var runFunctions = {};
function runOnce() {
if(!hasRun(arguments.callee)) {
/* do stuff here */
console.log("once");
}
}
function runAgain() {
if(!hasRun(arguments.callee)) {
/* do stuff here */
console.log("again");
}
}
function hasRun(functionName) {
functionName = functionName.toString();
functionName = functionName.substr('function '.length);
functionName = functionName.substr(0, functionName.indexOf('('));
if(runFunctions[functionName]) {
return true;
} else {
runFunctions[functionName] = true;
return false;
}
}
runOnce();
runAgain();
runAgain();
Run Code Online (Sandbox Code Playgroud)
很多这些方法的问题在于它们依赖于函数名称来工作:如果使用"x = function()..."创建函数,Mike的方法将失败,如果设置x = useThisFunctionOnce,则Lekensteyn的方法将失败在使用之前调用ThisFunctionOnce.
如果你想运行它马上或所采取的方法,我会建议使用拉斯的关闭方法Underscore.js如果要延迟执行:
function once(func) {
var ran = false, memo;
return function() {
if (ran) return memo;
ran = true;
return memo = func.apply(this, arguments);
};
}
var myFunction = once(function() {
return new Date().toString();
});
setInterval(function() {console.log(myFunction());}, 1000);
Run Code Online (Sandbox Code Playgroud)
在第一次执行时,执行内部函数并返回结果.在后续运行中,将返回原始结果对象.
如何立即调用匿名函数?
(function () {
// code in here to run once
})();
Run Code Online (Sandbox Code Playgroud)
代码将立即执行,并且不会在全局命名空间中留下任何痕迹.
如果需要从其他地方调用此代码,则可以使用闭包来确保函数的内容只运行一次.就个人而言,我更喜欢这个函数重写自己,因为我觉得这样做会引起混淆,但是每个人都有自己的:)这个特殊的实现利用了0是一个假值的事实.
var once = (function() {
var hasRun = 0;
return function () {
if (!hasRun) {
hasRun++;
// body to run only once
// log to the console for a test
console.log("only ran once");
}
}
})();
// test that the body of the function executes only once
for (var i = 0; i < 5; i++)
once();
Run Code Online (Sandbox Code Playgroud)