资源描述
JS运算符 — 位运算符
一. 按位与运算符(&)
1. 该运算符对它的运算数逐位执行布尔AND操作,只有两个运算数中相应的位都为1时,结果中的这一位才为1,它要求其运算数为整型,如果运算数不是整型,则会尝试将其转换为32位整型,如果无法转换,就返回NaN。
// 运算数均为整型
alert(9 & 9); // 9
alert(9 & 10); // 8
alert(1 & 3); // 1
// 运算数可以被转换为整型
alert([9] & '9'); // 9
alert([9] & ['10']); // 8
alert(1.25 & 3.25); // 1
// 一个或两个运算数均无法被转换整型
alert(1 & ['a']); // 0
alert({} & /\d/); // 0
alert(NaN & NaN); // 0
alert(Infinity & Infinity); // 0
alert(NaN & Infinity); // 0
alert(null & null); // 0
alert(undefined & undefined); // 0
alert(null & undefined); // 0
二. 按位或运算符(|)
1. 该运算符对它的运算数逐位执行布尔OR操作,如果其中一个运算数中相应位为1或者两个运算数中的相应位都为1,结果中的这一位就为1,它要求其运算数为整型,如果运算数不是整型,则会尝试将其转换为32位整型,如果无法转换,就返回NaN。
// 运算数均为整型
alert(9 | 9); // 9
alert(9 | 10); // 11
alert(1 | 3); // 3
// 运算数可以被转换为整型
alert([9] | '9'); // 9
alert([9] | ['10']); // 11
alert(1.25 | 3.25); // 3
// 一个运算数无法被转换整型
alert(1 | ['a']); // 1
alert(10 | null); // 10
alert(100 | NaN); // 100
// 两个运算数均无法被转换成整型
alert({} | /\d/); // 0
alert(NaN | NaN); // 0
alert(Infinity | Infinity); // 0
alert(NaN | Infinity); // 0
alert(null | null); // 0
alert(undefined | undefined); // 0
alert(null | undefined); // 0
三. 按位非运算符(~)
1. 该运算符的作用,相当于改变运算数的符号并减1。它要求其运算数为整型,如果运算数不是整型,则会尝试将其转换为32位整型,如果无法转换,就返回NaN。
alert(~5); // 相当于-5 - 1 = -6
alert(~{}); // -1
alert(~[]); // -1
alert(~[10]); // -11
alert(~'10'); // -11
alert(~'aa'); // -1
alert(~/\d/); // -1
alert(~undefined); // -1
alert(~Infinity); // -1
alert(~NaN); // -1
alert(~null); // -1
alert(~function() {}); // -1
2. ~的运算原理
// 网上有个老外对~~的运算原理做了分析,他的分析如下(以~~foo为例,foo是经过整型转换后的结果):
typeof foo === 'number' && !isNaN(foo) && foo !== Infinity ? foo > 0 ? Math.floor(foo) : Math.ceil(foo) : 0;
// 基于老外的分析,~的运算原理可以想象为这样:
typeof foo === 'number' && !isNaN(foo) && foo !== Infinity ? foo > 0 ? -(Math.floor(foo) + 1) : -(Math.ceil(foo) + 1) : -1;
3. 一个较特殊的例子
alert(~function(){alert(20);}()); // 先输出20,然后输出-1,why???
// 分析:
(1) "()"的优先级要高于"~",所以function(){alert(20);}会先与()结合,再与~结合;
(2) ~会执行其后的语句,但执行结果不会成为运算数,即~function(){alert(20);}()不会成为~20;
(3) ~还会对其后的语句进行求值运算,我们通过模拟来验证一下:
var func = function() {alert(1);};
func.valueOf = function() {return 10;}
alert(~function() {alert(1);}); // -1
alert(~func); // -11
四. 左移运算符(<<)
1. 该运算符有两个运算数:a<<b,将a左移b位相当于a乘以2的b次方;两个运算数都要求是整数,或可以被转换为整数。
// 运算数均为整数
alert(1 << 2); // 4
// 运算数可以被转换为整数
alert([1] << "2"); // 4
2. 当运算数a无法被转换为整数时,运算结果为0。
alert({} << 2); // 0
alert(NaN << 2); // 0
alert(Infinity << 2); // 0
alert(function() {} << 2); // 0
alert(undefined << 2); // 0
alert(null << 2); // 0
3. 当运算数b无法被转转换为整数时,运算结果为运算数a,相当于a<<0。
alert(2 << {}); // 2
alert(20 << NaN); // 20
alert(10 << Infinity); // 10
4. 当运算数a和b均无法被转换为整数时,运算结果为0。
alert("a" << Infinity); // 0
alert(NaN << NaN); // 0
五. 右移运算符(>>)
1. 该运算符有两个运算数:a<<b,将a右移b位相当于执行了这个操作:Math.floor(a/2的b次方),当运算数无法被转换成整数时,运算结果的情况与左移运算符相同。
// 运算数均为整数
alert(7 >> 1); // Math.floor(7/2) = 3
alert(-7 >> 1); // Math.floor(-7/2) = -4
// 运算数无法被转换为整数
alert(NaN >> 1); // 0
alert(NaN >> NaN); // 0
alert(20 >> NaN); 20
六. 用0补足的右移运算符(>>>)
1. 该运算符有两个运算数:a>>>b,当运算数无法被转换成整数时,运算结果的情况与左移运算符相同。
alert("a" >>> 2); // 0
alert("a" >>> NaN); // 0
alert(20 >>> NaN); // 20
展开阅读全文