Pergunta de associatividade “Uncaught TypeError: o objeto não é uma função” Javascript

92

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>

Isso vai lançar um:

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

Se eu envolver a chamada / invocação de função anônima em outro conjunto de parênteses, ele executará o alerta, mas ainda assim fornecerá um erro. Se eu colocar um ponto e vírgula após a definição de "var postTypes", tudo bem.

Fui levado a acreditar que o javascript não requer ponto-e-vírgula, então estou supondo que há algumas regras de associatividade estranhas de aplicação de função que não estou entendendo totalmente. Por que estou recebendo este erro?

PolandSpring
fonte
Parece que você está tentando criar uma função anônima e uma função estática e esperando que ela seja executada como uma só. O que acontece se você remover function ()
brumScouse

Respostas:

85

JavaScript requer ponto-e-vírgulas, é só que o interpretador irá inseri-los para você nas quebras de linha, sempre que possível * .

Infelizmente, o código

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

se não resultar em um erro de sintaxe, por isso não ;vai ser inserido. (Um exemplo que pode ser executado é

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

Para evitar surpresas como essa, treine-se para sempre terminar uma frase com ;.


* Esta é apenas uma regra prática e nem sempre verdadeira. A regra de inserção é muito mais complicada. Esta página do blog sobre inserção de ponto e vírgula tem mais detalhes.

Kennytm
fonte
13
Ou: Para evitar surpresas como essa, treine-se para escrever um código legível limpo (que sempre deve ser aplicável) e conheça as regras gerais do ASI ... realmente não é diferente de "saber" como os fechamentos em JS funcionam.
18

Seu código passa por um caso em que o processo de inserção automática de ponto-e-vírgula (ASI) não acontece.

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

var postTypes = new Array('hello', 'there'); // <--- Place a semicolon here!!

(function() { alert('hello there') })();

Seu código estava realmente tentando invocar o objeto array.

Christian C. Salvadó
fonte
Uma maneira de resolver o problema, mas não consigo apoiar o clube Crockford.
1
@pst: Deixe-me reformular, eu não estou no Crock's-clube em tudo :)
Christian C. Salvadó
Nesse caso, peço desculpas pelas palavras duras :(
Eu gostei do teste. ASI é de fato terrivelmente confuso com o código icky!
8

Recebi um erro semelhante e demorei um pouco para perceber que, no meu caso, chamei a variável de array payInvoices e a função também payInvoices. Isso confundiu os AngularJs. Depois de alterar o nome para processPayments (), finalmente funcionou. Só queria compartilhar esse erro e a solução, pois demorei muito para descobrir isso.

Naomi
fonte
O mesmo aqui, eu tinha uma variável chamada alerte estava tentando chamar a função de alerta javascript e dizia 'alert is not a function'. Ele estava tentando chamar a alertvariável em vez da função real
James111
0

Tente ter o corpo da função antes da chamada da função em seu arquivo JavaScript.

CMPE
fonte
0

Eu estava recebendo esse mesmo erro e passei um dia e meio tentando encontrar uma solução. A resposta de Naomi me levou à solução de que eu precisava.

Minha entrada (tipo = botão) tinha um atributo nameque era idêntico a um nome de função que estava sendo chamado pelo evento onClick. Depois que mudei o atributo, nametudo funcionou.

<input type="button" name="clearEmployer" onClick="clearEmployer();">

alterado para:

<input type="button" name="clearEmployerBtn" onClick="clearEmployer();">
tbriggs707
fonte
0

Tenho este erro ao compilar e agrupar o TS com o WebPack. Ele compila export class AppRouterElement extends connect(store, LitElement){....}no let Sr = class extends (Object(wr.connect) (fn, vr)) {....}que parece errado por causa da vírgula ausente. Ao empacotar com Rollup, nenhum erro.

Dzintars
fonte