一. 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的元素
注意:①當通過in判斷一個字符串是否是一個對象的屬性名時,這個判斷也會包含對該對象繼承屬性的檢測;
二. instanceof運算符
instanceof運算符希望左操作數是一個對象,右操作數標識對象的類。如果左側對象是右側類的實例,則表達式返回true,否則返回false。因為JavaScript中對象的類是通過初始化它們的構造函數來定義的,所以instanceof的右操作數應當是一個函數。例如:
var d = new Date(); //通過Date()構造函數來創建一個新對象 d instanceof Date; //=>true:d是由Date()創建的 d instanceof Object; //=>true:所有對象都是Object的實例 d instanceof Number; //=>false:計算結果為false,d不是一個Number對象 var a = [1, 2, 3]; a instanceof Array; //=>true:a是一個數組 a instanceof Object; //=>true:所有數組都是對象 a instanceof RegExp; //=>false:數組不是正則表達式 var b = 3; b instanceof Number; //=>false:右操作數不是一個對象,只是一個原始值(切記這里不做類型轉換:當右操作數是合法的函數時,只要右操作數是任何原始類型都會返回false)
注意:①所有對象都是Object的實例;②通過instanceof判斷一個對象是否是一個類的實例的時候,這個判斷也會包含對“父類”的檢測;③如果instanceof的左操作數不是對象的話,instanceof返回false,如果右操作數不是函數,則拋出一個類型錯誤異常(先檢測右操作數是否合法,再檢測左操作數,最后判斷表達式)。
三. typeof運算符
typeof是一元運算符,放在其單個操作數的前面,操作數可以是任意類型。返回值為表示操作數類型的一個字符串。下面是任意值在typeof運算后的返回值:
x | typeof x |
undefined | "undefined" |
null | "object" |
true或false | "boolean" |
任意數字或NaN | "number" |
任意字符串 | "string" |
任意函數 | "function" |
任意內置對象(非函數) | "object" |
任意宿主對象 | 有編譯器各自實現的字符串,但不是"undefined"、"boolean"、"number"或"string" |
typeof運算符可以帶上圓括號,這讓typeof看起來像一個函數名,而不是一個運算符:typeof(i)
新增:關於instanceof和typeof,下面記述一個例子:
四. delete運算符
delete是一元操作符,它用來刪除對象屬性或者數組元素,當然它也有返回值。例如:
var o = {x:1, y:2}; delete o.x; //=>true:成功刪除一個屬性 'x' in o; //=>false:這個屬性在對象中不再存在了 'y' in o; //=>true o.x; //=>undefined:讀取不存在的屬性將返回undefined delete o.x; //=>true:刪除不存在的屬性,返回true delete o.z; //=>true:刪除不存在的屬性,返回true var a = [1, 2, 3]; 2 in a; //=>true:元素2在數組中 delete a[2]; //=>true:成功刪除一個數組元素 2 in a; //=>false:元素2已經不在數組中了 a.length; //=>3:注意,數組長度並沒有改變 delete a[3]; //=>true:刪除不存在的元素,返回true a[2]; //=>undefined:讀取不存在的元素將返回undefined var b = [1, 2, undefined]; 2 in b; //=>true:元素2在數組b中 b[2]; //=>undefined:讀取元素2的值,返回其值undefined delete b[2]; //=>true:成功刪除一個數組元素 2 in b; //=>false:元素2已經不再數組中了 b.length; //=>3:數組長度未變 b[2]; //=>undefined:讀取不存在的元素返回undefined
可以看到:delete如果刪除成功或者刪除不存在的屬性或元素時都會返回true,那么什么時候返回false呢?其實,並不是所有屬性都可刪除,一些內置核心和客戶端屬性是不能刪除,用戶通過var語句聲明的變量不能刪除(當用var聲明全局變量時,這個變量也是全局對象window的一個屬性),同樣,通過function語句定義的函數和函數參數也不能刪除。例如:
var o = {x:1, y:2}; var aa = 22; delete o.x; //=>true typeof o.x; //=>undefined delete o; //=>false:不能刪除通過var聲明的變量,返回false delete aa; //=>false:不能刪除通過var聲明的變量,返回false delete window.aa; //=>false:無法刪除 delete this.aa; //=>false:無法刪除 function myTest(con){ console.log(delete con); //=>false:不能刪除函數參數 console.log('myTest:' + con); } delete myTest;//=>false:不能刪除通過function語句定義的函數
注意:在ECMAScript 5嚴格模式中,如果delete的操作數是非法的,比如變量、函數或函數參數,delete操作將拋出一個語法錯誤(Syntax Error)異常,只有操作數是一個屬性訪問表達式的時候它才會正常工作。在嚴格模式下,delete刪除不可配置的屬性時會拋出一個類型錯誤異常。在非嚴格模式下,這些delete操作都不會報錯,只會簡單地返回false,以表明操作數不能執行刪除操作。當使用var聲明一個變量時,創建的這個屬性就是不可配置的,所以上面各種刪除變量aa都返回false,表示無法刪除,當然我們這里討論的就是非嚴格模式嘛。在非嚴格模式中,如果給一個沒有使用var聲明的變量賦值的話,JavaScript會自動創建一個隱式的全局變量,以這種方式創建的變量是全局對象的正常的可配置屬性,所以可以刪除它們,Chrome運行結果也正是這樣:
更要注意的一點是:在使用任務鏈進行部分var聲明時,也會創建隱式全局變量,例如:
下面的例子更是驗證了這個:
要想避免這種隱式全局變量,就要這樣寫:
var aa=0,bb=0; delete aa;//=>false delete bb;//=>false
還有一點就是:delete希望它的操作數是一個左值,如果它不是左值,那么delete將不進行任何操作同時返回true。例如:
delete 1; //數字1不是一個左值,返回true
五. void運算符
void是一元運算符,它出現在操作數之前,操作數可以是任意類型,操作數會照常計算,但永遠返回undefined。例如:
var aa = 33; var bb = 44; var cc = 0; var dd = void(aa+bb); //dd=undefined var ee = void(cc = aa+bb); //ee=undefined,cc=77 //注意:最后一句不能寫成var ee = void(cc = aa + bb;);,因為void一元運算符,后面是操作數,不能是完整的語句