JavaScript Function
Function 構造函數創建一個新的 Function 對象。直接調用此構造函數可用動態創建函數,但會遭遇來自 eval 的安全問題和相對較小的性能問題?!?MDN
Function
可以用來創建函數,JavaScript 中的所有函數,都是 Function對象
。
1. 使用 Function 創建函數
Function 在被當作構造函數調用的時候,可以用來創建函數。
var fn = new Function(函數參數1, 函數參數2, ..., 函數參數n, 函數體);
函數體是一個字符串,字符串的內容是就是函數調用時候被執行的語句。
var fn = new Function('a', 'b', 'return a + b');
var result = fn(1, 3);
console.log(result); // 輸出:4
將上面創建函數的方式“翻譯”成常用的創建方式可以是:
var fn = function(a, b) {
return a + b;
};
var result = fn(1, 3);
console.log(result); // 輸出:4
對比一下就很好理解使用 new Function
時候所傳遞的參數的含義了。
2. 與常規方式創建函數的區別
這里指的常規方式是指函數聲明
、函數表達式
或 ES6 中的箭頭函數
。
使用 Function 創建的函數,最后一個參數,即函數體內在執行的時候作用域是在全局的。
var num = 20;
function fn() {
var num = 10;
var func = new Function('console.log(num)');
console.log(num);
func();
}
fn();
// 輸出:
// 10
// 20
這個例子在執行后,依次輸出了 10
,20
,根據結果可以知道 new Function
創建的函數,在執行過程中,上層作用域是頂級的全局作用域,在瀏覽器下即為 window
。
3. 使用場景
使用 Function 來創建函數是比較麻煩的,照道理講不會有小伙伴會喜歡用這種方式創建函數。
Function 的使用主要場景與 eval
類似,用于動態的運行代碼。
如在線的代碼解析器就可以配合 Function 完成。
var run = function(code, callback) {
window._callback = callback;
var fn = Function(code + ';_callback()');
fn();
};
run('console.log("動態執行的代碼");', function() {
console.log('代碼執行后做的事');
});
這樣就可以實現簡單的動態運行代碼。
注意:真正需要完成這個功能需要大量的細節處理,如處理輸出,處理異步,絕非這么簡單。
還有一些代碼編譯工具會將編譯后的代碼,使用 new Function
進行包裹,如以下代碼:
var number = 1;
var flag = false;
console.log(number, flag);
上面這份代碼在經過編譯后可能會變成:
(new Function('console.log(1,!1)'))()
這樣做是為了縮短代碼,另外就是讓格式化工具無法很好的格式化代碼。
4. 小結
開發者通常不會通過內建對象 Function
來創建函數,更多的是利用 Function
的特性來動態執行代碼。
通常情況下 Function
創建的函數,在執行過程中其 this 是指向最頂層的。