中级javascript程序员编写更好代码的技巧

Tips for an intermediate javascript programmer to write better code

本文关键字:代码 更好 javascript 程序员 中级      更新时间:2023-09-26

所以我是一个相当不错的javascript程序员,最近我刚刚完成了一个相当大的web应用程序的工作,该应用程序需要编写相当多的javascript。在调试脚本时,我能遇到的一件事是,我在整个脚本中使用的各种全局变量之间存在一些名称空间冲突。从本质上讲,我的javascript文件的结构是这样的:

global var a
global var b
global var c
function1(){}
function2(){}
function3(){}

在ready函数上使用jQuery文档将各种事件绑定到我的html中的按钮,并将我的函数作为事件处理程序回调调用。

有些人建议将我的整个脚本封装在一个巨大的函数中,以防止任何与范围相关的错误。我不太清楚这到底意味着什么。在我即将创建另一个web应用程序时,任何提示都将受到赞赏,该应用程序将涉及相当多的AJAX页面加载,以避免浏览器刷新和与各种事件相关的DOM操作。谢谢

我建议阅读jQuery插件创作指南(如果不是,我还建议您考虑使用jQuery(

http://docs.jquery.com/Plugins/Authoring

BTW这个问题被问了很多次(不是对再次提问的批评(

  • jQuery:全局变量命名空间问题
  • 避免javascript依赖项污染全局命名空间
  • JavaScript命名空间

我还强烈建议您阅读关于注册DOM事件的jQuery实时插件(我想它现在是内置的(:http://api.jquery.com/live/(这将最大限度地减少对取消绑定和重新绑定DOM节点的状态管理的恶劣需求(。

Michael和nnnnnn版本的类似替代方案是执行

var YourApp = {
    a: 1234,
    b: 5678,
    function1: function () {
    },
    etc
};

YourApp是唯一的全局var,其属性可以像一样访问

YourApp.function1();

YourApp.a;

我喜欢将每个文件的内容包装在一个匿名函数中。然后,您可以将window作为参数传递给它,并选择性地选择从每个文件导出的内容。

(function(exports) {
var MyClass = function() {
};
MyClass.prototype.method = function() {
};
// this won't be visible outside this file
var helperFunction = function() {
};
exports.module = exports.module || {};
exports.module.MyClass = MyClass;
})(window);

此外,如果this更符合您的编码风格,您可以按以下方式构建它,将其用作全局对象:

(function() {
this.Thing = function() { };
}).call(window);

我预计会被OO纯粹主义者否决,但

命名空间冲突的一个非常简单的解决方案是将变量和函数放入一个类中,即使它没有工作的构造函数或执行自己的任何内部处理。

function YourApp() {} // empty constructor...
YourApp.a = 1234;
YourApp.b = 5678;
YourApp.function1 = function() {};
YourApp.function2 = function() {};
function YourOtherApp() {} // empty constructor...
YourOtherApp.a = 1234;
YourOtherApp.b = 5678;
YourOtherApp.function1 = function() {};
YourOtherApp.function2 = function() {};
// Then you call it like:
YourApp.function1();
// And you have no more namespace collisions with other globals

基于您过去对许多全局变量和函数所做的工作,最快的第一步就是简单地获取所有这些变量和函数,并使它们成为单个对象的属性。该单个对象被声明为全局变量,但它是您的唯一全局变量,实际上是您的新命名空间,因此您只需要担心一个名称可能与其他库冲突。

因此,将其直接与你用a、b等给出的例子联系起来:

var SNS = {}; // create some namespace object
SNS.a = "something";
SNS.b = "something else";
SNS.c = 17;
SNS.method1 = function(x) {
   alert(SNS.a + x);
};
SNS.method2 = function() {
   SSN.method1(12); // call another function
};
SNS.SUB = {};
SNS.SUB.property1 = "sub namespace prop 1";
SNS.SUB.method1 = function() {};
// etc.

我的示例使用"SNS"表示"some namespace";我相信你可以立即看到,将其应用于你刚刚完成的项目是多么容易。您可能还看到了一个缺点,即为了使方法相互引用并引用变量,您必须在所有方法前面加上对象的名称。如果您有子名称空间,情况会变得更糟。幸运的是,有一些方法可以解决这个问题,但我声明它们超出了这个答案的范围。

说了这么多,你可以在(谷歌(上阅读"揭示模块模式"——这将帮助你实现更多的OO(如果你想要的话(。

您的问题可以在这里找到一个非常深入的答案:http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/

进一步阅读:http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth