表達式是js中的一個短語,js解釋器會將其計算出一個結果。
原始(原始值)表達式
- 常量
- 直接量
1.23 //數字直接量
'hello' //字符串直接量
/pattern/ //正則表達式直接量
- 關鍵字
true //返回一個布爾值:真
false //返回一個布爾值:假
null //返回一個值:空
this //返回'當前'對象
- 變量
a //返回變量a的值
undefined //undefined是全局變量,它不是一個關鍵字
- 當js中出現了標識符,js會將其當作變量而去查找它的值。如果變量名不存在,表達式運算結果爲undefined。而在es5嚴格模式中,對不存在的變量進行求值會拋出一個錯誤異常。
對象和數組的初始化表達式
對象和數組的初始化表達式實際上是一個新創建的對象和數組。這些初始化表達式有時稱作 ‘對象直接量 ’,‘數組直接量 ’。
和布爾值直接量不同,它們不是原始表達式,因爲 它們所包含的成員或者元素都是子表達式。
- 數組直接量中的列表逗號之間的元素可以省略,這時省略的空位會填充值undefined。
var s = [1,,,,5];
- 對象直接量中的屬性名可以是字符串而不是標識符。
var s = {'apple':{a:1,b:2}}
函數定義表達式
也可以叫做函數直接量
var square = function(x){return x * x};
屬性訪問表達式
屬性訪問表達式運算 得到一個對象屬性或一個數組的值。
expression.identifer
expression[expression] //如果屬性名稱是一個【1】保留字或者包含【2】空格和標點符號,或者是【3】數字(對於數組來說)則必須使用方括號。
var o = {x:1,y:{z:3}};
var a = {o,4,[5,6]};
o.x // 1:表達式o的屬性x
o.y.z // 3:表達式o.y的z屬性
o['x'] // 1:表達式o的屬性x
a[1] // 4:表達式a中索引爲1的元素
a[2]['1'] // 6:表達式a[2]中索引爲1的元素
a[0].x // 1:表達式a[0]的x屬性
調用表達式
是一種調用函數或方法的語法表示。函數表達式開始,表達式後跟隨一個括號,括號內是一個以逗號隔開的參數列表。
f(0) // f 是一個函數表達式,0是一個參數表達式
Math.max(x,y,z) // Math.max 是一個函數;x,y,z是參數
a.sort() // a.sort 是一個函數,它沒有參數
如果函數使用return語句給出一個返回值,那麼這個返回值就是整個調用表達式的值。
如果一個表達式是屬性訪問表達式,那麼這個調用稱做 ‘方法調用’。
在方法調用中,執行函數體的時候,作爲屬性訪問主題的對象和數組便是其調用方法內this的指向。這種特性使得在面向對象編程範例中,函數可以調用其宿主對象。
對象創建表達式
創建一個對象並調用一個函數初始化新對象的屬性。
調用的函數稱作構造函數。
對象創建表達式和函數調用表達式非常相似,只是對象創建表達式之前多了一個關鍵字new,如果對象創建表達式不需要傳如任何參數給構造函數的話,那麼括號可以省略。
new Object()
new Point(2,3)
new Object
new Date
運算符概述
運算順序
var a = 1;
var b =(a++)+a; //它這步a不變,這步結束a自增
console.log(b);
正確順序:
- 計算b [b = (a++)+a]
- 計算a++ (設 c) [c = 1]
- 計算a [a = 2]
- 計算c+a [3]
- c+a結果賦值給b [3]
算數表達式
‘+’ 運算符
- 加法或字符串連接。
- 如果存在字符串或類字符串(對象轉換爲字符串),優先考慮字符串連接。
- 加法操作符行爲:
如果其中一個操作數是對象,則根據對象到原始值的準換規則轉換成原始值。【toString() valueOf()】
轉換後,如果其中一個操作數是字符串,另一個操作數也會被轉換爲字符串,然後進行連接。
否則,都轉換成數字加法操作。
1 + 2 // 3 : 加法
'1' + '2' // '12' : 字符串連接
'1' + 2 // '12' : 數字轉換爲字符串後進行字符串拼接
1 + {} // '1[object Object]':對象轉換爲字符串後進行字符串連接
true + true // 2 : 布爾值轉化爲數字後做加法
2 + null // 2 : null轉化爲0後做加法
2 + undefined // NaN : undefined轉換爲NaN後做加法
一元算數運算符
’ + ’ ’ - ’ ’ ++ ’ ’ – ‘
- 根據需要把操作數轉換爲數字。
位運算符
關係表達式
相等和不相等運算符
比較運算符
- 更偏愛數字,只有兩個都是字符串的時候纔會進行字符串的比較
11 < 3 // 數字比較,false
'11' < '3' // 字符串比較,true
'11' < 3 // 數字的比較,false
'one' < 3 //數字的比較,'one'轉換爲NaN,false
in運算符
- in運算符希望它的左操作數是一個字符串或可以轉換爲字符串,希望它的右操作數是一個對象。
- 如果右側的對象 擁有一個名爲左操作數值的屬性名(索引),那麼表達式返回true
var point = {x:1,y:1};
'x' in point // true : 對象有一個名爲'x'的屬性
'z' in point // false : 對象中不存在名爲'z'的屬性
'toString' in point // true : 對象繼承了toString()方法
var data = [7,8,9];
'0' in data // true : 數組包含元素'0'
1 in data // true : 數字轉換爲字符串
3 in data // false : 沒有索引爲3的元素
instanceof運算符
- instanceof運算符希望左操作數是一個對象,右操作數標識對象的類。
- 如果左側的對象是右側的實例,則返回true。
- JS中對象的類是通過初始化它們的構造函數來定義的,這樣右操作數是一個函數。
var d = new Date();
d instanceof Date // true : d是由Date()創建的
d instanceof Object // true : 所有的對象都是Object()的實例
d instanceof Number // false : d不是一個Number對象
var a = [1,2,3];
a instanceof Array // true : a是一個數組
a instanceof Object // true : 所有的數組都是對象
a instanceof RegExp // false : 數組不是正則表達式
- 所有的對象都是Object的實例。當通過instanceof判斷一個對象是否是一個類的實例的時候,這個判斷也會包含對‘父類’的檢測。
邏輯表達式
邏輯與(&&)
並不總是返回true和false。
運算符首先計算左操作數的值,即首先計算’&&’左側的表達式。如果計算結果是假值,那麼整個表達式的結果一定也是假值,因此’&&’這時簡單地返回左操作數的值,而並不會對右操作數進行計算。
如果左操作數是真值,那麼整個表達式的結果則依賴於右操作數的值。如果右操作數是真值,那麼整個表達式也是真值。因此,當左操作數的真值時,’&&’運算符計算右操作數的值並將其返回作爲整個表達式的計算結果。
var a = 10 && 20; 20
var o = {x:1};
var p = null;
o && o.x // 1:o是真值,因此返回值爲o.x
p && p.x // null:p是假值,因此返回值爲p
// 計算表達式p.x會拋出一個錯誤異常,而使用邏輯與運算符避免了問題。
邏輯與運算是否繼續執行,看左操作數是否爲真值或轉換爲真值。
如果能,執行右操作數,返回右操作數的值;如果爲假值或轉換爲假值,返回左操作數的值,不繼續計算。
可以稱這種特性爲“短路”。
if (a == b) stop();
a == b && stop();
邏輯或(||)
首先計算第一個操作數的值,也就是說會首先計算左側的表達式。如果計算結果爲真值,那麼返回這個真值。否則,再計算第二個操作數的值,並返回這個表達式的結果。
常用方式是用來從一組備選表達式中選出第一個真值表打式:
var a = 10 || 20; 10 遇到真就返回
//如果max_width已經定義了,直接使用它;否則再preferences對象中查找max_width
//如果沒有定義它,則使用一個寫死的常量
var max = max_width || preference.max_width || 500
或者用來給參數提供默認值:
// 將o的成員屬性複製到p中,並返回p
function(o,p){
p = p || {}; //如果向參數p沒有傳入任何對象,則使用一個新創建的對象
}
邏輯非(!)
首先將其操作數轉換爲布爾值,然後再對布爾值求反。也就是說’!’總是返回true或者false,並且可以通過使用兩次邏輯非運算得到一個值的等價布爾值:!!x
賦值表達式
帶操作的的賦值運算
大多數情況下,表達式爲:a op= b
和下面的表達式等價:a = a op b注意:在第一行中,表達式計算了一次,第二行計算了兩次。
只有在a包含具有副作用的表達式(比如函數調用和賦值操作)的時候,兩者纔不等價。- a op= b + c -> a = a op (b + c)
var a = [10, 20, 30, 40];
var b = [10, 20, 30, 40];
var i = 0;
var j = 0;
var test1 = a[i++] *= 2;
// a[0] = 10 * 2;
var test2 = b[j++] = b[j++] * 2;
// b[0] = b[1] * 2;
i = 1; j = 2; test1 = 20; test2 = 40;
a = [20,20,30,40]; b = [40,20,30,40]
表達式計算
eval()
其它運算符
- 條件運算符
條件運算符是JS中唯一一個三元運算符。
x > 0 ? x : -x // 求絕對值
應用場景:判斷一個變量是否有定義(並擁有一個有意義的真值)
greeting = 'hello' + (username ? username : 'there');
// 與下面等價,更簡潔
greeting = 'hello';
if(username)
greeting += username;
else
greeting += 'there';
- typeof運算符
x typeof x
undefined 'undefined'
null 'object'
true false 'boolean'
數字,NaN 'number'
字符串 'string'
函數 'function'
內置對象 'object'
宿主對象 有編譯器各自實現的字符串,但不是以上的返回值
typeof最常用的用法是寫在表達式中:
(typeof value == 'string') ? " ' " + value + " ' " : value
typeof可以帶上括號,讓其看起來像一個函數名:
typeof(i)
typeof對於區分原始值很有效,對於對象的類,則需要使用其他手段:instanceof運算符,class特性,constructor屬性。數組會被返回爲’object’。
- delete運算符
var o = {x:1,y:2};
delete o.x;
'x' in o
var a = [1,2,3];
delete a[2];
2 in a; //false:元素2在數組中已經不存在了
a.length //3:注意數組長度還是3,儘管刪除了這個元素,但刪除後留下了一個洞,沒有修改數組長度。
注意:刪除屬性或者刪除數組元素不僅僅是設置了一個undefined的值,這個屬性將不再存在。讀取一個不存在的屬性將返回undefined,所以檢測這個屬性是否真正的消失可以通過in運算符。
- void運算符
操作數正常計算,但忽略計算結果並返回undefined。由於void會忽略操作數的值,因此在操作數具有副作用的時候使用void來讓程序更具語義。
這個運算符最常用在客戶端的URL中—-JavaScript:URL中,在URL中可以寫帶有副作用的表達式,而void則讓瀏覽器不必顯示這個表達式的計算結果:
<a href="javascript: window.open();">打開一個窗口</a>