為了便於操作基本類型值,ECMAScript還提供了3個特殊的引用類型:Boolean,Number,String.
實際上,每當讀取一個基本類型值的時候,後台應付創建一個對應的基本包裝類型的對象,從而讓我們能夠調用一些方法來操作這些數據.
var s1="some text"; var s2=s1.substring(2); console.log(s2);//me text
這個例子中s1包含了一個字符串,字符串是基本類型值.第二行調用了s1的subsstring()方法,並將返回的結果保存在了s2中.
當第二行代碼訪問s1時,,訪問過程處於一種讀取模式,也就是要從內存中讀取這個字符串的值.而在讀取模式中訪問字符串時,後台會自動完成下列處理.
(1)創建String類型的一個實例;
(2)在實例上調用指定的方法;
(3)銷毀這個實例.
可以將以上三個步驟想象成是執行了下列代碼:
var s1=new String("some text"); var s2=s1.substring(2); s1=null; console.log(s2);//me text
經過此番處理,基本的字符串值就變得跟對象一樣了.而且上面三個步驟也分別適用於Boolean和Number類型對應的布爾值和數字值.
引用類型與基本包裝類型的主要區別就是對象的生存期.
使用new操作符創建的引用類型的實例,在執行流離開當前作用域之前都一起保存在內存中.而自動創建的基本包裝類型的對象,則只存在於一行代碼的執行瞬間,然後立即被銷毀.這意味著我們不能在運行時為基本類型添加屬性和方法.
var s1="some text"; s1.color="red"; console.log(s1.color);//undefined
問題的原因就是第二行創建的String對象在執行第三行代碼時已經被銷毀了.第三行代碼又創建自己的String對象,而該對象沒有color屬性.
對基本包裝類型的實例調用typeof會返回"object",而且所有基本包裝類型的對象都會被轉換為布爾值true.
Object構造函數也會像工廠方法一樣,根據傳入值的類型返回相應基本包裝類型的實例.
var obj=new Object("some text"); console.log(obj instanceof String);//true
把字符串傳給Object構造函數,就會創建String的實例,而傳入數值參數會得到Number的實例,傳入布爾值參數就會得到Boolean的實例.
要注意的是,使用new調用基本包裝類型的構造函數,與直接調用同名的轉型函數是不一樣的.
var value="25"; var number=Number(value);//轉型函數 console.log(typeof number);//number var obj=new Number(value);//構造函數 console.log(typeof obj);//object
在這個例子中,變量number中保存的是基本類型的值25,而變量obj中保存的是Number的實例.
5.6.1 Boolean類型
Boolean類型是與布爾值對應的引用類型.要創建Boolean對象,可以像下面這樣調用Boolean構造函數並傳入true或false值.
var booleanObject=new Boolean(true);
Boolean類型的實例重寫了valueOf()方法,返回基本類型值true或false;重寫了toString()方法,返回字符串"true”和"false".可是,Boolean對象在ECMAScript中的用處不大,因為它經常會造成人們的誤解.
其中最常見的問題是在布爾表達式中使用Boolean對象.
var falseObject=new Boolean(false); var result=falseObject&&true; console.log(result);//true var falseValue=false; result=falseValue&&true; console.log(result);//false
在這個例子中,使用false值創建了一個Boolean對象.然後將這個對象與基本類型值true構造了邏輯與表達式.示例中這行代碼是對falseObject而不是它的值(false)進行求值.布爾表達式中所有對象都會被轉換成true,因此falseObject對象在布爾表達式中代表的是true.
基本類型與引用類型的布爾值還有兩個區別:首先,typeof操作對基本類型返回”boolean”,而對引用類型返回”object”.其次,由於 Boolean對象是Boolean類型的實例,所以使用instanceof操作符測試Boolean對象會返回true,而測試基本類型的布爾值則返回false.
console.log(typeof falseObject);//object console.log(typeof falseValue);//boolean console.log(falseObject instanceof Boolean);//true console.log(falseValue instanceof Boolean);//false
5.6.2 Number類型
Number是與數字值對應的引用類型.要創建Number對象,可以在調用Number構造函數時向其中傳遞相應的數值.
var numberObject=new Number(10); console.log(typeof numberObject);//object
與Boolean類型一樣,Number類型也重寫了valueOf(),toLocaleString()和toString()方法.
重寫後的valueOf()方法返回對象表殼的基本類型的數值,另外兩個方法則返回字符串形式的數值.
可以為toString()方法傳遞一個表示基數的參數,告訴它返回幾進制數值的字符串形式.
var num=10; console.log(num.toString());//10 console.log(num.toString(2));//1010 console.log(num.toString(8));//12 console.log(num.toString(10));//10 console.log(num.toString(16));//a
除了繼承的方法之外,Number類型還提供了一些用於將數值格式化為字符串的方法.
其中,toFixed()方法會按照指定的小數位返回數值的字符串表示.
var num=10;
console.log(num.toFixed(2));//10.00
這裡給toFixed()方法傳入了數值2,意思是顯示幾位小數.以0填補了必要的小數位.
如果數值本身包含的小數位比指定的還多,那麼接近指定的最大小數位的值就會捨入.
var num=10.007; console.log(num.toFixed(2));//10.01
能夠自動捨入的特性,使得toFixed()方法很適合處理貨幣值.但需要注意的是,不同浏覽器給這個方法設定的捨入規則可能會有所不同.在給toFixed()傳入0的情況下,IE8及之前的版本不能正確捨入范圍在{(-0.94,-0.5],[0.5,0.94)}之間的值.對於這個范圍內的值,IE會返回0,而不是-1或1;其他浏覽器都能返回正確的值.IE9修復了這個問題.
另外可用於格式 化數值的方法是toExponential(),該方法返回以指數表示法(也稱e表示法)表示數值的字符串形式.與toFixed()方法一樣,toExponential()也接收一個參數,而且該參數同樣也是指定輸出結果中的小數位數.
var num=10; console.log(num.toExponential(1));//1.0e+1
對於一個數值來說,toPrecision()方法可能會返回固定大小(fixed)格式,也可能返回指定(exponential)格式;具體規則是看哪種格式最合適.這個方法接收一個參數,即表示數值的所有數字的位數(不包括指數部分).
var num=99; console.log(num.toPrecision(1));//1e+2 console.log(num.toPrecision(2));//99 console.log(num.toPrecision(3));//99.0
第二行是用一位數來表示99,第三行是用兩位數來表示,第四行是用三位數來表示.
實際上,toPrecision()會根據要處理的數值決定到底是調用toFixed()還是調用toExponential(),而這三個方法都可以通過向上或向下捨入,做到以最准確的形式來表示帶有正確小數位的值.
toPrecision()方法可以表現1到21位小數.
仍然不建議直接實例化Number類型.具體來講,就是在使用typeof和instanceof操作符測試基本類型數值與引用類型數值時,得到的結果完全不同.
var numberObject=new Number(10); var numberValue=10; console.log(typeof numberObject);//object console.log(typeof numberValue);//number console.log(numberObject instanceof Number);//true console.log(numberValue instanceof Number);//false
在使用typeof操作符測試基本類型數值時,始終會返回"number",而在測試Number對象時,則會返回"object”.類似地,Number對象是Number類型的實例,而基本類型的數值則不是.
5.6.3 String類型
String類型是字符串的對象包裝類型,可以像下面這樣使用String構造函數來創建.
var stringObject=new String("hello world");
String對象的方法也可以在所有基本的字符串值中訪問到.其中,繼承的valueOf(),toLoaleString()和toString()方法,都返回對象所表示的基本字符串值.
String類型的每個實例都有一個length屬性,表示字符串包含多個字符.
var stringValue="hello world"; console.log(stringValue.length);
應該注意的是,即使字符串中包含雙字節字符(不是占一個字節的ASCII字符),每個字符也仍然算一個字符.
1.字符方法
兩個用於訪問字符串中特定字符的方法是:charAt()和charCodeAt().這兩個方法都接收一個參數,即基於0的字符位置.
charAt()方法以單字符字符串的形式返回給定位置的那個字符.
如果想得到的不是字符而是字符編碼,就需要使用charCodeAt()了.
ECMAScript還定義了另一個訪問個別字符的方法.在支持此方法的浏覽器中,可以使用方括號加數字索引來訪問字符串中的特定字符.
var stringValue="hello world"; console.log(stringValue[1]);//e
使用方括號表示法訪問個別字符的語法得到了IE8及FF,Safari,Chrome和Opera所有版本的支持.如果在IE7及更早版本中使用這種語法,會返回undefined值.
2.字符串操作方法
concat(),用於將一或多個字符串拼接起來,返回拼接得到的新字符串.
var stringValue="hello"; var result=stringValue.concat("world"); console.log(result);//helloworld console.log(stringValue);//hello
concat()返回一個拼接的字符串,不改變原數組的值.它可以接受任意多個參數,也就是說可以通過它拼接任意多個字符串.
var stringValue="hello"; var result=stringValue.concat("world","!") console.log(result);//hellowworld! console.log(stringValue);//hello
雖然concat()是專門用來拼接字符串的方法,但實踐中使用更多的還是加號操作符(+).而且,使用加號操作符在大多數情況下都比使用concat()方法要簡便易行(特別是在拼接多個字符串的情況下).
ECMAScript還提供了三個基於子字符串創建新字符串的方法:slice(),substr()和substring().
這三個方法都會返回被操作字符串的一個子字符串,而且也都接受一或兩個參數.第一個參數指定子字符串的開始位置,第二個參數(在指定的情況下)表示子字符串到哪裡結束.slice()和substring()的第二個參數指定的是子字符串最後一個字符後面的位置.而substr()的第二個參數指定的則是返回的字符個數.如果沒有給這些方法傳遞第二個參數,則將字符串的長度作為結束位置.與concat()方法一樣,slice(),substr()和substring()也不會修改字符串本身的值--它們只是返回一個基本類型的字符串值,對原始字符串沒有任何影響.
var stringValue="hello world"; console.log(stringValue.slice(3));//lo world console.log(stringValue.substring(3));//lo world console.log(stringValue.substr(3));//lo world console.log(stringValue.slice(3,7));//lo w console.log(stringValue.substring(3,7));//lo w console.log(stringValue.substr(3,7));//lo worl
substr()返回"lo worl”,因為它的第二個參數指定的是要返回的字符個數.
在傳遞給這些方法的參數是負值的情況下,slice()方法會將傳入的負值與字符串的長度相加,substr()方法將負的第一個參數加上字符串的長度,而將負的第二個參數轉換為0.最後,substring()方法會把所有負值參數都轉換為0.
var stringValue="hello world"; console.log(stringValue.slice(-3));//rld console.log(stringValue.substring(-3));//hello world console.log(stringValue.substr(-3));//rld console.log(stringValue.slice(3,-4));//lo w console.log(stringValue.substring(3,-4));//hel console.log(stringValue.substr(3,-4));//(空字符串)
注意:IE的JavaScript實現在處理向substr()方法傳遞負值的情況時存在問題,它會返回原始的字符串.IE9修復了這個問題.
當第二個參數是負值時,三個方法的行為各不相同.slice()方法會把第二個參數轉換成7,substring()方法會把第二個參數轉換為0,而由於這個方法會將小的數作為開始位置,將較大的數作為結束位置.substr()也會將第二個參數轉換成0,也就意味著返回包含零個字符的字符串,也就是一個空字符串.
3.字符串位置方法
有兩個可以從字符串中查找子字符串的方法:indexOf()和lastIndexOf().這兩個方法都是從一個字符串中搜索給定的子字符串,然後返子字符串的位置(如果沒有找到該字符串,則返回-1).
indexOf()方法從字符串的開頭向後搜索子字符串,而lastIndexOf()方法是從字符串的末尾向前搜索子字符串.
var stringValue="hello world"; console.log(stringValue.indexOf("o"));//4 console.log(stringValue.lastIndexOf("o"));//7
如果"o”在這個字符串中僅出現一次,那麼indexOf()和lastIndexOf()會返回相同的位置值.
這兩個方法都可以接收可選的第二個參數,表示從字符串中的哪個位置開始搜索.換句話說,indexOf()會從該參數指定的位置向後搜索,忽略該位置之前的所有字符;而lastIndexOf()則會從指定的的位置向前搜索,忽略該位置之後的所有字符.
var stringValue="hello world"; console.log(stringValue.indexOf("o"),6);//4 6 console.log(stringValue.indexOf("o",6));//7 console.log(stringValue.lastIndexOf("o",6));//4 var stringValue="Lorem ipsum dolor sit amet, consectetur adipisicing elit"; var positions=new Array(); var pos=stringValue.indexOf("e"); while(pos>-1){ positions.push(pos); pos=stringValue.indexOf("e",pos+1); } console.log(positions);//[3,24,32,35,52]
這個例子通過不斷增加indexOf()方法開始查找的位置,遍歷了一個長字符串.在循環之外,首先找到了"e"在字符串中的初始位置,而進入循環後,則每次都給indexOf()傳遞上一次的位置加1.這樣,就確保了每次搜索都從上一次找到的子字符串的後面開始.每次搜索返回的位置依次被保存在數組positions中,以便將來使用.
4.trim()方法
ECMAScript 5為所有字符串定義了trim()方法.這個方法會創建一個字符串的副本,刪除前置及後綴的所有空格,然後返回結果.
var stringValue=" hello world "; var trimmedStringValue=stringValue.trim(); console.log(stringValue);// hello world console.log(trimmedStringValue);//hello world
由於trim()返回的是字符串的副本,所以原始字符串中的前置及後綴空格會保持不變.支持這個方法的浏覽器有IE9+,FF3.5+,Safari5+,Opera 10.5+和Chrome.此外,FF3.5+,Safari 5+和Chrome 8+還支持非標准的trimLeft()和trimRight()方法,分別用於刪除字符串開頭和末尾的空格.
5.字符串大小寫轉換方法
ECMAScript中涉及字符串大小寫轉換的方法有4個:toLowerCase(),toLocaleLowerCase(),toUpperCase()和toLocaleUpperCase().
var stringValue="hello world"; console.log(stringValue.toLocaleUpperCase());//HELLO WORLD console.log(stringValue.toUpperCase());//HELLO WORLD console.log(stringValue.toLocaleLowerCase());//hello world console.log(stringValue.toLowerCase());//hello world
一般來說,在不知道自己的代碼將在哪種語言環境中運行的情況下,還是使用針對地區的方法更穩妥一些.
6.字符串的模式匹配方法
String類型定義了幾個用於在字符串中匹配模式的方法.第一個方法就是match(),在字符串上調用這個方法,本質上與調用RegExp的exec()方法相同.match()方法只接受一個參數,要麼是一個正則表達式,要麼是一個RegExp對象.
var text="cat,bat,sat,fat"; var pattern=/.at/; //與pattern.exec(text)相同 var matches=text.match(pattern); console.log(matches.index);//0 console.log(matches[0]);//cat console.log(pattern.lastIndex);//0
本例中的match()方法返回了一個數組;如果是調用RegExp對象的exec()方法並傳遞本例中的字符串作為參數,那麼也會得到與此相同的數組:數組的第一項是與整個模式匹配的字符串,之後的每一項(如果有)保存著與正則表達式中的捕獲組匹配的字符串.
另一個用於查找模式的方法是search().這個方法的唯一參數與match()方法的參數相同:由字符串或RegExp對象指定的一個正則表達式.search()方法返回字符串中第一個匹配項的索引;如果沒有找到匹配項,則返回-1.而且,search()方法始終是從字符串開頭向後查找模式.
var text="cat,bat,sat,fat"; var pos=text.search(/at/); console.log(pos);//1
為了簡化替換子字符串的操作,ECMAScript提供了replace()方法.這個方法接受兩個參數:第一個參數可以是一個RegExp對象或者一個字符串(這個字符串不會被轉換成正則表達式),第二個參數可以是一個字符串或者一個函數.如果第一個參數是字符串,那麼只會替換第一個子字符串.要想替換所有子字符串,唯一的辦法就是提供一個正則表達式,而且要指定全局(g)標志.
var text="cat,bat,sat,fat"; var result=text.replace("at","ond"); console.log(result);//cond,bat,sat,fat result=text.replace(/at/g,"ond");//cond,bond,sond,fond
後面是通過將第一個參數修改為帶有全局標志的正則表達式,就將全部"at"都替換成了"ond".
如果第二個參數是字符串,那麼還可以使用一些特殊的字符序列,將正則表達式操作得到的值插入到結果字符串中.
下面列出了ECMAScript提供的這些特殊的字符序列.
字符序列 替換文本 $$ $ $& 匹配整個模式的子字符串.與RegExp.lastMatch的值相同 $' 匹配的子字符串之前的子字符串.與RegExp.leftContext的值相同 $` 匹配的子字符串之後的子字符串.與RegExp.rightContext的值相同 $n 匹配第n個捕獲組的子字符串,其中n等於0~9.例如,$1是匹配第一個捕獲組的子字符串,$2是匹配第二個捕獲組的子字符串.以此類推.如果正則表達式中沒有定義捕獲組,則使用空字符串 $nn 匹配第nn個捕獲組的子字符串,其中nn等於01~99.例如,$01是匹配第一個捕獲組的子字符串,$02是匹配第二個捕獲組的子字符串,以此類推.如果正則表達式中沒有定義捕獲組,則使用空字符串
通過這些特殊的字符序列,可以使用最近一次匹配結果中的內容.
var text="cat,bat,sat,fat"; result=text.replace(/(.at)/g,"word ($1)"); console.log(result);//word(cat),word(bat),word(sat),word(fat)
在此,每個以".at”結尾的單詞都被替換了,替換結果是"word"後跟一對圓括號,而圓括號中是被字符序列$1所替換的單詞.
replace()方法的第二個參數也可以是一個函數.在只有一個匹配項(即與模式匹配的字符串)的情況下,會向這個函數傳遞3個函數:模式的匹配項,模式匹配項在字符串的位置和原始字符串.在正則表達式中定義了多個捕獲組的情況下,傳遞給函數的參數 依次是模式的匹配項,第一個捕獲組的匹配項,第二個捕獲組的匹配項....,但最後兩個參數仍然分別是模式的匹配項在字符串中的位置和原始字符串.這個函數應該返回一個字符串,表示應該被替換的匹配項使用函數作為replace()方法的第二個參數可以實現更加精細的替換操作.
function htmlEscape(text){ return text.replace(/[<>"&]/g,function(match,pos,originalText){ switch(match){ case "<": return "<"; case ">": return ">"; case "&": return "&"; case "\"": return """; } }); } console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>*"));//<p class="greeting">Hello world!</p>*
這裡,我們為插入HTML代碼定義了函數htmlEscape(),這個函數能夠轉義4個字符:小於號,大於號,和號以及雙引號.實現這種轉義的最簡單方式,就是使用正則表達式查找這幾個字符,然後定義一個能夠針對每個匹配的字符返回特定HTML實例的函數.
最後一個與模式匹配有關的方法是split(),這個方法可以基於指定的分隔符將一個字符串分割成多個子字符串,並將結果放在一個數組中.分隔符可以是字符串,也可以是一個RegExp對象(這個方法不會將字符串看成正則表達式).split()方法可以接受可選的第二個參數,用於指定數組的大小,以便確保返回的數組不會超過既定大小.
var colorText="red,blue,green,yellow"; var color1=colorText.split(","); console.log(color1);//["red", "blue", "green", "yellow"] var color2=colorText.split(",",2); console.log(color2);//["red", "blue"] var color3=colorText.split(/[^\,]+/); console.log(color3);//["", ",", ",", ",", ""]
在最後一次調用split()返回的數組中,第一項和最後一項是兩個空字符串.之所以會這樣,是因為通過正則表達式指定的分隔符出現在了字符串的開頭(即子字符串"red")和末尾(即子字符串"yellow").
對split()中正則表達式的支持因浏覽器而異.盡管對於簡單的模式沒有什麼差別,但對於未發現匹配項以及帶有捕獲組的模式,匹配的行為就不大相同了.以下是幾種覺的差別.
IE8及之前的版本會忽略捕獲組.IE9能正確地在結果中包含捕獲組.
FF3.6及之前版本在捕獲組未找到匹配項時,會在結果數組中包含空字符串;ECMA-262規定沒有匹配項的捕獲組在結果數組中應該用undefined表示.
在正則表達式中使用捕獲組時還有其他微妙的差別.
7.localeCompare()方法
這個方法比較兩個字符串,並返回下列值中的一個:
如果字符串在字母表中應該排在字符串參數之前,則返回一個負數(大多數情況下是-1,具體的值要視實現而定)
如果字符串等於字符串參數,則返回0.
如果字符串在字母表中應該排在字符串參數之後,則返回一個正數(大多數情況下是1,具體的值同樣要視實現而定)
var stringValue="yellow"; console.log(stringValue.localeCompare("brick"));//1 console.log(stringValue.localeCompare("yellow"));//0 console.log(stringValue.localeCompare("zoo"));//-1
因為localeCompare()返回的數值取決於實現,所以最好是像下面例子所示的這樣使用這個方法.
function determineOrder(value){ var result=stringValue.localeCompare(value); if(result<0){ console.log("The string 'yellow' comes before the string '"+value+"'."); }else if(result>0){ console.log("The string 'yellow' comes after the string '"+value+ "'."); }else{ console.log("The string 'yellow' is equal to the string '"+value+"'."); } } determineOrder("brick"); determineOrder("yellow"); determineOrder("zoo");
8.fromCharCode()方法
另外,String構造函數還有一個靜態方法:fromCharCode().這個方法的任務是接收一或多個字符編碼,然後將它們轉換成一個字符串.從本質上來看,這個方法與實例方法charCodeAt()執行的是相反的操作.
以上內容是小編給大家介紹的關於JavaScript高級教程5.6之基本包裝類型(詳細),希望大家喜歡。