Javascript "Uncaught TypeError: objeto não é uma função" questão de associatividade

O código é o seguinte:

<body>
    <a href="javascript:;" id="test">hello</a>
</body>

<script type="text/javascript">
    document.getElementById("test").addEventListener("click", function () {
      test()
    }, false)
    function test() {
      var postTypes = new Array('hello', 'there')   
      (function() { alert('hello there') })()
    }
</script>

Isto vai lançar um:

" Uncaught TypeError: objeto não é uma função"

Se eu embrulhar a chamada/invocação de função anônima em outro conjunto de parênteses, ele executará o alerta, mas ainda assim me dará um erro. Se eu colocar um ponto-e-vírgula depois do "var postTypes" definição então ele vai ficar completamente bem.

Fui levado a acreditar que o javascript não requer semicolons, então eu'estou fazendo um palpite de que há algumas regras estranhas de associatividade de aplicação de funções que eu não estou entendendo totalmente. Porque é que estou a receber este erro?

Solução

O Javascript requer semicolons, it's apenas que a interpretação irá inseri-lo para você em quebras de linha quando o código se torna sintaxa-erro sem ele*.

Infelizmente, o código

var a = new B(args)(stuff)()

é não um erro de sintaxe, portanto nenhum ; será inserido. (Um exemplo que pode ser executado é

var answer = new Function("x", "return x")(function(){return 42;})();

Para evitar surpresas como esta, treine a si mesmo para sempre terminar uma declaração com ;.

(*: Apenas uma regra de polegar. Nem sempre é verdade. A regra da inserção é muito mais complicada. Esta página do blog sobre inserção de ponto-e-vírgula tem mais detalhes).

Comentários (1)

Seu código experimenta um caso onde o processo [Inserção automática de ponto-e-vírgula][1] (ASI) não't acontece.

Você nunca deve confiar na ASI. Você deve usar ponto-e-vírgula para separar corretamente as declarações:


var postTypes = new Array('hello', 'there'); // 
Comentários (5)

Recebi um erro semelhante e demorei algum tempo a perceber que no meu caso eu nomeei a matriz variável payInvoices e a função payInvoices também. Isso confundiu os AngularJs. Uma vez que mudei o nome para processPayments() finalmente funcionou. Só queria compartilhar esse erro e solução, pois demorei muito tempo para descobrir isso.

Comentários (1)