因为 cs 仅在循环无法按预期工作时才声明变量。
这些循环的预期工作方式是什么?如果 不为空,则in 的条件while i = 0 < arr.length
将始终为真arr
,因此它将是一个无限循环。即使只有一个while
循环无法按预期工作(假设无限循环不是您要寻找的):
# This is an infinite loop; don't run it.
while i = 0 < arr.length
console.log arr[i]
i++
顺序迭代数组的正确方法是使用以下for ... in
构造:
arr = [[1,2], [1,2,3], [1,2,3]]
for hab in arr
# IDK what "hab" means.
for habElement in hab
console.log habElement
我知道这个答案听起来像是在切线;重点是为什么 CS 不鼓励可变阴影。但是,如果要用例子来论证支持或反对某事,那么例子应该是好的。这个例子无助于鼓励变量阴影的想法。
更新(实际答案)
关于变量阴影问题,值得澄清的一件事是讨论是否应该在不同的函数范围之间允许变量阴影,而不是块。在同一个函数范围内,变量将提升整个范围,无论它们首先被分配到哪里;这个语义继承自 JS:
->
console.log a # No ReferenceError is thrown, as "a" exists in this scope.
a = 5
->
if someCondition()
a = something()
console.log a # "a" will refer to the same variable as above, as the if
# statement does not introduce a new scope.
有时被问到的问题是为什么不添加一种方法来显式声明变量的范围,例如let
关键字(从而在封闭范围中隐藏其他具有相同名称的变量),或者=
总是在该范围中引入一个新变量,并且有类似:=
从封闭范围分配变量而不在当前范围中声明一个的东西。这样做的动机是避免这种错误:
user = ... # The current user of the application; very important!
# ...
# Many lines after that...
# ...
notifyUsers = (users) ->
for user in users # HO NO! The current user gets overridden by this loop that has nothing to do with it!
user.notify something
CoffeeScript 没有为隐藏变量提供特殊语法的论点是,您根本不应该做这种事情。清楚地命名你的变量。因为即使允许使用阴影,如果有两个具有两种不同含义的变量具有相同的名称,一个在内部范围内,一个在封闭范围内,这将是非常令人困惑的。
根据你有多少上下文使用适当的变量名:如果你有很少的上下文,例如一个顶级变量,你可能需要一个非常具体的名字来描述它,比如currentGameState
(特别是如果它不是一个常量并且它的值将随时间变化);如果您有更多上下文,则可以使用描述性较少的名称(因为上下文已经存在),例如循环变量:killedEnemies.forEach (e) -> e.die()
.
如果您想了解有关此设计决策的更多信息,您可能有兴趣阅读以下 HackerNews 线程中的 Jeremy Ashkenas 意见:链接、链接;或在讨论此主题的许多 CoffeeScript 问题中:#1121、#2697等。