背景信息是:在JavaScript中,float和int之间没有区别。只有数字,它是IEEE 754标准。所以在JavaScript中不应该有任何“float”vs“int”。即使在按位操作时将数字视为32位整数,结果也应为Number。换句话说,不应该有一个“整数”的类型。
(-1).toString === (-1 >>> 0).toString // => true
(-1).__proto__ === (-1 >>> 0).__proto__ // => true
(-1).toString(2) // => "-1"
(-1 >>> 0).toString(2) // => "11111111111111111111111111111111"
似乎对象包装器(使基本类型1成为对象的包装器)将创建两个对象具有相同的对象类型(如__proto__
所示),但不知何故,它认为它本身不是同一类型,一个是浮点数,一个是32位整数。这是为什么?
根据OOP接口的通常一般原则,如果两个对象属于同一类型(相同类型,如__proto__
所示相同),则它们不应该给出相同,相同的结果回复相同的“消息”,即toString(2)
?
答案 0 :(得分:1)
-1
,-1>>>0
都是“数字”类型
您可以分别从typeof -1
和typeof -1>>>0
进行检查。
因此,他们的两个方法.toString
字面上都是Number.prototype.toString
,相同。
这意味着所有以下内容都指向相同的Number.prototype.toString
。
(1).toString // Number.prototype.toString
(2).toString // Number.prototype.toString
(1.55555).toString // Number.prototype.toString
(Infinity).toString // Number.prototype.toString (Yes, typeof Infinity is Number)
(NaN).toString // Number.prototype.toString (typeof NaN is Number)
(1>>0).toString // Also Number.prototype.toString
这就是为什么他们的方法.toString
的比较结果为真的原因。它们都是Number.prototype.toString
。
它派生相同的Number.prototype.toString并不意味着它总是产生相同的输出。
该方法采用不同的输入值肯定会返回不同的结果值。
说明效果。打电话给这个。
(-1).toString(2);
与:
相同Number.prototype.toString.apply(-1,[2]); // Yields -1
另外,请致电:
(-1>>>0).toString(2);
与:
相同Number.prototype.toString.apply(-1>>>0,[2]); // Yields 11111111111111111111111111111111
现在你注意到他们的行为方式。
答案 1 :(得分:0)
这变成了您正在混淆一些事情...
为什么这个true
?
(-1).toString === (-1 >>> 0).toString // => true
因为两者都是Number
和Number.toString === Number.toString
。
我想你的意思是:
(-1).toString() === (-1 >>> 0).toString() // => false!!!
是否注意到多余的括号?
就数字处理而言,正如FrédéricHamidi指出的那样,移位运算(以及按位运算)将Number转换为32位整数,进行数学运算,然后将其转换回Number。您可以使用诸如C ++之类的类型化语言来编写以下内容,以使其清晰明了:
double d = -1;
uint32_t u = static_cast<uint32_t>(d)
u >>= 1
d = static_cast<double>(u)
static_cast<>()
不是必需的,该语言会自动为您完成这些操作,但是为了清楚起见,我将其放在此处。
重要的一点是,>>>
运算符假定输入整数是无符号的(因此uint32_t
),您可能认为应该将有符号整数用作中间变量,如下所示:
double d = -1;
int32_t i = static_cast<int32_t>(d)
uint32_t u = static_cast<uint32_t>(i);
u >>= 1
i = static_cast<int32_t>(u)
d = static_cast<double>(i)
但是,事实并非如此。 JavaScript确实将无符号整数转换回Number
(double
)。如果查看(-1 >>> 0).toString()
的输出,您会发现它不再是-1
,而是4294967295
。可以容纳32位(1 << 32 - 1
。)的最大无符号数字。
现在,我想您理解了无符号移位问题,这意味着符号位丢失了。在8位的情况下,移位后看起来像这样:
1111 1111 >> 1 = 1111 1111
1111 1111 >>> 1 = 0111 1111 (bit 7 becomes zero)
但是,在您的情况下,您使用了0位移,因此该值根本不会移位:
1111 1111 >> 0 = 1111 1111 signed, so it is -1
1111 1111 >>> 0 = 1111 1111 unsigned, so it is 255
,但在第二种情况下,整数变为无符号。由于double
尾数中有足够的空间按原样保存uint32_t
,因此您不会失去精度(这是一个有趣的JavaScript技巧!在C ++中,您肯定希望找回符号) 当您将uint32_t
保存在int32_t
...中时,如果您像C / C ++程序员一样。)
P.S。您对__proto__
的第二次测试也遇到了同样的问题。您正在比较参考,而不是内容。在JavaScript中,您有一个对数组和对象(and it can become hairy)进行深度比较的概念。 __proto__
是一个对象,您只是比较了引用。话虽这么说,由于两者都是Number
,因此深度比较也将返回true。