JavaScript 的in 操作符 (“如何判斷某值是否陣列中的元素”?)
在編寫JavaScript時,遇到一個常見的問題“如何判斷某值是否陣列中的元素”?這讓我想起了PHP中的in_array()函式和Python中in 操作符。但JavaScript似乎沒有內建類似的函式,而其in 操作符的作用也有點不同。通過查詢相關的資料,我發現JavaScript的in 操作符還是挺有用的。
一、問題
讓我想到in 操作符,正是因為這樣一個問題:“如何判斷某值是否陣列中的元素”?
在PHP中,您可能會這樣來處理:
if (in_array("Irix", $os)) {
echo "Got Irix";
}
Python 中,可能會是這樣:
if val in [1,4,5,7,12,14,17,20,34]: print "yes"
那JavaScript中該如何操作呢?先來看看in 操作符的說明。
二、in 操作符
現在寫JavaScript時,我喜歡參考兩個地方:MDC 的Core JavaScript 1.5 Reference 和 W3Schools 的JavaScript Tutorial。
從這裡,可找到in Operator的說明。可見,JavaScript中的in 操作符是對Object(物件)操作的,並不是針對陣列。
1、簡單用法
in 的右邊必須是物件變數,例如:
if ( "make" in mycar ) document.write('true');
else document.write('false'); // 顯示true
2、錯誤的用法
若我們把in 用於陣列的判斷時,會產生錯誤結果:
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
if ( "oak" in trees ) document.write('true');
else document.write('false'); //顯示false
反過來,我們把trees陣列看成一個物件,然後判斷物件中的元素,例如:
else document.write('false'); //顯示true
document.write(trees.length); //顯示trees陣列物件的length屬性值:5
if ( 'length' in trees ) document.write('true');
else document.write('false'); //顯示true,因為length是trees陣列物件的屬性
三、對陣列判斷的正確方法
雖然in 直接在用於判斷陣列時會產生錯誤結果,但也不是沒有辦法可以避免的。合適地使用in 操作符反而可以帶來便利。
1、通過迴圈來解決問題
其實,這是處理“如何判斷某值是否陣列中的元素”問題的最基本方法:
function in_array(searchString,array) {
for (i=0;i<array.length;i++) {
if ( searchString == array[i] ) return true;
}
return false;
}
if ( in_array('oak',trees) ) document.write('true'); //顯示true
else document.write('false');
2、合適的利用in 操作符
既然我們知道in 可以用於判斷物件的屬性值,那麼,同樣的,我們可以把陣列一一對映到物件的屬性,然後再用in 判斷。以下程式碼參考自:這裡。
{
var o = {}; //相當於var o = new Object();
for(var i=0;i<a.length;i++)
{
o[a[i]]=''; //注意該寫法,不能寫成o.a[i]
}
return o;
}
if ( 'oak' in oc(trees) ) document.write('true'); //顯示true
else document.write('false');
o = oc(trees);
if ( o.oak != 'undefined' ) document.write('true'); //顯示true
else document.write('false'); //true
if ( o['oak'] != 'undefined' ) document.write('true'); //顯示true
else document.write('false'); //true
這裡,oc 函式把一個數組轉換成物件,並把陣列的元素作為物件的屬性(值為空字串),然後利用了in 操作符判斷。
※ 注意:平時obj.key和obj['key']可以互通,但在for(;;)和for(in)語句中,物件屬性的寫法是obj['key'],而不是obj.key。
3、巧用in 操作符
除了陣列情況下可借用in 操作符外,我們還可以利用in 的特性來簡化if 語句在多個“或”條件情況時的寫法。
例如,下面一句:
{
//...
}
就可以寫成:
{
//...
}
判斷結果相同。
四、注意事項
使用in 操作符時,除了小心區分陣列與物件的區別外,還需要注意:
1、in 面向的必須是物件
例如,下面對字串的判斷中:
"length" in color1 // returns true
var color2 = "coral";
"length" in color2 // generates an error (color is not a String object)
因為JavaScript與Python不同,字串並不能直接就處理為字串物件。FireFox 中會報“invalid 'in' operand color2”,IE 中會報“缺少物件”。
2、物件屬性被刪除(deleted)或未定義(undefined)的判斷結果是不同的
用delete刪除物件的屬性值:
delete mycar.make;
"make" in mycar; // returns false
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
3 in trees; // returns false
把物件屬性值設定為undefined:
mycar.make = undefined;
"make" in mycar; // returns true
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
3 in trees; // returns true
3、關聯陣列
既然陣列可以轉換為物件,我們就可以把JavaScript的物件看成是“關聯陣列”(類似Python中的字典、Perl中的Hash),而普通陣列元素就對應物件的屬性(值為空)的情況。
oneArray["firstKey"]="firstValue";
oneArray["secondKey"]="secondValue";
var oneObject={};
oneObject.firstKey="firstValue";
oneObject.secondKey="secondValue";
for ( key in oneArray ) {
document.write(key+'=>'+oneArray[key]);
}
for ( key in oneObject ) {
document.write(key+'=>'+oneObject[key]);
}
這樣,有以下優勢:
b、物件中檢索屬性,例如:o['oak'],其時間複雜度為O(1),而要在陣列中找一個元素,時間複雜度為O(n)。
不過,也不說所有的陣列都可以用物件來代替的。至少,必須要求陣列中元素是唯一的。
例如,下面的陣列:
因為"oak"元素重複了,就不能直接等轉換為某個物件。
4、效率問題
根據介紹,見:這裡。其中提出:
集合的遍歷效率(從高到低)為:var value = obj[key]; > for ( ; ; ) > for ( in )。
所以說,如果陣列能用物件代替(值唯一),應首選物件形式。當遇到“判斷某值是否陣列中的元素”時,直接判斷該值obj.key == 'undefined',或if( 'key' in obj )即可。否則,用for(;;)方式判斷吧。
(物件沒有length,不能用for(;;)迴圈,只能用for(in))
另外,在:這裡,也提到了一個遍歷陣列的效率問題。其中提出,迴圈前,把陣列的length先賦值個某變數後,迴圈時直接呼叫,這樣效率會更高。
轉載:https://www.cnblogs.com/yu-709213564/p/6580392.html