第5章 語句
語句 (statement) 就是 JavaScript句或命令。正如英文是用句號作結尾來分隔語句, JavaScript 語句是以
分號結束。
5.1 表達式語句
具有副作用的表達式是 JavaScript 中最簡單的語句。這類語句已經在第4章講述了。賦值語句是一類比較重要的表達式語句。
5.2 複合語旬和空語句
可以用逗號運算符將幾個表達式連接在一起,形成一個表達式,同樣, JavaScript 中還可以將多條語句聯合在一起,形成一條複合語句 (compound statement) 。只須用花括號將多條語句括起來即可。
5.3 聲明語句
var和function 都是聲明語句,它們聲明或定義變量或函數。這些語句定義標識符(變量名和函數名)井給其賦值,這些標識符可以在程序中任意地方使用。
5.3.1 var
var語句用來聲明一個或者多個變量,它的語法如下:
var name_l [ = value_1] [ ,..., name_n [= value_n]]
vari;//一个简单的变量
var j=0;//一个带有初始值的变量
var p,q;//两个变量
var greeting="hello"+name;//更复杂的初始化表达式
var x=2.34,y=math.cos(0.75),r,theta;//很多变量
var x=2,y=x*x;//第二个变量使用了第一个变量
var x=2,//更多变量
f = function(x) { return x*x },//每一个变量都独占一行
y = f(x);
5.3.2 function
關鍵字 function 用來定義函數。函數定義也可以寫成語句的形式。
語法如下:
function funcname([argl [, arg2 [..., argn]]]) {statement
}
1. 函數名之後的圓括號中是參數列表,參數之間使用逗號分隔。當調用函數時,這些標識符則指代傳入函數的實參。
function hypotenuse(x, y) {return Math.sqrt(x*x + y*y);
}
2. 函數體是由 JavaScript 語句組成的,語句的數量不限,且用花括號括起來。在定義函數肘,並不執行函數體內的語句,它和調用函數時待執行的新函數對象相關聯。注意,function語句裡的花括號是必需的。
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
5.4 條件語句
條件語句是通過判斷指定表達式的值來決定執行還是跳過某些語句。這些語句是代碼的"決策點",有時稱為"分支"。如果說 JavaScript 解釋器是按照代碼的"路徑"執行的,條件語句就是這條路徑上的分叉點,程序執行到這裡時必須選擇其中一條路徑繼續執行。
5.4.1 if
這種語句有兩種形式,
第一種是:
if (expression)
statement
if (username == null) //如果 username null 或者 undefined
username = "John Doe"; //對其進行定義
if 關鍵字和帶圓括號的表達式之後必須跟隨一條語句,但可以使用語句塊將多條語句合井成一條。
if (!address) {
address = "";
message = "Please specify a mailing address.";
}
第二種是:
if (expression)
statement1
else
statement2
--------------------------------------------
if (n == 1)
console.log("You have 1 new message.");
else
console.log("You have " + n + " new messages.");
--------------------------------------------
5.4.2 else if
它由多條 if 語句組成,每條 if 語句的 else 從句又包含另外一條 if 語句。
--------------------------------
if (n == 1) {
//執行代碼塊 1
}
else if (n == 2) {
//執行代碼塊 2
}
else if (n == 3) {
//執行代碼塊 3
}
else {
//之前的條件都為 false. 則執行這裡的代碼塊 4
}
-----------------------------------
if (n == 1) {
//執行代碼塊1
}
else {
if (n == 2) {
//執行代碼塊2
}
else {
if (n == 3) {
//執行代碼塊3
}
else {
//如果所有的判斷都是 false ,執行代碼塊4
}
}
}
5.4.3 switch
當所有的分支部依賴於同一個表達式的值時,執行這條 switch語句的時候,它首先計算 expression 的值,然後查找 case子句中的表達式是否和 expression 的值相同。如果找到匹配的 case ,那麼將會執行這個 case 對應的代碼塊。
switch(n) {
case 1: //如果 === 1 ,從這裡開始執行
//執行代碼塊 1
break; //停止執行 switch 語句
case 2: //如果 === 2,從這裡執行
//執行代碼塊 2
break; //在這裡停止執行 switch 語句
case 3: //如果 === 3,從這裡執行
//執行代碼塊 3
break; //在這裡停止執行 switch 語句
default: //如果所有的條件都不匹配
//執行代碼塊 4
break; //在這裡停止執行 switch 語句
如果在函數中使用 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 Stri (x);
}
}
5.5 循环
循環語句(looping statement) 就是程序路徑的一個回路,可以讓一部分代碼重複執行。
有四種循環語句:while、do/while、for和for/in 。
5.5.1 while
語法如下:
while (expression)
statement
在執行 while 語句之前, JavaScript 解釋器首先計算 expression 的值,如果它的值是假值,那麼程序將跳過循環體中的邏輯 statement 轉而執行程序中的下一條語句。反之,如果表達式 expression 是真值, JavaScript 解釋器將執行循環體內的邏輯,然後再次計算表達expression 的值,這種循環會一直繼續下去,直到 expression 的值為假值為止。換一種說法就是當表達式 expression 是真值時則循環執行 statement 注意,使用 while(true)則會創建一個死循環。
5.5.2 do/while
語法如下:
do
statement
while (expression);
do/while 循環井不像while循環那麼常用。
5.5.3 for
語法如下:
for(initialize ; test ; increment)
statement
(例)
for(var count =0;count <10; count++)
console.log(count);
(例)
var i,j;
for(i=0,j=10;i<10;i++,j--)
sum +=i*j;
5.5.4 for/in
語法如下:
for
(variable in
object)
statement
variable通常是一個變量名,也可以是一個可以產生左值的表達式或者一個通過 var 語句聲明的變量,總之必須是一個適用於賦值表達式左側的值。
object 是一個表達式,這個表達式的計算結果是一個對象。
statement 是一個語句或語句塊,它構成了循環的主體。
for(var p in 0) //將屬性名字賦值給變量
console.log(o[p]); //輸出每一個屬性的值
在執行 for/in 語旬的過程中, JavaScript 解釋器首先計算 object 表達式。如果表達式為null 或者 undefined JavaScirpt 解釋器將會跳過循環井執行後續的代碼也。如果表達式等於一個原始值,這個原始值將會轉換為與之對應的包裝對象 (wrapper object) (見 3.6節)。否則, expression 本身已經是對象了。 JavaScript 會依次枚舉對象的屬性來執行循環。然而在每次循環之前, JavaScript 都會先計算 variable 表達式的值,井將屬性名(一個字符串)賦值給它。
5.6 跳转
使得JavaScript 的執行可以從一個位置跳轉到另一個位置。
break 語句是跳轉到循環或者其他語句的結束。可使用標籤語句
continue 語句是終止本次循環的執行井開始下一次循環的執行。可使用標籤語句
return語句讓解釋器跳出函數體的執行,井提供本次調用的返回值。
throw 語句觸發或者"拋出"一個異常,它是與 try/catch/finally 語句一同使用的,這些語句指定了處理異常的代碼邏輯。
5.6.1 標籤語句
語句是可以添加標籤的,標籤是由語句前的標識符和冒號組成:
identifier:statement
識別碼 聲明
可以在循環體內部使用 break continue 來退出循環或者直接跳轉到下一個循環的開始。
break 軍日 continue JavaScript 中唯一可以使用語句標籤的語句。
mainloop: while(token 1= null) {
//忽略這裡的代碼...
continue
mainloop; //跳轉到下一次循環
//忽略這裡的代碼...
}
5.6.2 break 語句
單獨使用 break 語句的作用是立即退出最內層的循環或 switch 語句。它的語法如下:
break;
允許 break 關鍵字後面跟隨一個語句標籤(只有標識符,沒有冒號)
5.6.3 continue 語句
continue 語句同樣可以帶有標籤
continue labelname;
5.6.4 return 語句
語法如下:
return
expression;
表達
5.6.5 throw 語句
所謂異常 (exception) 是當發生了某種異常情況或錯誤時產生的一個信號。
語法如下:
throw
expression;
5.6.6 try/catch/finally 語句
其中 try 從句定義了需要處理的異常所在的代碼塊。 catch 從句跟隨在 try 從句之後,當 try 塊內某處發生了異常肘,調用catch 內的代碼邏輯。 catch 從句後跟隨 finally 塊,後者中放置清理代碼,不管 try 塊中是否產生異常, finally 塊內的邏輯總是會執行。儘管 catch finally 都是可選的,但try 從句需要至少二者之一與之組成完整的語句。 try catch finally 語句塊都需要使用花括號括起來,這裡的花括號是必需的,即使從句中只有一條語句也不能省略花括號。
5.7 其他語句類型
剩餘的三種 JavaScript 語句 --
width、debugger和
use strict。
5.7.1 with 語句
語法如下:
with
(object)
statement
這條語句將 object 添加到作用域鏈的頭部,然後執行 statement 最後把作用域鏈恢復到原始狀態。在嚴格模式中是禁止使用 with 語句的,井且在非嚴格模式裡也是不推薦使用 with 語句的,盡可能避免使用 with 語句。
5.7.2 debugger 語句
debugger 語句通常什麼也不做。
實際上,這條語句用來產生一個斷點 (breakpoint) ,JavaScript 代碼的執行會停止在斷點的位置,這時可以使用調試器輸出變量的值、檢查調用等。
5.7.3 "use strict"
5.8 JavaScript 語句小結
|
語句
|
語法
|
用途
|
1
|
break
|
break [label]j
|
退出最內層迴圈或者退出 switch
旬,又或者退出 label 指定的語句
|
2
|
case
|
case expresslon:
|
在switch 語句中標記一條語句
|
3
|
continue
|
continue [label] ;
|
重新開始最內層的迴圈或重新開始
label 指定的迴圈
|
4
|
debugger
|
debugger;
|
中斷點器調試
|
5
|
default
|
default;
|
switch 中標記預設的語句
|
6
|
do/while
|
do statement
while(expression);
|
while 迴圈的一種替代形式
|
7
|
empty
|
;
|
什麼都不做
|
8
|
for
|
for(initjtestjincr)statement
|
一種簡寫的迴圈
|
9
|
for/in
|
for(var in object)statement
|
遍歷一個物件的屬性
|
10
|
function
|
function name([param[] ...]){body}
|
聲明一個函數
|
11
|
if/else
|
if(expr)statementl
[else statement2]
|
執行 statemen t1 或者 statement2
|
12
|
label
|
label:statement
|
statement 指定一個名字 label
|
13
|
return
|
return [expression];
|
從函數返回一個值
|
14
|
switch
|
switch(expression){statements}
|
用case 或者 "default:" 語句標記的
多分支語句
|
15
|
throw
|
throw expression;
|
拋出異常
|
16
|
try
|
try {statements}
[catch {handler statements}]
[finally {cleanup statements}]
|
捕獲異常
|
17
|
use strict
|
"use strict"
|
對腳本和函數應用嚴格模式
|
18
|
var
|
var name=[=expr][,...];
|
聲明並初始化一個或多個變數
|
19
|
while
|
while(expression)
statement
|
基本的迴圈結構
|
20
|
with
|
with(object) statement
|
擴展作用域鏈(不贊成使用)
|
label
|
標籤
|
expresslon
|
表達
|
default
|
默認
|
statement
|
聲明
|
empty
|
空
|
object
|
對象
|
catch
|
抓
|
handler
|
處理程序
|
finally
|
最後
|
cleanup
|
淨化
|
strict
|
嚴格
|
throw
|
扔
|
第6章 對象
它將很多值(原始值或者其他對象)聚合在一起,可通過名字訪問這些值。對象也可看做是屬性的無序集合,每個屬性都是一個名/值對。屬性名是字符串,因此我們可以把對象看成是從字符串到值的映射。
對象還可以從一個稱為原型的對象繼承屬性。對象的方法通常是繼承的屬性。
6.1 創建對象
可以通過對象直接量、關鍵字
new (ECMAScript 中的)
Object.create() 函數來創建
6.1.1 對象直接量
對象直接量是由若干名/值對組成的映射表,名/值對中間用冒號分隔,名/值對之間用逗號分隔,整個映射表用花括號括起來。
6.1.2 通過 new 創建對象
關鍵字 new 後跟隨一個函數調用。這裡的函數稱做構造函數 (constructor) ,構造函數用以初始化一個新創建的對象。 JavaScript 語言核心中的原始類型都包含內置
構造函數。
例如:
var 0 = new Object(); //創建一個空對象,和{}一樣
var a = new Array(); //創建一個空數組,和[ ]一樣
var d = new Date(); //創建一個表示當前時間的 Date 對象
var r = new RegExp("js");//創建一個可以進行模式匹配的 EegExp 對象
6.1.3 原型
每一個 JavaScript 對象(null 除外)都和另一個對象相關聯。"另一個"對象就是我們熟知的原型,每一個對象都從原型繼承屬性。
井可以通過 JavaScript 代碼bject.prototype 獲得對原型對象的引用。
6.1.4 Object. create()
它創建一個新對象,其中第一個參數是這個對象的原型。
Object.create() 是一個靜態函數,而不是提供給某個對象調用的方法。使用它的方法很簡單,只須傳入所需的原型對象即可:
var 01 = Object.create({X:1 , y:2}); //01繼承了屬性x和y
6.2 屬性的查詢和設置
可以通過點(.)或方括號([ ])運算符來獲取屬性的值。運算符左側應當是一個表達式,它返回一個對象。對於點(.)來說,右側必須是一個以屬性名稱命名的簡單標識符。對於方括號來說([ ]),方括號內必須是一個計算結果為字符串的表達式,這個字符串就是屬性的名字:
var author = book.author; //得到 book "author" 屬性
var name = author.surname //得到獲得 author "surname" 屬性
var title = book["main title"]// 得到 book "main title" 屬性
和查詢屬性值的寫怯一樣,通過點和方括號也可以創建屬性或給屬性賦值,但需要將它們放在賦值表達式的左側
book.edition = 6; //給 book 創建一個名為 "edition" 的屬性
book["main title"] = "ECMAScript"; //給 "main title" 屬性賦值
6.2.1 作為關聯數組的對象
??
6.2.2 繼承
??
6.2.3 屬性訪問錯誤
??
6.3 删除属性
delete運算符可以刪除對象的屬性。
語法如下:
delete book.author; // book 不再有屬性 author
delete book[ "main title"l; / / book 也不再有屬性 "main title"
6.4 檢測屬性
以通過 in 運算符、 hasOwnPreperty()和propertyIsEnumerable() 方法來完成這個工作。
語法如下:
var 0 = { x: 1 }
"X" in 0; // true: "x" 的属性
"y" in 0; // false: "y" 不是口的属性
"toString" in 0; // true: 继承 toString 属性
6.5 枚舉屬性
除了檢測對象的屬性是否存在,我們還會經常遍歷對象的屬性。通常使用 for/in 循環遍歷, ECMAScript 提供了兩個更好用的替代方案。
var 0 = {X:l, y:2 , z:3}; //三個可枚舉的自有屬性
o.propertyIsEnumerable("toString") // =>false. 不可枚舉
for(p in 0) //遍歷屬性
console.log(p); //輸出x,y和z,不會輸出 toString
6.6 屬性 getter和setter
我們知道,對象屬性是由名字、值和一組特性 (attribute) 構成的。屬性值可以用一個或兩個方法替代,這兩個方陸就是 getter和setter 。由 getter和setter 定義的屬性稱做"存取器屬性" (accessor property) ,它不同於"數據屬性" (data property) ,數據屬性只有一個簡單的值。
6.7 屬性的特性
除了包含名字和值之外,屬性還包含一些標識它們可寫、可枚舉和可配置的特性。
查詢和設置這些屬性特性的 API 。這些 API 對於庫的開發者來說非常重要,因為:可以通過這些 API 給原型對象添加方法,井將它們設置成不可枚舉的,這讓它們看起來更像內置方法。可以通過這些 API 給對象定義不能修改或刪除的屬性,借此"鎖定"這個對象。
我們將存取器屬性的 getter和setter 方法看成是屬性的特性。按照這個邏輯,我們也可以把數據屬性的值同樣看做屬性的特性。因此,可以認為一個屬性包含一個名字和 個特性。數據屬性的4個特性分別是它的
值 (value) 、
可寫性 (writable) 、
可枚舉性 (enumerable) 和
可配置性 (configurable) 。存取器屬性不具有值( value) 特性和可寫性,它們的可寫性是由 setter 方怯存在與否決定的。因此存取器屬性的4個特性是讀(get) 、
寫入 (set) 、可枚舉性和可配置性。
數據屬性的描述符對象的屬性有 value、writable、enumerable、configurable 。存取器屬性的描述符對象則用 get 屬性和 set 屬性代替 value和writable 。其中 writable、enumerable和configurable 都是布爾值,當然, get 屬性和set 屬性是函數值。
9/29
6.8 對象的三個屬性
每一個對象都有與之相關的原型 (prototype) 、類 (class) 和可擴展性 (extensible attribute) 。
6.8.1 原型屬性
通過 Object.create() 創建的對象使用第一個參數(也可以是 null) 作為它們的原型。
6.8.2 類屬性
對象的類屬性 (class attribute) 是一個字符串,用以表示對象的類型信息。
6.8.3 可擴展性
對象的可擴展性用以表示是否可以給對象添加新屬性。
6.9 序列化對象
將對象的狀態轉換為字符串,也可將字符串還原為對象。
內置函數 JSON.stringify()和JSON.parse() 用來序列化和還原JavaScript 對象。
6.10 對象方法
6.10.1 toString() 方法
toString() 方法沒有參數,它將返回一個表示調用這個方法的對象值的字符串。在需要將對象轉換為字符串的時候, JavaScript 都會調用這個方法。
6.10.2 toLocaleString() 方法
除了基本的 toString() 方法之外,對象都包含 toLocaleString() 方法,這個方法返回一個表示這個對象的本地化字符串。 Object 中默認的 toLocaleString() 方法並不做任何本地化自身的操作,它僅調用 toString() 方法井返回對應值。
6.10.3 toJSON() 方法
Object.prototype 實際上沒有定義 toJSON() 方法,但對於需要執行序列化的對象來說, JSON.stringify() 方法會調用 toJSON() 方法。
6.10.4 valueOf() 方法
需要將對象轉換為某種原始值而非字符串的時候才會調用它,尤其是轉換為數字的時候。
123456