Ich sehe, dass der instanceof
Operator nicht mit Instanzen von Error
Unterklassen arbeitet, wenn er unter babel-node Version 6.1.18 / Node Version 5.1.0 unter OS X ausgeführt wird. Warum ist das so? Der gleiche Code funktioniert gut im Browser. Versuchen Sie es mit meiner Geige .
Der folgende Code wird true
im Browser ausgegeben, während er unter babel-node falsch ist:
class Sub extends Error {
}
let s = new Sub()
console.log(`The variable 's' is an instance of Sub: ${s instanceof Sub}`)
Ich kann mir nur vorstellen, dass dies auf einen Fehler in babel-node zurückzuführen ist, da dies instanceof
für andere Basisklassen als funktioniert Error
.
.babelrc
{
"presets": ["es2015"]
}
Kompilierte Ausgabe
Dies ist das von babel 6.1.18 kompilierte JavaScript:
'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));
javascript
node.js
ecmascript-6
babeljs
aknuds1
quelle
quelle
Antworten:
tl; dr Wenn Sie auf Babel 6 sind, können Sie https://www.npmjs.com/package/babel-plugin-transform-builtin-extend verwenden
Das Erweitern von integrierten Typen wie
Array
undError
und wurde in Babel noch nie unterstützt. Es ist in einer realen ES6-Umgebung vollkommen gültig, aber es gibt Anforderungen, damit es funktioniert, die sehr schwer auf eine Weise zu transpilieren sind, die mit älteren Browsern kompatibel ist. In Babel 5 "funktionierte" es, indem es keinen Fehler auslöste, aber Objekte, die aus der erweiterten Unterklasse instanziiert wurden, funktionierten nicht so, wie sie es sollten, zum Beispiel:class MyError extends Error {} var e1 = new MyError(); var e2 = new Error(); console.log('e1', 'stack' in e1); console.log('e2', 'stack' in e2);
führt zu
e1 false e2 true
Obwohl kein Fehler aufgetreten ist, erhält die Unterklasse nicht ordnungsgemäß einen "Stapel", wie dies bei Fehlern der Fall sein sollte. Wenn Sie es erweitern
Array
, verhält es sich möglicherweise ähnlich wie ein Array und verfügt über Array-Methoden, verhält sich jedoch nicht vollständig wie ein Array.In der Babel 5-Dokumentation wurde dies ausdrücklich als Randfall von Klassen bezeichnet, die beachtet werden sollten.
In Babel 6 wurden Klassen geändert, um den Umgang mit Unterklassen spezifikationskonformer zu gestalten. Ein Nebeneffekt davon ist, dass der obige Code jetzt immer noch nicht funktioniert, aber nicht anders als zuvor. Dies wurde in https://phabricator.babeljs.io/T3083 behandelt , aber ich werde hier auf eine mögliche Lösung eingehen.
Um das Verhalten der Unterklassen von Babel 5 zurückzugeben (das sich daran erinnert, dass es immer noch nicht richtig oder empfohlen ist), können Sie den eingebauten Konstruktor in Ihre eigene temporäre Klasse einschließen, z
function ExtendableBuiltin(cls){ function ExtendableBuiltin(){ cls.apply(this, arguments); } ExtendableBuiltin.prototype = Object.create(cls.prototype); Object.setPrototypeOf(ExtendableBuiltin, cls); return ExtendableBuiltin; }
Mit diesem Helfer, anstatt zu tun
class MyError extends Error {}
machen
class MyError extends ExtendableBuiltin(Error) {}
In Ihrem speziellen Fall haben Sie jedoch angegeben, dass Sie sich auf Knoten 5.x befinden. Knoten 5 unterstützt native ES6-Klassen ohne Transpilieren. Ich würde empfehlen, dass Sie diese verwenden, indem Sie die
es2015
Voreinstellung löschen und stattdessen verwenden,node5
damit Sie unter anderem native Klassen erhalten. In diesem Zusammenhangclass MyError extends Error {}
wird so funktionieren, wie Sie es erwarten.
Für Benutzer, die nicht auf Node 4/5 oder nur in Chrome sind, sollten Sie beispielsweise https://www.npmjs.com/package/error verwenden . Sie können auch https://www.npmjs.com/package/babel-plugin-transform-builtin-extend erkunden . Die
approximate
Option hierfür ist das gleiche Verhalten wie in Babel 5. Beachten Sie, dass das Nicht-approximate
Verhalten definitiv ein Randfall ist und in 100% der Fälle möglicherweise nicht funktioniert.quelle
Error
, um neue Ausnahmeklassen zu erstellen. AFAICT, dies sollte der Unterklasse in ES6 entsprechen, es sei denn, ich übersehen etwas. Ich habe auch diesen Artikel über die Semantik der ES6-Klasse gefunden, der genau ein Beispiel für die Unterbesetzung enthältError
.Wontfix
dieses Problem in phabricator markiert. Das ist etwas enttäuschend, weil ich dachte, ich sollte erwarten, dass diese Funktion funktioniert, zumindest wenn Babel es richtig und gemäß der Spezifikation gemacht hat.var CustomError = function(message){ Error.call(this, message) this.message = message }
instanceof
funktioniert nicht für untergeordnete Fehler, wenn das Kompilierungsziel auf "es5" gesetzt ist. Ich habe das Ziel in meinem auf "es6" gesetzttsconfig.json
undinstanceof
das richtige Ergebnis erzielt .quelle