简体   繁体   English

JavaScript:避免在函数中使用全局变量

[英]JavaScript: Avoiding global variables in my functions

I am trying to get my head around the various techniques that can be used to avoid the use of global variables in JavaScript. 我试图弄清楚可以用来避免在JavaScript中使用全局变量的各种技术。

Consider the following code, that performs a redirect to a URL after a countdown timer: 考虑以下代码,该代码在倒数计时器之后执行到URL的重定向:

var _redirectTimer;
function startRedirectTimer() {
    clearTimeout(_redirectTimer);

    var redirectTimer = function(timeLeft) {
    if(timeLeft == 0) {
        // redirect to application path
        var redirectURL = window.location.protocol+"//"+window.location.host + "/" + location.pathname.split("/")[1];
        window.location.replace(redirectURL);
        return;
    } else {
        timeLeft--;
        _redirectTimer = setTimeout(function () {redirectTimer(timeLeft)}, 1000);
    }   
}   
redirectTimer(60);  

} }

My client code only ever calls startRedirectTimer() . 我的客户代码只能调用startRedirectTimer() However, _redirectTimer is a global variable that I'd rather not expose. 但是, _redirectTimer是我不希望公开的全局变量。 Ideally, I'd like this variable to be a "state" variable within startRedirectTimer() , similar to how you'd have a private method in a singleton java class. 理想情况下,我希望此变量成为startRedirectTimer()的“状态”变量,类似于您在单例java类中使用私有方法的方式。 Can someone advise on how I can achieve this? 有人可以建议我如何实现这一目标吗?

Thanks 谢谢

Well, the quick way around variables is just wrapping an extra function around the section in question: 好吧,解决变量的快速方法是将一个额外的函数包装在有问题的部分周围:

(function()
{//wrapper function
    var _redirectTimer;
    function startRedirectTimer()
    {
        clearTimeout(_redirectTimer);
        var redirectTimer = function(timeLeft) {
        if(timeLeft == 0)
        {
            // redirect to application path
            var redirectURL = window.location.protocol+"//"+window.location.host + "/" + location.pathname.split("/")[1];
            window.location.replace(redirectURL);
            return;
        }
        else
        {
            timeLeft--;
            _redirectTimer = setTimeout(function () {redirectTimer(timeLeft)}, 1000);
        }   
    }   
    redirectTimer(60);  
})();//call wrapper function

As always, you can choose when to call the timeout function by exposing it to the global object. 与往常一样,您可以通过将超时函数暴露给全局对象来选择何时调用超时函数。 However, if I understood correctly you're looking for a way to contain the _redirectTimer or link that to the startRedirectTimer function somehow (obviously without it loosing its state after each call). 但是,如果我正确理解,您正在寻找一种包含_redirectTimer或以某种方式将其链接到startRedirectTimer函数的方法(显然,每次调用后它都不会失去其状态)。 This is possible, in a number of ways: 这可以通过多种方式实现:

function startRedirectTimer()
{
    //as you would, only: add this line
    var _redirectTimer = startRedirectTimer._redirectTimer;
}
startRedirectTimer._redirectTimer;//functions are objects, so assign properties and methods at will

These properties and methods live as long as the function, so their values aren't reset after each call. 这些属性和方法与函数一样有效,因此在每次调用后都不会重置其值。 Downside: they're publicly accessible, and can be redefined by accident. 缺点:它们是公开可用的,并且可能被意外重新定义。
Closures are the best fit for cases like this: 封盖最适合以下情况:

var startRedirectTimer = (function()
{
    var _redirectTimer,timeLeft = 60;//initial value here
    var redirectURL = window.location.protocol+"//"+window.location.host + "/" + location.pathname.split("/")[1];//
    return function ()
    {
        clearTimeout(_redirectTimer);
        if (timeLeft === 0)
        {
            return window.location.replace(redirectURL);
        }
        timeLeft--;
        _redirectTimer = setTimeout(startRedirectTimer,1000);//just call the main function again
    }
})();//return value of this function will be the actual startRedirectTimer function

To set things in motion with the code above, just call startRedirectTimer() once, and it should work. 要使上面的代码动起来,只需调用一次startRedirectTimer() ,它就可以工作。 It's untested code, this, and I'm a bit feverish today, but it should . 这是未经测试的代码,今天我有点发狂,但是应该 IMO, less code, and more efficient. IMO,代码更少,效率更高。

You can enclose it in a closure: 您可以将其括在闭包中:

(function() {
    var _redirectTimer, redirectTimer;
    window.redirectTimer = redirectTimer = function() {
        // ......
    }
    redirectTimer(60);
})();

If you don't need redirectTimer outside this closure, you can remove the window.redirectTimer = part. 如果在此闭包之外不需要redirectTimer ,则可以删除window.redirectTimer = part。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM