今天在項目中看到有這樣一段代碼: java
if(~key.indexOf('I')){
priceTagData.adulti = {
tag: key,
price: value
}
}
我表示對~這個操做符感到無比陌生,天然也就理解不了做者的意圖。因爲目前本人的求知慾正處於旺盛期,因此決定學習一下這個操做符的用處。ios
看了眼ES5,原來它是位取反操做符。下面是ES5對這個操做符的說明: c++
![]() |
Bitwise NOT Operator ( ~ ) The production UnaryExpression : ~ UnaryExpression is evaluated as follows:編程 1.Let expr be the result of evaluating UnaryExpression. |
大概求值過程就是:學習
1.先求值~右邊的表達式,設求值結果爲exprlua
2.執行ToInt32(expr),設返回結果爲oldValuespa
![]() |
由於ECMAScript中Number類型存儲格式是64位浮點數,因此在進行位操做前要把浮點數轉換爲32位有符號整數,也就是上邊說明中的ToInt32方法。ToInt32是規範定義的內部類型轉換方法,ECMAScript程序使用者不能直接調用,ToInt32具體說明點這裏 。 |
3. 將oldValue按位取反並返回code
因爲返回的是32位整數,因此還須要將這個整數轉換爲64位浮點數。因而可知,ECMAScript中的位操做並不像c,c++那樣直接操做位,它須要在位操做以前和以後進行浮點數轉成整數和整數轉成浮點數的操做。索引
看一個具體例子:~4294962318,咱們經過上邊規範的定義來意淫下結果。。。
首先求值~右邊的表達式,求值後就是4294962318,
而後執行ToInt32(4294962318),
ToInt32的內部執行過程爲:
將4294962318進行ToNumber轉換,結果依舊爲4294962318
求值sign(4294962318) * floor(abs(4294962318)),結果依舊爲4294962318
求值4294962318 modulo 4294967296(2^32)的值,結果爲4294962318
4294962318 大於2147483648(2^31),因此返回4294962318 - 4294967296,也就是-4978
接下來要把-4978轉換成2進制,爲了方便我寫了段程序把一個10進制轉換成2進制,下邊是c++源碼,你能夠經過這個程序轉換你想轉換的數字
#include <iostream>
using namespace std;
int main () { int t; cout << "輸入一個要轉換爲2進製表示形式的數字:"; cin >> t; char str[255]; itoa(t, str, 2); cout << str << endl; system("pause"); return 0; }
-4978用二進制表示爲 1111 1111 1111 1111 1110 1100 1000 1110
按位取反後就是 0000 0000 0000 0000 0001 0011 0111 0001
這個取反後的結果理論上就是~4294962318計算出的值
接下來咱們在js控制檯執行~4294962318,獲得4977
再用程序將4977轉換成二進制結果是0000 0000 0000 0000 0001 0011 0111 0001
你會發現和咱們推導出的二進制是同樣的
理論和實踐都講過以後,咱們再回到最初的問題:
if(~key.indexOf('I')) {
做者這句到底想要幹什麼。。。
indexOf你們應該都知道,它是字符串的一個方法,用來查找傳入的字符在字符串中第一次出現的位置,若是有,則返回該字符在字符串中的索引值,若是沒有返回-1。
~-1正好等於0,而0在ECMAScript if條件中又至關於false,非0數都至關於true。終於!!!我明白了做者的意圖,那就是若是key字符串中若是含有I那就執行if條件爲true中的語句,若是不含有I,那就不執行if條件爲true中的語句。
和這種高帥富寫法等效的屌絲寫法就是:
if(key.indexOf('I') !== -1){
saveTheEarth();
}
最後就是吐槽時間了。。。
我我的不是很同意這種怪異的寫法(相對於我)。由於jser在平時編程中須要使用位操做的地方還算比較少的,因此在多人項目中若是寫了這樣一句代碼,往後別人來維護這塊代碼時就會感到一頭霧水,無形中增長了項目維護的難度和成本。