JavaScript精粹基礎進階(3)語句

JavaScript程序由語句組成,語句遵守特定的語法規則。例如:if語句, while語句, with語句等等。

語句

語句、嚴格模式

JavaScript程序由語句組成,語句遵守特定的語法規則。例如:if語句, while語句, with語句等等。

語句種類

Paste_Image.png

塊 block

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

語法:
{
  語句1;
  語句2;
  ...
  語句n;
}
比如
{
    var str = "hi";
    console.log(str);
}//但在實際開發中,很少單獨使用塊語句
而是用if...else  或者for  while去結合起來使用,

if(true){
//然後{}是一個塊,
然後{裡面可以放多條語句}
 console.log('hi');
}

聲明語句 var

聲明變量語句
var a=1;

在一個var裡也可以聲明多個變量
var a=b=1;
這段語句確實創建瞭a,b兩個變量並且賦值為1,但是其中b實際上是隱式的創建瞭全局變量,不信看下面的例子

function foo() {
    var a = b = 1;
}
foo();

console.log(typeof a);  // ‘undefined’
console.log(typeof b);  // ‘number  

在一條語句裡定義多個變量的方式使用,號分隔
var a=1,b=1;

try catch語句

try {    //工作流程首先執行try,catch中的代碼
    throw "test";    //如果拋出瞭異常  ,如果沒有發生異常catch中的代碼就會被忽略掉
} catch (ex) {    //會由catch去捕獲
    console.log(ex); // test    //並執行
} finally {    //finally 不管有沒有異常,finally 都會執行
    console.log('finally');
}

javascript中try...catch可以有三種形式
try {
    throw "test";
} catch (ex) {
    console.log(ex); // test
}

try {
    throw "test";
}finally {
    console.log('finally');
}

//還有一種就是兩者皆有
try {
    throw "test";
} catch (ex) {
    console.log(ex); // test
} finally {
    console.log('finally');
}

例子1

try {
    // do sth.
} finally {
    console.log('finally');
}
//不管有沒有異常最後都有執行finally中的內容

例子2

try {
    try {
        throw new Error("oops");
    }
    finally {
        console.log("finally");
    }
    //內部try沒有catch,那麼他會跳到最近的catch,也就是外層的catch去處理,再跳出block之前需要先執行finally
}
catch (ex) {
    console.error("outer", ex.message);
}
//所以這裡的執行結果
"finally"
"outer" "oops"

例子3

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
  }
  finally {
    console.log("finally");
  }
}
catch (ex) {
  console.error("outer", ex.message);
}//由於內部異常已經處理過,所以不會再跳出到外部處理
執行結果
"inner" "oops"
"finally"

例子4

try {
  try {
    throw new Error("oops");
  }
  catch (ex) {
    console.error("inner", ex.message);
    throw ex;
  }
  finally {
    console.log("finally");
  }
}
catch (ex) {
  console.error("outer", ex.message);
}//由於內部catch再次拋出異常就會由外部catch來處理
執行結果是
"inner" "oops"
"finally"
"outer" "oops"

function語句

函數聲明

fd(); // true
function fd() {
    // do sth.
    return true;
}

函數表達式

fe(); // TypeError
var fe = function() {  //定義變量fe,然後把一個匿名函數賦值給fe
    // do sth.
};

兩者區別在函數聲明前面調用函數也是可以的,函數表達式就不可以。

for…in語句

var p;
var obj = {x : 1, y: 2}

for (p in obj) {
}

順序不確定 enumerable為false時不會出現 for in對象屬性時受原型鏈影響

switch語句

例子1
var val = 2;

switch(val) {
    case 1:
        console.log(1);
        break;
    case 2:
        console.log(2);    //val==2,會執行這段代碼
        break;             //使用 break 來阻止代碼自動地向下一個 case 運行。
    default:               //使用 default 關鍵詞來規定匹配不存在時做的事情
        console.log(0);
        break;
}

例子2

var val = 2;

switch(val) {
    case 1:
        console.log(1);
    case 2:
        console.log(2);
    default:
        console.log(0);
}
//輸出2,0

例子3

var val = 2;

switch(val) {
    case 1:
    case 2:
    case 3:
        console.log(123);
        break;
    case 4:
    case 5:
        console.log(45); 
        break;
    default:
        console.log(0);
}
//輸出123

循環語句while

while (條件)
{
    需要執行的代碼
}

例子

var x="",i=0;
while (i<5){
    x=x + "該數字為 " + i ;
    i++;
}
console.log(x);

do/while 循環

do
{
    需要執行的代碼
}
while (條件);

例子

var x="",i=0;
do{
    x=x + "該數字為 " + i;
    i++;
}
while (i<5)  
console.log(x)
//該數字為 0該數字為 1該數字為 2該數字為 3該數字為 4

