当代数在表达式之前时,代字号会做什么?

wwa*_*waw 182 javascript syntax bit-manipulation

var attr = ~'input,textarea'.indexOf( target.tagName.toLowerCase() )
           ? 'value'
           : 'innerHTML'
Run Code Online (Sandbox Code Playgroud)

我在一个答案中看到了它,我以前从未见过它.

这是什么意思?

ale*_*lex 251

~是一个按位运算符,它会翻转其操作数中的所有位.

例如,如果您的数字是1,它的IEEE 754浮点数的二进制表示(JavaScript如何处理数字)将是......

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
Run Code Online (Sandbox Code Playgroud)

因此~将其操作数转换为32位整数(JavaScript中的按位运算符)...

0000 0000 0000 0000 0000 0000 0000 0001
Run Code Online (Sandbox Code Playgroud)

如果是负数,则将其存储在2的补码中:反转所有位并加1.

......然后翻转所有的东西......

1111 1111 1111 1111 1111 1111 1111 1110
Run Code Online (Sandbox Code Playgroud)

那么它的用途是什么呢?什么时候可以使用它?

它有很多用途.如果你正在编写低级别的东西,它很方便.如果您对应用程序进行了分析并找到了瓶颈,那么可以通过使用按位技巧(在更大的包中作为一种可能的工具)来提高性能.

这也是一个(一般)不清楚绝招打开indexOf()发现返回值放入truthy(同时使未找到falsy)人们通常会增加一倍它用它截断数字为32位(和丢弃其小数代替它的副作用,与Math.floor()正数有效相同).

我说不清楚,因为它的用途并不是很明显.通常,您希望您的代码能够清楚地与其他人阅读.虽然使用~可能看起来很酷,但它通常对自己的好处太聪明了.:)

它现在也不太相关的是,JavaScript有Array.prototype.includes()String.prototype.includes().这些返回一个布尔值.如果您的目标平台支持它,您应该更喜欢这个来测试字符串或数组中是否存在值.

  • 当您在一家拥有众多开发人员的大型公司工作时,您希望代码能够清晰地编写(英文)并且有详细记录.使用垃圾收集语言进行高级编码的目的是避免考虑二进制操作,许多前端开发人员甚至都没有自己的汇编语言经验. (7认同)
  • 讨厌的是正确的词吗?如果它有效,我只是称它为语言的成语.有很多成语.一旦你了解它们,它们并不清楚.如果您不了解列表推导并不清楚它们,并且可以使用更详细的循环来完成,但您永远不会要求Python程序员不要使用它们.同样`value = value || JavaScript中的default`是一种常见且有效的习惯用语,只要您知道何时可以使用它. (2认同)
  • @gman我猜是否有人使用并不重要。我认为将列表推导(语言功能)与此进行比较并不是一回事(*聪明*的方式,避免键入一些额外的字符)。如果您认为*讨厌*这个词太苛刻,请随时修改我的答案。 (2认同)
  • 也许更常见的例子是 `v = t ?a : b;`. 我发现这比 `var v; 清楚得多;if (t} { v = a; } else { v = b; }` 通常分为 5 行以上,并且比 `var v = b; if (t) { v = a; }` 通常为 4 + 行。但我知道很多人不熟悉 `?:` 运算符,他们更喜欢第二种或第三种方式。我发现第一种更易读。我同意一般原则,让代码清晰,不要使用 hacks。我想一旦我学会了`~v.indexOf('...')` 就会非常清楚。 (2认同)
  • 我不会称呼“〜”为惯用语。从技术上讲,它是* spec *语言的一部分,但在*一般用途*中,它并不是该语言的大部分。 (2认同)

Poi*_*nty 102

indexOf()表达式之前使用它有效地为您提供了一个truthy/falsy结果,而不是直接返回的数字索引.

如果返回值-1,则~-10因为-1为所有1位的字符串.任何大于或等于零的值都将给出非零结果.从而,

