JavaScript 的基本語法.md

JavaScript 的基本語法

語句

JavaScript 程序的執行單位爲行(line),也就是一行一行地執行。通常狀況下,每一行就是一個語句。javascript

語句(statement)是爲了完成某種任務而進行的操做,好比下面就是一行賦值語句。html

var a = 1 + 3;

這條語句先用var命令,聲明瞭變量a,而後將1 + 3的運算結果賦值給變量ajava

1 + 3叫作表達式(expression),指一個爲了獲得返回值的計算式。語句和表達式的區別在於,前者主要爲了進行某種操做,通常狀況下不須要返回值;後者則是爲了獲得返回值,必定會返回一個值。凡是 JavaScript 語言中預期爲值的地方,均可以使用表達式。好比,賦值語句的等號右邊,預期是一個值,所以能夠放置各類表達式。express

語句以分號結尾,一個分號就表示一個語句結束。多個語句能夠寫在一行內。app

var a = 1 + 3 ; var b = 'abc';

分號前面能夠沒有任何內容,JavaScript 引擎將其視爲空語句。ide

;;;

上面的代碼就表示3個空語句。函數

表達式不須要分號結尾。一旦在表達式後面添加分號,則 JavaScript 引擎就將表達式視爲語句,這樣會產生一些沒有任何意義的語句。測試

1 + 3;
'abc';

上面兩行語句只是單純地產生一個值,並無任何實際的意義。ui

變量

概念

變量是對「值」的具名引用。變量就是爲「值」起名,而後引用這個名字,就等同於引用這個值。變量的名字就是變量名。this

var a = 1;

上面的代碼先聲明變量a,而後在變量a與數值1之間創建引用關係,稱爲將數值1「賦值」給變量a。之後,引用變量名a就會獲得數值1。最前面的var,是變量聲明命令。它表示通知解釋引擎,要建立一個變量a

注意,JavaScript 的變量名區分大小寫,Aa是兩個不一樣的變量。

變量的聲明和賦值,是分開的兩個步驟,上面的代碼將它們合在了一塊兒,實際的步驟是下面這樣。

var a;
a = 1;

若是隻是聲明變量而沒有賦值,則該變量的值是undefinedundefined是一個特殊的值,表示「無定義」。

var a;
a // undefined

若是變量賦值的時候,忘了寫var命令,這條語句也是有效的。

var a = 1;
// 基本等同
a = 1;

可是,不寫var的作法,不利於表達意圖,並且容易不知不覺地建立全局變量,因此建議老是使用var命令聲明變量。

若是一個變量沒有聲明就直接使用,JavaScript 會報錯,告訴你變量未定義。

x
// ReferenceError: x is not defined

上面代碼直接使用變量x,系統就報錯,告訴你變量x沒有聲明。

能夠在同一條var命令中聲明多個變量。

var a, b;

JavaScript 是一種動態類型語言,也就是說,變量的類型沒有限制,變量能夠隨時更改類型。

var a = 1;
a = 'hello';

上面代碼中,變量a起先被賦值爲一個數值,後來又被從新賦值爲一個字符串。第二次賦值的時候,由於變量a已經存在,因此不須要使用var命令。

若是使用var從新聲明一個已經存在的變量,是無效的。

var x = 1;
var x;
x // 1

上面代碼中,變量x聲明瞭兩次,第二次聲明是無效的。

可是,若是第二次聲明的時候還進行了賦值,則會覆蓋掉前面的值。

var x = 1;
var x = 2;

// 等同於

var x = 1;
var x;
x = 2;

變量提高

JavaScript 引擎的工做方式是,先解析代碼,獲取全部被聲明的變量,而後再一行一行地運行。這形成的結果,就是全部的變量的聲明語句,都會被提高到代碼的頭部,這就叫作變量提高(hoisting)。

console.log(a);
var a = 1;

上面代碼首先使用console.log方法,在控制檯(console)顯示變量a的值。這時變量a尚未聲明和賦值,因此這是一種錯誤的作法,可是實際上不會報錯。由於存在變量提高,真正運行的是下面的代碼。

var a;
console.log(a);
a = 1;

最後的結果是顯示undefined,表示變量a已聲明,但還未賦值。

標識符

標識符(identifier)指的是用來識別各類值的合法名稱。最多見的標識符就是變量名,以及後面要提到的函數名。JavaScript 語言的標識符對大小寫敏感,因此aA是兩個不一樣的標識符。

標識符有一套命名規則,不符合規則的就是非法標識符。JavaScript 引擎遇到非法標識符,就會報錯。

