node - typeof javascript
¿Por qué la instancia de trabajo no funciona en instancias de subclases de error en babel-node? (1)
tl; dr Si estás en Babel 6, puedes usar https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
La extensión de tipos incorporados como
Array
y
Error
y otros nunca ha sido compatible con Babel.
Es perfectamente válido en un entorno ES6 real, pero hay requisitos para hacerlo funcionar que son muy difíciles de transpilar de una manera que sea compatible con los navegadores más antiguos.
"Funcionó" en Babel 5 en que no arrojó un error, pero los objetos instanciados de la subclase extendida no funcionaron como se suponía, por ejemplo:
class MyError extends Error {}
var e1 = new MyError();
var e2 = new Error();
console.log(''e1'', ''stack'' in e1);
console.log(''e2'', ''stack'' in e2);
resultados en
e1 false
e2 true
Si bien no se produjo un error, la subclase no obtiene correctamente una ''pila'' como se supone que deben obtener los errores.
Del mismo modo, si extendiera la
Array
, podría comportarse de manera similar a una matriz y tener métodos de matriz, pero no se comportaría completamente como una matriz.
La documentación de Babel 5 lo llamó específicamente como un caso límite de clases a tener en cuenta.
En Babel 6, las clases se cambiaron para cumplir con las especificaciones en cuanto a cómo se manejan las subclases, y un efecto secundario de esto es que ahora el código anterior todavía no funcionará, pero no funcionará de una manera diferente que antes. Esto se ha cubierto en https://phabricator.babeljs.io/T3083 , pero explicaré aquí una posible solución.
Para devolver el comportamiento de subclases de Babel 5 (que recuerde, todavía no es correcto o recomendado), puede ajustar el constructor incorporado en su propia clase temporal, por ejemplo
function ExtendableBuiltin(cls){
function ExtendableBuiltin(){
cls.apply(this, arguments);
}
ExtendableBuiltin.prototype = Object.create(cls.prototype);
Object.setPrototypeOf(ExtendableBuiltin, cls);
return ExtendableBuiltin;
}
Con este ayudante, en lugar de hacer
class MyError extends Error {}
hacer
class MyError extends ExtendableBuiltin(Error) {}
Sin embargo, en su caso específico, ha dicho que está en el Nodo 5.x.
El nodo 5 tiene soporte para clases nativas de ES6 sin transpilar.
Te recomiendo que los uses soltando el preset
es2015
y en su lugar usando
node5
para obtener clases nativas, entre otras cosas.
En ese contexto,
class MyError extends Error {}
funcionará de la manera que espera.
Para las personas que no están en el Nodo 4/5, o solo en Chrome reciente, puede considerar usar algo como
https://www.npmjs.com/package/error
.
También puede explorar
https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
.
La opción
approximate
de eso es el mismo comportamiento de Babel 5. Tenga en cuenta que el comportamiento no
approximate
es definitivamente innovador y puede no funcionar en el 100% de los casos.
Estoy viendo que el operador
instanceof
no funciona en instancias de subclases de
Error
, cuando se ejecuta en la versión 6.1.18
babel-node
babel / versión 5.1.0 del nodo en OS X. ¿Por qué es esto?
El mismo código funciona bien en el navegador, prueba mi
fiddle
como ejemplo.
El siguiente código genera
true
en el navegador, mientras que bajo babel-node es falso:
class Sub extends Error {
}
let s = new Sub()
console.log(`The variable ''s'' is an instance of Sub: ${s instanceof Sub}`)
Solo puedo imaginar que esto se debe a un error en el nodo babel, ya que
instanceof
funciona para otras clases base además de
Error
.
.babelrc
{
"presets": ["es2015"]
}
Salida compilada
Este es el JavaScript compilado por babel 6.1.18:
''use strict'';
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn''t been initialised - super() hasn''t been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var Sub = (function (_Error) {
_inherits(Sub, _Error);
function Sub() {
_classCallCheck(this, Sub);
return _possibleConstructorReturn(this, Object.getPrototypeOf(Sub).apply(this, arguments));
}
return Sub;
})(Error);
var s = new Sub();
console.log(''The variable /'s/' is an instance of Sub: '' + (s instanceof Sub));