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

Mic*_*arf 11 coffeescript

给出以下代码:

outer=1
f=->
  local=1
  outer=0
  local+outer
Run Code Online (Sandbox Code Playgroud)

coffeescript创建了一个varfor localbut ree uses outer:

var f, outer;

outer = 1;

f = function() {
  var local;
  local = 1;
  outer = 0;
  return local + outer;
};
Run Code Online (Sandbox Code Playgroud)

这是你的期望.

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

Aar*_*our 12

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

outer=1
f=->
  do (outer) ->
    local=1
    outer=0
    local+outer
Run Code Online (Sandbox Code Playgroud)

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

  • `do`非常有助于*冻结外部变量的状态.但是,我认为意外使用外部变量的问题是设计coffeescript范围的方式所固有的... (3认同)
  • 在我描述它的时候,我会使用`do`,我会知道`outer`正在影响外部变量.在这种情况下,我可以通过使用其他名称来避免它.我在谈论意外命名变量,如外部变量.如果你将一个函数移动到另一个地方并且突然有一个从外部作用域继承的变量,这可能会很棘手,否则就是本地....我正在寻找一个模式来确保我想要的所有局部变量都是本地的. ..可以对所有局部变量使用`do`,但这很奇怪.... (2认同)

Joa*_*uer 6

不,这个功能在CoffeeScript中显然不可用(强调我的):

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

  • 我知道了.例如,在python中,你可以访问外部变量但不能修改它们(在python 3.x中有一个关键字````nonlocal```来做).我认为,外部变量的隐式修改可能容易出错...... (2认同)

Juv*_*uve 6

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

outer=1
f=->
  local=1
  `var outer=0`
  local+outer
Run Code Online (Sandbox Code Playgroud)

对于大多数情况,我试图避免这种情况,而宁愿重命名外部变量,在其名称中指出它们的范围/上下文.但是,有时这很有用,例如,在使用调试模块时,我总是希望有一个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")`
Run Code Online (Sandbox Code Playgroud)

如果你想保持简单的JS至少只声明变量然后分配使用CoffeeScript:

  `var debug`; debug = require("debug") "foo:bar"
Run Code Online (Sandbox Code Playgroud)

该示例编译为:

// 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;    
})();
Run Code Online (Sandbox Code Playgroud)

我喜欢这种直接的方式来声明变量比(IMHO)更慢和更不易读的IIFE黑客更好.