JavaScript中的in運算符與數組

前言

JavaScript中有不少怪異點,這個in運算符後接數組就很奇特(雖然你們不多用到這個)。語義上講in是個介詞,詞性prep,表示在什麼什麼裏面。但在js中可能就不太同樣了。python

問題引出

不慌,先來看看python中的效果。算法

>>> array = [1,2,3,4]
>>> 0 in array
False
>>> 4 in array
True
>>> 4.0 in array
True
>>> 4n in array
SyntaxError: invalid syntax

複製代碼

顯然,此處in就是表示判斷左邊的元素是否存在與數組中。數組

>>> 4==4.0
True
>>> array.append('5')
>>> 5 in array
False
複製代碼

挨個匹配的,若是相等則返回True,顯然字符串‘5’和數字5並不相等。很是合理是否是。瀏覽器

再來看看瀏覽器中的狀況。markdown

let a = [1,2,3,4];
1 in a;//true 合理

1.0 in a;//true
0 in a;//true 合理嗎?
'1' in a;//true

3n in a;//true 離譜
複製代碼

image.png 發生甚麼事啦。app

一塊兒來研究下。oop

數組的本質

數組Array 時按次序排列的一組值。每一個值的位置都有編號(從0開始),整個數組用方括號表示。ui

任何類型的數組均可以放入數組。spa

let array = [a,2,[3,4]];// a 是[1,2,3,4]
array
(3) [Array(4), 2, Array(2)]
複製代碼

數組實際上一種的對象。typeof運算符會返回數組的類型是objectprototype

typeof a ;//"object"
Object.keys(a);//(4) ["0", "1", "2", "3"]
複製代碼

這裏能夠看出來,數組的鍵全是字符串數組,從0開始。

來看看對象的設定,js中的規定,對象的鍵都的是字符串。

當訪問對象的值是,有點式object.key和括號式object[key]。

let ob = {'0':0,'1':1,'k':'v'};

ob.k ;//"v"
ob["k"];  
"v"  // 兩種都能取值
ob.0  // 報錯啦!數字加點,還覺得是小數
Uncaught SyntaxError: Unexpected number
ob['0'] //數字字符串沒毛病
0
ob[0]  //[]內爲數字時,也能訪問
0
複製代碼

規定

  • 點式不能使用數字,不然識別爲小數,報錯。

  • 鍵名傳入非字符串時,會被轉爲字符串

正所以,數組才能使用數字索引訪問。而數組中的鍵都是字符串。

in 運算符 與包含

MDN上的解釋是這樣的:

若是指定的屬性在指定的對象或其原型鏈中,則**in 運算符**返回true

顯然這個in並非包含關係,而是包含該屬性。

"toString" in {}; //true
複製代碼

in右操做數必須是一個對象值,不能是字符串。而左側須要一個字符串,

當左側傳入不是字符串時,則調用tostring(),轉爲字符串.

順帶一提,要表達包含關係,可使用Array.prototype.includes() ,例如:

[1, 2, NaN].includes('1');//false
[1, 2, NaN].includes(1.0);//true
[1, 2, NaN].includes(NaN);//true 
複製代碼

1.0.toString ()與(1).toString()

這個問題也是個筆試常考題目。首先是不能寫1.toString(),由於有歧義,不知道這個.是小數點,仍是調用方法。只要能規避歧義的,都能獲得正確的結果。好比:

1 .toString;//'1'
(1).toString();//'1'
1.0.toString();//'1'
複製代碼

如今的問題是爲何1.0.toString()獲得的是字符串'1',而不是字符串’1.0‘呢?

1.0 === 1;//true
複製代碼

從存儲上來說,JavaScript數字所有是浮點數。 根據 IEEE 754標準中的64位二進制(binary64), 也稱做雙精度規範(double precision)來儲存。那麼1.0===1也合情合理。

在toString ()的實現算法中,是根據數字的大小來將數字解碼成字符串的。具體太複雜了,能夠看這個

所以1.0 或是1.00,乃至是1.0000000000000001.toString() 都是’1‘ (精度不夠了)。

那麼問題來了,有沒有數tostring()能夠獲得1.0呢?

俺也不知道

3n是什麼?

前文的內容徹底解釋了1.0 in a 和’1‘ in a獲得true的問題,可是最後一個3n 是什麼呢。

答案是ES2020新特性:一個用於處理任意精度整數的新數字基元--n

爲了更精確地表示沒有位數限制的整數,ES2020引入了不一樣於Number數字類型的BigInt數字類型, 只用來表示整數(大整數),沒有位數的限制,任何位數的整數均可以精確表示。爲了與 Number 類型區別,BigInt 類型的數據必須添加後綴n

typeof 3n //"bigint"
3n ==3;//true
3n === 3;//false
3n+4n;//7n
3n.toString();//"3"
複製代碼

因此3n in [1,2,3,4] ===true很是合理。

那麼1.0n.tostring() 能獲得1.0嗎?固然,報錯了。bigInt只能用於整數。

坐等ES2035修復小數的精度問題。

最後說下for in

for in 能夠用與遍歷,跟in差很少意思,用於遍歷獲得的是索引。

遍歷數組時,固然獲得的是字符串而不是數字。

for (let i in [1,2,3]){console.log(2+i)};
//20
//21
//22
複製代碼

也能遍歷到原型鏈上的屬性。

let a = [1,2,3,4];
a.k='v';
Array.prototype.key='val';
for (let i in a){console.log(i)};
0
1
2
3
k
key
複製代碼

ES6的for of,用於遍歷數組。

for (let i of a){console.log(i)}
1
2
3
4 //到4就結束了,拿不到屬性k
複製代碼

for of 遍歷對象或類數組會報錯。

綜上:for in 適合遍歷對象

for of 遍歷數組

總結

js中的in不是表示包含關係,並且表示屬性存在與否

數組中的屬性均爲字符串,in運算符判斷是存在類型轉換

相關文章
相關標籤/搜索