Как заставить переменную быть локальной в coffeescript?

С учетом следующего кода:

outer=1
f=->
  local=1
  outer=0
  local+outer

coffeescript создает var для local, но re-ueses outer:

var f, outer;

outer = 1;

f = function() {
  var local;
  local = 1;
  outer = 0;
  return local + outer;
};

Это то, чего вы ожидаете.

Однако, если вы используете локальную переменную в функции, она зависит от внешней области, если переменная объявлена ​​локальной или нет. Я знаю, что это функция, но она вызывала некоторые ошибки, потому что я должен проверять все внешние области для переменных с тем же именем (которые объявлены перед моей функцией). Интересно, есть ли способ предотвратить этот тип ошибки, объявив переменные локальными?

Ответ 1

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

outer=1
f=->
  do (outer) ->
    local=1
    outer=0
    local+outer

Это создает IIFE, с outer как один аргумент. Аргументы функции теневые внешние переменные, как и ключевое слово var, так что это будет иметь поведение, которое вы ожидаете. Однако, как я уже сказал, вы должны просто называть свои переменные более описательно.

Ответ 2

Нет, эта функция явно не доступна в CoffeeScript (внимание мое):

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

Ответ 3

Вы можете ввести обычный JavaScript в свой CoffeeScript, используя обратные ссылки:

outer=1
f=->
  local=1
  `var outer=0`
  local+outer

В большинстве случаев я стараюсь избегать этого и предпочитаю переименовывать внешние переменные, указывая их область/контекст в их имени. Однако иногда это полезно, например, при использовании модуля отладки, где я всегда хочу иметь функцию debug(), доступную для ведения журнала, как в этом примере:

#logging fn for module setup and other global stuff
debug = require("debug")("foo")

class Bar
  #local logging fn to allow Bar instances to log stuff
  `var debug = require("debug")("foo:bar")`

Если вы хотите сохранить простой JS как минимум, просто объявите переменную, а затем назначьте использование CoffeeScript:

  `var debug`; debug = require("debug") "foo:bar"

Пример компилируется в:

// Generated by CoffeeScript 1.7.1 -- removed empty lines for SO answer
var Bar, debug;    
debug = require("debug")("foo");    
Bar = (function() {
  function Bar() {}    
  var debug;    
  debug = require("debug")("foo:bar");    
  return Bar;    
})();

Мне нравится этот прямой способ объявления переменных лучше, чем (IMHO) более медленный и менее читаемый взлом IIFE.

Ответ 4

Как отметил Аарон, затенение действительно возможно:

outer=1
f=->
  do (outer) ->
    local=1
    outer=0
    local+outer

Поскольку внешнее значение не требуется внутри локальной функции, оно может быть инициализировано с помощью null только в том случае, если в какой-то момент переменная outer будет удалена из внешней области (что вызовет ошибку).

#outer=1
f=->
  do (outer=null) ->
    local=1
    outer=0
    local+outer

Ответ 5

important = 10 # global

main = ->
    agentId = '007'
    console.log 'global `important`', important # refers to the global variable

    ((important) -> # place the local variables as the arguments
        important = 20
        console.log 'local `important`', important # locally scoped
        console.log 'parent scope value', agentId # even access variables from the above scopes
    )() # not passing anything, so the local varibales would be left undefined at first

    console.log 'global `important`', important # the global variable remains untouched

main()