Подтвердить что ты не робот

Как определить пространство имен JavaScript для удовлетворения JSLint?

Я хочу иметь возможность упаковать код JavaScript в "пространство имен", чтобы предотвратить конфликты имен с другими библиотеками. Поскольку объявление пространства имен должно быть простым фрагментом кода, я не хочу зависеть от каких-либо внешних библиотек, чтобы предоставить мне эту функцию. Я нашел несколько советов о том, как это сделать просто, но ни один из них не может быть свободен от ошибок при прохождении через JSLint (используя ' Параметры "Хорошие детали" ).

В качестве примера я попробовал это из Advanced JavaScript (раздел Пространства имен без YUI):

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

Выполнение этого с помощью JSLint дает следующие ошибки:

Problem at line 2 character 12: 'MyNamespace' is not defined.
Problem at line 3 character 5: 'MyNamespace' is not defined.
Implied global: MyNamespace 2,3

Ошибка "Подразумеваемая глобальная" может быть исправлена ​​путем явного объявления MyNamespace...

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}

... и две другие ошибки могут быть исправлены путем объявления переменной вне блока if.

"use strict";
var MyNamespace;
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

Итак, это работает, но мне кажется, что (поскольку MyNamespace всегда будет undefined в той точке, где он проверен?), это эквивалентно намного проще:

"use strict";
var MyNamespace = {};

JSLint согласен с этим, но я обеспокоен тем, что я упростил код до такой степени, что он больше не будет правильно функционируют как пространство имен. Является ли эта окончательная формулировка разумной?

4b9b3361

Ответ 1

Не принимайте слово JSLint как евангелие. Многое из того, что он говорит, разумно, но в нем также содержится много догмы Крокфорда. В частности, я не всегда согласен с ним в отношении лучшего места для var.

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

Это нехорошо; JSLint правильно жаловаться на подразумеваемый глобальный. 'use strict' требует, чтобы вы не подразумевали глобальные переменные.

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}

Это хорошо. var поднимается, поэтому MyNamespace присутствует и устанавливается на undefined при вводе кода. Таким образом, вы можете выполнить этот тест как (MyNamespace===undefined), даже без возможности магической способности оператора typeof, чтобы вы могли ссылаться на переменные, которые не существуют.

Другим способом является использование однозначного оператора in (который является единственным способом отличить отсутствующее свойство, которое присутствует, но установлено на undefined). Для случая глобальных символов в обычном браузере script вы можете использовать его против глобального объекта window:

'use strict';
if (!('MyNamespace' in window)) {
    window.MyNamespace = {};
}

(JSLint тоже не нравится, поскольку "предполагается, что браузер не определяет window по какой-то непостижимой причине. Эй, хо).

Ответ 2

Вы можете попробовать гораздо более короткую версию:

var MyNamespace = MyNamespace || {};

Это должно быть справедливо в JSLint, даже в строгом режиме, используя имя, если оно уже существует, и создавая его, если это не так, как можно ожидать, что будет использоваться пространство имен в JavaScript.

Ответ 3

Это ДЕЙСТВИТЕЛЬНО старый вопрос, но я думал, что я все равно ответю, так как ни один из вышеперечисленных не очистил все ошибки jslint для меня, потому что я подозреваю, что lint'r был обновлен:-)

Там, возможно, другие способы сделать это, но с 2013 года это лучшее, что я могу придумать

Если вы хотите получить бесплатный шаблон jsLint с пространством имен и строго см. ниже

Предполагая, что это содержится в некотором .js файле...

this.ns = this.ns || {}; // Check for global namespace and if not found create 

(function(ns) {
  'use strict'   // restrict usage to this module 

  ns.myFunction = function() {
  } 

} (this.ns)); // Pass in the global namespace you 'might' have created above and 
              // drop 'this' reference

'this' необходим, чтобы избежать ошибки вне области видимости (похоже, это не имеет значения, но я предполагаю, что использование 'this' является явным или просто использует ns или var ns, оба из которых забрасывают ошибки.

Требуется шаблон iffy, чтобы избежать глобальной ошибки 'use strict'

Конечно, другим инструментам не нравится 'this' как предупреждение iffy о том, что он глобальный (это, конечно, цель), поэтому... томатный томат

Ответ 4

Вы можете получить доступ к глобальным переменным с помощью синтаксиса window["NAMEOFGLOBAL"], поэтому вместо этого вы можете сделать свой чек:

if(typeof(window['MyNamespace']) === 'undefined') {

Ответ 5

Конечно, точкой проверки undefined является обеспечение того, чтобы пользователи не выполняли двойную загрузку или переписывали существующее пространство имен. Таким образом, я думаю, вы зашли слишком далеко.

Как насчет:

var MyNs;
if(MyNs==null){
    //foo()
}

Ответ 6

Я столкнулся с этой проблемой раньше. Вы определенно не хотите использовать свою окончательную форму, поскольку она полностью обходит проверку определенной переменной и всегда будет перезаписывать ее на пустой объект, даже если в нем уже были сохранены.

Я думаю, что ваша вторая в последней форме самая подходящая для создания пространства имен, но на самом деле первая форма тоже приличная. Ошибки, которые JSLint сообщает с ним, являются, по-моему, уловкой-22, и не о чем беспокоиться. Причина, по которой я думаю, что не стоит оставлять объявление, заключается в том, что в случае, когда пространство имен загружается в какой-то предыдущий момент, вы попадаете в JSLint, "переменная была использована до ее определения", поэтому вы 'по существу, просто торгуя одним предупреждением для другого.