[英]Enclosing external jQuery script
我有一个外部 JavaScript 文件,该文件将用于包含许多其他脚本的页面。 我的脚本涉及很多用于监听事件的 jQuery,并且根据设计,我声明了许多全局变量。 我一直在阅读最佳实践文章,其中有很多关于“污染全局命名空间”和无意的脚本交互的说法。
封装(封装?)我的 JavaScript 文件的最佳方法是什么,以便:
我无权透露代码,因此即使是一般性的回复也值得赞赏。 此外,欢迎提供有关使脚本不易受到页面上其他脚本攻击的任何其他提示。
我发现常规 JavaScript 的附件 styles,但是使用 jQuery 会使这复杂化吗?
一种方法是这样命名空间:
var MyNamespace = {
doSomething: function() {},
reactToEvent: function() {},
counter: 0
}
您只需要使用命名空间引用函数或变量: MyNamespace.reactToEvent
。 这可以很好地分离window
(所有对抗都在其中)中通常拥有的东西。
您可以将代码包装在匿名 Javascript function 中,并且只返回您想要向外界公开的内容。 您需要为全局变量添加前缀var
,以便它们仅保留在匿名 function 的 scope 中。 像这样的东西:
var myStuff = (function() {
var globalVar1;
var globalVar2;
var privateVar1;
function myFunction() {
...
}
function myPrivateFunction() {
...
}
return {
var1: globalVar1,
var2: globalVar2,
myFunction: myFunction
};
})();
现在您可以访问myStuff.var1
和myStuff.myFunction()
。
通常,这归结为将您的对象封装到“命名空间”中。 我在那里使用引号是因为该术语在 JavaScript 中不是官方语义,而是通过基本的 object 封装实现的。
有几种方法可以做到这一点,最终归结为个人喜好。
一种方法是只使用基本的 JS object,并将所有内容保存在其中。 object 的名称应该是语义化的,并赋予 object 一些含义,但除此之外,它的目的只是包装您自己的代码并将其排除在全局命名空间之外。
var SomeName = {
alpha: 1,
beta: {a: 1, b: 2},
gamma: function(){
SomeName.alpha += 1;
}
}
在这种情况下,只有 SomeName 位于全局命名空间中。 这种方法的一个缺点是命名空间内的所有内容都是公共的,您必须使用完整的命名空间来引用 object,而不是使用 'this' - 例如,在 SomeName.gamma 中,我们必须使用 SomeName.alpha 来引用阿尔法的内容。
另一种方法是使您的命名空间成为具有属性的 function。 这种方法的优点是您可以通过闭包创建“私有”变量。 它还使您可以访问封闭的函数和变量,而无需完整的命名空间引用。
var SomeName = (function(){
var self = this;
var privateVar = 1;
var privateFunc = function() { };
this.publicVar = 2;
this.publicFunc = function(){
console.log(privateVar);
console.log(this.publicVar); // if called via SomeName.publicFunc
setTimeout(function(){
console.log(self.publicVar);
console.log(privateVar);
}, 1000);
};
}();
这种方法的另一个好处是它可以让您保护要使用的全局变量。 例如,如果您使用 jQuery 和另一个创建 $ 变量的库,您可以始终确保在通过以下方法使用 $ 时引用 jQuery:
var SomeName = (function($){
console.log($('div'));
})(jQuery);
封装或限制命名空间污染的两种方法
1)创建一个全局变量并将你需要的所有东西都塞进去。
var g = {};
g.somevar = "val";
g.someothervar = "val2";
g.method1 = function()
{
// muck with somevar
g.somevar = "something else";
};
2)对于内联脚本,考虑限制调用函数的scope。
<script>
(
function(window)
{
// do stuff with g.somevar
if(g.somevar=="secret base")
g.docrazystuff();
}
)(); // call function(window) then allow function(window) to be GC'd as it's out of scope now
</script>
我刚开始使用RequireJS ,现在已经迷上了它。
它基本上是一个模块化 JavaScript 格式的依赖管理系统。 通过这样做,您几乎可以消除将任何东西附加到全局命名空间的情况。
好在您只在页面require.js
上引用一个脚本,然后告诉它首先运行哪个脚本。 从那里开始,一切都是魔法......
这是一个示例实现脚本:
require([
//dependencies
'lib/jquery-1.6.1'
], function($) {
//You'll get access to jQuery locally rather than globally via $
});
通读 RequireJS API 看看这是否适合你。 我现在正在写我所有的脚本。 这很棒,因为在每个脚本的顶部,您确切地知道您的依赖项与服务器端语言相似 - Java 或 C#。
这是 jQuery 插件的常见做法,原因与您提到的相同:
;(function ($) {
/* ... your code comes here ... */
})(jQuery);
这是一个直接的 function。 如果你在里面声明你的“全局”变量,它们将是这个闭包的本地变量(对于你在里面创建的代码仍然是“全局的”)。 您的事件侦听器也将在这里工作,您仍然可以访问真正的全局变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.