如何避免JavaScript中的全局变量? [英] How to avoid global variables in JavaScript?

查看:110
本文介绍了如何避免JavaScript中的全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都知道全局变量只是最佳做法。但是有几个例子,如果没有它们就很难编码。你使用什么技术来避免使用全局变量?



例如,给定以下场景,你将如何不使用全局变量?



JavaScript代码

  var uploadCount = 0; 

window.onload = function(){
var frm = document.forms [0];

frm.target =postMe;
frm.onsubmit = function(){
startUpload();
返回false;



函数startUpload(){
var fil = document.getElementById(FileUpload+ uploadCount);

if(!fil || fil.value.length == 0){
alert(Finished!);
document.forms [0] .reset();
return;
}

disableAllFileInputs();
fil.disabled = false;
alert(上传文件+ uploadCount);
document.forms [0] .submit();

相关标记:

 < iframe src =test.htmname =postHereid =postHere
onload =uploadCount ++; if(uploadCount > 1)startUpload();>< / iframe>

<! - 必须在这里使用内嵌JavaScript进行onload事件
在每个表单提交后触发。 - >

这段代码来自一个包含多个< input type =文件> 。它一次上传一个文件以防止发生巨大的请求。它通过 POST 到iframe来完成,等待响应iframe onload,然后触发下一次提交。



你不必特别回答这个例子,我只是提供它来参考我所处的情况无法想到一种避免全局变量的方法。最简单的方法是将代码封装在一个闭包中,然后手动公开只有全局范围内需要的变量:

 (function(){
// Your code here

//暴露于全局
窗口['varName'] = varName;
})();

为了解决Crescent Fresh的评论:为了完全消除场景中的全局变量,开发人员需要改变问题中假设的一些事情。它看起来更像这样:



Javascript:

  (function(){
var addEvent = function(element,type,method){
if('addEventListener'in element){
element.addEventListener(type,method,false);
} else if('attachEvent'in element){
element.attachEvent('on'+ type,method);

//如果addEventListener和attachEvent都不可用,$
} else if('on'+ type in element){
//如果以前的内联事件存在,保留它,这不是' t
//测试过,它可能会吃掉你的宝贝
var oldMethod = element ['on'+ type],
newMethod = function(e){
oldMethod(e);
newMethod(e);
};
} else {
element ['on'+ type] = me thod;
}
},
uploadCount = 0,
startUpload = function(){
var fil = document.getElementById(FileUpload+ uploadCount);

if(!fil || fil.value.length == 0){
alert(Finished!);
document.forms [0] .reset();
return;
}

disableAllFileInputs();
fil.disabled = false;
alert(上传文件+ uploadCount);
document.forms [0] .submit();
};
$ b addEvent(window,'load',function(){
var frm = document.forms [0];

frm.target =postMe;
addEvent(frm,'submit',function(){
startUpload();
return false;
});
});

var iframe = document.getElementById('postHere');
addEvent(iframe,'load',function(){$ b $ uploadCount ++;
if(uploadCount> 1){
startUpload();
}
});

})();

HTML:

 < iframe src =test.htmname =postHereid =postHere>< / iframe> 

您不需 内联事件处理程序$ c>< iframe> ,它仍然会在每次加载时都会触发此代码。



strong>



以下是一个测试用例,演示您不需要内联 onload 事件。这取决于在同一台服务器上引用一个文件(/emptypage.php),否则你应该能够将它粘贴到一个页面中并运行它。

 <!DOCTYPE html PUBLIC -  // W3C // DTD XHTML 1.0 Strict // EN
http://www.w3.org/TR/xhtml1/DTD/xhtml1 -strict.dtd>
< html xmlns =http://www.w3.org/1999/xhtmlxml:lang =enlang =en>
< head>
< meta http-equiv =Content-Typecontent =text / html; charset = utf-8/>
< title>无标题< /标题>
< / head>
< body>
< script type =text / javascriptcharset =utf-8>
(function(){
var addEvent = function(element,type,method){
if('addEventListener'element){
element.addEventListener(type,method, false);
} else if('attachEvent'in element){
element.attachEvent('on'+ type,method);

//如果addEventListener和attachEvent是
//使用内联事件,这不应该发生
} else if('on'+ type in element){
//如果存在之前的内联事件,则保留它。这不是
//测试,它可能会吃掉你的宝贝
var oldMethod = element ['on'+ type],
newMethod = function(e){
oldMethod (e);
newMethod(e);
};
} else {
元素['on'+ type] =方法;
}
};

//解决IE 6/7错误,表单提交的目标是
//一个新窗口,而不是iframe。 SO建议在这里:
// http://stackoverflow.com/q/875650
var iframe;
try {
iframe = document.createElement('< iframe name =postHere>');
} catch(e){
iframe = document.createElement('iframe');
iframe.name ='postHere';
}

iframe.name ='postHere';
iframe.id ='postHere';
iframe.src ='/emptypage.php';
addEvent(iframe,'load',function(){
alert('iframe load');
});

document.body.appendChild(iframe);

var form = document.createElement('form');
form.target ='postHere';
form.action ='/emptypage.php';
var submit = document.createElement('input');
submit.type ='submit';
submit.value ='提交';

form.appendChild(submit);

document.body.appendChild(form);
})();
< / script>
< / body>
< / html>

每次点击Safari,Firefox,IE 6,7和8中的提交按钮时,都会触发警报。


We all know that global variables are anything but best practice. But there are several instances when it is difficult to code without them. What techniques do you use to avoid the use of global variables?

For example, given the following scenario, how would you not use a global variable?

JavaScript code:

var uploadCount = 0;

window.onload = function() {
    var frm = document.forms[0];

    frm.target = "postMe";
    frm.onsubmit = function() {
        startUpload();
        return false;
    }
}

function startUpload() {
    var fil = document.getElementById("FileUpload" + uploadCount);

    if (!fil || fil.value.length == 0) {
        alert("Finished!");
        document.forms[0].reset();
        return;
    }

    disableAllFileInputs();
    fil.disabled = false;
    alert("Uploading file " + uploadCount);
    document.forms[0].submit();
}

Relevant markup:

<iframe src="test.htm" name="postHere" id="postHere"
  onload="uploadCount++; if(uploadCount > 1) startUpload();"></iframe>

<!-- MUST use inline JavaScript here for onload event
     to fire after each form submission. -->

This code comes from a web form with multiple <input type="file">. It uploads the files one at a time to prevent huge requests. It does this by POSTing to the iframe, waiting for the response which fires the iframe onload, and then triggers the next submission.

You don't have to answer this example specifically, I am just providing it for reference to a situation in which I am unable to think of a way to avoid global variables.

解决方案

The easiest way is to wrap your code in a closure and manually expose only those variables you need globally to the global scope:

(function() {
    // Your code here

    // Expose to global
    window['varName'] = varName;
})();

To address Crescent Fresh's comment: in order to remove global variables from the scenario entirely, the developer would need to change a number of things assumed in the question. It would look a lot more like this:

Javascript:

(function() {
    var addEvent = function(element, type, method) {
        if('addEventListener' in element) {
            element.addEventListener(type, method, false);
        } else if('attachEvent' in element) {
            element.attachEvent('on' + type, method);

        // If addEventListener and attachEvent are both unavailable,
        // use inline events. This should never happen.
        } else if('on' + type in element) {
            // If a previous inline event exists, preserve it. This isn't
            // tested, it may eat your baby
            var oldMethod = element['on' + type],
                newMethod = function(e) {
                    oldMethod(e);
                    newMethod(e);
                };
        } else {
            element['on' + type] = method;
        }
    },
        uploadCount = 0,
        startUpload = function() {
            var fil = document.getElementById("FileUpload" + uploadCount);

            if(!fil || fil.value.length == 0) {    
                alert("Finished!");
                document.forms[0].reset();
                return;
            }

            disableAllFileInputs();
            fil.disabled = false;
            alert("Uploading file " + uploadCount);
            document.forms[0].submit();
        };

    addEvent(window, 'load', function() {
        var frm = document.forms[0];

        frm.target = "postMe";
        addEvent(frm, 'submit', function() {
            startUpload();
            return false;
        });
    });

    var iframe = document.getElementById('postHere');
    addEvent(iframe, 'load', function() {
        uploadCount++;
        if(uploadCount > 1) {
            startUpload();
        }
    });

})();

HTML:

<iframe src="test.htm" name="postHere" id="postHere"></iframe>

You don't need an inline event handler on the <iframe>, it will still fire on each load with this code.

Regarding the load event

Here is a test case demonstrating that you don't need an inline onload event. This depends on referencing a file (/emptypage.php) on the same server, otherwise you should be able to just paste this into a page and run it.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>untitled</title>
</head>
<body>
    <script type="text/javascript" charset="utf-8">
        (function() {
            var addEvent = function(element, type, method) {
                if('addEventListener' in element) {
                    element.addEventListener(type, method, false);
                } else if('attachEvent' in element) {
                    element.attachEvent('on' + type, method);

                    // If addEventListener and attachEvent are both unavailable,
                    // use inline events. This should never happen.
                } else if('on' + type in element) {
                    // If a previous inline event exists, preserve it. This isn't
                    // tested, it may eat your baby
                    var oldMethod = element['on' + type],
                    newMethod = function(e) {
                        oldMethod(e);
                        newMethod(e);
                    };
                } else {
                    element['on' + type] = method;
                }
            };

            // Work around IE 6/7 bug where form submission targets
            // a new window instead of the iframe. SO suggestion here:
            // http://stackoverflow.com/q/875650
            var iframe;
            try {
                iframe = document.createElement('<iframe name="postHere">');
            } catch (e) {
                iframe = document.createElement('iframe');
                iframe.name = 'postHere';
            }

            iframe.name = 'postHere';
            iframe.id = 'postHere';
            iframe.src = '/emptypage.php';
            addEvent(iframe, 'load', function() {
                alert('iframe load');
            });

            document.body.appendChild(iframe);

            var form = document.createElement('form');
            form.target = 'postHere';
            form.action = '/emptypage.php';
            var submit = document.createElement('input');
            submit.type = 'submit';
            submit.value = 'Submit';

            form.appendChild(submit);

            document.body.appendChild(form);
        })();
    </script>
</body>
</html>

The alert fires every time I click the submit button in Safari, Firefox, IE 6, 7 and 8.

这篇关于如何避免JavaScript中的全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