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

Автоматически создаваемые переменные из идентификаторов в JS?

Только сегодня, через пару лет программирования javascript, я наткнулся на то, что меня поразило. Браузеры создают объекты для каждого элемента с идентификатором. Имя объекта будет соответствовать идентификатору.

Итак, если у вас есть:

<div id ="box"></div>

Вы можете сделать:

alert(box); //[object HTMLDivElement]

Не назначая ничего этой переменной. См. демонстрацию.

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

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

Обновление: Кажется, что FF делает это только в режиме quirks. Другие браузеры, такие как IE6 + и Chrome, делают это сразу же с места.

4b9b3361

Ответ 1

ECMAScript 5 strict должен помочь с этим, так как вы не можете использовать необъявленные переменные. Я не уверен, какие браузеры в настоящее время поддерживают строгий режим, но я знаю, что Firefox 4 делает.

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

Я не знаю, включена ли эта функция в исходную спецификацию, но я ожидаю, что она будет удалена, запрещена или иным образом аннулирована в последующих версиях ECMAScript. ES6 будет основываться на строгом ES5.

В JavaScript есть много возможностей, которые облегчают использование для новичков и новичков, я подозреваю, что это одна из таких функций. Если вы профессионал и хотите, чтобы качественный код использовал "use strict"; и всегда JSLint ваш код. Если вы используете эти рекомендации, эта функция никогда не должна вас беспокоить.

Вот полезное видео о ES5, предоставленное YUI Theatre (это уже 2 года, хотя, но все еще актуально в настоящее время, поскольку ES6 пока).

Ответ 2

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

Если вы объявите свою собственную глобальную переменную, она просто переопределит все, что создавал браузер для вас, чтобы на самом деле не было конфликта. Единственное место, где я мог видеть, что это потенциально может вызвать проблему, - это тестирование на существование глобального объявления и "авто" глобального на основе идентификатора объекта, полученного на пути и смущения.

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

Ответ 3

Да, большинство браузеров делают это, но потом снова, как вы сказали, некоторые не делают (firefox), поэтому не рассчитывайте на это. Также легко переписать эти переменные в js, я могу себе представить, что что-то вроде container может быть перезаписано прямо на летучей мыши кем-то, использующим эту переменную, не объявив сначала.

Нет никакого способа превратить это в chrome afaik, но даже тогда это может быть хлопот, чтобы понять это и исправить его для всех браузеров.

Не придавайте этому слишком большого значения, но остерегайтесь этого. Это одна из тех причин, почему вы избегаете глобальной области переменных.

Для завершения этих браузеров они, безусловно, делают это по умолчанию: Chrome, IE9 и compat, Opera

Обновление: будущие версии ECMAScript могут включать в себя некоторую опцию, поскольку обсуждение дается, но это не будет исправлять проблему в более старых браузерах.

Ответ 4

Я не думаю, что есть способ отключить его, но вам не нужно придавать этому большое значение. Если вы боитесь непредсказуемых ошибок, вы можете избежать их, используя JSHint или JSLint. Они помогут вам избежать ошибок. Например, они будут предупреждать вас, если вы используете необъявленную переменную.

Ответ 5

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

1) Как показано в статье, с которой вы связаны, вы можете обойти это, указав каждую переменную перед ее использованием. Я бы достиг этого, выполнив мой код через JSLint, который предупреждает об этом (в дополнение к кучей других распространенных ошибок).

2) Однако, поскольку можно забыть запустить код через JSLint, вы можете предпочесть шаг в цепочке инструментов, который вы не можете забыть. В этом случае посмотрите CoffeeScript - это langauge, очень похожая на javascript, которую вы компилируете в javascript перед использованием, и вставляет правильную var для вас. На самом деле, я подозреваю, что вы не можете писать код, который опирается на автоматическую создание переменных элементов с помощью CoffeeScript.

Ответ 6

Вот что я смог придумать для удаления глобальных переменных, которые автоматически создаются для объектов DOM с идентификационным значением:

function clearElementGlobals() {
    function clearItem(iden, item) {
        if (iden && window[iden] && (window[iden] === item)) {
            window[iden] = undefined;
        }
    }

    var list = document.getElementsByTagName("*");
    for (var i = 0, len = list.length; i < len; i++) {
        var item = list[i];
        clearItem(item.id, item);
        clearItem(item.name, item);
    }
}

Получает список всех объектов на странице. Он просматривает поиск значений с идентификатором и когда для него существует значение id и глобальная переменная, и эта глобальная переменная указывает на этот объект DOM, эта глобальная переменная устанавливается на undefined. Как оказалось, браузеры также делают это же авто-глобальное для некоторых типов тегов с атрибутом имени (например, элементами формы), поэтому мы также очищаем их.

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

К сожалению, вы не можете удалить глобальные переменные в javascript, поэтому настройка его на undefined - это лучшее, что можно сделать.

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

FYI, вы спросили о строгом режиме в своем вопросе. строгий режим применяется только к заданной области кода, поэтому не было бы никакого способа заставить его влиять на способ создания глобального пространства имен. Чтобы повлиять на что-то подобное, это должно было быть что-то на уровне документа до того, как документ был проанализирован как опция DOCTYPE или что-то в этом роде.

Предостережения с этой функцией.

  • Запустите его, прежде чем создавать какие-либо из ваших собственных глобалов или не создавайте никаких своих глобальных глобалов с тем же именем, что и атрибут ID или name, который также указывает на этот объект DOM.
  • Это одноразовый снимок, а не непрерывный. Если вы динамически создаете новые объекты DOM, вам придется повторно запустить эту функцию, чтобы очистить все новые глобальные переменные, которые могли быть сделаны из новых объектов DOM.
  • Глобалы устанавливаются на undefined, что немного отличается от того, что они никогда не были там в первую очередь. Я не могу придумать случай программирования, где это действительно имеет значение, но оно не идентично. К сожалению, вы не можете удалить глобальные переменные.