JavaScript 的in 操做符 (「如何判斷某值是否數組中的元素」?)

  在編寫JavaScript時,遇到一個常見的問題「如何判斷某值是否數組中的元素」?這讓我想起了PHP中的in_array()函數和Python中in 操做符。但JavaScript彷佛沒有內置相似的函數,而其in 操做符的做用也有點不一樣。經過查詢相關的資料,我發現JavaScript的in 操做符仍是挺有用的。

1、問題
讓我想到in 操做符,正是由於這樣一個問題:「如何判斷某值是否數組中的元素」?
在PHP中,您可能會這樣來處理:

javascript

$os = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $os)) {
    echo "Got Irix";
}


Python 中,可能會是這樣:

html

val = 17
if val in [1,4,5,7,12,14,17,20,34]: print "yes"


那JavaScript中該如何操做呢?先來看看in 操做符的說明。

2、in 操做符
如今寫JavaScript時,我喜歡參考兩個地方:MDC 的Core JavaScript 1.5 Reference 和 W3Schools 的JavaScript Tutorial
這裏,可找到in Operator的說明。可見,JavaScript中的in 操做符是對Object(對象)操做的,並非針對數組。
一、簡單用法
in 的右邊必須是對象變量,例如:

java

var mycar = {make: "Honda", model: "Accord", year: 1998};
if ( "make" in mycar ) document.write('true');
  else document.write('false');  // 顯示true


二、錯誤的用法
若咱們把in 用於數組的判斷時,會產生錯誤結果:

數組

var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
if ( "oak" in trees ) document.write('true');
  else document.write('false');  //顯示false


反過來,咱們把trees數組當作一個對象,而後判斷對象中的元素,例如:

jsp

if ( 0 in trees ) document.write('true');
  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數組對象的屬性


3、對數組判斷的正確方法
雖然in 直接在用於判斷數組時會產生錯誤結果,但也不是沒有辦法能夠避免的。合適地使用in 操做符反而能夠帶來便利。
一、經過循環來解決問題
其實,這是處理「如何判斷某值是否數組中的元素」問題的最基本方法:

函數

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');



二、合適的利用in 操做符
既然咱們知道in 能夠用於判斷對象的屬性值,那麼,一樣的,咱們能夠把數組一一映射到對象的屬性,而後再用in 判斷。如下代碼參考自:這裏

code

function oc(a)
{
  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。

三、巧用in 操做符
除了數組狀況下可借用in 操做符外,咱們還能夠利用in 的特性來簡化if 語句在多個「或」條件狀況時的寫法。
例如,下面一句:

htm

if ( foo == 'bar' || foo == 'foobar' || foo == 'foo' )
{
//...
}


就能夠寫成:

對象

if ( foo in { 'bar':'', 'foobar':'', 'foo':'' } )
{
//...
}


判斷結果相同。

4、注意事項
使用in 操做符時,除了當心區分數組與對象的區別外,還須要注意:
一、in 面向的必須是對象
例如,下面對字符串的判斷中:

blog

var color1 = new String("green");
"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 中會報「缺乏對象」。

二、對象屬性被刪除(deleted)或未定義(undefined)的判斷結果是不一樣的
用delete刪除對象的屬性值:

var mycar = {make: "Honda", model: "Accord", year: 1998};
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:

var mycar = {make: "Honda", model: "Accord", year: 1998};
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


三、關聯數組
既然數組能夠轉換爲對象,咱們就能夠把JavaScript的對象當作是「關聯數組」(相似Python中的字典、Perl中的Hash),而普通數組元素就對應對象的屬性(值爲空)的狀況。

var oneArray=new Array();
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]);
}


這樣,有如下優點:

引用
a、咱們就能夠很是方便的利用in 來判斷元素是否在對象中;
b、對象中檢索屬性,例如:o['oak'],其時間複雜度爲O(1),而要在數組中找一個元素,時間複雜度爲O(n)。


不過,也不說全部的數組均可以用對象來代替的。至少,必需要求數組中元素是惟一的。
例如,下面的數組:

var trees = new Array("redwood", "bay", "cedar", "oak", "maple","oak");


由於"oak"元素重複了,就不能直接等轉換爲某個對象。

四、效率問題
根據介紹,見:這裏。其中提出:
集合的遍歷效率(從高到低)爲:var value = obj[key]; > for ( ; ; ) > for ( in )。
因此說,若是數組能用對象代替(值惟一),應首選對象形式。當遇到「判斷某值是否數組中的元素」時,直接判斷該值obj.key == 'undefined',或if( 'key' in obj )便可。不然,用for(;;)方式判斷吧。
(對象沒有length,不能用for(;;)循環,只能用for(in))
另外,在:這裏,也提到了一個遍歷數組的效率問題。其中提出,循環前,把數組的length先賦值個某變量後,循環時直接調用,這樣效率會更高。

相關文章
相關標籤/搜索