1. 程式人生 > >javascript語句

javascript語句

變量初始化 href obj 跳過 java object targe name efault

前面的話

  默認情況下,javascript解釋器依照語句的編寫順序依次執行。而javascript中的很多語句可以改變語句的默認執行順序。本文介紹可以改變語句默認執行順序的條件語句、循環語句和跳轉語句

條件語句

  腳本的威力體現在它們可以根據人們給出的各種條件做出決策,javascript使用條件語句來做判斷

  條件語句(conditianal statement)通過判斷表達式的值來決定執行還是跳過某些語句,包括if語句和switch語句

【if語句】

  最常見的條件語句是if語句。if語句的條件必須放在if後面的圓括號內,條件的求值結果永遠是一個布爾值,即只能是true或false。花括號中的語句,不管它們有多少條,只有在給定條件的求值結果是true的情況下才會執行

if(expression){
    statements;
}

  [註意]if語句中,括住expression的圓括號在語法上是必需的

  實際上,if語句中的花括號不是必不可少的。如果if語句中的花括號部分只包含一條語句,可以不使用花括號。但因為花括號可以提高腳本的可讀性,所以在if語句中總是使用花括號是個好習慣

技術分享
//可行,但不推薦
if(1>2)alert(‘1‘);

//推薦寫法
if(1>2){
    alert(‘1‘);
}
技術分享

  if語句根據表達式的值改變程序流程。當expression的值為true時執行跟在其後的代碼塊,當expression的值為false時,執行else的邏輯

if(expression)
    statement1
else
    statement2

  當在if/else語句中嵌套使用if語句時,必須註意確保else語句匹配正確的if語句

//錯誤暗示
if( i == j) if(j == k) console.log(‘i == k‘); else console.log(‘i != j‘);

  javascript中的if/else匹配規則是:else總是和就近的if語句匹配

技術分享
//實際解釋
if( i == j){
    if(j == k)
        console.log(‘i == k‘);
    else
        console.log(‘i != j‘);//錯誤
}
技術分享 技術分享
//使用花括號
if(i == j){
    if(j == k){
        console.log(‘i == k‘);
    }
}else{
    console.log(‘i != j‘);
}
技術分享

  當代碼有多條分支時,需要使用else if語句。else if語句並不是真正的javascript語句,它是多條if/else語句連在一起時的一種慣用寫法

技術分享
if(n == 1){
    //代碼1
}else if(n == 2){
    //代碼2
}else if(n == 3){
    //代碼3
}else{
    //其他代碼
}
技術分享

  可以用if語句的嵌套形式來完成在語法上等價的代碼,但沒有else if語句清晰

技術分享
if(n == 1){
    //代碼1
}else{
    if(n == 2){
        //代碼2
    }else{
        if(n == 3){
            //代碼3
        }else{
           //其他代碼
        }
    }
}
技術分享

【switch語句】

  當所有的分支都依賴於同一個表達式的值時,else if並不是最佳解決方案。在這種情況下,重復計算多條if語句中的條件表達式是非常浪費的做法,而switch語句正適合處理這種情況

  switch語句執行一個多路分支,首先計算expression的值,然後查找case子句的表達式是否和expression的值相同。如果找到匹配的case,那麽將會執行這個case對應的代碼塊。如果找不到匹配的case,那麽將會執行default標簽中的代碼塊。如果沒有default標簽,switch語句將跳過它的所有代碼塊

技術分享
switch (expression)
  case value1: statement1;
    break;
  case value2: statement2;
    break;
  case value3: statement3;
    break;
  default: statement4;
