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