如何强制变量在coffeescript中是本地的?

时间:2013-08-14 11:17:19

标签: coffeescript

给出以下代码:

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

coffeescript为var创建local但重新outer

var f, outer;

outer = 1;

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

这是您的期望。

但是,如果在函数中使用局部变量,则如果变量声明为local,则它取决于外部作用域。我知道这是一个功能,但它导致了一些错误,因为我必须检查所有外部作用域的同名变量(在我的函数之前声明)。我想知道是否有办法通过声明变量本地来防止这种类型的错误?

5 个答案:

答案 0 :(得分:12)

当您没有使用适当的描述性变量名称时,通常会出现此类错误。也就是说,尽管接受的答案是:

,但有一种方法可以遮蔽外部变量
outer=1
f=->
  do (outer) ->
    local=1
    outer=0
    local+outer

这会创建一个IIFE,outer作为一个参数。函数参数与var关键字一样影响外部变量,因此这将具有您期望的行为。但是,就像我说的那样,你应该更具描述性地命名你的变量。

答案 1 :(得分:6)

不,该功能在CoffeeScript中明确(强调我的):

  

这种行为实际上与Ruby的局部变量范围相同。由于您无法直接访问var关键字,无法故意隐藏外部变量,因此您只能引用它。因此,如果您正在编写一个深层嵌套的函数,请注意不要意外地重用外部变量的名称。

答案 2 :(得分:6)

您可以使用反引号将纯JavaScript注入到CoffeeScript中:

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

对于大多数情况,我试图避免这种情况,而是宁愿重命名外部变量,在其名称中指出它们的范围/上下文。但是,有时这很有用,例如,在使用 debug 模块时,我总是希望有一个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黑客更好。

答案 3 :(得分:2)

正如亚伦指出的那样,阴影确实是可能的:

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

答案 4 :(得分:0)

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()