coffeescript

coffeescript - Subclasificar objetos nativos: instanceof no funciona correctamente



(1)

Estoy intentando subclasificar el objeto JS Error nativo en CoffeeScript para obtener tipos de error especializados, pero encontré que la instanceof no funciona correctamente si no defino un constructor en las subclases:

class SimpleError extends Error class EmptyConstructorError extends Error constructor: -> class SuperConstructorError extends Error constructor: -> super new SimpleError instanceof SimpleError # -> false new EmptyConstructorError instanceof EmptyConstructorError # -> true new SuperConstructorError instanceof SuperConstructorError # -> true

El problema parece estar causado por la forma en que se definen las funciones de constructor JS generadas . Cuando no defino un constructor en CoffeeScript:

SimpleError = (function(_super) { __extends(SimpleError, _super); function SimpleError() { return SimpleError.__super__.constructor.apply(this, arguments); } return SimpleError; })(Error);

Y cuando defino un constructor en CoffeeScript:

SuperConstructorError = (function(_super) { __extends(SuperConstructorError, _super); function SuperConstructorError() { SuperConstructorError.__super__.constructor.apply(this, arguments); } return SuperConstructorError; })(Error);

Como puede ver, la diferencia es un simple return en el primer caso. Sin embargo, no entiendo por qué esto hace ninguna diferencia en la instanceof comportamiento, ya que el súper constructor solo se está aplicando a this objeto (es decir, el súper constructor no se llama con el new ), pero nuevamente no entiendo un mucho de cómo trabajan los constructores JS = P

Y lo extraño es que este comportamiento parece ocurrir solo cuando se subclasifican objetos JS nativos. Si subclasifico en las clases de CoffeeScript, todo funciona como se espera.

¿Alguna idea de por qué podría estar sucediendo esto y cómo podría evitar escribir constructores ficticios para que el operador instanceof funcione correctamente?

¡Gracias!

Actualizar

Así que el usuario matyr answered con un enlace a la confirmación donde se introdujo este comportamiento, pero no explica exactamente lo que está sucediendo aquí, así que intentaré explicarlo un poco en caso de que alguien más se pregunte por qué esto funciona de esta manera. .

El principal problema es esta "característica" desagradable heredada de JavaScript que nos permite definir una función constructora que devuelve un objeto distinto al que se está construyendo:

function Foo() { return {''LOL'': ''You fool!''}; } new Foo() instanceof Foo // -> false

Y también está el hecho de que algunos constructores nativos, como Error , Array , String y otras cosas, no necesitan ser llamados con new : simplemente devolverán un nuevo objeto del tipo correspondiente si lo olvidas.

Al final, agregue estas dos cosas feas juntas y el resultado es que debe recordar escribir la class MyError extends Error then constructor: -> super lugar de la class MyError extends Error más intuitiva class MyError extends Error si desea que la instanceof operador funcione correctamente con MyError . Esto se debe a que el constructor implícito de CoffeeScript solo devolverá lo que devuelva el constructor principal, y en este caso return Error.apply(this, arguments) que solo devolverá un nuevo objeto de error brillante en lugar del objeto que pasó como this argumento. ¡Hurra!

Actualización 2 (25 de febrero de 2013)

Este problema se solucionó en CoffeeScript 1.5.0 ! = D

Ahora la extensión de los objetos nativos funciona como se espera:

class MyError extends Error new MyError instanceof MyError # -> true :)

Actualización 3 (04 de marzo de 2013)

Aaand se ha ido en 1.6.0 = P


Para bien o para mal, la return se added en 1.3.1 para corregir #1966 (y #2111 ).