淺談JavaScript中的string擁有方法的原因
引子
我們都知道,JavaScript數(shù)據(jù)類型分兩大類,基本類型(或者稱原始類型)和引用類型。
基本類型的值是保存在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段,它們是按值訪問(wèn)的。JS中有五種基本類型:Undefined、Null、Boolean、Number和String。
引用類型的值是保存在堆內(nèi)存中的對(duì)象,它的值是按引用訪問(wèn)的。引用類型主要有Object、Array、Function、RegExp、Date。
對(duì)象是擁有屬性和方法的,所以我們看到下面這段代碼一點(diǎn)也不奇怪.
var favs=['雞蛋','蓮蓬']; favs.push('秋葵'); console.log(favs);//["雞蛋", "蓮蓬", "秋葵"] console.log(favs.length);//3
Array是引用類型,所以它自然可以擁有屬性(length)和方法(push),這天經(jīng)地義地就像夏天一定要吃冰淇淋一樣。但是,再看下面的代碼,仔細(xì)想想,這這這,合法嗎?
var realMessage="Said I love you but I lied"; var myMessage=realMessage.substring(5,15); console.log(myMessage); //"I love you"
有一個(gè)心碎的女紙任性地對(duì)一個(gè)用來(lái)分手的字符串任性地執(zhí)行了“substring”方法,然后開心地看著剪輯版睡過(guò)去了??墒强墒强墒牵皇钦f(shuō)string是基本類型嗎,為什么它可以擁有方法??還有沒(méi)有王法啊青天大老爺!
其實(shí),這一切,都是因?yàn)橛袀€(gè)叫“基本包裝類型”的東東。這個(gè)基本包裝類型特別耿直,是真正的“事了拂衣去,深藏功與名”!
基本包裝類型
除了一開始提到的Object、Array等引用類型,JavaScript還為我們提供了三種特殊的引用類型:String、Number和Boolean,方便我們操作對(duì)應(yīng)的基本類型。
繼續(xù)看上面的剪輯字符串的例子,有沒(méi)有注意到,盡管使用了substring方法,realMessage本身的值是不會(huì)變的,調(diào)用這個(gè)方法只是返回了一個(gè)新的字符串。
這就是基本包裝類型的作用了。本來(lái)你是沒(méi)有方法的,但是你想用方法的時(shí)候,你盡管調(diào),對(duì)應(yīng)的基本包裝類型有這個(gè)方法就行。例如上面的substring方法,string這個(gè)基本類型是不可能有這個(gè)方法的,但是String這個(gè)包裝類型有啊,它會(huì)吭吭哧哧地把這個(gè)方法執(zhí)行完把結(jié)果返回。在執(zhí)行到:
realMessage.substring(5,15)
這行代碼時(shí),發(fā)生了很多事。
首先,它會(huì)從內(nèi)存中讀取realMessage的值。當(dāng)處于這種讀取模式下的時(shí)候,后臺(tái)就開始干活了。JS高程是這樣描述后臺(tái)完成的這些動(dòng)作的:
1.創(chuàng)建String類型的一個(gè)實(shí)例;
2.在實(shí)例上調(diào)用指定的方法;
3.銷毀這個(gè)實(shí)例
上面的例子可以用這樣的代碼來(lái)說(shuō)明:
var _realMessage=new String("Said I love you but I lied"); var myMessage=_realMessage.substring(5,15); _realMessgae=null; //方法調(diào)用后即銷毀
所以,這樣我們就明白了,并不是基本類型string執(zhí)行了自身方法,而是后臺(tái)為它創(chuàng)建了一個(gè)對(duì)應(yīng)的基本包裝類型String,它根據(jù)基本類型的值實(shí)例化出了一個(gè)實(shí)例,讓這個(gè)實(shí)例去調(diào)用指定方法,最后銷毀自己,感天動(dòng)地有木有。
注意最后一步基本包裝類型“會(huì)銷毀”的特性,這決定了我們不能為基本類型值添加自定義屬性和方法。
var me="sunjing"; me.age=18; console.log(me.age);//undefined
我給“me“這個(gè)字符串添加了age屬性,值設(shè)為美好的18歲,然并卵,再次訪問(wèn)時(shí),這個(gè)屬性已經(jīng)渺無(wú)蹤跡了。這是因?yàn)?
執(zhí)行到第二行代碼屬性賦值時(shí),后臺(tái)創(chuàng)建了一個(gè)基本包裝類型的實(shí)例,這個(gè)age屬性確實(shí)掛到實(shí)例上去了,但是緊跟著,這個(gè)實(shí)例就被銷毀了。執(zhí)行到第三行時(shí),又重新創(chuàng)建了新的基本包裝類型的實(shí)例,自然是沒(méi)有age屬性的。
顯示使用基本包裝類型
除了在字符串處于讀取模式下,后臺(tái)會(huì)幫我們創(chuàng)建基本包裝類型實(shí)例時(shí),我們自己也可以顯示地創(chuàng)建。
var str=new String("hello"); var str2=str.toUpperCase(); console.log(str2);//"HELLO:
這樣與后臺(tái)幫我們創(chuàng)建時(shí)變量中保存的東西是不同的。
var str1=new String("hello"); var str2="hello"; typeof str1 //"object" typeof str2 //"string"
總結(jié)
多虧了有基本包裝類型,我們操作string、boolean、number這三種基本類型更方便了。每當(dāng)讀取這三種基本類型值時(shí),后臺(tái)會(huì)創(chuàng)建對(duì)應(yīng)的包裝類型實(shí)例,這個(gè)實(shí)例會(huì)調(diào)用指定方法,調(diào)用完會(huì)被銷毀。這種短暫的生命周期決定了我們不能為基本類型添加自定義的屬性和方法。
我們?cè)賮?lái)看下javascript中String類的subString()方法和slice()方法
最近在看《Javascript高級(jí)程序設(shè)計(jì)》一書,在書中發(fā)現(xiàn)一些以前沒(méi)有接觸過(guò)的且比較實(shí)用的技巧和知識(shí)點(diǎn),想通過(guò)博客記錄一下,以加深記憶。
在該書2.8.4節(jié)中講到String類中的subString()方法和slice()方法,其用法和返回結(jié)果都基本相同,如下示例:
var strObj = new String("hello world"); alert(strObj.slice(3)); // 輸出結(jié)果:"ol world" alert(strObj.subString(3)); // 輸出結(jié)果:"ol world" alert(strObj.slice(3, 7)); // 輸出結(jié)果:"lo w" alert(strObj.subString(3,7)); // 輸出結(jié)果:"lo w"
由以上代碼的輸出結(jié)果可已看出,slice()方法和subString()方調(diào)用方法法和輸出結(jié)果完全一樣,這兩種方法返回的都是要處理的字符串的子串,都接受一個(gè)或兩個(gè)參數(shù),第一個(gè)參數(shù)是要獲取的子串的起始位置,第二個(gè)參數(shù)是要獲取子串的終止位置,如果第二個(gè)參數(shù)省略終止位置就默認(rèn)為字符串的長(zhǎng)度,且兩個(gè)方法都不改變String對(duì)象自身的值。
為什么有兩個(gè)功能完全相同的方法呢?事實(shí)上,這兩個(gè)方法并不完全相同,不過(guò)只在參數(shù)為負(fù)值時(shí),他們處理參數(shù)的方式稍有不同。
對(duì)于負(fù)數(shù)參數(shù),slice()方法會(huì)用字符串的長(zhǎng)度加上參數(shù),subString()方法將其作為0處理,例如:
var strObj = new String("hello world"); alert(strObj.slice(-3)); // 輸出結(jié)果:"rld" alert(strObj.subString(-3)); // 輸出結(jié)果:"hello world" alert(strObj.slice(3,-4)); // 輸出結(jié)果:"lo w" alert(strObj.subString(3,-4)) // 輸出結(jié)果:"hel"
這樣既可看到slice()和subString()方法的主要不同。當(dāng)只有參數(shù)-3時(shí),slice()返回"rld",subString()則返回"hello world"。這是因?yàn)閷?duì)于字符串"hello world",slice(-3)將被轉(zhuǎn)換成slice(8),而subString(-3)則轉(zhuǎn)化成subString(0)。同樣,使用3和-4差別也是很明顯。slice()方法將被轉(zhuǎn)換成slice(3,7),與前面的例子相同,返回"lo w"。而subString()方法則將這個(gè)兩個(gè)參數(shù)解釋為subString(0,3),實(shí)際上是:subString(0,3),因?yàn)閟ubString()總是把較小的參數(shù)作為起始位,較大的數(shù)字最為終止位。
- javascript substr和substring用法比較
- Javascript將string類型轉(zhuǎn)換int類型
- JavaScript中valueOf函數(shù)與toString方法深入理解
- Javascript Boolean、Nnumber、String 強(qiáng)制類型轉(zhuǎn)換的區(qū)別詳細(xì)介紹
- JavaScript中json對(duì)象和string對(duì)象之間相互轉(zhuǎn)化
- JavaScript中使用Substring刪除字符串最后一個(gè)字符
- JavaScript截取字符串的Slice、Substring、Substr函數(shù)詳解和比較
- javascript從image轉(zhuǎn)換為base64位編碼的String
- JavaScript中number轉(zhuǎn)換成string介紹
相關(guān)文章
JavaScript實(shí)現(xiàn)點(diǎn)擊圖片換背景
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)點(diǎn)擊圖片換背景,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11JS中的THIS和WINDOW.EVENT.SRCELEMENT詳解
對(duì)于js初學(xué)著必須理解this和srcElement的應(yīng)用,這也是面試中經(jīng)??嫉降?。下面我們就通過(guò)幾個(gè)示例來(lái)詳細(xì)了解下2015-05-05使用TypeScript實(shí)現(xiàn)一個(gè)類型安全的EventBus示例詳解
EventBus是工作中常用的工具,本文用Typescript實(shí)現(xiàn)一個(gè)具備基礎(chǔ)功能且類型安全的EventBus,是我近期學(xué)習(xí)Typescript的知識(shí)總結(jié),對(duì)TypeScript實(shí)現(xiàn)EventBus相關(guān)知識(shí)感興趣的朋友一起看看吧2022-06-06javascript設(shè)計(jì)簡(jiǎn)單的秒表計(jì)時(shí)器
這篇文章主要介紹了javascript設(shè)計(jì)簡(jiǎn)單的秒表計(jì)時(shí)器,該秒表將包括兩個(gè)按鈕和一個(gè)用于顯示時(shí)間的文本框,當(dāng)單擊開始按鈕時(shí)開始計(jì)時(shí),最小單位為0.01秒,此時(shí)再次單擊按鈕則停止計(jì)時(shí),文本框顯示經(jīng)過(guò)的時(shí)間,需要的朋友可以參考下2015-11-11十個(gè)你必須要會(huì)的TypeScript技巧分享
學(xué)習(xí)Typescript通常是一個(gè)重新發(fā)現(xiàn)的過(guò)程。這篇文章為大家整理了十個(gè)你必須要會(huì)的TypeScript技巧,希望對(duì)大家學(xué)習(xí)TypeScript有所幫助2023-06-06JavaScript實(shí)現(xiàn)電燈開關(guān)小案例
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)電燈開關(guān)小案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03區(qū)別JavaScript函數(shù)聲明與變量聲明
這篇文章給大家分享了關(guān)于JavaScript中函數(shù)聲明與變量聲明之間的區(qū)別以及相關(guān)知識(shí)點(diǎn),有興趣的朋友參考下。2018-09-09詳解JavaScript中Arguments對(duì)象用途
本文主要介紹了詳解JavaScript中Arguments對(duì)象用途,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08