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

发布于 2024-11-17 18:36:36 字数 468 浏览 2 评论 0原文

所以我是一个相当不错的 JavaScript 程序员,最近我刚刚完成了一个相当大的 Web 应用程序的工作,其中涉及编写相当多的 JavaScript。当我调试脚本时,我遇到的一件事是,与我在整个脚本中使用的各种全局变量存在一些命名空间冲突。本质上,我的 javascript 文件的结构如下:

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

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

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

So I'm a fairly decent javascript programmer and I've just recently finished working on a fairly big web application that involved writing quite a bit of javascript. One of the things I can across when I was debugging my script was that there were some namespace conflicts with my various global variables I used throughout my script. Essentially, my javascript file was structured as such:

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

with a jQuery document on-ready function to bind various events to buttons in my html and call my functions as event handler callbacks.

Some people recommended encapsulating my entire script in one gigantic function to prevent any scope-related errors. I couldn't quite figure out exactly what that would entail. Any tips are appreciated as I am about to create another web app that will involve quite a bit of AJAX page loads to avoid browser refreshes and DOM manipulation bound to various events. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

会发光的星星闪亮亮i 2024-11-24 18:36:36

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

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

顺便说一句,这个问题已经被问过很多次了(不是对重新问的批评)

我还强烈建议您阅读有关注册 DOM 事件的 jQuery live 插件(我猜它现在是内置的):
http://api.jquery.com/live/
(这将最大限度地减少对解除绑定和重新绑定 DOM 节点的状态管理的讨厌需求)。

I recommend reading the jQuery plugin authoring guide (I also recommend you consider using jQuery if you are not)

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

BTW this been asked many times (not a criticism for re-asking)

I also highly recommend you read about jQuery live plugin for register DOM events(I guess its built-in now):
http://api.jquery.com/live/
(this will minimize the nasty need for state management of unbinding and rebinding your DOM nodes).

琉璃梦幻 2024-11-24 18:36:36

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

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

    },
    etc
};

YourApp 是唯一的全局变量,并且可以像

YourApp.function1();

或一样访问其属性

YourApp.a;

A similar alternative to Michael's and nnnnnn's version is to do

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

    },
    etc
};

YourApp is the only global var and its properties can be accessed like

YourApp.function1();

or

YourApp.a;
沉睡月亮 2024-11-24 18:36:36

我喜欢将每个文件的内容包装在匿名函数中。然后,您可以将 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);

I like wrapping the contents of each file inside an anonymous function. You can then pass window to this as a parameter and selectively choose what to export from each file.

(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);

Also, you can structure it in the following way to use this as the global object instead, if that appeals more to your coding style:

(function() {

this.Thing = function() { };

}).call(window);
恬淡成诗 2024-11-24 18:36:36

我预计会遭到 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

I expect to get downvoted from OO purists, but...

A very simple solution to the namespace collisions is to place your variables and functions into a class, even if it doesn't have a working constructor or perform any internal processing of its own.

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
谷夏 2024-11-24 18:36:36

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

因此,将其直接与您给出的 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”表示“某个名称空间”;我相信您可以立即看到如何轻松地将其应用到您刚刚完成的项目中。您可能还可以看到一个缺点,即为了让您的方法相互引用以及变量,您必须在它们前面加上对象名称的前缀。如果你有子命名空间,情况会变得更糟。幸运的是,有一些方法可以解决这个问题,但我声明它们超出了本答案的范围。

话虽如此,您可以在(Google)上阅读“揭示模块模式” - 将帮助您更多地面向对象(如果这就是您想要的)。

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

进一步阅读:
http://www.adequatelygood.com/2010/3/JavaScript -模块模式深入

The quickest first step based on what you have done in the past with lots of global variables and functions is to simply take all of those and make them properties of a single object. That single object is declared as a global variable, but it is your only global variable and is effectively your new namespace and thus you only have to worry about one name potentially clashing with other libraries.

So relating that directly to the example you gave with a, b, etc:

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.

My example uses 'SNS' for 'some namespace'; I'm sure you can immediately see how that would be pretty easy to apply to the project you just finished. You can probably also see the disadvantage that for your methods to refer to each other and to your variables you have to prefix them all with the name of your object. If you have sub namespaces that gets worse. Fortunately there are ways around that, but I'm declaring them outside the scope of this answer.

Having said all that, something for you to read up on (Google) is the "revealing module pattern" - will help you go a bit more OO (if that's what you want).

A really in-depth answer to your question can be found here: http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/

Further reading:
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文