数组索引使用按位与/或运算符时,实际访问的是什么?
你遇到的核心是JavaScript的按位运算知识点——数组索引里的|、&不是逻辑运算符,而是按位或(Bitwise OR)和按位与(Bitwise AND),它们会先将操作数转换为32位整数计算,最终结果作为数组索引/对象属性键。
一、数组索引中的按位运算详解
先明确数组myMap的索引对应值:myMap[0]=1、myMap[1]=2、myMap[2]=3、myMap[3]=4、myMap[4]=5、myMap[5]=6、myMap[6]=7,索引超出0-6范围时返回undefined。
1. 按位或(|)规则
两个二进制位只要有一个为1,结果位就是1;全为0时结果位为0。计算时先把十进制转成二进制,再逐位运算,最后转回十进制。
1 | 4:
1的二进制是0001,4是0100,按位或后得到0101(十进制5),所以取myMap[5],结果为6。4 | 1:
按位或满足交换律,结果同样是5,取myMap[5]=6。4|1|4|1|1|1|1:
多次按位或1和4,结果始终是5,取myMap[5]=6。4|1|3|1|1|1|1:
先算4|1=5,再算5|3(5是0101,3是0011),按位或得到0111(十进制7),后续按位或1不改变结果,myMap[7]超出数组长度,返回undefined。
2. 按位与(&)规则
两个二进制位都为1时,结果位才是1;否则为0。
1 & 4:
1是0001,4是0100,没有同时为1的位,结果是0000(十进制0),取myMap[0]=1。1 &5:
5的二进制是0101,和1的0001按位与,得到0001(十进制1),取myMap[1]=2。5&1:
按位与满足交换律,结果同样是1,取myMap[1]=2。1&6:
6的二进制是0110,和1的0001按位与,没有同时为1的位,结果是0,取myMap[0]=1。
3. 组合运算(5&1&5|2)
按位运算优先级:&高于|,所以先算5&1=1,再算1&5=1,最后算1|2(1是0001,2是0010),得到0011(十进制3),取myMap[3]=4。
二、对象属性访问中的按位运算
当用字符串做按位运算时,JavaScript会先将字符串转换为数值:
'hello'转换为数值是NaN,''转换为数值是0;按位运算中
NaN会被强制转换为0。obj['hello' & '']:等价于obj[0 & 0]即obj[0],对象中无此属性,返回undefined。obj['hello' | '']:等价于obj[0 | 0]即obj[0],对象中无此属性,返回undefined。obj['hello' || '']:这里是逻辑或(Logical OR),逻辑或返回第一个真值,'hello'是真值,所以等价于obj['hello'],返回'world'。
内容的提问来源于stack exchange,提问作者Mike K

