Использование void в качестве синтаксического сахара для защиты от неявных глобалов, да или нет? - PullRequest
4 голосов
/ 12 марта 2011

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

var OuterFunction = function() { // closure container
    var renamedCounter = 0; // someone renamed counter,
    this.resetCounter = function () {
        counter = 0; // ... but forgot to check the inner functions as well.
        return this;
    };
    return this;
}

В этом примере counter внезапно становится глобальной переменной, а не локально ограничен экземплярами OuterFunction.

Объявляя переменную, захваченную замыканием void, вы получаете бесплатное утверждение, очень как и любой другой код, который использует counter без присвоения .

this.resetCounter = function () {
    void counter; // this will throw an Error if counter is not in scope.
    counter = 0;
    return this;
};

Редактировать : как указал jleedev , простое использование имени переменной, по-видимому, проверяет, оно существует, то есть

this.resetCounter = function () {
    counter;
    counter = 0;
    return this;
};

будет работать так же хорошо.

Я вижу следующие преимущества:

  • Это коротко писать.
  • Это выглядит как объявление переменной, до некоторой степени.
  • Отредактировано для добавления : Если все сделано последовательно, то для средства проверки синтаксиса (мяса или программы) очень просто выявлять ошибки такого рода.

С другой стороны:

  • Это сбивает с толку. На самом деле код ничего не делает .
  • Будущие интерпретаторы могут определить его как бессмысленный, бесполезный код и оптимизировать его.

Есть ли какие-то аспекты, которые я пропускаю? Это глупая идея или, по крайней мере, в некоторой степени оправданно?

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

Отредактировано для большой глупости : конечно, += пытается извлечь значение выражения перед приращением. Поэтому переименуйте пример в resetCounter, а не incrementCounter, чтобы он стал немного понятнее.

Ответы [ 2 ]

3 голосов
/ 12 марта 2011

В соответствии со спецификацией ECMASCript Language :

11.4.2. Оператор void

Производство UnaryExpression: void UnaryExpression оценивается следующим образом:

  1. Пусть expr будет результатом вычисления UnaryExpression.
  2. Вызов GetValue (expr).
  3. Возврат не определен.

NOTE GetValueдолжен вызываться, даже если его значение не используется, потому что оно может иметь наблюдаемые побочные эффекты.

Так что его никогда не следует оптимизировать.

Однако он не выглядит ИМХО удаленнокак «объявление» переменной, и, конечно, она не действует как единица, поэтому ее следует избегать.

РЕДАКТИРОВАТЬ: действительно, ее не следует использовать именно потому, что вызов GetValue может иметь побочные эффекты, например, еслипеременная на самом деле является свойством с «получателем».

1 голос
/ 12 марта 2011

Не уверен, является ли это ответом на ваш вопрос, но ECMAScript 5 вводит строгий режим , который предотвращает неявные глобальные объявления:

Присвоение необъявленного идентификатора или иным неразрешимым ссылкам не создает свойства в глобальном объекте. Когда в коде строгого режима происходит простое присвоение, его LeftHandSide не должен преобразовываться в неразрешимую ссылку. Если это так, выдается исключение ReferenceError ( 8.7.2 ). LeftHandSide также не может быть ссылкой на свойство данных со значением атрибута {[[Writable]]: false }, на свойство метода доступа со значением атрибута {[[Set]]: undefined }, а также к несуществующему свойству объекта, чье внутреннее свойство [[Extensible]] имеет значение false . В этих случаях выдается исключение TypeError ( 11.13.1 ).

В браузерах, которые его поддерживают (на данный момент это только Firefox 4), вы можете активировать строгий режим с помощью

"use strict";

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

...