簡單說,標識符命名規則以下。

  • 第一個字符,能夠是任意 Unicode 字母(包括英文字母和其餘語言的字母),以及美圓符號($)和下劃線(_)。
  • 第二個字符及後面的字符,除了 Unicode 字母、美圓符號和下劃線,還能夠用數字0-9

下面這些都是合法的標識符。

arg0
_tmp
$elem
π

下面這些則是不合法的標識符。

1a  // 第一個字符不能是數字
23  // 同上
***  // 標識符不能包含星號
a+b  // 標識符不能包含加號
-d  // 標識符不能包含減號或連詞線

中文是合法的標識符,能夠用做變量名。

var 臨時變量 = 1;

JavaScript 有一些保留字,不能用做標識符:arguments、break、case、catch、class、const、continue、debugger、default、delete、do、else、enum、eval、export、extends、false、finally、for、function、if、implements、import、in、instanceof、interface、let、new、null、package、private、protected、public、return、static、super、switch、this、throw、true、try、typeof、var、void、while、with、yield。

註釋

源碼中被 JavaScript 引擎忽略的部分就叫作註釋,它的做用是對代碼進行解釋。JavaScript 提供兩種註釋的寫法:一種是單行註釋,用//起頭;另外一種是多行註釋,放在/**/之間。

// 這是單行註釋

/* 這是 多行 註釋 */

此外,因爲歷史上 JavaScript 能夠兼容 HTML 代碼的註釋,因此<!---->也被視爲合法的單行註釋。

x = 1; <!-- x = 2; --> x = 3;

上面代碼中,只有x = 1會執行,其餘的部分都被註釋掉了。

須要注意的是,-->只有在行首,纔會被當成單行註釋,不然會看成正常的運算。

function countdown(n) {
  while (n --> 0) console.log(n);
}
countdown(3)
// 2
// 1
// 0

上面代碼中,n --> 0實際上會看成n-- > 0,所以輸出二、一、0。

區塊

JavaScript 使用大括號,將多個相關的語句組合在一塊兒,稱爲「區塊」(block)。

對於var命令來講,JavaScript 的區塊不構成單獨的做用域(scope)。

{
  var a = 1;
}

a // 1

上面代碼在區塊內部,使用var命令聲明並賦值了變量a,而後在區塊外部,變量a依然有效,區塊對於var命令不構成單獨的做用域,與不使用區塊的狀況沒有任何區別。在 JavaScript 語言中,單獨使用區塊並不常見,區塊每每用來構成其餘更復雜的語法結構,好比forifwhilefunction等。

條件語句

JavaScript 提供if結構和switch結構,完成條件判斷,即只有知足預設的條件,纔會執行相應的語句。

if 結構

if結構先判斷一個表達式的布爾值,而後根據布爾值的真僞,執行不一樣的語句。所謂布爾值,指的是 JavaScript 的兩個特殊值,true表示真,false表示

if (布爾值)
  語句;

// 或者
if (布爾值) 語句;

上面是if結構的基本形式。須要注意的是,「布爾值」每每由一個條件表達式產生的,必須放在圓括號中,表示對錶達式求值。若是表達式的求值結果爲true,就執行緊跟在後面的語句;若是結果爲false,則跳過緊跟在後面的語句。

if (m === 3)
  m = m + 1;

上面代碼表示,只有在m等於3時,纔會將其值加上1。

這種寫法要求條件表達式後面只能有一個語句。若是想執行多個語句,必須在if的條件判斷以後,加上大括號,表示代碼塊(多個語句合併成一個語句)。

if (m === 3) {
  m += 1;
}

建議老是在if語句中使用大括號,由於這樣方便插入語句。

注意,if後面的表達式之中,不要混淆賦值表達式(=)、嚴格相等運算符(===)和相等運算符(==)。尤爲是賦值表達式不具備比較做用。

var x = 1;
var y = 2;
if (x = y) {
  console.log(x);
}
// "2"

上面代碼的原意是,當x等於y的時候,才執行相關語句。可是,不當心將嚴格相等運算符寫成賦值表達式,結果變成了將y賦值給變量x,再判斷變量x的值(等於2)的布爾值(結果爲true)。

這種錯誤能夠正常生成一個布爾值,於是不會報錯。爲了不這種狀況,有些開發者習慣將常量寫在運算符的左邊,這樣的話,一旦不當心將相等運算符寫成賦值運算符,就會報錯,由於常量不能被賦值。