技術分享 技術分享
if(n == 1){
    //代碼1
}else if(n == 2){
    //代碼2
}else if(n == 3){
    //代碼3
}else{
    //其他代碼
}
技術分享 技術分享
//等價於
switch(n){
    case 1:
        //代碼1
        break;
    case 2:
        //代碼2
        break;
    case 3:
        //代碼3
        break;
    default:
        //代碼4
}
技術分享

  每一個case語句塊的結尾處都使用了關鍵字break。break語句可以使解釋器跳出switch語句或循環語句

  在switch語句中,case只是指明了要執行的代碼起點,但並沒有指明終點。如果沒有break語句,那麽switch語句就會從與expression的值相匹配的case標簽處的代碼塊開始執行,依次執行後續的語句,一直到整個switch代碼塊的結尾

技術分享
//如果沒有break語句,若switch語句匹配1,則不僅執行代碼1,也會執行代碼2和代碼3
switch(n){
    case 1:
        //代碼1
    case 2:
        //代碼2
    default:
        //代碼3
}
技術分享

  如果確實需要混合幾種情形,要在代碼中添加註釋,說明是有意省略了break關鍵字

技術分享
switch(i){
    //合並兩種情形
    case 25:
    case 35:
        console.log(‘25 or 35‘);
        break;
    case 45:
        console.log(‘45‘);
        break;
    default:
        console.log(‘other‘);
}
技術分享

  如果在函數中使用switch語句,可以使用return來代替break,return和break都用於終止switch語句,也會防止一個case語句塊執行完後繼續執行下一個case語句塊

技術分享
//函數中使用switch語句
function convert(x){
    switch(typeof x){
        case ‘number‘:
            return x.toString(16);
        case ‘string‘:
            return ‘"‘ + x + ‘"‘;
        default:
            return String(x);
    }
}
技術分享

  雖然ECMAScript中的switch語句借鑒自其他語言,但這個語句也有自己的特色。可以在switch語句中使用任何數據類型(在很多其他語言中只能使用數值),而且每個case的值不一定是常量,可以是變量或表達式

技術分享
var num = 25;
switch(true){
    case num < 0:
        console.log(‘less than 0.‘);
        break;
    case num >=0 && num <=10:
        console.log(‘between 0 and 10.‘);
        break;
    case num >10 && num <=20:
        console.log(‘between 10 and 20.‘);
        break;
    default:
        console.log(‘more than 20.‘);
}
技術分享

  使用switch語句時,要註意以下幾點:

  【1】由於每次執行switch語句時,並不是所有的case表達式都能執行到,因此,應該避免使用帶有副作用的case表達式,比如函數調用表達式和賦值表達式,最安全的做法是在case表達式中使用常量表達式

  【2】default標簽一般都出現在switch的末尾,位於所有case標簽之後,當然這是最合理也是最常用的寫法,實際上,default標簽可以放置在switch語句內的任何地方

  【3】switch語句中,對每個case的匹配操作實際上是‘===‘恒等運算符比較,而不是‘==‘相等運算符比較,因此,表達式和case的匹配並不會做任何類型轉換

技術分享
//由於1並不會轉換為‘1‘,所以結果是3
var n = 1;
switch(n){
    case ‘1‘:
        console.log(1);
        break;
    case 2:
        console.log(2);
        break;
    default:
        console.log(3);
}
技術分享

循環語句

  條件語句把javascript中的代碼變成一條條的分支路徑,而循環語句(looping statement)就是程序路徑的一個回路,可以讓一部分代碼重復執行

  javascript有4種循環語句:while、do/while、for、for/in,它們的工作原理幾乎一樣:只要給定條件仍能得到滿足,包含在循環語句裏的代碼就將重復地執行下去。一旦給定條件的求值結果不再是true,循環也就到此為止。其中最常用的循環就是對數組元素的遍歷

【while語句】

  while語句屬於前測試循環語句,也就是說,在循環體內的代碼被執行之前,就會對出口條件求值

while(expression){
  statement
}

  當表達式expression是真值時則循環執行statement,直到expression的值為假值為止;如果是假值,那麽程序將跳過循環

  [註意]使用while(true)會創建一個死循環

  大多數循環都會有一個像count這樣的計數器變量。盡管循環計數器常用i、j、k這樣的變量名,但如果想要讓代碼可讀性更強,就應當使用更具語義的變量名

var count = 0;
while(count < 10){
    console.log(count);
    count++;
}

【do while語句】

  do while語句是後測試循環,即退出條件在執行循環內部的代碼之後計算。這意味著在計算表達式之前,至少會執行循環主體一次

do{
    statement
}while(expression);

  do/while循環和普通的while循環有兩點語法方面不同:

  【1】do/while循環要求必須使用關鍵字do來標識循環的開始,用while來標識循環的結尾並進入循環條件判斷

  【2】do/while循環用分號結尾。如果while循環體使用花括號括起來,則while循環也不用使用分號做結尾

技術分享
function printArray(a){
    var len = a.length,i=0;
    if(len == 0){
        console.log(‘empty‘);
    }else{
        do{
            console.log(a[i]);
        }while(++i<len);
    }
}
技術分享

【for語句】

  for語句提供了一種比while語句更加方便的循環控制結構,用for循環來重復執行一些代碼的好處是循環控制結構更加清晰

  大部分的循環都具有特定的計數器變量,計數器的三個關鍵操作是初始化、檢測和更新。for語句將這三步明確聲明為循環語法的一部分,各自使用一個表達式來表示

for(initialize;test;increment){
    statement;    
}
技術分享
//等價於:
initialize;
while(test){
    statement
    increment;
}
技術分享

  [註意]使用continue語句時,while循環和for循環並不等價

  initialize、test和increment三個表達式之間用分號分隔,它們分別負責初始化操作、循環條件判斷和計數器變量的更新。將它們放在循環的第一行會更容易理解for循環正在做什麽,而且也可以防止忘記初始化或者遞增計數器變量

  initialize表達式只在循環開始之前執行一次;每次循環執行之前會執行test表達式,並判斷表達式的結果來決定是否執行循環體,如果test計算結果為真值,則執行循環體中的statement,最後,執行increment表達式

  在for循環的變量初始化表達式中,也可以不使用var關鍵字,該變量的初始化可以在外部執行

var count = 10;
var i;
for(i = 0; i < count; i++){
    console.log(i);
}

  由於ECMAScript中不存在塊級作用域,因此在循環內部定義的變量也可以在外部訪問到

var count = 10;
for(var i = 0; i < count; i++){
    console.log(i);
}
console.log(i);//10

  for循環常見用途是對某個數組裏的全體元素進行遍歷處理

var beatles = Array(‘John‘,‘Paul‘,‘George‘,‘Ringo‘);
for(var count = 0; count < beatles.length; count++){
    alert(beatles[count]);
}

  如果循環中的一次叠代會改變多個變量,則需要用到逗號運算符,它將初始化表達式和自增表達式合並入一個表達式中以用於for循環

var i,j;
for(i = 0,j =10; i<10; i++,j--) sum+= i*j;

  代碼中的循環變量除了是數字外,也可以是其他類型

  可以使用for循環來遍歷鏈表數據結構,並返回鏈表中的最後一個對象(也就是第一個不包含next屬性的對象)

function tail(o){
    for(;o.next;o = o.next)/*empty*/;
    return o;
}

  for循環中的initialize、test和increment這三個表達式中的任何一個都可以忽略,但是兩個分號必不可少。如果省略test表達式,那麽這將是一個死循環。同樣,和while(true)類似,死循環的另外一種寫法是

for(;;)

【for in語句】

  for/in語句也使用for關鍵字,但它和常規的for循環是完全不同的一類循環

for(variable in object){
    statement
}

  variable通常是一個變量名,也可以是一個可以產生左值的表達式或一個通過var語句聲明的變量,總之必須是一個適用於賦值表達式左側的值。object是一個表達式,這個表達式的計算結果是一個對象。同樣,statement是一個語句或語句塊,它構成了循環的主體

  for/in循環可以用來更方便地遍歷對象屬性成員

for(var p in o){
    console.log(o[p]);
}

  在執行for/in語句的過程中,javascript解釋器首先計算object表達式。如果表達式為null或undefined。javascript解釋器將會跳過循環並執行後續的代碼。如果表達式等於一個原始值,這個原始值將會轉換為與之對應的包裝對象(wrapper object)。否則,expression本身已經是對象了。javascript會依次枚舉對象的屬性來執行循環。然而,在每次循環前,javascript都會先計算variable表達式的值,並將屬性名(一個字符串)賦值給它

  [註意]只要for/in循環中variable的值可以當做賦值表達式的左值,它可以是任意表達式,每次循環都會計算這個表達式,也就是說每次循環它計算的值有可能不同

技術分享
var obj = {
  x: 1,
  y: 2
};
var props = [];
var i = 0;
for (props[i++] in obj);
props // [‘x‘, ‘y‘]
技術分享

  javascript數組不過是一種特殊的對象,因此,for/in循環可以像枚舉對象屬性一樣枚舉數組索引

技術分享
var o = {a: 1, b: 2, c: 3};
for (var i in o) {
  console.log(o[i]);
}
// 1
// 2
// 3
技術分享

  [註意]for/in循環並不會遍歷對象的所有屬性,只有可枚舉(enumerable)的屬性才會遍歷到

  ECMAScript規範並沒有指定for/in循環按照何種順序來枚舉對象屬性。但實際上,主流瀏覽器廠商的javascript實現是按照屬性定義的先後順序來枚舉簡單對象的屬性,先定義的屬性先枚舉。如果使用對象直接量的形式創建對象,則將按照直接量中屬性的出現順序枚舉。有一些網站和javascript庫是依賴於這種枚舉順序的,瀏覽器廠商不大可能會修改這個順序

跳轉語句

  跳轉語句(jump statement)可以讓解釋器跳轉到程序的其他部分繼續執行,包括break、continue和return語句

【label語句】

  介紹跳轉語句不得不提到標簽(label)語句,通過給語句定義標簽,就可以在程序的任何地方通過標簽名引用這條語句

  標簽語句通常與break語句和continue語句配合使用,跳出特定的循環

identifier: statement

  [註意]用做標簽的identifier必須是一個合法的javascript標識符,而不能是一個保留字

mainloop: while(token != null){
    //Todo
    continue mainloop;
}

  標簽的命名空間和變量或函數的命名空間是不同的,因此可以使用同一個標識符作為語句標簽和作為變量名或函數名

  語句標簽只有在它所起作用的語句(當然也可以在它的子句中)內是有定義的。一個語句標簽不能和它內部的語句標簽重名,但在兩個代碼段不相互嵌套的情況下,是可以出現同名的語句標簽的。帶有標簽的語句還可以帶有標簽,也就是說,任何語句可以有很多個標簽

【break語句】

  單獨使用break語句的作用是立即退出最內層的循環或switch語句

break;
for(var i = 0; i < a.length; i++){
    if(a[i] == target) break;
}

  break語句只有出現在循環語句或switch語句中才合法,出現在其他語句中會報錯

技術分享
//報錯
if(true){
    break;
}
//報錯
function test(){
    var i = 0;
    break;
}
test();
技術分享

  當希望通過break來跳出非就近的循環體或switch語句時,就會用到帶標簽的break語句

break labelname;

  當break和標簽一塊使用時,程序將跳轉到這個標簽所標識的語句塊的結束,或者直接終止這個閉合語句塊的執行。當沒有任何閉合語句塊指定了break所用的標簽,這時會產生一個語法錯誤

技術分享
top:
  for (var i = 0; i < 3; i++){
    for (var j = 0; j < 3; j++){
      if (i === 1 && j === 1) break top;
      console.log( i, j);
    }
  }
技術分享

  [註意]不管break語句帶不帶標簽,它的控制權都無法越過函數的邊界。比如,對於一條帶標簽的函數定義語句來說,不能從函數內部通過這個標簽來跳轉到函數外部

【continue語句】

  continue語句和break語句非常類似,但它不是退出循環,而是轉而執行下一次循環

continue;
continue labelname;

  不管continue語句帶不帶標簽,它只能在循環體內使用。在其他地方使用將會報語法錯誤

  當執行到continue語句時,當前的循環邏輯就終止了,隨即執行下一次循環。但在不同類型的循環中,continue行為也有所不同:

  【1】while循環中,循環開始處指定的exression會重復檢測,如果檢測結果為true,則循環體會從頭開始執行

  【2】do while循環中,程序執行直接跳到循環結尾處,這時會重新判斷循環條件,之後才會繼續下一次循環

  【3】for循環中,首先計算自增表達式,然後再次檢測test表達式,用以判斷是否執行循環體

  【4】在for/in循環中,循環開始遍歷下一個屬性名,這個屬性名賦給了指定的變量

  [註意]continue語句在while和for循環中的區別:while循環直接進入下一輪的循環條件判斷,但for循環首先計算其increment表達式,然後判斷循環條件

技術分享
//1 3
for(i = 0; i < 5; i++){
    if(i % 2 === 0)continue;
    console.log(i);
}
//1 3 5 var i = 0; while(i<5){ i++; if(i % 2 === 0)continue; console.log(i); }
技術分享

  由於continue在這兩種循環中的行為表現不同,因此使用while循環不可能完美地模擬等價的for循環

  和break語句類似,帶標簽的continue語句可以用在嵌套的循環中,用以跳出多層嵌套的循環體邏輯

技術分享
top:
  for (var i = 0; i < 3; i++){
    for (var j = 0; j < 3; j++){
      if (i === 1 && j === 1) continue top;
      console.log(‘i=‘ + i + ‘, j=‘ + j);
    }
  }
技術分享

【return語句】

  函數調用是一種表達式,而所有表達式都有值。函數中的return語句就是指定函數調用後的返回值

return expression;

  return語句只能出現在函數體內,如果不是會報語法錯誤。當執行到return語句時,函數終止執行,並返回expression的值給調用程序

function square(x)
{    
    return x*x
};
square(2);

  如果沒有return語句,則函數調用僅僅依次執行函數體內的每一條語句直到函數結束,最後返回調用程序。這種情況下,調用表達式的結果是undefined。return語句經常作為函數內的最後一條語句出現,但並不是說一定要放在函數最後,即使在執行return語句的時候還有很多後續代碼沒有執行到,這時函數也還是會返回調用程序

  return語句可以單獨使用而不必帶有expression,這樣的話也會向調用程序返回undefined

function display_object(o){
    if(!o) return;
}

  在javascript詞法結構中,已經提到過分號的用法。所有的跳轉語句包括break、continue、return等語句,都不可以在關鍵字和表達式之間換行,因為javascript會在換行處填補分號

//以及return語句舉例,break、continue語句也類似
return
true;

  javascript將其解析為:

return;true;

  而代碼的本意是:

return true;

參考資料

【1】 ES5/語句 https://www.w3.org/html/ig/zh/wiki/ES5/statements
【2】 阮一峰Javascript標準參考教程——語法概述 http://javascript.ruanyifeng.com/grammar/basic.html#toc12
【3】 W3School-Javascript高級教程——語句 http://www.w3school.com.cn/js/pro_js_statements_if.asp
【4】《javascript權威指南(第6版)》第5章 語句
【5】《javascript高級程序設計(第3版)》第3章 基本概念
【6】《javascript DOM編程藝術(第2版)》第2章 Javascript語法
【7】《javascript語言精粹》 第2章 語法

javascript語句