Как лучше использовать расширение Firefox, чтобы не загрязнять глобальное пространство имен?
Я читал о загрязнении глобального пространства имен при разработке расширения для Firefox, и я хочу избежать этого в своем расширении, насколько это возможно. Существует несколько решений, но, как правило, решения сосредоточены вокруг объявления только одной глобальной переменной для вашего расширения и добавления всего этого. Таким образом, вы добавляете только одну дополнительную переменную в глобальное пространство имен, что не так уж плохо.
Вкратце, мне было предложено решение, позволяющее избежать добавления каких-либо дополнительных переменных в глобальное пространство имен; обернуть все в функцию. Проблема в том, что в ваших оверлейных программах XUL нет ничего, на что можно сослаться. Вы должны объявить элементы в ваших оверлеях, а затем в JS добавить тонну addEventListener
s, чтобы заменить то, что было бы что-то вроде oncommand="..."
в XUL. Я не хочу этого делать; Я определенно хочу, чтобы мой XUL включал события в сам XUL, потому что я думаю, что он выглядит чище, так что это не решение для меня. Поэтому мне нужно как минимум 1 глобальная переменная для XUL oncommand="..."
атрибуты для ссылки.
Таким образом, консенсус, похоже, состоит в том, чтобы иметь одну (и только одну) переменную для вашего расширения, и поместить весь ваш код в нее. Вот проблема: обычно люди рекомендуют, чтобы эта переменная называлась длинным уникальным именем, чтобы иметь почти нулевой шанс на столкновение с другими переменными. Так что, если идентификатор моего расширения myextension@mycompany.com
Я мог бы назвать мою переменную myextensionAtMycompanyDotCom
, или же com.mycompany.myextension
, Это хорошо для предотвращения коллизий в глобальном пространстве имен, но есть одна проблема; имя этой переменной длинное и громоздкое. Мой XUL будет изобиловать ссылками на обработчики событий в соответствии с oncommand="myextensionAtMycompanyDotCom.doSomeEvent"
, Нет никакого способа избежать обращения к глобальному пространству имен в моих наложениях XUL, потому что наложение просто добавляется в DOM окна браузера; у него нет собственного пространства имен, поэтому мы не можем каким-то образом ограничить область переменных нашего расширения только нашими собственными оверлеями. Итак, на мой взгляд, есть четыре решения:
1. Просто используйте длинное имя переменной в XUL
Это приводит к довольно громоздкому, подробному XUL-коду:
<statusbarpanel id="myStatusBar" onmousedown="myextensionAtMycompanyDotCom.onMyStatusBarClick();">
2. Добавьте элемент случайности к короткому имени переменной
Мы придумали более приятное короткое имя переменной для нашего расширения, скажем, myExt
и добавьте несколько случайных символов, чтобы сделать его почти наверняка уникальным, например: myExtAX8T9
, Тогда в XUL мы имеем:
<statusbarpanel id="myStatusBar" onmousedown="myExtAX8T9.onMyStatusBarClick();">
Понятно, что это приводит к довольно уродливому и даже запутанному коду, поскольку случайные символы выглядят странно и делают его похожим на временную переменную.
3. Не объявляйте глобальные переменные вообще
Вы можете просто обернуть все в функции. Это, конечно, означает, что в вашем XUL нет ничего, на что можно ссылаться, и поэтому каждое событие должно быть присоединено к элементам XUL с помощью addEventListener
в вашем коде JavaScript. Мне не нравится это решение, потому что, как упомянуто выше, я думаю, что было бы лучше иметь ссылки на события в коде XUL, а не искать тонну кода JS, чтобы найти, какие события присоединены к каким элементам XUL.
4. Просто используйте короткое имя переменной в XUL
Я мог бы просто вызвать переменную моего расширения myExt
, а затем я получаю хороший код XUL, как:
<statusbarpanel id="myStatusBar" onmousedown="myExt.onMyStatusBarClick();">
Конечно, это короткое имя гораздо чаще сталкивается с чем-то другим в глобальном пространстве имен и поэтому не является идеальным.
Итак, я что-то пропустил? Есть ли альтернатива 4 решениям, которые я предложил выше? Если нет, то что было бы лучшим из 4 (учитывая, что № 3 в принципе неприемлемо для меня), и почему?
2 ответа
Мы используем шаблон модуля JavaScript, описанный в этом сообщении в блоге: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth. Вы можете экспортировать символы, которые вы хотите использовать в ваших обработчиках XUL, как описано.
Кроме того, мы используем обратное имя хоста в качестве префикса имени модуля, чтобы гарантировать, что мы контролируем пространство имен:
/* Set up the global namespace. */
if (typeof(com) == "undefined") var com = {};
if (!com.salsitasoft) com.salsitasoft = {};
/* Main namespace. */
com.salsitasoft.myExtensionGlobalStuffGoesHere = (function (my) {
return my;
})(com.salsitasoft.myExtensionGlobalStuffGoesHere || {});
Обновление: я изменил это, чтобы передать com.salsitasoft.myExtensionGlobalStuffGoesHere в замыкание, если оно уже существует, чтобы пространство имен можно было распределить по нескольким файлам.
Ваши функции должны "жить" где-то в любом случае, поэтому вы не можете не претендовать на какое-то пространство имен. Я также согласен с вашей точкой зрения, что лучше определить событие в XUL, чем присоединить их. Итак, я предлагаю гибрид между 3+4:
- Найдите пространство имен, которое является уникальным для вашего плагина, но как можно более запоминающимся, например "catchyseo".
Поместите весь код вашего плагина и все переменные в это пространство имен. Используйте шаблон обертки анонимной функции, как (взгляните на некоторые плагины jQuery в качестве примеров кода):
window.catchyseo = (function(){var private = x; [...] })();
В вашем пространстве имен предоставьте некоторые обработчики событий, на которые вы можете ссылаться в вашем XUL.
Этот подход дает вам лучшее из двух миров: вы можете определять свои события в XUL, и у вас есть закрытое пространство имен без какого-либо глобального загрязнения пространства имен - за исключением одной переменной пространства имен.