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

Я хочу смочь упаковать свой код JavaScript в 'пространство имен' для предотвращения столкновений имени с другими библиотеками. Так как объявление пространства имен должно быть простой частью кода, я не хочу зависеть от любых внешних библиотек для предоставления мне эту функциональность. Я нашел различные советы о том, как сделать это просто, но ни один, кажется, не свободен от ошибок при пробежке JSLint (использующий опции 'The Good Parts').

Как пример, я попробовал это от Усовершенствованного JavaScript (раздел Namespaces без 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 = {};
}

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

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

Таким образом, это работает, но это кажется мне этим (так как MyNamespace всегда будет не определено в точке, она проверяется?) это эквивалентно намного более простому:

"use strict";
var MyNamespace = {};

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

20
задан Matthew Murdoch 5 May 2010 в 16:53
поделиться

4 ответа

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

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

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

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

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

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

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

(JSLint это тоже не нравится, так как «предположить браузер», похоже, не определить окно по какой-то непостижимой причине. Привет, хо.)

18
ответ дан 30 November 2019 в 00:09
поделиться

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

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

1
ответ дан 30 November 2019 в 00:09
поделиться

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

if(typeof(window['MyNamespace']) === 'undefined') {
3
ответ дан 30 November 2019 в 00:09
поделиться

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

Как насчет:

var MyNs;
if(MyNs==null){
    //foo()
}
1
ответ дан 30 November 2019 в 00:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: