これをバグ、または少なくとも文書化されていないエッジケースまたはあいまいさと呼ぶと思います。ドキュメントには、CoffeeScript で新しいローカル変数がいつ作成されるかを明示的に指定するものは何も表示されないため、通常の
現在の実装がXを実行するときにXを実行しますが、これは現在の実装がそのように実行するために発生します。
みたいなこと。
新しい変数の作成をトリガーすると思われる条件は代入です。値を与えようとすると、CoffeeScript が新しい変数の作成を決定したように見えます。したがって、この:
a = ->
e = e + 1
になる
var a;
a = function() {
var e;
return e = e + 1;
};
値を明示的に割り当てているため、ローカルe
変数を使用e
します。単にe
式で参照する場合:
b = ->
e += 1
その場合、CoffeeScript は新しい変数を作成しませんe
。そこに割り当てがあることを認識しないからです。e +=1
CS は式を認識しますが、 と同等と見なすほどスマートではありませんe = e + 1
。
興味深いことに、op=
JavaScript ではなく CoffeeScript の一部であるフォームを使用すると、CS は問題を認識します。例えば:
c = ->
e ||= 11
次のエラーが発生します。
変数 "e" は定義されていないため ||= で代入できません
同様の苦情を申し立てることe += 1
は、賢明で一貫性があると思います。または、すべてのa op= b
式を展開してa = a op b
同等に扱う必要があります。
CoffeeScript のソースを見ると、何が起こっているかがわかります。少し調べてみると、すべてのop=
構成が最終的に通過することがわかりAssign#compileNode
ます。
compileNode: (o) ->
if isValue = @variable instanceof Value
return @compilePatternMatch o if @variable.isArray() or @variable.isObject()
return @compileSplice o if @variable.isSplice()
return @compileConditional o if @context in ['||=', '&&=', '?=']
#...
そのため、CoffeeScript 固有のop=
条件構造には、期待どおりの特別な処理があります。簡単なレビューでは、無条件a op= b
(op
つまり、 、、およびop
以外の) は JavaScript に直接渡すことをお勧めします。それで、何が起こっているのですか?予想どおり、宣言されていない変数を使用していないことを確認します。||
&&
?
compileCondtional
compileConditional: (o) ->
[left, right] = @variable.cacheReference o
# Disallow conditional assignment of undefined variables.
if not left.properties.length and left.base instanceof Literal and
left.base.value != "this" and not o.scope.check left.base.value
throw new Error "the variable \"#{left.base.value}\" can't be assigned with #{@context} because it has not been defined."
#...
表示されるエラー メッセージと、がどこかに定義されていない場合は-> a ||= 11
許可されていないことを示すコメントがあります。a ||= b
a