Советы для среднего программиста javascript, чтобы написать лучший код
Итак, я довольно приличный программист javascript, и я только недавно закончил работу над довольно большим веб-приложением, которое включало написание довольно большого количества javascript. Одна из вещей, с которой я столкнулся, когда отлаживал свой сценарий, заключалась в том, что были некоторые конфликты пространства имен с моими различными глобальными переменными, которые я использовал в своем сценарии. По сути, мой javascript-файл был структурирован следующим образом:
global var a
global var b
global var c
function1(){}
function2(){}
function3(){}
С помощью функции jQuery document on-ready для привязки различных событий к кнопкам в моем html и вызов моих функций в качестве обратных вызовов обработчика событий.
Некоторые люди рекомендовали инкапсулировать весь мой сценарий в одну гигантскую функцию, чтобы предотвратить любые ошибки, связанные с областью действия. Я не мог точно понять, что это повлечет за собой. Любые советы приветствуются, поскольку я собираюсь создать еще одно веб-приложение, которое будет включать довольно много загрузок страниц AJAX, чтобы избежать обновления браузера и манипуляций DOM, связанных с различными событиями. Спасибо!
5 ответов:
Я рекомендую прочитать руководство по разработке плагинов jQuery (я также рекомендую вам рассмотреть возможность использования jQuery, если вы не являетесь)
Http://docs.jquery.com/Plugins/Authoring
Кстати, об этом спрашивали много раз (не критика за повторный вопрос)
- jQuery: проблема пространства имен глобальных переменных
- избегая загрязнения глобального пространства имен зависимостями javascript
- Пространство Имен JavaScript
I также очень рекомендую вам прочитать о плагине jQuery live для регистрации событий DOM (я думаю, что теперь он встроен): http://api.jquery.com/live/ (это сведет к минимуму неприятную необходимость в управлении состоянием развязки и повторной привязки узлов DOM).
Аналогичная альтернатива версии Майкла и ннннн-это сделать
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);
я ожидаю получить понижение от ОО пуристов, но...
Очень простое решение конфликтов пространств имен-поместить переменные и функции в класс, даже если он не имеет работающего конструктора или выполняет какую-либо внутреннюю обработку самостоятельно.
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, 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.
В моем примере используется " SNS " для "некоторого пространства имен"; я уверен, что вы сразу увидите, как это было бы довольно легко применить к проекту, который вы только что закончили. Вы, вероятно, также можете видеть недостаток, что для того, чтобы ваши методы ссылались друг на друга и на ваши переменные, вы должны префиксировать их все именем вашего объекта. Если у вас есть подпространства, это становится еще хуже. К счастью, есть способы обойти это, но я объявляю их вне сферы этого ответ.
Сказав Все это, кое - что для вас, чтобы прочитать на (Google) является "выявление шаблон модуля" - поможет вам пойти немного больше 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