Javascript Assoziativitätsfrage „Nicht gefangener Typfehler: Objekt ist keine Funktion“

91

Der Code lautet wie folgt:

<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>

Dies wird ein:

"Nicht gefangener TypeError: Objekt ist keine Funktion"

Wenn ich den anonymen Funktionsaufruf / Aufruf in einen anderen Satz von Klammern einbinde, wird die Warnung ausgeführt, es wird jedoch weiterhin ein Fehler ausgegeben. Wenn ich nach der Definition "var postTypes" ein Semikolon einfüge, ist das völlig in Ordnung.

Ich wurde zu der Überzeugung gebracht, dass für Javascript keine Semikolons erforderlich sind, daher vermute ich, dass es einige seltsame Assoziativitätsregeln für die Funktionsanwendung gibt, die ich nicht vollständig verstehe. Warum erhalte ich diesen Fehler?

PolandSpring
quelle
Sieht fast so aus, als würden Sie versuchen, sowohl eine anonyme als auch eine statische Funktion zu erstellen, und erwarten, dass sie als eine ausgeführt wird. Was passiert, wenn Sie function ()
brumScouse

Antworten:

85

Für JavaScript sind Semikolons erforderlich. Der Interpreter fügt sie nur dann in Zeilenumbrüche ein, wenn dies möglich ist * .

Leider ist der Code

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

führt nicht zu einem Syntaxfehler, daher wird no ;eingefügt. (Ein Beispiel, das ausgeführt werden kann, ist

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

Um solche Überraschungen zu vermeiden, trainieren Sie sich, eine Aussage immer mit zu beenden ;.


* Dies ist nur eine Faustregel und nicht immer wahr. Die Einfügungsregel ist viel komplizierter. Diese Blog-Seite zum Einfügen von Semikolons enthält weitere Details.

kennytm
quelle
13
Oder: Um solche Überraschungen zu vermeiden, trainieren Sie sich darin, sauberen lesbaren Code zu schreiben (der immer gelten sollte) und die allgemeinen ASI-Regeln zu kennen. Es ist wirklich nichts anderes, als zu "wissen", wie Schließungen in JS funktionieren.
18

In Ihrem Code tritt ein Fall auf, in dem der ASI-Prozess ( Automatic Semicolon Insertion ) nicht stattfindet.

Sie sollten sich niemals auf ASI verlassen. Sie sollten Semikolons verwenden, um Anweisungen richtig zu trennen:

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

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

Ihr Code hat tatsächlich versucht, das Array-Objekt aufzurufen.

CMS
quelle
Eine Möglichkeit, das Problem zu beheben, aber ich komme nicht hinter den Crockford-Club.
1
@pst: Lassen Sie mich anders formulieren, ich bin nicht in dem Crock's-Club bei allen :)
CMS
In diesem Fall entschuldige ich mich für die harten Worte :(
Ich habe das Quiz genossen. ASI ist in der Tat furchtbar verwirrend mit icky-Code!
8

Ich habe einen ähnlichen Fehler erhalten und es hat eine Weile gedauert, bis mir klar wurde, dass ich in meinem Fall die Array-Variable payInvoices und die Funktion payInvoices benannt habe. Es verwirrte AngularJs. Nachdem ich den Namen in processPayments () geändert hatte, funktionierte es endlich. Ich wollte nur diesen Fehler und diese Lösung teilen, da ich lange gebraucht habe, um das herauszufinden.

Naomi
quelle
Ebenso hatte ich eine Variable mit dem Namen alertund versuchte, die Javascript-Alarmfunktion aufzurufen, und es würde heißen, dass "Alarm keine Funktion ist". Es wurde versucht, die alertVariable anstelle der eigentlichen Funktion
aufzurufen
0

Versuchen Sie, den Funktionskörper vor dem Funktionsaufruf in Ihrer JavaScript-Datei zu haben.

CMPE
quelle
0

Ich bekam den gleichen Fehler und verbrachte anderthalb Tage damit, eine Lösung zu finden. Naomis Antwort führte mich zu der Lösung, die ich brauchte.

Meine Eingabe (Typ = Schaltfläche) hatte ein Attribut name, das mit einem Funktionsnamen identisch war, der vom Ereignis onClick aufgerufen wurde. Nachdem ich das Attribut geändert hatte, namefunktionierte alles.

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

gewechselt zu:

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

Ich habe diesen Fehler beim Kompilieren und Bündeln von TS mit WebPack. Es kompiliert export class AppRouterElement extends connect(store, LitElement){....}in let Sr = class extends (Object(wr.connect) (fn, vr)) {....}denen wegen der fehlenden Komma falsch zu sein scheint. Beim Bündeln mit Rollup kein Fehler.

Dzintars
quelle