1. 程式人生 > 程式設計 >ES6中new Function()語法及應用例項分析

ES6中new Function()語法及應用例項分析

本文例項講述了ES6中new Function()語法及應用。分享給大家供大家參考,具體如下:

學習《ECMAScript6入門》中的模板字串的案例中看見了new Function()建立函式的語法:

let str = 'return ' + '`Hello ${name}!`';
let func = new Function('name',str);
func('Jack') // "Hello Jack!"

上面的程式碼傳入name引數和字串函式體,字串函式體由模板字串提供,非常簡潔方便。

為理解new Function,於是找到了下面這篇文章:

下文翻譯自:https://javascript.info/new-function

這裡有一個很少被用到的新建函式的方法,但是有時候不得不使用它。

語法

新建函式的語法:

let func = new Function ([arg1[,arg2[,...argN]],] functionBody)

換句話說,函式的引數(或更確切地說,各引數的名稱)首先出現,而函式體在最後。所有引數都寫成字串形式。

通過檢視示例,可以更容易理解。這是一個有兩個引數的函式:

let sum = new Function('a','b','return a + b');
alert( sum(1,2) ); // 3

如果所要新建的函式沒有引數,那麼new Function()只有一個函式體引數:

let sayHi = new Function('alert("Hello")');
sayHi(); // Hello

這個方式與其他方式最主要的不同點在於,函式是由在執行時傳入的字串建立的。

之前的所有宣告都要求程式設計師在指令碼中編寫功能程式碼。

但new Function允許將任何字串轉換為函式。例如,我們可以從伺服器接收新函式然後執行它:

let str = ... receive the code from a server dynamically ...
let func = new Function(str);
func();

它在非常特殊的情況下使用,例如當我們從伺服器接收程式碼時,或者使用模板動態編譯函式。對此的需求通常出現在開發的進階階段。

閉包(Closure)

通常,函式將它所建立的位置記錄在特殊屬性[[Environment]]中。 它引用了建立地點的詞法環境。

但是當使用new Function()建立函式時,其[[Environment]]不是引用當前的詞法環境,而是引用全域性環境。

function getFunc() {
 let value = "test";
 let func = new Function('alert(value)');
 return func;
}
getFunc()(); // error: value is not defined

與常規方法比較:

function getFunc() {
 let value = "test";
 let func = function() { alert(value); };
 return func;
}
getFunc()(); // "test",來自getFunc的詞法環境

這個特殊的new Function表面看起來很奇怪,但在實踐中顯得非常有用。

想象一下,我們必須從字串建立一個函式。在編寫指令碼時不知道該函式的程式碼(這就是我們不使用常規函式的原因),但在執行過程中將會知道。我們可能會從伺服器或其他來源收到它。

我們的新函式需要與主指令碼進行互動。

也許我們希望它能夠訪問外部的區域性變數?

問題是在JavaScript釋出到生產之前,它是使用minifier壓縮的——一個通過刪除額外的註釋,空格來縮小程式碼的特殊程式,而且 - 重要的是,會將區域性變數重新命名為較短的變數。

例如,如果一個函式中有let userName,那麼minifier會替換它為let a(或者如果a被佔用,則用另一個字母替換),這個過程會在任何地方進行。這通常是一件安全的事情,因為被替換的變數是區域性的,函式外部沒有任何東西可以訪問它。並且在函式內部,minifier取代了它的每一個提及。Minifiers很聰明,他們會分析程式碼結構,所以他們不會破壞任何東西。他們不是隻會愚蠢地發現和替換。

但是,如果new Function可以訪問外部變數,那麼它將無法找到userName,因為userName在程式碼縮小後才作為字串傳入。

所以,即使我們可以在new Function中訪問外部詞彙環境,我們也會遇到minifiers的問題。

而這時,new Function的“特色”可以讓我們免於犯錯。

它強制執行更好的程式碼。如果我們需要將某些東西傳遞給由new Function建立的函式,我們應該將它作為引數顯式傳遞(可以避免直接讀取外部變數時產生的問題)。

我們的“sum”函式實際上是這樣正確使用的:

let sum = new Function('a','return a + b');
let a = 1,b = 2;
// 外部變數作為引數傳入
alert( sum(a,b) ); // 3

總結

語法:

let func = new Function(arg1,arg2,...,body);

歷史原因,引數也可以以逗號分隔的列表的形式給出。

這三個意思相同:

new Function('a','return a + b'); // 基礎語法
new Function('a,b','return a + b'); // 逗號分隔
new Function('a,'return a + b'); // 逗號加空格分隔

使用new Function建立的函式,其[[Environment]]引用全域性詞法環境,而不是包含該函式的外部詞法環境。因此,他們不能使用外層的變數。但這確實很好,因為它可以使我們免於錯誤。明確地傳遞引數在架構上是一種更好的方法,並且不會在使用minifiers時不會產生問題。

感興趣的朋友可以使用線上HTML/CSS/JavaScript程式碼執行工具:http://tools.jb51.net/code/HtmlJsRun測試上述程式碼執行效果。

更多關於JavaScript相關內容可檢視本站專題:《JavaScript操作DOM技巧總結》、《JavaScript頁面元素操作技巧總結》、《JavaScript事件相關操作與技巧大全》、《JavaScript查詢演算法技巧總結》、《JavaScript資料結構與演算法技巧總結》、《JavaScript遍歷演算法與技巧總結》及《JavaScript錯誤與除錯技巧總結》

希望本文所述對大家JavaScript程式設計有所幫助。