JavaScript for 循環

cars=["BMW","Volvo","Saab","Ford"];
for (var i=0;i<cars.length;i++){ bmw="" for="" pre="" saab="" volvo=""><blockquote>

不同類型的循環

JavaScript 支持不同類型的循環:

for – 循環代碼塊一定的次數

for/in – 循環遍歷對象的屬性

while – 當指定的條件為 true 時循環指定的代碼塊

do/while – 同樣當指定的條件為 true 時循環指定的代碼塊

with語句

with 語句可以方便地用來引用某個特定對象中已有的屬性,但是不能用來給對象添加屬性。要給對象創建新的屬性,必須明確地引用該對象

語法格式

with(object instance) 
{ 
        //代碼塊 
}  

舉例

function Lakers() {
   this.name = "kobe bryant";
   this.age = "28";
   this.gender = "boy";
}
var people=new Lakers();
console.log(people)
with(people)
{
   var str = "姓名: " + name + "
";
   str += "年齡:" + age + "
";
   str += "性別:" + gender;
   document.write(str);
}
// 姓名: kobe bryant
// 年齡:28
// 性別:boy

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

JavaScript 嚴格模式

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

function func() {
    'use strict';
}

'use strict';
function func() {

}

不允許用with

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

!function() {
    'use strict';
     with({x : 1}) {
            console.log(x);
      }
}();
SyntaxError報錯

不允許未聲明的變量被賦值

!function() {
     x = 1;    //全局變量
      console.log(window.x);
}();
//輸出1

!function() {
    'use strict';
     x = 1;
      console.log(window.x);
}();
//ReferenceError
//在use strict如果沒有被聲明的變量會報錯

arguments變為參數的靜態副本

arguments.length 屬性返回函數調用過程接收到的參數個數:
arguments屬性返回函數調用過程接收到的值

一般模式下

!function(a) {
    arguments[0] = 100;//給函數第一個值變成100
    console.log(a);//輸出的a變成100
}(1);
//輸出100

!function(a) {
    arguments[0] = 100;
    console.log(a);
}();//如果()沒有傳值arguments長度為空所以更改arguments的值不成立
輸出undefined

嚴格模式下

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

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

delete參數、函數名報錯

一般模式下

!function(a) {
    console.log(delete a);
}(1);
//false

‘use strict’;模式下

!function(a) {
    'use strict';
    delete a;
}(1);
SyntaxError報錯語法錯誤

delete不可配置的屬性報錯

一般模式下

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

‘use strict’;模式下

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

對象字面量重復屬性名報錯

一般模式下

!function() {
    var obj = {x : 1, x : 2};//對象屬性字面量去重復去寫屬性,這樣也是合法的,屬性以最後一個為準
    console.log(obj.x);
}();
//輸出為2

‘use strict’;模式下

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

//嚴格模式下
//SyntaxError報錯

禁止八進制字面量

一般模式下

!function() {
    console.log(0123);//8進制的值
}();
//輸出83

在嚴格模式下是不允許8進制

!function() {
    'use strict';
    console.log(0123);
}();
//SyntaxError報錯語法錯誤

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

一般模式

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

嚴格模式

!function() {
    'use strict';
    function eval(){}
}();
//SyntaxError語法錯誤

eval獨立作用域

一般模式

!function() {
    eval('var evalVal = 2;');      //在eval函數下定義變量evalVal等於數字2
    console.log(typeof evalVal);   //evalVal所在的函數內部仍然可以拿到 evalVal
}();
//所以輸出number

嚴格模式

!function() {
    'use strict';
    eval('var evalVal = 2;');    //eval代碼會在獨立作用域執行
    console.log(typeof evalVal); //這裡拿evalVal是拿不到的
}();
//所以輸出undefined

嚴格模式總結

不允許用with
所有變量必須聲明, 賦值給為聲明的變量報錯,而不是隱式創建全局變量。
eval中的代碼不能創建eval所在作用域下的變量、函數。而是為eval單獨創建一個作用域,並在eval返回時丟棄。
函數中得特殊對象arguments是靜態副本,而不像非嚴格模式那樣,修改arguments或修改參數變量會相互影響。
刪除configurable=false的屬性時報錯,而不是忽略
禁止八進制字面量,如010 (八進制的8)
eval, arguments變為關鍵字,不可作為變量名、函數名等

一般函數調用時(不是對象的方法調用,也不使用apply/call/bind等修改this)this指向null,而不是全局對象。
若使用apply/call,當傳入null或undefined時,this將指向null或undefined,而不是全局對象。
試圖修改不可寫屬性(writable=false),在不可擴展的對象上添加屬性時報TypeError,而不是忽略。
arguments.caller, arguments.callee被禁用

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

發佈留言