JavaScript中的运算符|=是什么作用?

53

我在一个JS项目中发现了以下代码:

var a = new Array();
a[0] = 0;
for (var b = 0; b < 10; b++) {
  a[0] |= b; 
}

在for循环的循环体中,|=是做什么用的?

代码示例可能有问题,但它被V8提供 这里 来展示优化性能的示例。

更新的示例

上面的示例在大多数情况下等同于 var a = [15];。更现实的一个使用 |= 运算符的示例是在单个变量中设置二进制标志,例如在权限对象上:

//Set up permission masks
var PERMISSION_1_MASK = parseInt('0001',2);
var PERMISSION_2_MASK = parseInt('0010',2);
..

//Set up permissions
userPermissions = 0;
userPermissions |= hasPermissionOne && PERMISSION_1_MASK;
userPermissions |= hasPermissionTwo && PERMISSION_2_MASK;
..

//Use permissions
if(userPermissions & PERMISSION_1_MASK){
    ..//Do stuff only allowed by permission 1
}

我刚意识到这段代码来自这里: http://www.html5rocks.com/en/tutorials/speed/v8/ - razpeitia
2
@razpeitia,请仔细阅读问题,你会找到URL... - ContentiousMaximus
4个回答

98
a[0] |= b

基本上就是

a[0] = a[0] | b

"| 是一个或按位运算符。更新:当 a[0] 被赋值为 0 时,在二进制中,a[0]0000。在循环中,"
  1. b = 0

    a[0] = 0 (base 10) = 0000 (base 2)
    b    = 0 (base 10) = 0000 (base 2)
                       ---------------
    a[0] | b           = 0000 (base 2) = 0 (base 10)
    
  2. b = 1

    a[0] = 0 (base 10) = 0000 (base 2)
    b    = 1 (base 10) = 0001 (base 2)
                       ---------------
    a[0] | b           = 0001 (base 2) = 1 (base 10)
    
  3. b = 2

    a[0] = 1 (base 10) = 0001 (base 2)
    b    = 2 (base 10) = 0010 (base 2)
                       ---------------
    a[0] | b           = 0011 (base 2) = 3 (base 10)
    
  4. b = 3

    a[0] = 3 (base 10) = 0011 (base 2)
    b    = 3 (base 10) = 0011 (base 2)
                       ---------------
    a[0] | b           = 0011 (base 2) = 3 (base 10)
    
  5. b = 4

    a[0] = 3 (base 10) = 0011 (base 2)
    b    = 4 (base 10) = 0100 (base 2)
                       ---------------
    a[0] | b           = 0111 (base 2) = 7 (base 10)
    
  6. b = 5

    a[0] = 7 (base 10) = 0111 (base 2)
    b    = 5 (base 10) = 0101 (base 2)
                       ---------------
    a[0] | b           = 0111 (base 2) = 7 (base 10)
    
  7. b = 6

    a[0] = 7 (base 10) = 0111 (base 2)
    b    = 6 (base 10) = 0110 (base 2)
                       ---------------
    a[0] | b           = 0111 (base 2) = 7 (base 10)
    
  8. b = 7

    a[0] = 7 (base 10) = 0111 (base 2)
    b    = 7 (base 10) = 0111 (base 2)
                       ---------------
    a[0] | b           = 0111 (base 2) = 7 (base 10)
    
  9. b = 8

    a[0] = 7 (base 10) = 0111 (base 2)
    b    = 8 (base 10) = 1000 (base 2)
                       ---------------
    a[0] | b           = 1111 (base 2) = 15 (base 10)
    
  10. b = 9

    a[0] = 15 (base 10) = 1111 (base 2)
    b    =  9 (base 10) = 1001 (base 2)
                        ---------------
    a[0] | b            = 1111 (base 2) = 15 (base 10)
    
在循环结束时,a[0] 的值为 15

很高兴能帮到你 :) - Jacob George
3
为了明确一点,步骤4、6、7、8和10都是多余的,因此这个循环不是性能提升的好例子... - Izkata

53
x |= y;

等同于

x = x | y;

其中|表示按位或操作。


有惯用的意思吗?或者有什么技巧,就像使用 ~~ 将浮点数向下取整一样? - katspaugh
1
@katspaugh 有的。例如,它可以用于有效地编码和检查权限(这也适用于 OP 代码)。阅读这篇文章 - freakish
1
@katspaugh 你说的“向下取整浮点数”是什么意思?我从未听说过这种东西! - Jacob George

11

和大多数赋值操作符一样,它等价于再次使用左侧的值来应用该操作符:

a |= b
a = a | b

就像

a += b
a = a + b

请到Moz Dev Net查看更多信息。

[编辑:脑残了,混淆了 | 和 ||。需要喝更多的咖啡。以下已修改]

由于|是按位或运算符,因此a|b的结果将是表示具有ab所有1位的位字符串的整数。请注意,javascript没有原生的int或bitstring类型,因此它将首先将ab转换为int,然后在位上进行OR运算。因此,二进制下的9 | 2是1001 | 0010 = 1011,即11,但8 | 2=8。

其效果是将b的标志位添加到a中。所以如果您有一些标志WEEVILFLAG = parseInt(00001000, 2)

// a = parseInt(01100001,2)
if(isWeevilish(a))
    a |= WEEVILFLAG;
// now a = parseInt(01101001,2)

该操作将在a中将对应的位设置为1。


1
这与逻辑或相同吗?例如:var a =“title”|| x - ContentiousMaximus
4
你混淆了逻辑或和按位或。 - katspaugh
2
Bah. 按位或不是逻辑或。大脑是有趣的东西。现在已经修复。 - Phil H

5

如果两个操作数的相应位都为1,则按位或运算符返回每个位位置上的1。

代码: result = a | b;

^是按位异或运算符,它对于其操作数的相应位中仅有一个(不是两个)为1的位置返回1。下一个示例返回4(0100):


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接