JavaScript數(shù)據(jù)類型及相互間的轉(zhuǎn)換規(guī)則
數(shù)據(jù)類型的分類
JS中的數(shù)據(jù)類型有七中原始數(shù)據(jù)類型:
- 原始數(shù)據(jù)類型[值類型/基本數(shù)據(jù)類型]:
- number 數(shù)字
- string 字符串
- boolean 布爾
- null 空對象指針
- undefined 未定義
- symbol 唯一值
- bigint 大數(shù)
- 對象類型[引用數(shù)據(jù)類型]
- object
- 標準普通對象 object
- 標準特殊對象 Array、RegExp、Date、Math、Error...
- 非標準特殊對象 Number、String、Boolean...
- 可調(diào)用/執(zhí)行對象 函數(shù)Function
- object
非標準特殊對象
除了null和undefined每個原始值類型都有一個自己對應的對象類型值
Symbol
Symbol是唯一值,他是不能通過New操作符進行創(chuàng)建的,每次執(zhí)行Symbol都是創(chuàng)建一個唯一值,下方代碼A和B雖然看起來是一樣的但卻不相等的兩個值。假如如果把C=A這樣把A的值賦給C,那么A和C肯定是相等的
let A = Symbol('i東東') let B = Symbol('i東東') let C = A console.log(A === B); // false console.log(A === C); // true
應用場景:
- 給對象設置唯一值的屬性名,在ES6之前對象的屬性名只能是字符串類型,但是新增了ES6之后對象的屬性名增加了可以用Symbol類型的屬性名。
- Map新的數(shù)據(jù)結(jié)構(gòu):可以允許屬性名是對象
- Symbol.asyncIterator/iterator/hasInstance/toStringTag...是某些JS知識底層實現(xiàn)機制
- 在派發(fā)行為標識進行統(tǒng)一管理的時候,可以基于Symbol類型的值,保證標識的唯一性
用字符串和數(shù)字類型的都可以取到值,name就可以認為他們的屬性名是字符串類型的
下方代碼console.log([Symbol('AA')])
是無法取到值的,因為這個相當于創(chuàng)建了一個新的唯一值,用新的唯一值去訪問是不對應的,正確的方法應該是創(chuàng)建一個唯一值,再把這個唯一值作為屬性去訪問。
let key = Symbol('88') let obj = { num: 100, 10:'數(shù)字', [Symbol('AA')]:'Symbol類型的屬性名', // 在大括號中加Symbol語法要求必須加大括號 [key]:400 } console.log(obj[Symbol('AA')]); // undefined console.log(obj[key]); // 400說
一個對象的屬性名是不能重復的,用唯一值做屬性的好處就是,他是不會重復的
let obj = { [Symbol('AA')]: 100, [Symbol('AA')]: 100, // 這兩個是不同的兩個值 }
BigInt 大數(shù)類型
JS中的最大安全數(shù) Number.MAX_SAFE_INTEGER = 9007199254740991
JS中的最小安全數(shù) Number.MIN_SAFE_INTEGER = -9007199254740991
超過安全數(shù)后,進行運算或者訪問,結(jié)果會不準確??! 數(shù)據(jù)庫當中存取數(shù)據(jù)會分成整型、長整型、短整型,長整型支持的數(shù)字長度是比JS的安全數(shù)大的,當服務器返回給客戶端一個長整型的數(shù)字,如果超出最大安全數(shù)值就會出現(xiàn)問題。
解決方案:
- 服務器端給客戶端返回大數(shù),按照字符串格式返回!
- 客戶端把其變換成 Bigint
- 最后把運算后的BigInt轉(zhuǎn)換為字符串,再傳遞給服務器
console.log(BigInt('9007199254740991') + BigInt(12345)); // 9007199254753336n console.log(9007199254753336n.toString()); // 9007199254753336 // 123n 在數(shù)字后面直接加`n`也表示大數(shù)BigInt
數(shù)據(jù)類型檢測
- typeof
- instanceof
- constryctor
- Object.prototype.toString.call
- Array.isArray
- isNaN
在日常開發(fā)中用到最多的就是typeof檢測數(shù)據(jù)類型,所有的數(shù)據(jù)類型值,在計算機底層都是按照'64位'的二進制進行存儲的!type是按照二進制值進行檢測類型的
例如:
- 二進制的前三位是0,認為是對象,然后再去看有沒有實現(xiàn)call方法,如果實現(xiàn)了返回'functhon',沒有時間,則返回'object'
- 第一位是1為整數(shù)
- 010浮點數(shù)
- 100字符串
- 110布爾
- 000000... null(null為64個0) ==> object [因為typeof的局限性]
- ......
檢測未被申明的變量,值為undefined
console.log(a); // ReferenceError: a is not defined console.log(typeof a); // undefined
場景1:檢測當前值是否是一個對象
const fn = options =>{ let type = typeof options if(options !== null && (type === 'object' || type === 'function')){ // 這樣進來的才能確保是一個對象 } } fn({ num:10 })
場景2:支持更多的模塊導入方案
(function(){ if(typeof window !== 'undefined') window.utils = utils if(typeof module === 'object' && typeof module.exports == 'object') module.exports = utils })()
數(shù)據(jù)類型間的相互轉(zhuǎn)換
數(shù)據(jù)類型間的相互轉(zhuǎn)換主要有隱式數(shù)據(jù)類型轉(zhuǎn)換和顯示數(shù)據(jù)類型轉(zhuǎn)換兩種。 一般用于瀏覽器中的隱式轉(zhuǎn)換:
- 數(shù)學運算
- isNaN檢測
- == 比較
比如說在數(shù)據(jù)運算時會進行隱式數(shù)據(jù)類型轉(zhuǎn)換,10-2的時候?qū)嶋H上默認就調(diào)用了Number('2')進行了類型轉(zhuǎn)換之后才進行的減法運算。
比如用isNaN來判斷時前值是不是一個有效數(shù)字,就相當于調(diào)用了下面的方法,先調(diào)用Number再執(zhí)行isNaN。
規(guī)則
Number([val])
- 字符串轉(zhuǎn)換為數(shù)字:空字符串變?yōu)?,如果出現(xiàn)任何非有效數(shù)字字符都是NaN
- 把布爾值轉(zhuǎn)換成數(shù)字:true=>1 false=>0
- null=>0 undefined=>NaN
- Symbol無法轉(zhuǎn)換為數(shù)字,會報錯:Cannot convert a Symbol value to a number
- BigInt去除'n'(超出安全數(shù)字的會按照科學計數(shù)法處理)
- 那對象轉(zhuǎn)換為數(shù)字:先調(diào)用對象的
Symbol.toPrimitive
方法,如果不存在這個方法,再調(diào)用valueOf
獲取原始值,如果獲取的值不是原始值,在調(diào)用toString
把其變?yōu)樽址?,最后自傲把字符串用過Number
方法進行轉(zhuǎn)換
let time = new Date() console.log(Number(time)); // 1662715039452 console.log(time[Symbol.toPrimitive]('number')); // 1662715039452 // 首先檢測 Symbol.toPrimitive有沒有, 結(jié)果:有 而且是一個函數(shù) time[Symbol.toPrimitive]('number')
let arr = [10] console.log(Number(arr)); /** * 首先arr[Symbol.toPrimitive] => undefined * 然后arr.valueOf() 數(shù)組是沒有原始值的 => [10] 任何一個對象都有valueOf * 再然后 arr.toString => '10' * 最后在把字符串'10'轉(zhuǎn)換為數(shù)字 => 10 */
let num = new Number(10) console.log(Number(num)); /** * 首先num[Symbol.toPrimitive] => undefined * 然后num.valueOf() 數(shù)組是沒有原始值的 => 10 */
parseInt([val],[radix]) parseFloat([val])
parseInt([val],[radix])是可以傳兩個值進去的:
- value必須是字符串,不是字符串會會先隱式轉(zhuǎn)換成字符串,通過String([val]),如果是對象會用上面的三步進行轉(zhuǎn)換
- radix進制,如果不寫或者寫0,則默認為10進制,如果字符串是以0x開始的,默認為16進制,有效進制范圍2~36之間(如果不在這個區(qū)間結(jié)果直接是NaN)。從[val]字符串左側(cè)開始第一個字符開始查找,查找出符合[radix]進制的值(遇到不符合的則結(jié)束查找,無論后面是否還有有符合的),把找到的內(nèi)容按照[radix]進制,轉(zhuǎn)化為10進制!!
console.log(parseInt('10103px13',2)); // 10 /** * 首先找到符合二進制的數(shù) '1010' * 把這個二進制值轉(zhuǎn)換為十進制 '按權(quán)展開求和' * 1*2^3+0*2^2+1*2^1+0*2^0 => 8+0+2+2 => 10 */
這里放一道字節(jié)面試題
arr會輸出什么,為什么? let arr = [27.2,0,'0013','14px',123] arr = arr.map(parseInt)
解題步驟:
- arr.map方法:迭代數(shù)組中的每一項,并且把每一項進行修改,原始數(shù)組不變,以新數(shù)組的形式返回。迭代數(shù)組中的每一項item為當前值,index為索引。
- map中應該接受一個函數(shù),現(xiàn)在我們是把
parseInt
作為這個函數(shù)傳遞進去了,所以每次迭代都會執(zhí)行parseInt
并且將item和index作為參數(shù)傳遞進去
/** * parseInt(27.2,0) => 找符合二進制的'27',當做十進制轉(zhuǎn)成十進制=> 27 * parseInt(0,1) => 超出有效進制范圍 => NaN * parseInt('0013',2) => 001 當做二進制轉(zhuǎn)化為十進制 => 0+0+1 => 1 * parseInt('14px',3) => 1 當做三進制轉(zhuǎn)成十進制 => 1 * parseInt(123,4) => parseInt('123',4) => 123當做四進制轉(zhuǎn)成十進制 1*4^2+2*4^1+3*4^0 => 16+8+4 => 27 */
所以最終得:arr = [27, NaN, 1, 1, 27]
注:
parseInt('0013',2) => 001 當做二進制轉(zhuǎn)化為十進制 => 0+0+1 => 1 parseInt(0013,2) => 0013 當js中遇到以0開頭的數(shù)字會默認當做8進制轉(zhuǎn)為10進制然后在進行其他運算 => 當做八進制轉(zhuǎn)為十進制 0*8^3+0*8^2+1*8^1+3*8^0 => 11 => 二進制轉(zhuǎn)十進制 11 2+1=3
把其他類型轉(zhuǎn)換為String
轉(zhuǎn)換規(guī)則:
- '+'出現(xiàn)左右兩邊,其中一邊是字符串,或者是某些對象,會以字符串拼接的規(guī)則處理
- '+'出現(xiàn)在一個值的左邊,轉(zhuǎn)換為數(shù)字
console.log(10 + '10'); // 1010 console.log(10 + new Number(10)); // new Number(10)[Symbol.toPrimitive] -> undefined // new Number(10).valueOf() => 10 // 10 + 10 = 20 console.log(10 + new Date()); // new Date()[Symbol.toPrimitive]('default') -> 不知道傳遞什么會傳defaulu => 'Tue Sep 13 2022 17:00:40 GMT+0800 (中國標準時間)' // 最終等于:10'Tue Sep 13 2022 17:00:40 GMT+0800 (中國標準時間)' console.log(10 + [10]); // [10][Symbol.toPrimitive] -> undefined // [10].valueOf => '[10]' // [10].toString() => '10' // 最終等于: '1010' let num = '10' console.log(+num) // 10 轉(zhuǎn)換為數(shù)字
把其他類型的值轉(zhuǎn)換成Boolean
Boolean(0) = false 除了0 NaN undefined 空字符串 null 以外都是true
==兩個等號比較規(guī)則
- ==相等,兩邊數(shù)據(jù)類型不同,首先要轉(zhuǎn)換為相同類型,然后在進行比較
- 對象==字符串 對象轉(zhuǎn)字符串[Symbol.toPrimitive]->valueOf()->toString()
- null == nudefined -> true null/undefined和其他任何值都不相等
- null === undefined -> false
- 對象==對象 比較的是堆內(nèi)存地址,地址相同則相等
- NaN !== NaN
- 除了以上情況,只要兩邊類型不一致,剩下的都是轉(zhuǎn)換為數(shù)字,然后在進行比較的,'==='絕對相等,如果兩邊類型不同則直接是false,不會轉(zhuǎn)換數(shù)據(jù)類型。
NaN == NaN // false NaN永遠不可能等于NaN console.log(Object.is(NaN,NaN)); // true
貼一道面試題 下面輸出為什么?
console.log([]==false); // 首先都會轉(zhuǎn)換為數(shù)字, 0 == 0 => true console.log(![]==false); // 先處理![]=>false == false =>true
Js中的裝箱和拆箱
裝箱和拆箱都是瀏覽器進行數(shù)據(jù)類型隱式轉(zhuǎn)換的過程
let num = 10 console.log(num.toFixed(2)); // 10.00 // num是原始值,不是對象,按常理來講是不能做'成員訪問'的 // 默認會做裝箱操作: new Number(num) 變?yōu)榉菢藴疏F樹對象,這樣就可以調(diào)用toFixed了 let num = new Number(10) console.log(num + 10); // 20 // 在操作的過程中瀏覽器會將num這個非標準特殊對象變?yōu)樵贾? [Symbol.toPrimitive] -> valueOf -> toString 這個操作叫做拆箱 // 裝箱和拆箱都是瀏覽器進行數(shù)據(jù)類型隱式轉(zhuǎn)換的過程
到此這篇關(guān)于JavaScript數(shù)據(jù)類型及相互間的轉(zhuǎn)換規(guī)則的文章就介紹到這了,更多相關(guān)JavaScript數(shù)據(jù)類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
微信小程序使用webview打開pdf文檔以及顯示網(wǎng)頁內(nèi)容的方法步驟
在線查看PDF文件,已經(jīng)是很常見的需求了,下面這篇文章主要給大家介紹了關(guān)于微信小程序使用webview打開pdf文檔以及顯示網(wǎng)頁內(nèi)容的方法步驟,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2022-07-07JS實現(xiàn)數(shù)組簡單去重及數(shù)組根據(jù)對象中的元素去重操作示例
這篇文章主要介紹了JS實現(xiàn)數(shù)組簡單去重及數(shù)組根據(jù)對象中的元素去重操作,涉及javascript數(shù)組元素的遍歷、判斷、追加等操作實現(xiàn)去重功能的相關(guān)技巧,需要的朋友可以參考下2018-01-01setTimeout與setInterval的區(qū)別淺析
這篇文章主要給大家介紹了關(guān)于setTimeout與setInterval區(qū)別的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用js具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧2019-03-03用javascript修復瀏覽器中頭痛問題的方法整理篇[譯]
我們提倡無論何時都盡可能地使用CSS,這樣我們更容易取得成功.現(xiàn)在瀏覽器對CSS的支持已經(jīng)非常好,肯定足以讓你用來控制你的網(wǎng)頁布局與排版.但,即使如此,還是有某些頁面元素會在不同的瀏覽器下表現(xiàn)也不一樣.2008-11-11Javascript頁面跳轉(zhuǎn)常見實現(xiàn)方式匯總
這篇文章主要介紹了Javascript頁面跳轉(zhuǎn)常見實現(xiàn)方式,結(jié)合實例匯總分析了JavaScript常用的七種頁面跳轉(zhuǎn)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11document.documentElement && document.documentElement
document.documentElement && document.documentElement.scrollTop...2007-12-12