-
當(dāng)前位置:首頁 > 創(chuàng)意學(xué)院 > 技術(shù) > 專題列表 > 正文
js底層原理(js底層原理常見問題)
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于js底層原理的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
ChatGPT國內(nèi)免費在線使用,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等
只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁版、PC客戶端
官網(wǎng):https://ai.de1919.com
本文目錄:
一、typeof & instanceof 原理
typeof 可判斷類型比較有限,它的輸出值只有八種,即用 typeof 判斷一個變量,得到的結(jié)果只會是以下八種類型中的一種
第一版 JS 的 typeof 實現(xiàn)如下,在 JS 誕生之初就只有六種類型判斷。
typeof 的輸出值中沒有 array 這一項,所以當(dāng)需要判斷數(shù)組類型時,可以使用 instanceof 。 instanceof 會判斷右側(cè)表達(dá)式是否在左側(cè)表達(dá)式的原型鏈上,所以下面的兩個 instanceof 都為 true 。
答案是 NO ,前面說了, typeof 只有八種類型,其中并沒有 null 這一類型,如果用 typeof 判斷,會得到 object 的結(jié)果。
因為在 Javascript 底層存儲變量的時候,會在變量的機器碼低位 1-3 位表示類型信息。而 null 的低位 1-3 解析到的為 000 ,而 000 表示的是 obecjt 類型。
答案依然是 NO ,因為 null 根本沒有 __proto__ 屬性,所以用 instanceof 去檢測永遠(yuǎn)都不會返回 true
拓展: Object.prototype.toString 可以判斷所有類型
下面的表達(dá)式分別輸出什么呢?如果全部回答正確,你對原型鏈和 instanceof 的理解應(yīng)該非常到位了。
二、JS位運算異常(位運算精度丟失)的原因探究
《【轉(zhuǎn)+補充】深入研究js中的位運算及用法》
《【JS時間戳】獲取時間戳的最快方式探究》
日常開發(fā)中一直沒遇到過位運算導(dǎo)致精度丟失的問題,直到這天,搞10位時間戳取整的時候,終于被我撞上了。具體是個什么場景呢,我們來還原下案發(fā)現(xiàn)場:
可以看到輸出的結(jié)果為:
得到的 t 是一個精確到微秒的時間戳。但是請求接口的時候需要的是一個10位(精確到秒)的時間戳,所以這里需要將它轉(zhuǎn)換為10位,自然就是 ➗1000 即可,然后通過位運算來實現(xiàn)類似 Math.trunc 的取證效果,得到了我們要的10位時間戳。至此完美解決!那問題又是如何發(fā)生的呢?
按照上面的運算規(guī)律,如果我們要獲取13位時間戳,是不是直接對 t>>0 就可以了呢?我們來看一下:
輸出結(jié)果如下:
WTF!!!看到了咩!?。【尤惠敵隽艘粋€負(fù)數(shù)?。?!我們想要的結(jié)果應(yīng)該是 1597113682985 才對?。槭裁磿霈F(xiàn)了負(fù)數(shù)呢?。?!
由此,怪物出現(xiàn)啦!我們今天就來解讀(xiang fu)一下它!
想到這里,我們一定就會怪是位運算的鍋!那這個鍋該怎么讓位運算背起來呢!我們來研究一下!
首先我們知道,JS中沒有真正的整型,數(shù)據(jù)都是以double(64bit)的標(biāo)準(zhǔn)格式存儲的,這里就不再贅述了,要想搞透其中的原理,請打開 【傳送門】
位運算是在數(shù)字底層(即表示數(shù)字的 32 個數(shù)位)進(jìn)行運算的。由于位運算是低級的運算操作,所以速度往往也是最快的(相對其它運算如加減乘除來說),并且借助位運算有時我們還能實現(xiàn)更簡單的程序邏輯,缺點是很不直觀,許多場合不能夠使用。
以下來源于w3shool:
ECMAScript 整數(shù)有兩種類型,即有符號整數(shù)(允許用正數(shù)和負(fù)數(shù))和無符號整數(shù)(只允許用正數(shù))。 在 ECMAScript 中,所有整數(shù)字面量默認(rèn)都是有符號整數(shù) ,這意味著什么呢?
有符號整數(shù)使用 31 位表示整數(shù)的數(shù)值,用第 32 位表示整數(shù)的符號,0 表示正數(shù),1 表示負(fù)數(shù)。數(shù)值范圍從 -2147483648 到 2147483647 。
可以以兩種不同的方式存儲二進(jìn)制形式的有符號整數(shù),一種用于存儲正數(shù),一種用于存儲負(fù)數(shù)。 正數(shù)是以真二進(jìn)制形式存儲的 ,前 31 位中的每一位都表示 2 的冪,從第 1 位(位 0)開始,表示 20,第 2 位(位 1)表示 21。沒用到的位用 0 填充,即忽略不計。例如,下圖展示的是數(shù) 18 的表示法。
那在js中二進(jìn)制和十進(jìn)制如何轉(zhuǎn)換呢?如下
負(fù)數(shù)同樣以二進(jìn)制存儲,但使用的格式是二進(jìn)制補碼。計算一個數(shù)值的二進(jìn)制補碼,需要經(jīng)過下列3個步驟:
例如,要確定-18的二進(jìn)制表示,首先必須得到18的二進(jìn)制表示,如下所示:
0000 0000 0000 0000 0000 0000 0001 0010
接下來,計算二進(jìn)制反碼,如下所示:
1111 1111 1111 1111 1111 1111 1110 1101
最后,在二進(jìn)制反碼上加 1,如下所示:
1111 1111 1111 1111 1111 1111 1110 1101 +
0000000000000000000000000000 0001 =
1111 1111 1111 1111 1111 1111 1110 1110
因此,-18 的二進(jìn)制就是 1111 1111 1111 1111 1111 1111 1110 1110
而其相反數(shù)18的二進(jìn)制為 0000 0000 0000 0000 0000 0000 0001 0010
ECMAScript會盡力向我們隱藏所有這些信息,在以二進(jìn)制字符串形式輸出一個負(fù)數(shù)時,我們看到的只是這個負(fù)數(shù)絕對值的二進(jìn)制碼前面加上了一個負(fù)號
JavaScript 只有一種數(shù)字類型 ( Number )
我們將 1596596596.3742654.toString(2) 轉(zhuǎn)為二進(jìn)制字符串表示如下:
1011111001010100010000101110100.0101111111001111110111
但實際在內(nèi)存中的存儲如下:
說到這里就不得不簡單提一下數(shù)字精度丟失的問題。上面也知道,JS中所有的數(shù)字都是用double方式進(jìn)行存儲的,所以必然會存在精度丟失問題。
以下轉(zhuǎn)自文章: JavaScript數(shù)字精度丟失問題總結(jié)
此時只能模仿十進(jìn)制進(jìn)行四舍五入了,但是二進(jìn)制只有 0 和 1 兩個,于是變?yōu)?0 舍 1 入。這即是計算機中部分浮點數(shù)運算時出現(xiàn)誤差,丟失精度的根本原因。
大整數(shù)的精度丟失和浮點數(shù)本質(zhì)上是一樣的,尾數(shù)位最大是 52 位,因此 JS 中能精準(zhǔn)表示的最大整數(shù)是 Math.pow(2, 53) ,十進(jìn)制即 9007199254740992
大于 9007199254740992 的可能會丟失精度:
9007199254740992 >> 10000000000000...000 ``// 共計 53 個 0
9007199254740992 + 1 >> 10000000000000...001 ``// 中間 52 個 0
9007199254740992 + 2 >> 10000000000000...010 ``// 中間 51 個 0
實際上
9007199254740992 + 1 ``// 丟失
9007199254740992 + 2 ``// 未丟失
9007199254740992 + 3 ``// 丟失
9007199254740992 + 4 ``// 未丟失
以上,可以知道看似有窮的數(shù)字, 在計算機的二進(jìn)制表示里卻是無窮的,由于存儲位數(shù)限制因此存在“舍去”,精度丟失就發(fā)生了。
想了解更深入的分析可以看這篇論文(你品!你細(xì)品?。?What Every Computer Scientist Should Know About Floating-Point Arithmetic
關(guān)于精度和范圍的內(nèi)容可查看 【JS的數(shù)值精度和數(shù)值范圍】
通過前面的知識補充,我們已經(jīng)知道:
這也就是為什么對于整數(shù)部位為10位的時間戳,通過位運算可以進(jìn)行取整(因為目前時間戳159xxxxxxx<2147483647),不存在時間戳超過范圍的問題。但是對于13位時間戳,如 1596615447123>2147483647 ,此時再通過位運算操作的時候就會導(dǎo)致異常,如:
這主要是因為在進(jìn)行位運算之前,JS會先將64bit的浮點數(shù) 1596615447015.01 轉(zhuǎn)為32bit的有符號整型后進(jìn)行運算的,這個轉(zhuǎn)換過程如下:
為了驗證上述過程,我們再舉一個例子: 1590015447015.123 >> 0 = 877547495
將將將將!沒錯的吧!所以JS的這個坑還真是。。。 讓人Orz
三、JS防水涂料怎么,優(yōu)缺點各是什么?
JS防水涂料實際上是一類復(fù)合型防水涂料,J就是指聚合物,S是指水泥,JS就是聚合物水泥防水涂料,它是一種以聚丙烯酸酯乳液、乙烯-醋酸乙烯酯共聚乳液等聚合物乳液與各種添加劑組成的有機液料,和水泥、石英砂、輕重質(zhì)碳酸鈣等無機填料及各種添加劑所組成的無機粉料通過合理配比、復(fù)合制成的一種雙組份、水性建筑防水涂料;相對于其他防水涂料而言,其突出的優(yōu)點比較多,主要有:1、無毒無害,屬環(huán)保型防水涂料,經(jīng)檢測符合國家生活飲用水標(biāo)準(zhǔn);2、可在潮濕基層施工,基層不受含水率限制,可縮短施工工期;3、具有較高的抗拉強度和延伸率,對基層有微小裂縫追隨性強,涂層堅韌,具有明顯的柔韌性;4、粘結(jié)力強,涂膜與基層、飾石層粘結(jié)牢固,不論涂刷在垂直面、斜面及各種基層上均有良好的粘結(jié)效果。
四、js中fib()函數(shù)是自定義的還是系統(tǒng)自帶的?
你自己都說fib()是自定函數(shù)那肯定就是自定義函數(shù)啊。
function fib(n){
return (n===1||n===2)?1:fib(n-1)+fib(n-2);
}
console.log(fib(8));
如果用ES6來寫可以這樣:
let fib=n=>(n===1||n===2)?1:fib(n-1)+fib(n-2);
console.log(fib(8));
以上就是關(guān)于js底層原理相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會為您講解更多精彩的知識和內(nèi)容。
推薦閱讀:
三只兔子可以合體變身的動漫(三只兔子可以合體變身的動漫有哪些)