天天看點

javascript權威指南學習筆記(2)--表達式與運算符

1、數組初始化表達式

數組直接量中的清單逗号之間的元素可以省略,這時省略的空位會填充undefined。如:

var arr = [1,,,,,6]; 
console.log(arr[2]); //列印數組中索引為2的值->undefined
           

數組直接量的元素清單結尾處可以留下單個逗号,這時并不會建立一個新的值為undefined的元素。

2、運算符

(1)、javascript總是嚴格按照從左至右的順序來計算表達式的。 如:

w = x + y * z; 
/*
首先計算表達式w,然後計算x,y,z,然後y的值與z的值相乘,再加上x的值,最後指派給w所指代的變量或屬性。
*/
           

(2)、所有數字都是浮點型,除法運算的結果也是浮點型。如5/2結果是2.5。 (3)、加号的轉換規則優先考慮字元串的連接配接。(操作數中含有字元串時),但是 “++”或“--”運算符從不進行字元串的連接配接操作。

in運算符 用于檢測某個屬性名是否屬于某個對象。 當屬性名所對應的值初始化為undefined時,檢測結果也為true; 當屬性名被delete後,再次檢測,結果為false。

var point = {    //定義一個對象
		x: 1,
		y: 1
};
console.log("x" in point); //true
console.log("z" in point); //false
console.log("toString" in point); //true:對象繼承了toString()方法
           

instanceof運算符 用于檢測某個對象是否是某個類的執行個體。所有的對象都是Object的執行個體。

var d = new Date(); //通過Date()構造函數執行個體化一個新的對象
console.log(d instanceof Date);    //true
console.log(d instanceof Object);     //true
console.log(d instanceof Number);    //false
           

3、邏輯表達式

(1)、 邏輯與(&&) 原理:運算符首先計算左操作數的值,即“&&”左側的表達式。如果計算結果是假值,那麼整個表達式的結果也一定是假值,是以“&&”會傳回左操作數的值,而并不會對右操作數進行計算,将左操作數的值作為整個表達式計算的結果。 反過來,左操作數的值為真值時,會計算右操作數的值,不管是真是假,都會傳回右操作的值作為整個表達式計算的結果。

var o = {
		x: 3
};
var p = null;
console.log(o && o.x);     //o和o.x都為真,傳回o.x的值3
console.log(p && p.x);    //p為假值,傳回p的值null,不去計算p.x
           

(2)、 邏輯或(||) 原理: 運算符首先計算左操作數的值,即“||”左側的表達式。如果計算結果是真值,那麼整個表達式的結果也一定是真值,是以“||”會傳回左操作數的值,而并不會對右操作數進行計算,将左操作數的值作為整個表達式計算的結果。 反過來,左操作數的值為假值時,會計算右操作數的值,不管是真是假,都會傳回右操作的值作為整個表達式計算的結果。 最常用的方式是從一組備選表達式中選出第一個真值表達式:

//如果max_width已經定義,直接使用它;否則在preferences對象中查找max_width
//如果沒有定義它,則使用一個寫死的常量
var max = max_width || preference.max_width || 500;
           

(3)、 邏輯非(!) 對操作數的布爾值進行求反。 如:x是真值,則!x傳回false。

// 對于p和q取任意值,這兩個等式都永遠成立
!(p && q) == !p || !q
!(p || q) == !p && !q
           

4、指派表達式

在大多數情況下,表達式 a op= b (op代表一個運算符) 這個表達式和 a = a op b 是等價的。 特例:下面兩個表達式不等價

var data = [1, 2, 3, 4];

for (var i = 0; i < 4; i++) {
    //根據表達式從左到右的運算順序,++運算法則,先計算data[i]的值為1,i再加1
    //1*2 = 2,求得第一個值,i++,i為3,再次執行循環
    console.log(data[i++] *= 2); //2,6

}

for (var j = 0; j < data.length; j++) {
    //同上,先計算=左邊的值後,j+1變為1,然後計算右邊的表達式值,
    //此時j為1,data[j]=2,求得第一個值為4,然後j+1變為2,
    //j++,j為3,再次執行循環
    console.log(data[j++] = data[j++] * 2); //4 NaN
}
           

5、eval()

隻有一個參數。如果傳入的參數不是字元串,它直接傳回這個參數。 作用:解析并運作由javascript源碼組成的字元串。 如:

eval("3+2") // 5
eval("var y = 3");     //聲明一個新的局部變量y
           

它使用了調用它的變量作用域環境。直接調用eval()時,它總是在調用它的上下文作用域内執行。其他的間接調用則使用全局對象作為其上下文作用域,并且無法讀、寫、定義局部變量和函數。如:

var geval = eval;    //使用别名調用eval将是全局eval
var x = "global",
    y = "global";

function f() {     //函數内執行的是局部的eval
    var x = "local";
    eval("x += 'change';");     // 直接eval更改局部變量的值
    return x;     //傳回更改後的局部變量
}

function g() {     //函數内執行的是全局的eval
    var y = "local";
    geval("y += 'changed';"); //間接調用更改了全局變量的值
    return y;    //傳回未更改的局部變量
}

console.log(f(), x);     // localchange global
console.log(g(), y);    // local globalchanged
           

在嚴格模式下,即es5 。代碼段以 “ use strict ”開始,eval執行的代碼段可以查詢或更改局部變量,但不能在局部作用域中定義新的變量或函數。同時,eval被列為保留字,不能用一個别名覆寫eval()函數,并且變量名、函數名、函數參數或異常捕獲的參數都不能取名為“eval”。

6、delete運算符

delete是一進制操作符,它用來删除對象屬性或數組元素。 如:

var o = { x : 1, y : 2};     //定義一個對象
delete o.x;                    //删除一個屬性
"x" in o                    //false 屬性不存在

var a = [1,2,3];            //定義一個數組
delete a[2];                //删除索引為2 的數組元素
2 in a;                    //false 索引為2的數組元素不存在
a.length                   // 3, 數組長度并沒有改變,因為其它值的索引并沒有改變
           

但是,一些内置核心和用戶端屬性是不能被删除的,通過var語句聲明的變量也不能删除,function語句定義的函數和函數參數也不能删除。 在es5嚴格模式下,如果删除的操作數非法,将抛出一個文法錯誤的異常,同時删除不可配置屬性時會抛出類型錯誤異常。在非嚴格模式下,隻是簡單的傳回false,并不會報錯。

var o = { x:1, y:2};  
delete o.x;    //true  
typeof o.x;    //undefined 屬性不存在  
delete o.x;     //true 不存在屬性  
delete o;    //false var聲明不能删除  
  
delete 1;    //true 不是左值(屬性)  
this.x = 1;    //全局定義一個屬性  
delete x;     //true(非嚴格模式下) 嚴格模式下使用 delete this.x
           

繼續閱讀