淺析JS給原始數(shù)據(jù)類型加屬性和方法為什么不報(bào)錯(cuò)
前言
近日看到一道阿里前端面試題,由于不了解JS包裝類的特性,果然不出意外的做錯(cuò)了。題目如下:
var str = 'abc' str += 1 var test = typeof (str) if (test.length == 6) { test.sign = 'typeOf的返回結(jié)果可能為String' } console.log(test.sign)
上述代碼的輸出結(jié)果是什么?報(bào)錯(cuò)?還是typeOf的返回結(jié)果可能為String?最終結(jié)果都不是上面兩種,最后輸出結(jié)果為undefined,為什么會(huì)這樣呢?為什么徹底理解此類問(wèn)題,我們有必要深入了解一下包裝類。
我們都知道JavaScript中的數(shù)據(jù)類型分為兩種,第一種是原始數(shù)據(jù)類型,另一種是引用數(shù)據(jù)類型(也稱為復(fù)雜數(shù)據(jù)類型)。
原始數(shù)據(jù)類型
let a = 'hello' let b = 123 let c = true let u =undefined let n = null
原始數(shù)據(jù)類型主要分為六種,如上述代碼所示,字符串類型、Number類型、Boolean類型、undefined類型、null類型。還有一種是ES6新增的Symbol類型(表示獨(dú)一無(wú)二的值,Symbol最大的用途是用來(lái)定義對(duì)象的唯一屬性名)
特點(diǎn)
這些原始數(shù)據(jù)類型都是不可變的,這意味著它們的值一旦被創(chuàng)建,就不能被修改,也意味著不能給原始數(shù)據(jù)類型加屬性和方法,屬性和方法是對(duì)象獨(dú)有的。在JavaScript中,變量存儲(chǔ)原始數(shù)據(jù)類型的值,而不是直接存儲(chǔ)數(shù)據(jù)本身。原始數(shù)據(jù)類型的比較是基于它們的值,而不是引用,因此兩個(gè)具有相同值的原始數(shù)據(jù)類型變量將被認(rèn)為相等。
引用數(shù)據(jù)類型
在JavaScript中,除了原始數(shù)據(jù)類型(字符串、數(shù)字、布爾、未定義、空值和符號(hào))之外,還有一種復(fù)雜的數(shù)據(jù)類型,被稱為引用數(shù)據(jù)類型。引用數(shù)據(jù)類型是一種用于存儲(chǔ)和處理更復(fù)雜數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)類型。它們不直接包含實(shí)際數(shù)據(jù),而是存儲(chǔ)對(duì)數(shù)據(jù)的引用。JavaScript中的引用數(shù)據(jù)類型包括對(duì)象(Object)、數(shù)組(Array)、函數(shù)(Function)、正則表達(dá)式(RegExp)、日期(Date)等。下面簡(jiǎn)單介紹一下部分引用數(shù)據(jù)類型。
對(duì)象
對(duì)象是JavaScript中最常見(jiàn)的引用數(shù)據(jù)類型。它是一個(gè)無(wú)序的數(shù)據(jù)集合,包含鍵值對(duì)。每個(gè)鍵值對(duì)的鍵是字符串,值可以是任意數(shù)據(jù)類型,包括原始數(shù)據(jù)類型和其他引用數(shù)據(jù)類型。對(duì)象用花括號(hào) {}
定義。例如:
let person = { name : '小明', age: 18, hobby: basketball }
數(shù)組
數(shù)組是一種有序的集合,可以存儲(chǔ)多個(gè)值,每個(gè)值可以是任意數(shù)據(jù)類型,包括原始數(shù)據(jù)類型和其他引用數(shù)據(jù)類型。數(shù)組用方括號(hào) []
定義。例如:
let num =[1,2,3,4]
函數(shù)
函數(shù)是JavaScript中的一種對(duì)象,也是引用數(shù)據(jù)類型的一種。函數(shù)可以被定義、傳遞、賦值和作為參數(shù)傳遞給其他函數(shù)。函數(shù)用 function
關(guān)鍵字定義,如下:
function sayHello(){ console.log("Hello") }
正則表達(dá)式
正則表達(dá)式是一種用于匹配字符串模式的對(duì)象。它可以用于字符串的搜索、替換、分割等操作,提供了強(qiáng)大的文本處理功能。
let pattern = /[0-9]+/; // 匹配一個(gè)或多個(gè)數(shù)字
日期
日期對(duì)象用于處理日期和時(shí)間。它提供了各種方法來(lái)操作日期和時(shí)間,例如獲取年、月、日、時(shí)、分、秒等信息,以及執(zhí)行日期和時(shí)間的計(jì)算。
let nowDate = new Date();
引用數(shù)據(jù)類型在JavaScript中用于處理更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)和操作,它們提供了靈活性和功能性,使得JavaScript成為一種強(qiáng)大的編程語(yǔ)言。通過(guò)組合使用原始數(shù)據(jù)類型和引用數(shù)據(jù)類型,開(kāi)發(fā)者可以處理各種類型的數(shù)據(jù)和問(wèn)題。
介紹了一下JavaScript中的數(shù)據(jù)類型,接下來(lái)我們就可以講解一下什么是包裝類了。
在JavaScript中,包裝類(Wrapper Objects)是一種特殊的對(duì)象,它們用來(lái)包裝原始數(shù)據(jù)類型(如字符串、數(shù)字和布爾值),使其具備對(duì)象的方法和屬性。這些包裝類提供了對(duì)原始數(shù)據(jù)類型的操作,例如字符串的長(zhǎng)度、數(shù)字的精度等。
我們?cè)诮榻B原始數(shù)據(jù)類型的時(shí)候曾講到過(guò),原始數(shù)據(jù)類型都是不可變的,這意味著它們的值一旦被創(chuàng)建,就不能被修改,也意味著不能給原始數(shù)據(jù)類型加屬性和方法,屬性和方法是對(duì)象獨(dú)有的 上述加粗字體這些規(guī)則的存在顯然是必要的,正是有了這些規(guī)則,使得我們不能直接給原始數(shù)據(jù)隨便添加屬性和方法,這使得原始數(shù)據(jù)往往都是很簡(jiǎn)單的。而在我們的日常代碼練習(xí)中,你一定有用到過(guò)一些原始類型數(shù)據(jù)自帶的方法,比如字符串類型的數(shù)據(jù)往往都會(huì)自帶一個(gè)length方法,它能夠直接返回一個(gè)字符串的長(zhǎng)度,由于上述規(guī)則的限定,顯然我們不能直接修改字符串的長(zhǎng)度。這確保的數(shù)據(jù)的完整性,使原始數(shù)據(jù)在創(chuàng)建后不會(huì)被無(wú)意或者惡意更改,尤其是在多線程或者并發(fā)編程環(huán)境中尤為重要。等等!我們剛剛不是講到原始數(shù)據(jù)不能附加屬性和方法嗎?那字符串類型的length方法是哪來(lái)的呢?這就是我們要特別介紹的包裝類。
包裝類
包裝類的設(shè)計(jì)正是為了給原始數(shù)據(jù)類型增加方法和屬性。
在JavaScript引擎內(nèi)部,會(huì)對(duì)原始數(shù)據(jù)類型進(jìn)行了一些封裝和包裝,使其能夠調(diào)用一些內(nèi)置方法和屬性。當(dāng)你嘗試訪問(wèn)原始數(shù)據(jù)類型的方法或?qū)傩詴r(shí),JavaScript引擎會(huì)自動(dòng)將原始數(shù)據(jù)類型包裝成對(duì)應(yīng)的包裝對(duì)象,然后調(diào)用相應(yīng)的方法或?qū)傩?,然后再將包裝對(duì)象銷毀。這個(gè)過(guò)程被稱為"自動(dòng)包裝"。例如,當(dāng)你訪問(wèn)字符串的 length
屬性時(shí),JavaScript引擎會(huì)在內(nèi)部將字符串包裝成 String
對(duì)象,然后訪問(wèn)其 length
屬性。這一切都是自動(dòng)完成的,你無(wú)需手動(dòng)創(chuàng)建包裝對(duì)象。雖然原始數(shù)據(jù)類型不能附加自定義屬性和方法,但這種自動(dòng)包裝機(jī)制使得它們可以調(diào)用一些內(nèi)置的屬性和方法,使其更方便。不過(guò)需要注意,包裝對(duì)象在訪問(wèn)完成后會(huì)被銷毀,所以無(wú)法在原始數(shù)據(jù)類型上保留自定義屬性或方法。如果需要自定義屬性和方法,通常會(huì)使用對(duì)象類型來(lái)實(shí)現(xiàn)。
了解了這些,我們?cè)倩氐阶畛蹩吹侥堑烂嬖囶},嘗試著去分析它,相信問(wèn)題就迎刃而解了。
var str = 'abc' str += 1 var test = typeof (str) if (test.length == 6) { test.sign = 'typeOf的返回結(jié)果可能為String' } console.log(test.sign)
分析題目
- str是一個(gè)字符串類型,當(dāng)它和1相加時(shí)我們能夠知道,字符串和其他東西相加會(huì)將它‘同化’最終也變?yōu)樽址?,于是,我們得到得str變?yōu)?#39;abc1'。
- typeof會(huì)讀取到一個(gè)數(shù)據(jù)并返回它的類型,最終我們得到test被賦值為string.
- 由于string的長(zhǎng)度為6,進(jìn)入if判斷語(yǔ)句。
- 但是test為字符串類型,為原始數(shù)據(jù),它本身不能添加屬性和方法,但由于包裝類存在的緣故,test.sign = 'typeOf的返回結(jié)果可能為String' 會(huì)被執(zhí)行為:new String(test).sign = 'typeOf的返回結(jié)果可能為String' 然后delete被銷毀掉。
- 接著,我們退出if語(yǔ)句,控制臺(tái)輸出test.sign,由于我們之前創(chuàng)建的test.sign已經(jīng)被銷毀,但此時(shí)又讀到了test.sign,JavaScript引擎又會(huì)生成 *new String(test).sign *
- 但由于 new String(test).sign并未被賦值,所以最終我們得到結(jié)果:undefined。
以上就是淺析JS給原始數(shù)據(jù)類型加屬性和方法為什么不報(bào)錯(cuò)的詳細(xì)內(nèi)容,更多關(guān)于JS原始數(shù)據(jù)類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript學(xué)習(xí)小結(jié)(一)——JavaScript入門基礎(chǔ)
本教程比較適合javascript初學(xué)者,對(duì)javascript基本知識(shí)的小結(jié)包括變量,基本類型等知識(shí)點(diǎn),需要的朋友一起來(lái)學(xué)習(xí)吧2015-09-09javascript ajax 仿百度分頁(yè)函數(shù)
百度分頁(yè)想必大家都知道吧,瀏覽網(wǎng)頁(yè)的朋友都應(yīng)該知道,下面有個(gè)小例子使用到了js、ajax等來(lái)模仿百度的分頁(yè),感興趣的朋友可以參考下2013-10-10JS中的Replace方法使用經(jīng)驗(yàn)分享
本文給大家分享的是我們?cè)谑褂胘avascript中的replace方法的時(shí)候需要注意的一個(gè)事項(xiàng),我就是沒(méi)有注意到,才被這個(gè)bug煩了好久,這里記錄下來(lái),有需要的小伙伴可以參考下。2015-05-05JavaScript字符和ASCII實(shí)現(xiàn)互相轉(zhuǎn)換
這篇文章主要介紹了JavaScript字符和ASCII實(shí)現(xiàn)互相轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06javascript 判斷字符串是否包含某字符串及indexOf使用示例
js javascript 判斷字符串是否包含某字符串,String對(duì)象中查找子字符及indexOf具體使用,感興趣的朋友可以參考下2013-10-10IE6-IE9使用JSON、table.innerHTML所引發(fā)的問(wèn)題
這篇文章主要介紹了IE6-IE9使用JSON、table.innerHTML所引發(fā)的問(wèn)題 ,需要的朋友可以參考下2015-12-12不同js異步函數(shù)同步的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇不同js異步函數(shù)同步的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05