2012-07-05 23 views
0

更新:JavaScript的嚴格模式是如何實現的

或許函數的調用方式是難辭其咎的,所以這裏的吧:

2 JS文件
    Main.js :爲(加載)事件添加事件偵聽器的自調用(非嚴格)函數。
回調函數調用一個加載函數,它解析location.pathname並調用init函數,並分離/刪除'(on)load'偵聽器返回null(顯式地)。

    PageSpecific.js:包含_init函數,將幾個事件偵聽器添加到主體。
其中一個偵聽器的回調函數(也從閉包中返回)調用使用argument.callee作爲遞歸參考的嚴格函數。
返回該事件處理程序的關閉可能-depending在瀏覽器的結合或不結合,並解除綁定其他事件,但我認爲這是無關緊要的這裏,因爲這是在IE <模仿的onchange事件9

我希望這是相當清楚的,所以:它是:
anon。 F =>事件偵聽
                          =>處理器(命名,但宣佈在不久F)=> pageloader =>
                                    init => eventListener
                                    結合功能通過閉合
                           返回              =>調用函數嚴格

順便說一句:Here's a trimmed down version of the _init function被調用時,我實際使用。更具體地說:將事件監聽器和處理器綁定在一起的閉包。它的另一個我的長度問題,沒有人似乎知道答案...暗示 ;-)


我調試了一些相當大的(和複雜)的JavaScript。在這樣做的時候,我注意到我有一個函數,使用嚴格的模式,但工作正常,但如果我沒有弄錯,應該拋出錯誤。因爲腳本是相當龐大的,複雜的(事件委託,堆疊封閉等),這裏有一個簡單的例子:

function withCalleeRecursion(foo) 
{ 
    'use strict';//strict throws typeError on arguments.callee 
    foo = foo.replace(/(a|b)+/gi, function (p1,p2) 
    { 
     if (p1.match(/(a|b){2,}/i)) 
     { 
      return p1.replace(/(a|b)/gi,arguments.callee);//no errors 
     } 
     return (p2.match(/a/i) ? 'X':'Y'); 
    }); 
    return foo; 
} 

(function() 
{//not strict 
    alert(withCalleeRecursion('Abba makes me barf')); 
})(); 

在我的實際腳本,這個工作完全正常。當我在Firebug和Chrome控制檯中粘貼這個時,會出現一個錯誤。我試過這個代碼here,所以IE也應該拋出錯誤,但是當我在IE的調試器中運行代碼時,它工作得很好。據我所知,改變doctype(試用html5和html4)沒有區別。

我是否認爲(大多數)瀏覽器對'use strict';指令沒有嚴格要求,因爲它的名稱暗示?在分析腳本時檢測到可能的錯誤時,似乎瀏覽器會選擇忽略它。這是真的?


與此同時,我對功能做了輕微的改動,只是出於防範。因爲我在這裏看到的人想知道如何得到嚴格模式callee參考了不少問題,我在這裏粘貼,太:

function withCalleeRecursion(foo) 
{ 
    'use strict'; 
    foo = foo.replace(/(a|b)+/gi, function abR(p1,p2) 
    { 
     if (p1.match(/(a|b){2,}/i)) 
     { 
      return p1.replace(/(a|b)/gi,abR); 
     } 
     return (p2.match(/a/i) ? 'X':'Y'); 
    }); 
    return foo; 
} 

名稱的回調,這就是全部。

+2

從[MSDN](http://msdn.microsoft.com/zh-cn/library/br230269(v = vs.94).aspx) - 「Internet Explorer 10之前版本的Internet Explorer不支持嚴格模式「。你認爲'arguments.callee'應該在嚴格模式下拋出錯誤是正確的。 – 2012-07-05 13:32:49

+1

嚴格模式實現背後的思想是,在非支持的瀏覽器中使用「嚴格使用」語句是完全無害的。 – Pointy 2012-07-05 13:34:02

+0

夠公平的,我儘管儘管如此......但是,腳本也在FF和chrome中工作。最新版本 - 他們確實支持'嚴格模式' – 2012-07-05 13:34:49

回答

0

也許this文章可以幫助您瞭解更多。無論如何,解決方案就是你提到的那個,錯誤是因爲訪問arguments.caller和arguments.callee會在嚴格模式下拋出異常。因此,任何想要引用的匿名函數都需要進行命名。

+0

我已經閱讀過這篇文章。我的問題不是爲什麼錯誤被拋出,但爲什麼不拋出**。不在IE中,不在FF中,不在Chrome中...... – 2012-07-05 13:39:04

2

這可能是因爲瀏覽器控制檯使用eval(),這改變了事情。雖然在傳遞到eval()的代碼字符串的起始位置放上"use strict";,但按照預期方式工作,控制檯實現可能會將代碼添加到已輸入控制檯的字符串中,這意味着"use strict";不再是執行的第一條語句,並且因此被忽略。

有它的一個引用和下面的文章中建議的解決方法:

http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/

建議的解決方法是立即執行的函數內的控制檯來包裝代碼:

(function() { 
    "use strict"; 
    nonExistentVariable = 1; // Error is now thrown 
})(); 
+0

我已經這樣做了,但我想我的問題並不清楚:錯誤在控制檯(FF和chrome)中拋出,但不在頁面上使用該功能!當我在實際腳本中調用該函數時,我可以'alert()','console.log()',並使用'arguments.callee'就好像''use strict';'不在那裏。上面的代碼工作(我的意思是:它不)在任何地方,但不是在我的腳本本身 – 2012-07-05 14:03:01

+0

@EliasVanOotegem:啊,對不起,我想我沒有正確地閱讀這個問題。 – 2012-07-05 14:03:58