Pregunta de asociatividad de Javascript "Uncaught TypeError: el objeto no es una función"

92

El código es el siguiente:

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

Esto arrojará un:

"Error de tipo no detectado: el objeto no es una función"

Si envuelvo la llamada / invocación de función anónima en otro conjunto de paréntesis, ejecutará la alerta, pero aún así me dará un error. Si pongo un punto y coma después de la definición de "var postTypes", estará completamente bien.

Me hicieron creer que javascript no requiere punto y coma, así que supongo que hay algunas reglas de asociatividad extrañas de aplicación de funciones que no entiendo completamente. ¿Por qué recibo este error?

PoloniaPrimavera
fuente
Casi parece que está intentando crear una función anónima y una función estática y espera que se ejecute como una. ¿Qué ocurre si se quita la función ()
brumScouse

Respuestas:

85

JavaScript requiere punto y coma, es solo que el intérprete los insertará en los saltos de línea cuando sea posible * .

Desafortunadamente, el código

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

no da como resultado un error de sintaxis, por lo que no ;se insertará. (Un ejemplo que se puede ejecutar es

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

Para evitar sorpresas como esta, entrénate para terminar siempre una declaración con ;.


* Esto es solo una regla de oro y no siempre es cierto. La regla de inserción es mucho más complicada. Esta página de blog sobre la inserción de punto y coma tiene más detalles.

Kennytm
fuente
13
O bien: Para evitar sorpresas como esta, entrénate para escribir código legible limpio (que siempre debe aplicarse) y conoce las reglas generales de ASI ... realmente no es diferente a "saber" cómo funcionan los cierres en JS.
18

Su código experimenta un caso en el que el proceso de inserción automática de punto y coma (ASI) no ocurre.

Nunca debe confiar en ASI. Debe usar punto y coma para separar correctamente las declaraciones:

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

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

Su código en realidad estaba tratando de invocar el objeto de matriz.

Christian C. Salvadó
fuente
Una forma de solucionar el problema, pero no puedo respaldar al club Crockford.
1
@pst: Déjame reformular, no estoy en el club de Crock en absoluto :)
Christian C. Salvadó
En ese caso, me disculpo por las duras palabras :(
Disfruté el cuestionario. ¡ASI es de hecho terriblemente confuso con icky-code!
8

Recibí un error similar y me tomó un tiempo darme cuenta de que en mi caso nombré la variable de matriz payInvoices y la función también payInvoices. Confundió AngularJs. Una vez que cambié el nombre a processPayments () finalmente funcionó. Solo quería compartir este error y solución, ya que me tomó mucho tiempo resolverlo.

Naomi
fuente
Lo mismo aquí, tenía una variable nombrada alerty estaba tratando de llamar a la función de alerta de JavaScript y decía 'alerta no es una función'. Intentaba llamar a la alertvariable en lugar de a la función real
James111
0

Intente tener el cuerpo de la función antes de la llamada a la función en su archivo JavaScript.

CMPE
fuente
0

Recibí este mismo error y pasé un día y medio tratando de encontrar una solución. La respuesta de Naomi me llevó a la solución que necesitaba.

Mi entrada (tipo = botón) tenía un atributo nameque era idéntico a un nombre de función que estaba siendo llamado por el evento onClick. Una vez que cambié el atributo, nametodo funcionó.

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

cambiado a:

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

Tengo este error al compilar y empaquetar TS con WebPack. Se compila export class AppRouterElement extends connect(store, LitElement){....}en lo let Sr = class extends (Object(wr.connect) (fn, vr)) {....}que parece incorrecto debido a que falta una coma. Al empaquetar con Rollup, no hay error.

Dzintars
fuente