2016-05-13 37 views
2

在一個允許用戶使用javascript的網絡應用程序中,我要求他們在其「程序」中有一個function main()。有一個「運行」按鈕和一個「編輯」按鈕。當您按「運行」時,<textarea>中的文本用於創建腳本塊並將其插入到DOM中。然後調用main()瀏覽器是否持久地緩存腳本元素的編譯版本?

我抓住window.onerror向用戶顯示錯誤。這通常工作正常。如果沒有main(),則顯示相應的錯誤消息。

當您按下「編輯」時,腳本塊被設置爲空白(script.text = '';),並從DOM中刪除。

測試,我發現,如果我有「計劃」包括剛:

function main() { printLn('main here'); } 

它的工作如預期,但是當我改變了到:的

function moon() { printLn('moon here'); } 

,而不是得到一個消息說main() not defined,它仍然像以前一樣工作,儘管腳本塊有「月亮」文本。如果我爲每個創建的腳本塊分配了不同的ID,並且在刪除它之前將腳本塊類型更改爲text/plain,則會繼續發生。

該問題發生在當前的Firefox,Chrome和Opera中。您可以看到會發生什麼here

回答

4

即使您刪除定義它的腳本,功能仍然定義。

這與CSS形成鮮明對比,其中刪除或修改樣式表會相應地移除或更新頁面上的樣式。

有一個很好的理由,那就是CSS被設計成在更改時很容易被重新評估。另一方面,JavaScript太複雜,瀏覽器無法理解「刪除腳本」實際執行的操作。

所以,假設你已經運行了一個功能main(),即使你刪除它也會繼續存在。

我的建議是創建一個閉包來運行你的腳本。你可以像這樣做...

var input = "........"; // user's input 
var runner = "if(typeof main === 'undefined') {"+ 
    "showErrorMessage('No main() defined');"+ // or whatever your error function is 
    "} else { main(); }"; 
var func = new Function("(function() {"+input+runner+"})()"); 
func(); 

它總是值得注意的是,在全球範圍內仍然可以訪問,例如,如果用戶忘記var自己的局部變量,或如果他們直接訪問window.something。只要它只在用戶自己的機器上運行,這不是什麼大問題,但如果人們可以與他人分享他們的代碼,那麼您需要更加小心。

+0

動態定義和調用函數來調用main不會有幫助。 Main是用戶輸入的代碼中的一個函數。動態創建的函數調用它,然後typeof main返回「函數」。我想知道是否最好的方法是通過標記一個遞增的整數來使主函數名稱唯一化,然後在頁面達到100或某個任意數字時重新加載頁面以清除垃圾。 –

+0

@SteveTeale這個答案中的代碼創建一個閉包,'main'將被定義和調用。它不會在閉包之外存在,因此不需要確保唯一性或增加它。 –

+0

用戶已經創建了定義函數main()的腳本塊。要使頁面正常工作,需要調用該功能。 –