<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                在ECMAScript中,有兩個最常用的創建函數對象的方法,即使用函數表達式或者使用函數聲明。對此,ECMAScript規范明確了一點,即是,即函數聲明 必須始終帶有一個標識符(Identifier),也就是我們所說的函數名,而函數表達式則可以省略。 **函數聲明的語法是這樣的:** ~~~ <script> function functionName(){ 函數體 } </script> ~~~ 首先是function關鍵字,這個關鍵字表示我聲明的是一個函數,或者說我將要聲明一個函數了,告訴瀏覽器一下;然后是函數的名字,我們講函數的名字一定要見名知義,接著里面是我們的函數體,也可以了解為函數表達式;在各大主流瀏覽器里面都給函數定義了一個非標準的name屬性,通過這個屬性可以訪問到給函數指定的名字,這個屬性的值永遠等同于function后面的標識符; ~~~ function functionName(){ } alert(functionName.name); ~~~ 函數聲明解析過程如下: 1\. 創建一個new Function對象,FormalParameterList指定參數,FunctionBody指定函數體。將當前正在運行環境中作用域鏈作為它的作用域。 2\. 為當前變量對象創建一個名為Identifier的屬性,值為Result(1)。 **函數聲明提升** 關于函數有一個重要的特性就是函數聲明提升.意思是在讀取代碼前會先讀取函數聲明。這就意味著可以把函數聲明放在調用它額語句后面;例如一下; ~~~ alert(functionName.name); function functionName(){ } ~~~ 這個例子不會拋出錯誤,因為在alert之前會先去讀取這個函數聲明; 函數表達式 第二種創建函數的方法是使用函數表達式: 函數表達式: (函數表達式分為匿名和具名函數表達式) function Identifier opt( FormalParameterList opt){ FunctionBody } ?//這里是具名函數表達式 具名函數表達式的解析過程如下: 1\. 創建一個new Object對象 2\. 將Result(1)添加到作用域鏈的頂端 3\. 創建一個new Function對象,FormalParameterList指定參數,FunctionBody指定函數體。將當前正在運行的執行環境中作用域鏈作為它的作用域。 4\. 為Result(1)創建一個名為Identifier 的屬性,其值為為Result(3),只讀,不可刪除 5\. 從作用域鏈中移除Result(1) 6\. 返回Result(3) 簡單來說,ECMAScript是通過上下文來區分這兩者的:假如 function foo(){} 是一個賦值表達式的一部分,則認為它是一個函數表達式。而如果 function foo(){} 被包含在一個函數體內,或者位于程序(的最上層)中,則將它作為一個函數聲明來解析。顯然,在省略標識符的情況下,“表達式” 也就只能是表達式了。 ~~~ function foo(){}; // 聲明,因為它是程序的一部分 var bar = function foo(){}; // 表達式,因為它是賦值表達(AssignmentExpression)的一部分 new function bar(){}; // 表達式,因為它是New表達式(NewExpression)的一部分 (function(){ function bar(){}; // 聲明,因為它是函數體(FunctionBody)的一部分 })(); ~~~ 還有一種情況: ~~~ (function foo(){})   這種情況也是函數表達式,它被包含在一對圓括號中的函數,在其上下文環境中,()構成了一個分組操作符,而分組操作符只能包含表達式,更多的例子: function foo(){}; // 函數聲明 (function foo(){}); // 函數表達式:注意它被包含在分組操作符中 try { (var x = 5); // 分組操作符只能包含表達式,不能包含語句(這里的var就是語句) } catch(err) { // SyntaxError(因為“var x = 5”是一個語句,而不是表達式——對表達式求值必須返回值,但對語句求值則未必返回值。——譯 } ~~~ 下面簡單說說函數聲明與函數表達式的異同。聲明和表達式的行為存在著十分微妙而又十分重要的差別。 首先,函數聲明會在任何表達式被解析和求值之前先行被解析和求值。即使聲明位于源代碼中的最后一行,它也會先于同一作用域中位于最前面的表達式被求值。 簡單總結,區別在什么地方呢? 1\. 聲明總是在作用域開始時先行解析;? 2\. 表達式在遇到時候才運算。 函數聲明還有另外一個重要的特點,即通過條件語句控制函數聲明的行為并未標準化,因此不同環境下可能會得到不同的結果。即是:? // 千萬不要這樣做! // 不同[瀏覽器](http://www.2cto.com/os/liulanqi/)會有不同返回結果, ~~~ if (true) { function foo() { return 'first'; } } else { function foo() { return 'second'; } } foo(); ~~~ // 記住,這種情況下要使用函數表達式: ~~~ var foo; if (true) { foo = function() { return 'first'; }; } else { foo = function() { return 'second'; }; } foo(); ~~~ 那么,使用函數聲明的實際規則到底是什么?  FunctionDeclaration(函數聲明)只能出現在Program(程序)或FunctionBody(函數體)內。從句法上講,它們 不能出現在Block(塊)({ ... })中,例如不能出現在 if、while 或 for 語句中。因為 Block(塊) 中只能包含Statement(語句), 而不能包含FunctionDeclaration(函數聲明)這樣的SourceElement(源元素)。 另一方面,仔細看一看產生規則也會發現,唯一可能讓Expression(表達式)出現在Block(塊)中情形,就是讓它作為ExpressionStatement(表達式語句)的一部分。但是,規范明確規定了ExpressionStatement(表達式語句)不能以關鍵字function開頭。而這實際上就是說,FunctionExpression(函數表達式)同樣也不能出現在Statement(語句)或Block(塊)中(別忘了Block(塊)就是由Statement(語句)構成的)。 由于存在上述限制,只要函數出現在塊中(像上面例子中那樣),實際上就應該將其看作一個語法錯誤,而不是什么函數聲明或表達式。 那么我們應該在什么時候使用函數聲明或函數表達式呢?函數聲明只能出現在“程序代碼”中,意味著只能在其它函數體中或者全局空間;它們的定義不能不能賦值給一個變量或屬性,或者作為一個參數傳遞出現在函數調用中;下面的例子是函數聲明的允許的用法,foo(),bar()和local()都是通過函數聲明模式聲明:? // 全局環境 ~~~ function foo() {} function local() { // 局部環境 function bar() {} return bar; } ~~~ 當你在語法上不能使用函數聲明的時候,你就可以使用函數表達式。比如:傳遞一個函數作為參數或者在對象字面量中定義一個函數:? // 這是一個匿名函數表達式 ~~~ callMe(function () { //傳遞一個函數作為參數 }); ~~~ //?**其他函數表達式** ~~~ var myobject = { say: function () { // I am a function expression } }; ~~~ 這種情況看起來好像是常規的變量賦值語句,即創建一個函數并將它復制給變量functionName.這種情況下創建的函數叫匿名函數。因為function關鍵字后面沒有標識符。匿名函數的name屬性是空字符串。函數表達式與其他表達式一樣,在使用前必須先復制。而且函數表達式并不會函數生, 提升,即先執行函數表達式,再聲明會報錯; [JavaScript](http://lib.csdn.net/base/18 "JavaScript知識庫")有很多有趣的用法,在[Google Code Search](http://www.google.com/codesearch?as_q=%22~function%22&as_lang=javascript)里能找到不少,舉一個例子: ~~~ <script> ~function() { alert("hello, world."); }(); </script> ~~~ 試一下就知道這段代碼的意思就是聲明一個函數,然后立刻執行,因為Javascript中的變量作用域是基于函數的,所以這樣可以避免變量污染,但這里的位運算符『~』乍一看讓人摸不到頭腦,如果去掉它再運行則會報錯:SyntaxError。 為什么去掉位操作符『~』后運行會報錯,這是因為從語法解析的角度看,Javascript不允許在函數聲明的后面直接使用小括號,而函數表達式則沒有這個限制,通過在函數聲明前面加上一個『~』操作符,就可以讓語法解析器把后面看成是函數表達式,同樣的,在函數聲明前面加上『!,+,-』等操作符也是可行的。 那我們為什么不使用下面這種函數表達式的方式呢? ~~~ <script> var foo = function() { alert("hello, world."); }(); </script> ~~~ 雖然從語法解析的角度看沒有問題,但是上面的代碼存在弊端,它引入了一個變量,可能會污染現有的運行環境,帶來潛在的問題。 使用位操作符“~”的方法顯得有點奇技淫巧,其實把函數聲明用小括號套起來更易讀: ~~~ <script> (function() { alert("hello, world."); })(); </script> ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看