jashkenas / coffeescript

Unfancy JavaScript
https://coffeescript.org/
MIT License
16.51k stars 1.99k forks source link

Bug: weird behavior in name resolving because of the lack of "var" in compiled code #5023

Closed whoiscc closed 6 years ago

whoiscc commented 6 years ago
test = ->
    dynamic_scoped_function = ->
        console.log("variable function value: #{variable_function()}")

    variable_function = ->
        "not in nested function"

    nested_function = ->
        variable_function = ->
            "in nested function"

        nested_caller = ->
            console.log("calling dynamic scoped function from nested caller...")
            dynamic_scoped_function()

        {nested_caller}

    {dynamic_scoped_function, nested_function}

# variable function value: not in nested function
test().dynamic_scoped_function()
# calling dynamic scoped function from nested caller...
# variable function value: in nested function
test().nested_function().nested_caller()

This behavior is awkward in my opinion, because when I was writing dynamic_scoped_function, I assumed that variable_function would always be resolved to the outer one. In the original version of my buggy code where I found this problem, the inner variable_function has nothing to do with dynamic_scoped_function. They just happen to have the same name.

This unexpected situation could be eliminated if I add var on both variable_function's definition. Could the compiler act in this way, too?

vendethiel commented 6 years ago

This unexpected situation could be eliminated if I add var on both variable_function's definition. Could the compiler act in this way, too?

CoffeeScript uses implicit scope. If we did that, we'd make it impossible to mutate a variable. There were discussion to have an assignment operator for outer scope (the fork livescript uses :=) though.