[解決済み] babel-nodeでErrorのサブクラスのインスタンスにinstanceofが効かないのはなぜですか?
質問
私は
instanceof
のインスタンスでは
Error
サブクラスのインスタンスでは動作しません。
バベルノード
バージョン 6.1.18/Node バージョン 5.1.0 で OS X 上で動作しているときです。これはなぜでしょうか?同じコードがブラウザではうまく動作します。
フィドル
を試してみてください。
以下のコードで出力される
true
を出力しますが、babel-nodeの下ではfalseです。
class Sub extends Error {
}
let s = new Sub()
console.log(`The variable 's' is an instance of Sub: ${s instanceof Sub}`)
これはbabel-nodeのバグによるものとしか思えません、なぜなら
instanceof
以外のベースクラスでは
Error
.
.babelrc
{
"presets": ["es2015"]
}
コンパイル出力
babel 6.1.18でコンパイルされた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));
どのように解決するのですか?
tl;dr Babel 6を使用している場合は、以下のようになります。 https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
のような組み込み型の拡張
Array
と
Error
などはBabelではサポートされたことがありません。実際のES6環境では完全に有効ですが、古いブラウザと互換性のある方法でトランスパイルするのが非常に困難な、動作させるための要件があります。Babel 5 では、エラーを投げないという点では動作しましたが、たとえば、拡張サブクラスからインスタンス化されたオブジェクトは、想定したようには動作しませんでした。
class MyError extends Error {}
var e1 = new MyError();
var e2 = new Error();
console.log('e1', 'stack' in e1);
console.log('e2', 'stack' in e2);
の結果は
e1 false
e2 true
エラーにはなりませんでしたが、このサブクラスはエラーが想定しているような「スタック」を適切に取得しません。同様に、もしあなたが
Array
を拡張した場合、それは多少配列のように振る舞い、配列メソッドを持つかもしれませんが、完全に配列のように振る舞うわけではありませんでした。
Babel 5 のドキュメントでは、注意すべきクラスのエッジケースとして、特にこれを呼び出しています。
Babel 6 では、クラスはサブクラスがどのように処理されるかについて、より仕様に準拠するように変更され、その副作用として、現在、上記のコードは まだ は動作しませんが、以前とは異なる方法で動作するわけではありません。これについては https://phabricator.babeljs.io/T3083 で説明しましたが、ここでは潜在的な解決策について詳しく説明します。
Babel 5 のサブクラス化動作を返すために (これはまだ正しくも推奨もされていないことを覚えておいてください)、組み込みコンストラクタを独自の一時的なクラスでラップすることができます。
function ExtendableBuiltin(cls){
function ExtendableBuiltin(){
cls.apply(this, arguments);
}
ExtendableBuiltin.prototype = Object.create(cls.prototype);
Object.setPrototypeOf(ExtendableBuiltin, cls);
return ExtendableBuiltin;
}
このヘルパーを使うと
class MyError extends Error {}
する
class MyError extends ExtendableBuiltin(Error) {}
Node 5では、トランスパイルせずにES6ネイティブクラスをサポートします。私は、それらを使用することをお勧めします。
es2015
プリセットを削除して、代わりに
node5
を使用することで、特にネイティブクラスを取得することができます。その中で
class MyError extends Error {}
は期待通りに動作します。
Node 4/5でない人、最近のChromeのみの人は、次のようなものを使うことを検討するとよいでしょう。
https://www.npmjs.com/package/error
. また
https://www.npmjs.com/package/babel-plugin-transform-builtin-extend
. は
approximate
オプションはBabel 5と同じ動作です。注意点としては、非
approximate
の動作は間違いなくエッジケースであり、100%のケースで動作しない可能性があることに注意してください。
関連
-
[解決済み】IE8で配列のindexOfが効かないのはなぜ?
-
[解決済み] JSのDateからDay名
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] Javascriptによるタッチスクリーンデバイスの検出
-
[解決済み] javascriptで2つの数値を連結する方法は?
-
[解決済み] JavaScriptで:hoverのCSSプロパティを変更する
-
[解決済み] Javascript / jQueryでAndroid端末を検出する。
-
[解決済み] AngularJS - ngRepeatフィルタリングされた結果の参照を取得する方法
-
[解決済み] $.ajax実行中にローディングイメージを表示する
-
[解決済み] JavaScriptで長い配列を小さい配列に分割する方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] jqueryでdivの要素がオーバーフローしていないかチェックする
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] なぜ "use strict "はパフォーマンスを10倍向上させるのか?
-
[解決済み] Chart.jsを使ってドーナツチャートの中にテキストを追加するには?
-
[解決済み] Javascript / jQueryでAndroid端末を検出する。
-
[解決済み] JavaScript のオブジェクトの配列を比較し、最小値/最大値を取得する
-
[解決済み] 文字列とラベルのローカライズとグローバリゼーションのベストプラクティス【終了しました
-
[解決済み] <ng-content>が空かどうかを確認する方法は?(これまでのAngular 2+で)
-
[解決済み] JavaScriptのArray.sort()メソッドでシャッフルするのは正しいのか?
-
[解決済み] 変異を伴わないオブジェクトからの値の削除