轉載請注明出處:http://www.cnblogs.com/shamoyuu/p/6145384.html
一、什么是表達式
表達式就是JavaScript里一個短句,JavaScript解釋器會將其計算出一個結果。
二、表達式分類
1、原始表達式
原始表達式是最簡單的表達式,它也是表達式最簡單的類型,復雜的表達式都是由原始表達式組合起來的。
JavaScript中原始表達式包含常量、直接量、關鍵字和變量。
例如:
1.23 // 數字直接量 "hello" // 字符串直接量 /\d/ // 正則表達式直接量 true // 關鍵字 false // 關鍵字 null // 關鍵字 this // 關鍵字
2、對象和數組的初始化表達式
對象和數組的初始化表達式實際上是一個新創建的對象和數組,這些初始化表達式有時稱作“對象直接量”和“數組直接量”。然而和原始表達式不同的是,它不是原始表達式,因為它所包含的成員或者元素都是子表達式。
例如:
[] // 一個空數組 [1 + 2, 3 + 4] //兩個元素的數組 {} // 一個空對象 {x: 2.3, y: -1.2} //有兩個屬性的對象
3、函數定義表達式
函數定義表達式定義一個JavaScript函數,表達式的值是這個新定義的函數,從某種意義上講,函數定義表達式也可以稱為“函數直接量”。
例如:
function(x){ return x * x; } // 返回一個包含了一個參數的函數
4、屬性訪問表達式
屬性訪問表達式運算得到一個對象屬性或者一個數組元素的值,它有兩種語法。
例如:
obj.x // 返回obj對象的x屬性 obj["x"] // 同上。這里可以傳入變量,例如var str = "x"; obj[str] === obj["x"] arr[0] // 返回數組的第一個元素
5、調用表達式
調用表達式是一種調用函數或方法的語法表示,它以一個函數表達式開始,后面跟隨一對小括號,括號里是逗號隔開的參數。
例如:
foo() // 調用foo方法,沒有參數 Math.max(1, 2, 3) // 調用Math對象的max方法,傳入3個參數
6、對象創建表達式
對象創建表達式創建一個對象並調用一個函數初始化新對象的屬性(這個函數稱作構造函數)。對象創建表達式和調用表達式非常類似,只是對象創建表達式前面多了一個關鍵字new。
例如:
new Object() // 創建一個Object對象 new Point(2, 3) //創建一個Point對象,並傳入兩個參數
如果一個對象創建表達式不需要傳入任何參數給構造函數的話,那么這對小括號是可以省略的。
例如:
new Object // 創建一個Object對象 new Date //創建一個日期對象
7、算術表達式
算術表達式是將基礎表達式通過運算符進行運算的復合型表達式。
算術表達式根據不同的運算符可以分為下面幾類:
a) "+"運算符
可以用作數字加法,也可以用來連接字符串。
例如:
1 + 2 // => 3 "hello" + " " + "world" // => "hello world"
1 + "2" // => "12"
b) 一元算術運算符
一元算術運算符作用於一個單獨的操作數,並產生一個新值,它擁有非常高的優先級,而且是右結合。需要注意的是,在必要時,它會把操作數轉換為數字。“+”和“-”是一元運算符,也是二元運算符。
例如:
i++ // => 先返回i再對i+1 ++i // => 先計算結果再返回i i-- --i +”1” // => 1 -”1” // => -1
c) 位運算符
位運算符可以對由數字表示的二進制數據進行更低層的按位運算。
因為不常用,這里就不一一講解了,有興趣的同學可以自己網上搜一下。主要有:
按位與(&)
按位或(|)
按位異或(^)
按位非(~)
左移(<<)
帶符號右移(>>)
無符號右移(>>>)
8、關系表達式
關系運算法用於測試兩個值之間的關系(例如“相等”,“小於”,或“是...的屬性”),根據關系是否成立而返回true或false。關系表達式總是返回一個布爾值。
例如:
1 > 2 // => false 3 <= 4 // => true 1 == "1" // => true 1 === "1" // => false 2 != 2 // => false 2 !== "2" // => true “a” < “b” // => true 通過ASCII編碼進行比較("a"是97,"b"是98) null == null // => true null === null // => true undefined == undefined // => true undefined === undefined // => true null == undefined // => true null === undefined // => false Infinity == Infinity // => true Infinity === Infinity // => true NaN == NaN // => false NaN === NaN // => false "toString" in new Object // => true new Object instanceof Object // => true
注:“==”運算符的運算規則請點擊此處查看
9、邏輯表達式
邏輯表達式是對操作數進行布爾算術運算,但它的返回值類型由兩個操作數來決定。
例如:
true && false // => false true && true // => true 1 && true // => true true && 1 // => 1 (x == y) && stop() // 只有x 等於 y 的時候才會執行stop()方法 true || false // => true false || true // => true undefined || 3 // => 3 可以用來設置默認值 !true // => false !false // => true !-1 // => false !0 // => true !undefined // => true !null // => true !NaN // => true ![] // => false !!true // => true !!0 // => false
10、賦值表達式
JavaScript使用“=”運算符來給變量或者屬性賦值。“=”運算符希望它的左操作數是一個左值——一個變量或者對象屬性。它的右操作數可以是任意類型的任意值。賦值表達式的值就是右操作數的值。賦值表達式的副作用是,右操作數會賦值給左側的變量或對象屬性。它具有非常低的優先級。
例如:
obj.x = 1 // 為obj的x屬性賦值為1 a = 1 // 為a賦值為1 b = a = 3 // a是3,然后返回3,然后b也是3 a += 2 // 相當於a = a + 2 b = a -= 6 // 相當於 b = a = a - 6
12、表達式計算
和其他很多解釋性語言一樣,JavaScript同樣可以解釋運行由JavaScript源代碼組成的字符串,並產生一個值。JavaScript通過全局函數eval()來完成這個工作。需要注意的是,eval里並不是所有的語句都可以執行,例如return、break等會報錯。
例如:
eval("3 + 2") // => 5
eval("if(true){ 1 + 2 }") // => 3
eval("{x: 1, y: 2}") // => 會報錯,因為eval把大括號看作塊區域
eval("({x: 1, y: 2})") // => 返回正確的對象
13、其他運算符
a) 條件運算符(?:)
條件運算符是JavaScript里唯一一個三元運算符,有時也直接稱它為“三元運算符”。第一個操作數在“?”之前,第二個操作數在“?”和“:”之間,第三個操作數在“:”之后。當“?”之前的表達式運算結果為true則返回“:”之前的內容,否則返回“:”之后的內容。
例如:
x >= 0 ? x : -x // 求x的絕對值
b) typeof運算符
typeof是一元運算符,放在單個操作數前面,操作數可以是任意類型。
返回值為表示操作數類型的一個字符串,它的值為"number","boolean","string","function","object","undefined" 這六個之一。
例如:
typeof 1 // => “number” typeof true // => “boolean” typeof "abc" // => “string” typeof function(){} // => “function” typeof undefined // => “undefined” typeof new Object // => “object” typeof null // => “object” typeof [] // => “object” typeof NaN // => “number” typeof Infinity // => “number” typeof /\d{1, 3}/ // => “object”
c) delete運算符
delete是一元運算符,它用來刪除對象的屬性或者數組元素,刪除失敗則返回false,其他情況下(例如屬性不存在)返回true。需要注意的是,刪除數組的屬性並不會改變數組的length。delete並不是簡單地將屬性值置為undefined,delete之后的屬性使用in運算符判斷會返回false。
例如:
delete obj.x // 刪除obj對象的x屬性 delete arr[1] // 刪除數組第2個位置上的元素,但不會改變數組的長度
d) void運算符
void是一元運算符,它出現在操作數之前,操作數可以是任意類型,操作數可以正常計算,但是會忽略計算結果並返回undefined。
例如:
void 0 // => undefined
e) 逗號運算符
逗號運算符是一個二元運算符,它的操作數可以是任意類型。它首先計算左操作數,然后計算右操作數,然后返回右操作數的值。左側表達式的計算結果會被忽略。
例如:
x = 1, y = 2, z = 3; // 返回3 a = (x = 1, y = 2, z = 3) // a的值是3
三、其他
上面講了數組是一個object,它的typeof返回的的確是”object”,![]也的確是返回false的。那么看下面這段代碼
var arr = []; if(arr == true){ alert(1); }
這個alert(1)會不會執行呢?
答案是不會。為什么呢?因為“==”運算符會轉換數據的類型,以盡量保證他們倆相同,這個在JavaScript里有一套完整的轉換類型的規則[詳情請點擊此處]。數組並不是通過兩個非運算符轉換它,而是通過“+”來轉換,而+[]是0。然后就會變成 0==true,0又可以轉換為false,所以這里的alert(1)不會執行。
如果這里改成if(!!arr == true),則alert(1)會執行。
四、習題
來看一道習題,看看上面的這些你是否都融會貫通。
下面這段模擬代碼有一個很嚴重的bug,不知道你能不能看出來
function foo(){ var rep = ajaxGet("/xxx.do"); //如果后台成功返回了type if(rep.type){ //打印信息 console.info(rep.message); } } //模擬網絡請求(不考慮異步) function ajaxGet(){ return { //類型 -1 ~ 3 type: 3, //請求信息 message: "請求成功" } }
自己想3分鍾,如果想不出來,就去評論區看答案吧。
參考文獻
《JavaScript權威指南》第五版
