type node isstring isobject check array javascript node.js ecmascript-6 babeljs

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