我有一个变量,存储的是 false
或 true
,但我需要分别得到 0
或 1
。如何做到这一点?
我有一个变量,存储的是 false
或 true
,但我需要分别得到 0
或 1
。如何做到这一点?
使用一元加号运算符,它将其操作数转换为数字。
+ true; // 1
+ false; // 0
请注意,当然您仍需要在服务器端对数据进行清理处理,因为无论客户端代码如何,用户都可以向您的服务器发送任何数据。
bool === true ? 1 : 0
是最快的,其次是 bool | 0
。 - Qix - MONICA WAS MISTREATEDJavascript有一个三元运算符可以使用:
var i = result ? 1 : 0;
if
语句。 - Mr PizzaGuy我认为最好的解决方案是:
fooBar | 0
这在 asm.js 中用于强制整数类型。
1 | 0 = 1; 0 | 0 = 0; true | 0 = 1; false | 0 = 0; 'foo' | 0 = 0; undefined | 0 = 0
- Luke Miles这个任务的正式操作方式如下:
Number(true) // 1
Number(false) // 0
NaN
的例子吗? - Philip我创建了一个JSperf比较所有建议答案的测试。
简单来说 - 所有现代浏览器的最佳选项是:
val | 0;
更新:
看起来这些方法现在都差不多,除了Number()
函数最慢,而最好的是val === true ? 1 : 0;
。
Number
构造函数和+bool
,默认使用简单的if
语句;如果您的项目中基准测试表现更好,则可以使用bool | 0
、1 * bool
。这是一个相当古老的问题,有许多有效的答案。我注意到这里的所有基准测试都不相关 - 没有考虑分支 预测。此外,现在的JS引擎不仅仅解释代码,它们JIT 编译成本机代码并在执行前进行优化。这意味着除了分支预测外,编译器甚至可以用最终值替换表达式。
现在,这两个因素如何影响布尔转整数的性能呢?让我们来看看!在我们进入基准测试之前,了解我们要测试什么非常重要。对于转换,我们使用以下七种转换方法:数字构造函数:Number(bool)
、if语句(使用三目运算符):bool ? 1 : 0
、一元操作符+
:+bool
、按位或:bool | 0
、按位与:bool & 1
、按位双重否定:~~bool
、数字乘法:bool * 1
“Conversion”指将false
转换为0
,将true
转换为1
1。每个转换方法都运行了100,000次,测量每毫秒的操作次数。在下表中,转换方法将根据其结果分组。结果后面的百分比表示该方法相对于同一浏览器中最快方法慢的程度。如果没有百分比,则该方法要么是最快的,要么差异可以忽略不计(小于0.01%)。基准是在配备Apple M1 Pro 10核CPU和16GB RAM的Macbook Pro 16英寸机器上进行的。浏览器是Chrome 102、Firefox 101和Safari 15.5。true
转换。
方法 | Chrome (V8) | Firefox (Spidermonkey) | Safari (Webkit) |
---|---|---|---|
Number(bool) |
31745.89 | 392.35 - 91.48% | 31231.79 |
bool ? 1 : 0 |
31592.8 - 0.48% | 4602.64 | 27533.47 - 11.84% |
+bool |
31332.57 - 1.3% | 4463.41 - 3.02% | 27378.7 - 12.34% |
bool | 0 |
31488.5 - 0.81% | 4441.4 - 3.5% | 27222 - 12.84% |
bool & 1 |
31383.17 - 1.14% | 4459.64 - 3.11% | 27317.41 - 12.53% |
~~bool |
31265.85 - 1.51% | 4442.35 - 3.48% | 27434.72 - 12.16% |
bool * 1 |
31374.4 - 1.17% | 4444.05 - 3.45% | 27381.19 - 12.33% |
Number
与V8的表现类似,其他方法落后,但彼此之间非常接近。有哪些收获?浏览器大多数情况下能够用简单的值1
替换我们的转换。当我们能够将布尔值心理上替换为常量值时,就会进行此优化。Number
构造函数是一个有趣的异常情况 - 它在Firefox中严重落后(慢了91%!),而在Safari中则是最快的!Math.random() < 0.5
。这将产生50%的true
和50%的false
的机会。我们的结果会发生变化吗?让我们运行benchmark来查看。
方法 | Chrome (V8) | Firefox (Spidermonkey) | Safari (Webkit) |
---|---|---|---|
Number(bool) |
1648.83 - 2.26% | 280.34 - 86.4% | 8014.69 |
bool ? 1 : 0 |
804.27 - 52.32% | 731.57 - 64.5% | 1294.02 - 83.85% |
+bool |
1670.79 - 0.95% | 2057.94 | 7753.99 - 3.25% |
bool | 0 |
1668.22 - 1.11% | 2054.17 | 7764.81 - 3.12% |
bool & 1 |
1675.52 - 0.67% | 2056.76 | 7193.08 - 10.25% |
~~bool |
1676.24 - 0.63% | 2056.18 | 7669.48 - 4.31% |
bool * 1 |
1686.88 | 2060.88 | 7751.48 - 3.28% |
Number
构造函数在Firefox上表现最差。由于生成分支,三元运算符落后了。总体而言,Safari似乎是我们的最佳表现者,每种方法都产生了极快的结果!Math.random() < 0.01
,这意味着1%的true
,99%的false
。
方法 | Chrome(V8) | Firefox(Spidermonkey) | Safari(Webkit) |
---|---|---|---|
Number(bool) |
1643.13 - 1.68% | 280.06 - 86.4% | 8071.65 |
bool ? 1 : 0 |
1590.55 - 4.83% | 1970.66 - 4.32% | 7119.59 - 11.8% |
+bool |
1662.09 - 0.55% | 2054.09 | 7762.03 - 3.84% |
bool | 0 |
1669.35 | 2051.85 | 7743.95 - 4.06% |
bool & 1 |
1661.09 - 0.61% | 2057.62 | 7454.45 - 7.65% |
~~bool |
1662.94 - 0.5% | 2059.65 | 7739.4 - 4.12% |
bool * 1 |
1671.28 | 2048.21 | 7787.38 - 3.52% |
Number
在Firefox中的可怕性能-为什么?if (bool)
而不是那个丑陋的三元运算符!我希望 JavaScript 有像 Rust 或 Python 那样的东西...if
导致性能不佳 - 如果是这种情况,请随意进入 branchless programming!但不要太深入这个兔子洞,相信我,没有人会从像 -1 * (a < b) + 1 * (a > b)
这样的东西中受益。以下是一些具体细节:
Number(bool)
。虽然全球范围内,Chromium平台(Chrome+Edge)的市场份额约为68%,Safari为19%,Firefox仅为3.6%,但有足够快速且不会完全牺牲用户的其他方法。Firefox在桌面市场份额中占7%,这相当于173百万用户。+bool
在Firefox中表现得与Number
类似糟糕,也许也要考虑到这一点-位操作技巧和乘法在所有浏览器和所有情况下都能给出一致的高性能结果。bool | 0
最有可能为其他开发人员所熟悉。如果您一直阅读到了最后,我将永远感激您-这是我第一个更长、更重要的StackOverflow答案,如果它有所帮助并且具有洞察力,那对我来说意义重大。如果您发现任何错误,请随时纠正我!
编辑:之前的基准测试工具提供了含糊不清、没有度量单位的结果。我已经更改了它,并添加了Safari的基准测试,这些测试影响了结论。start = performance.now(); for (let i = 0; i < 1000000; i++) { let x = + (Math.random() <0.5);} end = performance.now(); console.log(end-start)
。我对此的理解有误吗? - Trentium当JavaScript期望一个数字值但实际接收到一个布尔值时,它会将该布尔值转换为数字:true和false分别转换为1和0。因此,您可以利用这一点;
var t = true;
var f = false;
console.log(t*1); // t*1 === 1
console.log(f*1); // f*1 === 0
console.log(+t); // 0+t === 1 or shortened to +t === 1
console.log(+f); //0+f === 0 or shortened to +f === 0
更多阅读:类型转换。请参考《JavaScript权威指南》第3.8章。
我最近写代码时也遇到了这个问题。我的解决方案是使用位与运算符。
var j = bool & 1;
解决经常出现的问题更快捷的方法是创建一个函数。这样可以提高代码的可读性,方便在维护阶段进行理解,并且可以消除书写错误的可能性。
function toInt( val ) {
return val & 1;
}
var j = toInt(bool);
编辑 - 2014年9月10日
在Chrome浏览器中,使用三元运算符和相等操作符进行转换并不能提高速度。这种情况似乎没有任何意义,但我想这可能是某种低级别优化,从某些方面来看是有意义的。
var j = boolValue === true ? 1 : 0;
自己测试一下:http://jsperf.com/boolean-int-conversion/2
在 Firefox 和 Internet Explorer 中,通常使用我发布的版本速度更快。
编辑-2017年7月14日
好吧,我不会告诉你应该使用哪个版本。每个浏览器都在不断变化,每种方法执行操作的速度也在不断变化。有一段时间,Chrome实际上比其他浏览器的按位&版本表现更好,但突然就变得更糟了。我不知道他们在做什么,所以我就只是说谁在乎呢。几乎没有理由关心这种操作完成的速度。即使在移动设备上,这也是一个微不足道的操作。
另外,这里有一种新的添加“toInt”原型的方法,它不能被覆盖。
Object.defineProperty(Boolean.prototype, "toInt", { value: function()
{
return this & 1;
}});
bool === true ? 1 : 0
,因为它在 V8 引擎中是最快的。 - Qix - MONICA WAS MISTREATEDbool ? 1 : 0;
。该语句的意思是,如果布尔值为真,则返回1,否则返回0。 - Mouloud85