if (x = 2) { // 不報錯
if (2 = x) { // 報錯

至於爲何優先採用「嚴格相等運算符」(===),而不是「相等運算符」(==),請參考《運算符》章節。

if...else 結構

if代碼塊後面,還能夠跟一個else代碼塊,表示不知足條件時,所要執行的代碼。

if (m === 3) {
  // 知足條件時,執行的語句
} else {
  // 不知足條件時,執行的語句
}

上面代碼判斷變量m是否等於3,若是等於就執行if代碼塊,不然執行else代碼塊。

對同一個變量進行屢次判斷時,多個if...else語句能夠連寫在一塊兒。

if (m === 0) {
  // ...
} else if (m === 1) {
  // ...
} else if (m === 2) {
  // ...
} else {
  // ...
}

else代碼塊老是與離本身最近的那個if語句配對。

var m = 1;
var n = 2;

if (m !== 1)
if (n === 2) console.log('hello');
else console.log('world');

上面代碼不會有任何輸出,else代碼塊不會獲得執行,由於它跟着的是最近的那個if語句,至關於下面這樣。

if (m !== 1) {
  if (n === 2) {
    console.log('hello');
  } else {
    console.log('world');
  }
}

若是想讓else代碼塊跟隨最上面的那個if語句,就要改變大括號的位置。

if (m !== 1) {
  if (n === 2) {
    console.log('hello');
  }
} else {
  console.log('world');
}
// world

switch 結構

多個if...else連在一塊兒使用的時候,能夠轉爲使用更方便的switch結構。

switch (fruit) {
  case "banana":
    // ...
    break;
  case "apple":
    // ...
    break;
  default:
    // ...
}

上面代碼根據變量fruit的值,選擇執行相應的case。若是全部case都不符合,則執行最後的default部分。須要注意的是,每一個case代碼塊內部的break語句不能少,不然會接下去執行下一個case代碼塊,而不是跳出switch結構。

var x = 1;

switch (x) {
  case 1:
    console.log('x 等於1');
  case 2:
    console.log('x 等於2');
  default:
    console.log('x 等於其餘值');
}
// x等於1
// x等於2
// x等於其餘值

上面代碼中,case代碼塊之中沒有break語句,致使不會跳出switch結構,而會一直執行下去。正確的寫法是像下面這樣。

switch (x) {
  case 1:
    console.log('x 等於1');
    break;
  case 2:
    console.log('x 等於2');
    break;
  default:
    console.log('x 等於其餘值');
}

switch語句部分和case語句部分,均可以使用表達式。

switch (1 + 3) {
  case 2 + 2:
    f();
    break;
  default:
    neverHappens();
}

上面代碼的default部分,是永遠不會執行到的。

須要注意的是,switch語句後面的表達式,與case語句後面的表示式比較運行結果時,採用的是嚴格相等運算符(===),而不是相等運算符(==),這意味着比較時不會發生類型轉換。

var x = 1;

switch (x) {
  case true:
    console.log('x 發生類型轉換');
    break;
  default:
    console.log('x 沒有發生類型轉換');
}
// x 沒有發生類型轉換

上面代碼中,因爲變量x沒有發生類型轉換,因此不會執行case true的狀況。這代表,switch語句內部採用的是「嚴格相等運算符」,詳細解釋請參考《運算符》一節。

三元運算符 ?:

JavaScript 還有一個三元運算符(即該運算符須要三個運算子)?:,也能夠用於邏輯判斷。

(條件) ? 表達式1 : 表達式2

上面代碼中,若是「條件」爲true,則返回「表達式1」的值,不然返回「表達式2」的值。

var even = (n % 2 === 0) ? true : false;

上面代碼中,若是n能夠被2整除,則even等於true,不然等於false。它等同於下面的形式。

var even;
if (n % 2 === 0) {
  even = true;
} else {
  even = false;
}

這個三元運算符能夠被視爲if...else...的簡寫形式,所以能夠用於多種場合。

var myVar;
console.log(
  myVar ?
  'myVar has a value' :
  'myVar does not have a value'
)
// myVar does not have a value

上面代碼利用三元運算符,輸出相應的提示。

var msg = '數字' + n + '是' + (n % 2 === 0 ? '偶數' : '奇數');

上面代碼利用三元運算符,在字符串之中插入不一樣的值。

循環語句

循環語句用於重複執行某個操做,它有多種形式。

while 循環

While語句包括一個循環條件和一段代碼塊,只要條件爲真,就不斷循環執行代碼塊。

while (條件)
  語句;

// 或者
while (條件) 語句;

while語句的循環條件是一個表達式,必須放在圓括號中。代碼塊部分,若是隻有一條語句,能夠省略大括號,不然就必須加上大括號。

while (條件) {
  語句;
}

下面是while語句的一個例子。

var i = 0;

while (i < 100) {
  console.log('i 當前爲:' + i);
  i = i + 1;
}

上面的代碼將循環100次,直到i等於100爲止。

下面的例子是一個無限循環,由於循環條件老是爲真。

while (true) {
  console.log('Hello, world');
}

for 循環

for語句是循環命令的另外一種形式,能夠指定循環的起點、終點和終止條件。它的格式以下。

for (初始化表達式; 條件; 遞增表達式)
  語句

// 或者

for (初始化表達式; 條件; 遞增表達式) {
  語句
}

for語句後面的括號裏面,有三個表達式。

  • 初始化表達式(initialize):肯定循環變量的初始值,只在循環開始時執行一次。
  • 條件表達式(test):每輪循環開始時,都要執行這個條件表達式,只有值爲真,才繼續進行循環。
  • 遞增表達式(increment):每輪循環的最後一個操做,一般用來遞增循環變量。

下面是一個例子。

var x = 3;
for (var i = 0; i < x; i++) {
  console.log(i);
}
// 0
// 1
// 2

上面代碼中,初始化表達式是var i = 0,即初始化一個變量i;測試表達式是i < x,即只要i小於x,就會執行循環;遞增表達式是i++,即每次循環結束後,i增大1。

全部for循環,均可以改寫成while循環。上面的例子改成while循環,代碼以下。

var x = 3;
var i = 0;

while (i < x) {
  console.log(i);
  i++;
}

for語句的三個部分(initialize、test、increment),能夠省略任何一個,也能夠所有省略。

for ( ; ; ){
  console.log('Hello World');
}

上面代碼省略了for語句表達式的三個部分,結果就致使了一個無限循環。

do...while 循環

do...while循環與while循環相似,惟一的區別就是先運行一次循環體,而後判斷循環條件。

do
  語句
while (條件);

// 或者
do {
  語句
} while (條件);

無論條件是否爲真,do...while循環至少運行一次,這是這種結構最大的特色。另外,while語句後面的分號注意不要省略。

下面是一個例子。

var x = 3;
var i = 0;

do {
  console.log(i);
  i++;
} while(i < x);

break 語句和 continue 語句

break語句和continue語句都具備跳轉做用,可讓代碼不按既有的順序執行。

break語句用於跳出代碼塊或循環。

var i = 0;

while(i < 100) {
  console.log('i 當前爲:' + i);
  i++;
  if (i === 10) break;
}

上面代碼只會執行10次循環,一旦i等於10,就會跳出循環。

for循環也可使用break語句跳出循環。

for (var i = 0; i < 5; i++) {
  console.log(i);
  if (i === 3)
    break;
}
// 0
// 1
// 2
// 3

上面代碼執行到i等於3,就會跳出循環。

continue語句用於當即終止本輪循環,返回循環結構的頭部,開始下一輪循環。

var i = 0;

while (i < 100){
  i++;
  if (i % 2 === 0) continue;
  console.log('i 當前爲:' + i);
}

上面代碼只有在i爲奇數時,纔會輸出i的值。若是i爲偶數,則直接進入下一輪循環。

若是存在多重循環,不帶參數的break語句和continue語句都只針對最內層循環。

標籤(label)

JavaScript 語言容許,語句的前面有標籤(label),至關於定位符,用於跳轉到程序的任意位置,標籤的格式以下。

label:
  語句

標籤能夠是任意的標識符,但不能是保留字,語句部分能夠是任意語句。

標籤一般與break語句和continue語句配合使用,跳出特定的循環。

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=' + i + ', j=' + j);
    }
  }
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0

上面代碼爲一個雙重循環區塊,break命令後面加上了top標籤(注意,top不用加引號),知足條件時,直接跳出雙層循環。若是break語句後面不使用標籤,則只能跳出內層循環,進入下一次的外層循環。

標籤也能夠用於跳出代碼塊。

foo: {
  console.log(1);
  break foo;
  console.log('本行不會輸出');
}
console.log(2);
// 1
// 2

上面代碼執行到break foo,就會跳出區塊。

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);
    }
  }
// i=0, j=0
// i=0, j=1
// i=0, j=2
// i=1, j=0
// i=2, j=0
// i=2, j=1
// i=2, j=2

上面代碼中,continue命令後面有一個標籤名,知足條件時,會跳過當前循環,直接進入下一輪外層循環。若是continue語句後面不使用標籤,則只能進入下一輪的內層循環。

參考連接

相關文章
相關標籤/搜索