Как лучше использовать расширение 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, и у вас есть закрытое пространство имен без какого-либо глобального загрязнения пространства имен - за исключением одной переменной пространства имен.

Другие вопросы по тегам