Pri*_*ERO 17 javascript jquery design-patterns globals
不久之前,我提出了一个JavaScript设计模式(模块模式 - 见下文),我从John Resig的例子中得到了一个解决某人问题的一部分,我收到了以下评论:
"......这种模式有点过于设计而不是那么好.仍然渗透到全球范围.而你不打开自己的异步装载机.但它比ad-hoc编码更好!"
所以…
如果"泄漏"到全局范围意味着"您的对象被附加到浏览器窗口(对象)"......那么所有内容都已经被追加(全局):
这"泄漏"到全球范围:
window.jQuery
Run Code Online (Sandbox Code Playgroud)
...只需调用: window.jQuery
并将其解析为函数();
这"泄漏"到全球范围:
function HelloWorld() { alert(‘Howdy’); }
Run Code Online (Sandbox Code Playgroud)
......打电话给window.HelloWorld()
你:你会得到'你好'.
这"泄漏"到全球范围:
var myVariable = 10;
Run Code Online (Sandbox Code Playgroud)
......打电话给window.myVariable
你:你会得到10分
如果评论者是正确的,那么以上所有"泄漏"到全球范围.所以,就个人而言,我没有看到一种不"泄漏"到全局范围内的方法,因为即使你的表单控件也存在(也是如此).
因此,这是我的问题......
这是我上面提到的模块模式:
<script type="text/javascript">
var myNamespace = (function($) {
var publicInstances = {};
// ***********************
// myObject
publicInstances.myObject = myObject;
function myObject() {
/// <summary>A pointer to this</summary>
var self = this;
this.someProperty = new String();
this.initialize = function() {
/// your code here
}
this.someMethod = function() {
/// your code here
}
self.initialize();
}
return publicInstances;
})(jQuery);
jQuery(document).ready(function() {
// Use would look like
var myInstance = new myNamespace.myObject();
});
</script>
Run Code Online (Sandbox Code Playgroud)
重新获得以下答案:
当局部范围内使用的东西无意中可用于全局范围(例如窗口对象)时,会发生"泄漏"到全局范围.这很糟糕,因为它会打开页面以查找可能导致变量解析为意外值或类型的潜在命名冲突.
故意使变量全局化不被视为"泄漏".但是,需要正确地命名对象以减少所述命名冲突的可能性.
您无法避免全局范围的变量,但您可以通过使用异步加载器和在RequireJS或Curl等插件中提供的定义模块来降低上述风险.
"泄漏"到全球范围内是指本地范围内使用的内容无意中可用于全球范围.这意味着分配给当前范围中尚未定义的变量:
function myFunction() {
a=1;
}
myFunction();
alert(a);
//-> 1
Run Code Online (Sandbox Code Playgroud)
这很糟糕,因为可能存在命名冲突,导致变量具有与预期不同的值/类型.当您忘记对语句中var
使用的变量使用关键字时,它也可能导致旧版Internet Explorer中的错误for
.
我不打算故意将变量全局变为"泄漏",因为它更像是将它"倾注"到全球范围内.然而,这仍然被一些人认为是不好的做法(尽管我认为这有点戏剧性),因为仍然存在与window
对象的当前属性或其他脚本和库设置的变量的潜在命名冲突.
[[短篇故事]]
永远不要创建全局变量并使用像requirejs或curl这样的异步模块加载器
[[很长的故事]]
该评论结构不佳。
模块系统没有任何问题。我一直在抱怨使用全局变量。(我仍然认为完整的通用模块模式是臃肿的)。
您是否应该避免使用所有全局变量是一个不同的问题,我认为是风格问题。您可以使用异步加载器来传递模块或使用window
来传递模块。
我的意思是你创建全局变量。最小化全局变量的使用是一种模式。在函数式编程中,全局变量可能为零,但这与使用全局模块的模式不同。
全局拥有任何状态都可能导致该状态被破坏。
你不能。不过,您可以最大限度地减少全局变量的数量。为了避免完全拥有全局状态,您可以使用异步加载器。这些为您定义了一些全局变量,然后您可以使用它们。
模块模式没有任何问题。问题是全局存储模块。问题是具有全局命名空间。
现在我已经澄清了评论的意图,这个问题并不真正相关
该评论充其量是措辞不佳。我反对全局命名空间而不是模块,但没有正确说明这一点。
另一种方法是使用异步加载器并定义模块。这些可以缩小到两个全局变量。define
和require
。
require = function(moduleName, callback)
这将获得一个模块,然后将其返回给您。
define = function(obj)
这定义了一个模块。
这里的概念是你多文件代码如下:
// main.js
require([
"foo.js",
"bar.js",
...,
], function(foo, bar, ...) {
// do stuff
});
//foo.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
//bar.js
(function() {
var namespace = modulePatternCode;
...
define(namespace):
})();
Run Code Online (Sandbox Code Playgroud)