亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

為什么不要在 JavaScript 中使用位操作符?

eternalshallow / 497人閱讀

摘要:但事實(shí)上,位操作符并不是這么認(rèn)為的。再者,在中使用位操作符的地方畢竟太少,如果你執(zhí)意使用位操作符,未來(lái)維護(hù)這段代碼的人又對(duì)中的位操作符的坑不熟悉,這也會(huì)造成不利的影響。所以,我對(duì)大家的建議是,盡量在中別使用位操作符。

  

本文最早在我的個(gè)人博客《咀嚼之味》發(fā)布:http://jerryzou.com

如果你的第一門(mén)編程語(yǔ)言不是 JavaScript,而是 C++ 或 Java,那么一開(kāi)始你大概會(huì)看不慣 JavaScript 的數(shù)字類(lèi)型。在 JavaScript 中的數(shù)字類(lèi)型是不區(qū)分什么 Int,F(xiàn)loat,Double,Decimal 的??瓤龋艺f(shuō)的當(dāng)然是在 ES6 之前的 JS,在 ES6 的新標(biāo)準(zhǔn)中提出了像 Int8Array 這樣新的數(shù)據(jù)類(lèi)型。不過(guò)這不是本文敘述的重點(diǎn),暫且就不談啦。本文將更著重地談 JS 的數(shù)字類(lèi)型以及作用于它的位操作符,而關(guān)于包裝對(duì)象 Number 的更多了解可以看拔赤翻譯的《JavaScript設(shè)計(jì)模式》

數(shù)字類(lèi)型的本質(zhì)

實(shí)際上,JavaScript的數(shù)字類(lèi)型的本質(zhì)就是一個(gè)基于 IEEE 754 標(biāo)準(zhǔn)的雙精度 64 位的浮點(diǎn)數(shù)。按照標(biāo)準(zhǔn),它的數(shù)據(jù)結(jié)構(gòu)如圖示這樣:由1位符號(hào)位,11位指數(shù)部分以及52位尾數(shù)部分構(gòu)成。

在浮點(diǎn)數(shù)中,數(shù)字通常被表示為:

(-1)sign × mantissa × 2exponent

而為了將尾數(shù)規(guī)格化,并做到盡量提高精確度,就需要把尾數(shù)精確在 [1,2) 的區(qū)間內(nèi),這樣便可省去前導(dǎo)的1。比如:

11.101 × 23 = 1.1101 × 24
0.1001 × 25 = 1.001 × 24

并且標(biāo)準(zhǔn)規(guī)定指數(shù)部分使用 0x3ff 作為偏移量,也就有了雙精度浮點(diǎn)數(shù)的一般公式:

(-1)sign × 1.mantissa × 2exponent - 0x3ff

舉一些例子,應(yīng)該能幫助你理解這個(gè)公式:

3ff0 0000 0000 0000  =  1
c000 0000 0000 0000  =  -2
3fd5 5555 5555 5555  ~  1/3
0000 0000 0000 0000  =  0
8000 0000 0000 0000  =  -0
7ff0 0000 0000 0000  =  無(wú)窮大 ( 1/0 )
fff0 0000 0000 0000  =  負(fù)無(wú)窮大 ( 1/-0 )
7fef ffff ffff ffff  ~  1.7976931348623157 x 10^308 (= Number.MAX_VALUE)
433f ffff ffff ffff  =  2^53 - 1 (= Number.MAX_SAFE_INTEGER)
c33f ffff ffff ffff  =  -2^53 + 1 (= Number.MIN_SAFE_INTEGER)

得益于尾數(shù)省略的一位“1”,使用雙精度浮點(diǎn)數(shù)來(lái)表示的最大安全整數(shù)為 -253+1 到 253-1 之間,所以如果你僅僅使用 JavaScript 中的數(shù)字類(lèi)型進(jìn)行一些整數(shù)運(yùn)算,那么你也可以近似地將這一數(shù)字類(lèi)型理解為 53 位整型。

讓人又愛(ài)又恨的位操作符

熟悉 C 或者 C++ 的同學(xué)一定對(duì)位操作符不陌生。位操作符最主要的應(yīng)用大概就是作為標(biāo)志位與掩碼。這是一種節(jié)省存儲(chǔ)空間的高明手段,在曾經(jīng)內(nèi)存的大小以 KB 為單位計(jì)算時(shí),每多一個(gè)變量就是一份額外的開(kāi)銷(xiāo)。而使用位操作符的掩碼則在很大程度上緩解了這個(gè)問(wèn)題:

#define LOG_ERRORS            1  // 0001
#define LOG_WARNINGS          2  // 0010
#define LOG_NOTICES           4  // 0100
#define LOG_INCOMING          8  // 1000

unsigned char flags;

flags = LOG_ERRORS;                                 // 0001
flags = LOG_ERRORS | LOG_WARNINGS | LOG_INCOMING;   // 1011

因?yàn)闃?biāo)志位一般只需要 1 bit,就可以保存,并沒(méi)有必要為每個(gè)標(biāo)志位都定義一個(gè)變量。所以按上面這種方式只使用一個(gè)變量,卻可以保存大量的信息——無(wú)符號(hào)的 char 可以保存 8 個(gè)標(biāo)志位,而無(wú)符號(hào)的 int 則可以同時(shí)表示 32 個(gè)標(biāo)志位。

可惜位操作符在 JavaScript 中的表現(xiàn)就比較詭異了,因?yàn)?JavaScript 沒(méi)有真正意義上的整型??纯慈缦麓a的運(yùn)行結(jié)果吧:

var a, b;

a = 2e9;   // 2000000000
a << 1;    // -294967296

// fxck!我只想裝了個(gè)逼用左移1位給 a * 2,但是結(jié)果是什么鬼?。?!

a = parseInt("100000000", 16); // 4294967296
b = parseInt("1111", 2);       // 15
a | b;                         // 15

// 啊啊啊,為毛我的 a 絲毫不起作用,JavaScript真是門(mén)吊詭的語(yǔ)言!?。?

好吧,雖然我說(shuō)過(guò)大家可以近似地認(rèn)為,JS 的數(shù)字類(lèi)型可以表示 53 位的整型。但事實(shí)上,位操作符并不是這么認(rèn)為的。在 ECMAScript? Language Specification 中是這樣描述位操作符的:

  

The production A : A @ B, where @ is one of the bitwise operators in the productions above, is evaluated as follows:

Let lref be the result of evaluating A.

Let lval be GetValue(lref).

Let rref be the result of evaluating B.

Let rval be GetValue(rref).

Let lnum be ToInt32(lval).

Let rnum be ToInt32(rval).

Return the result of applying the bitwise operator @ to lnum and rnum. The result is a signed 32 bit integer.

需要注意的是第5和第6步,按照ES標(biāo)準(zhǔn),兩個(gè)需要運(yùn)算的值會(huì)被先轉(zhuǎn)為有符號(hào)的32位整型。所以超過(guò)32位的整數(shù)會(huì)被截?cái)?,而小?shù)部分則會(huì)被直接舍棄。

而反過(guò)來(lái)考慮,我們?cè)谑裁辞闆r下需要用到位操作符?使用左移來(lái)代替 2 的冪的乘法?Naive啊,等遇到像第一個(gè)例子的問(wèn)題,你就要抓狂了。而且對(duì)一個(gè)浮點(diǎn)數(shù)進(jìn)行左移操作是否比直接乘 2 來(lái)得效率高,這也是個(gè)值得商榷的問(wèn)題。

那用來(lái)表示標(biāo)志位呢?首先,現(xiàn)在的內(nèi)存大小已經(jīng)不值得我們用精簡(jiǎn)幾個(gè)變量來(lái)減少存儲(chǔ)空間了;其次呢,使用標(biāo)志位也會(huì)使得代碼的可讀性大大下降。再者,在 JavaScript 中使用位操作符的地方畢竟太少,如果你執(zhí)意使用位操作符,未來(lái)維護(hù)這段代碼的人又對(duì) JS 中的位操作符的坑不熟悉,這也會(huì)造成不利的影響。

所以,我對(duì)大家的建議是,盡量在 JavaScript 中別使用位操作符。

參考資料

維基百科:雙精度浮點(diǎn)數(shù)

MDN:JavaScript數(shù)據(jù)結(jié)構(gòu)

MDN:按位操作符

How to use bitmask?

ECMAScript? Language Specification - 11.10 Binary Bitwise Operators

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/85708.html

相關(guān)文章

  • JavaScript的“黑話(huà)”

    摘要:數(shù)值表示法科學(xué)計(jì)數(shù)法是一種數(shù)學(xué)術(shù)語(yǔ),將一個(gè)數(shù)表示為乘以的次方,如光速萬(wàn)公里每秒,在計(jì)算中通常將米做單位,則記為,而在中我們可使用科學(xué)計(jì)數(shù)法表示。以下情況會(huì)自動(dòng)將數(shù)值轉(zhuǎn)為科學(xué)計(jì)數(shù)法表示小數(shù)點(diǎn)前的數(shù)字多于位。 showImg(https://segmentfault.com/img/bVbhNqT?w=1024&h=683); 因?yàn)榍蚴菆A的,所以不論發(fā)生什么都有可能,對(duì)這點(diǎn)我是深信不疑的,...

    fjcgreat 評(píng)論0 收藏0
  • JavaScript 性能優(yōu)化

    摘要:如果你忽略這兩個(gè)步驟,那么在第二步所產(chǎn)生的任何修改都會(huì)觸發(fā)一次重排。 更多文章 加載與執(zhí)行 將標(biāo)簽放在前面,不要放在中,防止造成堵塞 盡量減少請(qǐng)求,單個(gè)100KB的文件比4個(gè)25KB的文件更快,也就是說(shuō)減少頁(yè)面中外鏈的文件會(huì)改善性能 盡量使用壓縮過(guò)的JS文件,體積更小,加載更快 數(shù)據(jù)存取 使用局部變量和字面量比使用數(shù)組和對(duì)象有更少的讀寫(xiě)消耗 盡可能使用局部變量代替全局變量 如無(wú)必...

    ad6623 評(píng)論0 收藏0
  • 高程3總結(jié)#第24章最佳實(shí)踐

    摘要:也就是說(shuō)避免屬性查找或其他的操作。簡(jiǎn)化循環(huán)體循環(huán)體是執(zhí)行最多的,所以要確保其被最大限度地優(yōu)化。代碼組織組織代碼要考慮到可維護(hù)性并不一定是傳送給瀏覽器的最好方式。 最佳實(shí)踐 可維護(hù)性 什么是可維護(hù)性的代碼 如果說(shuō)代碼是可維護(hù)的,它需要遵循以下特點(diǎn) 可理解性——其他人可以接手代碼并理解它的意圖和一般途徑,而無(wú)需原開(kāi)發(fā)人員的完整解釋。 直觀性——代碼中的東西一看就能明白,不管其操作過(guò)程多...

    zhiwei 評(píng)論0 收藏0
  • JavaScript作符的特殊作用

    摘要:主要有以下幾種位操作符一般來(lái)說(shuō),我們?cè)谥泻苌倌苡玫竭@些位操作符,但在某些特殊情況下,這些簡(jiǎn)單的操作符卻能抵得上好幾行代碼如果不在乎可讀性的話(huà)。 Javascript主要有以下幾種位操作符: AND ( & ) OR ( | ) XOR ( ^ ) NOT ( ~ ) LEFT SHIFT ( ) ZERO-FILL RIGHT SHIFT ( >>> ) 一般來(lái)說(shuō),我們?cè)贘ava...

    NeverSayNever 評(píng)論0 收藏0
  • JavaScript是怎樣編碼數(shù)字的[How numbers are encoded in Java

    摘要:譯者注規(guī)范化就是把小數(shù)點(diǎn)放在第一個(gè)非零數(shù)字的后面總結(jié)當(dāng)指數(shù)的范圍是十進(jìn)制分?jǐn)?shù)不是所有的十進(jìn)制分?jǐn)?shù)都能夠非常精確的表示例如和都不能夠被精確的表示成二進(jìn)制浮點(diǎn)數(shù)。相同的,也不能被精確表示成一個(gè)十進(jìn)制分?jǐn)?shù),它大概能被表示成。 在JavaScript中所有的數(shù)字都是浮點(diǎn)數(shù),本篇文章將介紹這些浮點(diǎn)數(shù)在JavaScript內(nèi)部是怎樣被轉(zhuǎn)為64位二進(jìn)制的。我們會(huì)特別考慮整數(shù)的處理,所以讀完本篇之后,...

    oysun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<