1 回答
TA貢獻1811條經驗 獲得超5個贊
首先來說,你是希望構造一個函數對象,而它同時又具有你自定義的類方法……這在 ES6 里其實是很容易通過繼承實現的
class Foo extends Function { ... }不過在 ES5 里也有不是很完美的實現方法,比如改變 f 的 __proto__ 為 Foo.prototype。不過這樣改過之后你會發現 f不再具有函數對象的一些方法,比如 call()、apply()、bind() 等。同時 __proto__ 不在標準中,所以不能保證每一個 JS 引擎都實現了。
回過頭來說 ES6 的辦法——因為 ES6 可以通過很多工具,比如 babel 翻譯成 ES5 的,所以 ES6 實現了,ES5 也就能實現 (現在我對這句話表示懷疑——具體請看后面) 。
ES6 中,Foo 從 Function 繼承,所以可以通過 Foo 構造一個函數對象,同時它可以用 Foo 中定義的方法。但問題在于構造這個對象的時候不能使用 function 定義語法,也不能使用函數表達式等,必須直接使用 Function 構造函數。構造函數需要函數體文本為作參數,比如
const f = new Function("console.log(\"Foo\");");當然函數體很短的時候不是問題,比較長的時候才是麻煩的事情。當然可以用 es6 引入的 模板字符串 來解決,它允許多行字符。這會損失編輯器對其語法的檢查。所以我的辦法是定義一個臨時函數,再通過 toString() 和正則表達式把函數體找出來。
最終完成的代碼是這樣的:
// es6 syntaxconst body = function() { console.log("Foo");
}.toString().replace(/^function\s*\(\)\s*\{|\}$/g, "");class Foo extends Function { constructor() { super(body);
}
outStr() { console.log("abc");
}
}var f = new Foo();
f();
f.outStr();不過很遺憾,使用 TypeScript 和 Babel 轉出來的 es5 代碼都不能運行……
添加回答
舉報
