1. 程式人生 > >javascript 語句和嚴格模式(三)

javascript 語句和嚴格模式(三)

一、語句

javascript程式由語句組成,語句遵守特定的語法規則。

  • block
  • break
  • continue
  • empty
  • if...else
  • switch
  • try catch
  • var
  • function
  • return
  • do...while
  • for
  • for...in
  • while
  • debugger
  • label
  • with

1、block語句、var語句

1.1 block語句

 塊語句常用於組合0~多個語句。塊語句用一對花括號定義。

開發中,塊語句通常和if for迴圈 while結合起來用。

注意:

在firefox控制檯中輸入{a:1,b:2},用作物件字面量時,會報語法錯誤,因為瀏覽器把它當成塊處理了,如果想讓瀏覽器理解為物件字面量,可以賦值給一個變數或者用括號括起來。

注意:

ES6前沒有塊級作用域。

1.2宣告語句

正確宣告方法:var a=1;

坑:var a=b=1;

正確的做法是:var a=1,b=1;

2、try-catch語句

執行try塊中的語句。

有異常執行catch。

不管有沒有異常,最後都會執行finally從句。

javascript中的try...catch有3種形式:try...catch;try...finally;try...catch...finally。

注意:try...catch巢狀

如果內部的異常沒有處理,拋給外面了,在外面處理之前,要先執行裡面的finally語句。

1、裡面有個try...finally,外面有個try...catch,裡面丟擲異常。

執行順序,裡面沒有catch,所以會跳到最近的一層catch處理,也就是外層的catch處理,但是在跳出裡面的block之前需要先執行finally。

所以執行結果是:先"finally",然後是"outer oops"。

 2、裡面有個try...catch...finally,外面有個try...catch,裡面丟擲異常。

異常在內部處理過了,自然就不會再拋到外面再去處理。

3、內部try...catch...finally

內部catch中再丟擲異常。

此時,在finally執行後,又會輸出“outer oops”。

3、函式、switch、迴圈

function語句用來定義函式物件。

1、函式宣告和函式表示式區別

函式宣告會被前置,所以在函式宣告的程式碼前置呼叫也是可以正常執行的。

 

 還可以通過new Function構造器的方式去建立函式物件。

2、for...in

 

注意:

  1. for...in順序不確定:具體順序依賴於引擎的實現
  2. enumerable為false時不會出現
  3. for in的物件屬性會受原型鏈的影響

3、switch語句

4、with語句

with語句可以修改作用域

直接x輸出1,不用謝物件.x。

在一層層訪問很多層關係時,用with會比較方便。

比如在瀏覽器裡想檢視form下所有元素時,用

with(document.forms[0]){

    console.log(name.value);

}//實際上就是隱式呼叫了document.forms[0].name.value。

實際上這種深層次的訪問,完全可以定義一個變數來代替,比如:

var form=document.forms[0];
console.log(form.name.value);

 不建議使用with,因為with會使javascript引擎優化變的更加難,因為在with裡面作用域會變得複雜,在with裡的每一個語句,每一個變數查詢都有考慮到with後面的這個物件。總結:

  • 讓JS引擎優化更難
  • 可讀性差
  • 可被變數定義代替
  • 嚴格模式下被禁用

二、嚴格模式

 嚴格模式是一種特殊的執行模式,它修復了部分語言上的不足,提供了更強的錯誤檢查,並增強了安全性

嚴格模式是向上相容的,在用javascript寫一些富應用,一些重的應用,或者是寫一些node.js後端程式設計的時候,嚴格模式下的javascript執行對我們編寫高質量、健壯性的程式碼非常有用。

1、怎樣進入嚴格模式

向上相容,比如老的IE,不支援嚴格模式,'use strict';會被當成普通字串被忽略掉。

1、函式內程式碼在嚴格模式下執行

2、整個js檔案內全部程式碼都在嚴格模式下執行。

在整個js檔案開頭用'use strict'。

小坑

‘use strict’;並不一定非要是第一行的程式碼。在'use strice';前面單引號引起來比如'abc';或者其他指令,這樣也是可以的。

如果寫了其他的語句,比如var a;varb;這樣就不可以了。

2、嚴格模式和普通模式的區別

  •  with語句會報SyntaxError錯
  • 未宣告的變數被賦值會報ReferenceError錯
  • arguments在嚴格模式下變為引數的靜態副本,傳入的引數與arguments無關係
  • delete引數函式名會報錯
  • delete不可配置的屬性也會報錯
  • 物件字面量的重複屬性名會報錯
  • 禁止八進位制字面量
  • eval,arguments變為關鍵字,不能作為變數、函式名
  • eval變成了獨立作用域

1、不允許用with

一般模式輸出1,嚴格模式報一個SyntaxError錯誤。

 解釋一下!function(){}():

直譯器在解釋一個語句時,如果以function開頭,就會理解為函式宣告。

而前面加一個!可以讓直譯器理解為函式表示式,這樣就可以立即呼叫了。

        !function(){
            with({x:1}){
                console.log(x);
            }
        }();

而省略了!的話:

        function(){
            with({x:1}){
                console.log(x);
            }
        }();

就會理解為函式宣告,而函式宣告沒有名字會報錯。

2、不允許未宣告的變數被賦值

嚴格模式未宣告的變數被賦值會報錯ReferenceError。

 3、arguments變為引數的靜態副本

 一般模式下:

arguments和形參有繫結關係,修改了arguments[0]為100,a的值也被改成了100。

!function (a){
            console.log(a); //a=1
            arguments[0]=100;
            console.log(a);//a=100
        }(1);   

如果a的值不傳,a就是undefined,這事修改了arguments[0]=100,a仍然是undefined,不會受arguments影響

!function (a){
            arguments[0]=100;
            console.log(a);
        }();   //a=undefined

嚴格模式:

arguments變成的形參的靜態副本,不管a傳不傳,都不會受argumetns影響。

!function (a){
            'use strict';
            console.log(a); //a=1
            arguments[0]=100;
            console.log(a);//a=1
        }(1);   

注意一點:

雖然說嚴格模式下arguments和形參a是沒有繫結關係的,如果傳入了形參是物件,因為javascript中是共享傳遞的,所以修改了物件的屬性,仍然會相互影響。

4、delete引數、函式名報錯

 一般模式:

把一個引數delete,比如delete a,

!function (a){
            //'use strict';
            console.log(a); //a=1
            console.log(delete a);
            console.log(a);//a=1
        }(1);   

實際上這樣做沒有什麼意義,會返回false,並且刪除不成功,但是也不會報錯。

嚴格模式:

嚴格模式下嘗試去刪除引數,或者函式名的話,會報語法錯誤:

!function (a){
            'use strict';
            console.log(a); //a=1
            console.log(delete a);
            console.log(a);//a=1
        }(1);   

5、delete不可配置的屬性報錯

一般模式:

刪除configurable標籤為false的屬性,返回false並且刪除失敗。

!function (a){
            //'use strict';
            var obj={};
            Object.defineProperty(obj,
                'a',{configurable:false});
            console.log(delete obj.a); //flase
        }(1);   

嚴格模式:

試圖刪除configurable為false的屬性時就會報TypeError。

!function (a){
            'use strict';
            var obj={};
            Object.defineProperty(obj,
                'a',{configurable:false});
            console.log(delete obj.a); //flase
        }(1);   

6、物件字面量重複屬性名報錯

一般模式:

物件的屬性字面量重複寫屬性也是合法的,並且屬性以最後一個為準。所以下面obj.x為2。

!function (){
            //'use strict';
            var obj={x:1,x:2};
            console.log(obj.x); //2
        }();   

嚴格模式:

嚴格模式下物件字面量重複屬性名會報SyntaxError錯。但是我在chrome55和firefox51下都沒有報錯。

!function (){
            'use strict';
            var obj={x:1,x:2};
            console.log(obj.x); //2
        }();   

7、禁止8進位制的字面量

一般模式:

console.log(0123)會輸出83。

!function (){
            //'use strict';
            console.log(0123); //83
        }();   

嚴格模式:

!function (){
            'use strict';
            console.log(0123); //83
        }();   

報錯

8、eval,arguments變為關鍵字,不能作為變數、函式名

一般模式:

!function (){
            //'use strict';
            function eval(){}
            console.log(eval); //function eval(){}
        }();  

嚴格模式:

!function (){
            'use strict';
            function eval(){}
            console.log(eval); 
        }();   

9、嚴格模式下eval變成了獨立作用域

一般模式:

eval中定義的變數在eval所在的函式內部仍然可以拿到變數。

!function (){
            //'use strict';
            eval('var evalVar=2');
            console.log(evalVar);  //2
            console.log(typeof evalVar); //number
        }();   

嚴格模式:

在嚴格模式下,eval()中的程式碼會在一個獨立的作用域中執行,所以就拿不到evalVar了。

會報錯

!function (){
            'use strict';
            eval('var evalVar=2');
            console.log(evalVar);  
            console.log(typeof evalVar); 
        }();   

參考:

call by sharing——JavaScript中“共享傳遞”、“按值傳遞”、“按引用傳遞”

http://blog.csdn.net/u012860063/article/details/52840275