CoffeeScript 中简单的显式 Variable Shadowing

Coffeescript 里面一个比较特别的地方就是没有显式的 variable shadowing:

e.g. 1:

outer = 1
innerGlobal = 42

changeNumbers = ->
  inner = -1
  innerGlobal = -1
  outer = 10

inner = changeNumbers()

alert "#{inner} #{innerGlobal}"

这个做法最大的问题就是开发者很容易会在某一个层级的作用域把高层级作用域中的同名变量(name conflict)给覆盖掉,从而污染了上级作用域:

e.g. 2:

{sin, cos, PI} = math

coolCos = (x) ->
  cos = sin(x - PI / 2)

alert cos  # should be a function
alert cos PI / 2  # should be 0
alert coolCos(PI / 2)  # should be 0
alert cos  # cos is 0 now!

现实生活中的例子,请务必看 EDIT 部分。

虽然我很理解和认同 Jeremy 老师的说法

The real solution to this is to keep your top-level scopes clean, and be aware of what’s in your lexical scope. If you’re creating a variable that’s actually a different thing, you should give it a different name.

但如果真的要实实在在多人合作的话,还是提供一个官方的 work around 会比较好吧?(参考 lua 的 local)


#712 这个 issue 中,也有人提出了一个看起来还不错的解决方法

具体原理就是利用 JavaScript 的函数参数优先级比外层作用域高的特点,明确限定我们的局部变量的作用域。

(当然用 literal 的 var 也行,哪个好看就见仁见智了。)

于是 e.g. 2 可以改成如下:

e.g. 3:

outer = 1
innerGlobal = 42

changeNumbers = -> do (innerGlobal) ->
  inner = -1
  innerGlobal = -1
  outer = 10
  alert innerGlobal  # should be -1
  return outer

inner = changeNumbers()

alert "#{inner} #{innerGlobal}"  # innerGlobal should be 42

通过上述的方法(do 不是必须的),妈妈就再也不用担心同事把我的 coffeescript 代码弄坏啦!(虽然就是丑了点。)

comments powered by Disqus

Since 2014