if (~someString.indexOf(something)) {
}
Run Code Online (Sandbox Code Playgroud)

if当"something"在"someString"中时,将导致代码运行.如果你试图.indexOf()直接使用布尔值,那么这将无法工作,因为有时它返回零(当"某事物"在字符串的开头).

当然,这也有效:

if (someString.indexOf(something) >= 0) {
}
Run Code Online (Sandbox Code Playgroud)

而且它不那么神秘.

有时候你也会看到这个:

var i = ~~something;
Run Code Online (Sandbox Code Playgroud)

~像这样使用运算符两次是将字符串转换为32位整数的快速方法.第一个~进行转换,第二个转换~回位.当然,如果操作符应用于无法转换为数字的内容,则会得到NaN结果.(编辑 - 实际上它~是第一个应用的第一个,但你明白了.)

  • @adlwalrus很好地传统的'0`是'false`而非零是'true`的回溯,至少在70年代是C,可能还有许多其他当代系统编程语言.它可能源于硬件的工作方式; 许多CPU在操作后设置为零位,并具有相应的分支指令来测试它. (7认同)
  • 将它转换为32位int的更快方法是`| 0`,在这种情况下它只有一个操作. (4认同)
  • 对于那些不想一点一滴地求反的人,当对整数执行“〜”时,它等于“-(x + 1)”。 (2认同)

zan*_*ngw 23

~按位NOT运算符,~x是大致相同的-(x+1).它更容易理解.所以:

~2;    // -(2+1) ==> -3
Run Code Online (Sandbox Code Playgroud)

考虑-(x+1).-1可以执行该操作来生成一个0.

换句话说,~与一系列数值一起使用将仅对输入值产生false(强制0来自-1)-1值,否则产生任何其他>= 0值.

众所周知,-1通常称为哨兵值.它用于返回许多功能indexOf()的成功~失败~语言.其中~xJavaScript 的返回值规则相同.

以这种方式检查-(x+1)另一个的存在/不存在是常见的-(x+1)

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}
Run Code Online (Sandbox Code Playgroud)

但是,通过-1以下方式更容易实现

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}
Run Code Online (Sandbox Code Playgroud)

你不懂JS:Kyle Simpson的类型和语法


Jor*_*ran 21

~indexOf(item) 经常出现,这里的答案很棒,但也许有些人只需要知道如何使用它并"跳过"理论:

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }
Run Code Online (Sandbox Code Playgroud)

  • 我同意。Airbnb JavaScript 风格指南不允许 `++` 和 `--` 因为它们“鼓励过度狡猾”,但不知何故 `~` 幸存下来(潜伏在阴影中)https://github.com/airbnb/javascript/issues/540 (2认同)

Dan*_*man 11

对于那些考虑使用波浪形技巧从结果中创建一个值的人来说indexOf,它更明确,并且更少使用该includes方法String.

'hello world'.includes('hello') //=> true
'hello world'.includes('kittens') //=> false
Run Code Online (Sandbox Code Playgroud)

请注意,这是ES 2015中的一种新标准方法,因此它不适用于旧版浏览器.如果重要,请考虑使用String.prototype.includes polyfill.

此功能也适用于使用相同语法的阵列:

['apples', 'oranges', 'cherries'].includes('apples') //=> true
['apples', 'oranges', 'cherries'].includes('unicorns') //=> false
Run Code Online (Sandbox Code Playgroud)

如果您需要较旧的浏览器支持,这是Array.prototype.includes polyfill.

  • 或者只是使用编译器,这样你就可以编写更清晰的代码,而不是根据最差的公分母JS解释器编写语言...... (8认同)
  • @Ben 是对的,它也不适用于 Netscape 4.72。 (5认同)
  • 避免使用includes().在撰写本文时,任何版本的IE(不仅仅是旧浏览器)都不支持它:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/includes (2认同)