簡體   English   中英

為什么 instanceof 在 babel-node 下的 Error 子類的實例上不起作用?

[英]Why doesn't instanceof work on instances of Error subclasses under babel-node?

我看到在 OS X 上的babel-node版本 6.1.18/Node 版本 5.1.0 下運行時, instanceof運算符不適用於Error子類的實例。這是為什么? 相同的代碼在瀏覽器中運行良好,以我的小提琴為例。

以下代碼在瀏覽器中輸出為true ,而在 babel-node 下為假:

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-b​​uiltin-extend

Babel 從未支持擴展內置類型,如ArrayError等。 它在真實的 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.x。 Node 5 支持原生 ES6 類,無需轉譯。 我建議您通過刪除es2015預設來使用node5 ,而是使用node5以便您獲得本機類等。 在這種情況下,

class MyError extends Error {}

將按照您期望的方式工作。

對於不使用 Node 4/5 或僅使用最新 Chrome 的人,您可能需要考慮使用類似https://www.npmjs.com/package/error 的內容 您還可以探索https://www.npmjs.com/package/babel-plugin-transform-b​​uiltin-extend 其中的approximate選項與 Babel 5 的行為相同。請注意,非approximate行為絕對是邊緣情況,可能無法在 100% 的情況下工作。

如果編譯目標設置為“es5”, instanceof將不適用於子類錯誤。 我設定的目標為“ES6”在我tsconfig.jsoninstanceof產生正確的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM