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坑
注意:
- for...in順序不確定:具體順序依賴於引擎的實現
- enumerable為false時不會出現
- 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