9.正則表達(dá)式
首先,js定義了RegExp()構(gòu)造函數(shù)莱衩,用來創(chuàng)建表示文本匹配模式的對象爵嗅。這就是正則表達(dá)式。正則表達(dá)式并不是js的基本類型笨蚁,它和Date(日期)一樣操骡,只是一種具有實用API(應(yīng)用程序接口)的特殊對象。它是一種強大的文本處理工具赚窃。有豐富的API册招。
js里的正則表達(dá)式具有直接量的寫法。例如
var pattem=/abc/
在兩條斜線之間的文本構(gòu)成一個正則表達(dá)式直接量勒极。第二條斜線之后可以帶有字母參數(shù)是掰,代表用來修飾模式的含義,正則表達(dá)式的語法是
/正則表達(dá)式主體/修飾符(可選)
例如
var pattem=/abc/i //i表示不區(qū)分大小寫 g表示執(zhí)行全局匹配 m執(zhí)行多行匹配
RegExp對象定義了很多有用的方法辱匿,字符串同樣具有接受RegExp參數(shù)的方法,這里我們先說一下,我們先知道js也有這個東西就可以了键痛,以后的時候會更加詳細(xì)的研究這個正則表達(dá)式,因為正則表達(dá)式是非常強大的。
10.布爾值
何為布爾值匾七,非常好理解絮短,布爾值只有兩個值,真(true)或者假(false)js程序中的比較語句通常都是布爾值昨忆,比如
a==1;
如果啊=1丁频,那么a==1就是true,否則就為false.布爾值通常用在循環(huán)控制結(jié)果中邑贴,例如if/els語句等
if(flag){
//dosomthing}
else{
//doanohting
}
如果flag轉(zhuǎn)換成布爾值為true,就執(zhí)行//dosomething代碼席里,否則就執(zhí)行//doanothing代碼。從上面可以知道拢驾,js還有個轉(zhuǎn)換功能奖磁,要知道,任意js的值都可以轉(zhuǎn)換成布爾值繁疤,如果轉(zhuǎn)換為true的話我們稱之為真值咖为,如果轉(zhuǎn)換為false的話秕狰,我們稱之為假值,例如下面這些只會被轉(zhuǎn)換成false
undefined
null
0
-0
NaN"" //空字符串
所有其他的值躁染,包括對象(數(shù)組)都會轉(zhuǎn)換成true
11.null和undefined
null是js的關(guān)鍵字封恰,表示一個特殊字,常用來描述“空值”褐啡,它也是一個對象诺舔,只是表示的是“非對象”,它是它自由類型的唯一一個成員,例如
console.log(typeof null) //object typeof是一個操作符,能夠判斷所操作值的類型
undefined是表示“未定義”咧欣,它是變量的一種取值牙躺,表明變量沒有初始化,多種情況下能返回undefined如果要查詢不存在的對象屬性或者不存在數(shù)組元素2.函數(shù)沒有返回值的時候,返回undefined3.引用沒有實參的函數(shù)形參的值(關(guān)于函數(shù)實參(實際參數(shù))和形參(形式參數(shù)),這里簡單說下 比如定義一個函數(shù) function fn(a){console.log(a);}a就是函數(shù)的形參,調(diào)用函數(shù)fn(2) 2就是函數(shù)的實參)
undefined是預(yù)定義的全局變量拌喉,它的值就是未定義,要記住undefined是只讀的俐银。
null和undefined的關(guān)系
null==undefined//true
null===undefined false
相當(dāng)運算符(==)認(rèn)為他們是相同的尿背,全等運算符(===)則任務(wù)他們是不相等的他們都不包含任何屬性和方法,捶惜,如果田藐,我們要預(yù)定義一個變量,并且不知道這個變量的類型的話吱七,選擇null是最佳的汽久。例如
var a=null; //表示值的空缺
12.全局對象
對象中還有一類很重要的對象,那就是全局對象踊餐,當(dāng)js解析器啟動的時候景醇,或者wen瀏覽器加載新頁面的時候,會創(chuàng)建一個新的對象吝岭,并給他一組定義的初始屬性全局屬性三痰,比如undefined、NaN等全局函數(shù) alert() isNaN()等構(gòu)造函數(shù) Date()苍碟、RegExp()酒觅、String()等
在代碼的最頂級,不在任何函數(shù)內(nèi)的js代碼微峰,可以用js關(guān)鍵字this來引用全局對象
var win=this;
而在瀏覽器中,Window對象充當(dāng)了全局對象抒钱。當(dāng)初次創(chuàng)建的時候蜓肆,全局對象定義了js中所有預(yù)定義全局的值颜凯。如果代碼聲明了一個全局變量,這個變量就是全局對象的一個屬性
var a=1;
console.log(window.a) //1
console是屬于全局對象的仗扬,只是瀏覽器中症概,我們可以忽略window,
window.alert(window.a) //1
window.console.log(a) //1
13.包裝對象
js的對象是屬性或者已命名值的集合早芭,通過“.”符號來引用屬性值彼城,當(dāng)屬性值是一個函數(shù)的時候,稱之為方法退个,通過o.m()來調(diào)用對象o中的方法募壕。但是,我們看到字符串也同樣具有屬性和方法语盈,例如
var str="abc123";
var str2=str.indexOf(' ');
str.length;str2.length;
為什么字符串既然不是對象舱馅,那它還會有屬性和方法了。原來是刀荒,只要引用了字符串str的屬性或者方法代嗤,那么js就會將字符串值通過條用new String(str)的方式轉(zhuǎn)成對象。而這個由str轉(zhuǎn)換而來的對象繼承了字符串的方法缠借,并被用來出來屬性的引用干毅,一旦屬性引用結(jié)束后,這個對象就會被銷毀泼返,這個對象溶锭,我們可以先暫時叫他臨時對象,是用來處理對其的屬性引用的符隙。
var a="123123";
a.len=6;
console.log(a.len); //undefined
當(dāng)運行結(jié)果后趴捅,a.len的值為undefined。這樣是不是會很疑惑霹疫,是這樣的拱绑,代碼在讀取字符串,數(shù)字和布爾值的屬性或者方法的時候丽蝎,其表現(xiàn)的形式就像對象一樣猎拨。
但是如果試圖給其屬性賦值的話,則會忽略這個作屠阻,要記得红省,修改只是發(fā)生在臨時對象上,而這個臨時對象并未繼續(xù)保留下來国觉,它只是在讀取的時候被創(chuàng)建后又被銷毀了吧恃。
同字符串一樣,數(shù)字和布爾值也具有各自的方法麻诀,通過Number()痕寓、Boolean()構(gòu)造函數(shù)創(chuàng)建一個臨時對象傲醉,這些方法的調(diào)用均來自這個臨時對象。 null和undefined沒有這個對象呻率,所以訪問它們的屬性和拋出類型錯誤硬毕。
在讀取字符串、數(shù)字或者布爾值的屬性時創(chuàng)建的臨時對象稱作包裝對象礼仗,只是用來區(qū)分字符串值和字符串對象吐咳、數(shù)字和數(shù)值對象、布爾值和布爾對象元践。一般來說韭脊,包裝對象只是被看作以一種實現(xiàn)的細(xì)節(jié),由于他們只是只讀的卢厂,并且不能給他們定義新屬性乾蓬,因此他們是有別于對象的。
js會在必要的時候?qū)b對象轉(zhuǎn)換成原始值慎恒,“==”運算符將原始值和其包裝對象視為相等任内,“===”則視為不相等。通過typeof運算符可以看到原始值和其包裝對象的不同
var a=new String('123');
var b="123";
console.log(a);
console.log(b);
不可變的原始值和可變的對象引用
js的原始值(undefined融柬、null死嗦、布爾值、數(shù)字和字符串)和對象(包含數(shù)組和函數(shù))的根本區(qū)別就是粒氧,原始值是不可更改的越除,但是對象的值是可更改的比如
4=5;
false=true;
改變數(shù)字本身就說不通了,對于字符串來說外盯,我們要知道摘盆,因為字符串看起來像有字符組成的數(shù)組,我們通過字符串方法修改字符串中的字符不就是改變了原始值了嗎饱苟?不就改變了原始值了嗎孩擂?實際上是這樣的,通過字符串方法修改的是返回一個新的字符串箱熬,而原先的字符串還是沒有修改的
var text="hello javascript";
var text2=text.replace(/l/g,'');
console.log(text);
console.log(text2);
我們用replace()將textd的“l(fā)”字符替換成空类垦,但是我們輸出text的話,發(fā)現(xiàn)text還是沒有改變的城须,只是操作text后返回了一個新的字符串蚤认。
js的原始值的比較是通過值的對比,只有它們的值相等時候它們才相等糕伐,當(dāng)然了砰琢,對于除了字符串外的原始值有點難懂了,因為沒有其他方法可以直接來比較他們。當(dāng)時對于字符串來說氯析,當(dāng)且僅當(dāng)兩個字符串的長度相等并且每個索引的字符都相等的時候亏较,js才認(rèn)為他們是相等的莺褒。
對象和原始值不一樣掩缓,它們的值是可以修改的
var obj={a:1} //定義一個對像obj,并且obj有個a屬性等于1
obj.a=2; //改變obj.a的值
obj.y=3; //為obj賦予新的屬性y,并且y=3
console.log(a);
console.log(obj);
var arr=[1,2,3,4];
a[0]=0; //更改數(shù)組元素a[4]=5; //給數(shù)組增加一個新元素
對象的比較遵岩,并非是比較值你辣,即使兩個對象包含同樣的屬性同樣的值,索引元素完全相等兩個對象也是不相等的尘执。因為對象是引用類型舍哄,何為引用呢?簡單的來說就是要給指針誊锭,指向內(nèi)存中的某一個對象表悬。而對象的比較實際上是引用的比較,當(dāng)它們引用同一個對象的時候丧靡,它們才相等蟆沫。
var obj={x:1};
var obj2=obj;
obj.x=2;
console.log(obj2.x);
上面代碼運行可知道,給對象或者數(shù)組賦值一個變量温治,僅僅只是復(fù)制了引用值饭庞,對象本身并沒有賦值了一份,它們還是共同引用同一個對象熬荆,當(dāng)用引用值取修改對象的時候舟山,對象就已經(jīng)發(fā)生修改了,所以所有引用了該對象的都會被修改了卤恳。
當(dāng)然了累盗,如果我們需要賦值對象的一個副本,而不是僅僅只是賦值引用突琳,我們可以遍歷對象的屬性和方法若债,將它們復(fù)制放到一個新的對象中。以后我們會更深入探究本今。例如拆座,數(shù)組復(fù)制
var arr=['1','2','3'];
var arr2=[];
var i;
for(i=0;i<arr.length;i++) { //遍歷數(shù)組arr中的每一個元素
arr2[i]=arr[i] //將元素值復(fù)制到arr2數(shù)組中
}
當(dāng)然我們也來看下比較兩個數(shù)組的函數(shù)
function equalArr(arr1,arr2){ //定義函數(shù) 用function 關(guān)鍵字 +函數(shù)名(參數(shù)){//具體實現(xiàn)}
if(arr1.lenght!=arr2.length) {
return false} //當(dāng)兩個數(shù)組的長度不一樣的話函數(shù)就返回false 關(guān)于函數(shù)返回值的知識,我們以后漸漸會將冠息,這個只要知道挪凑,一旦函數(shù)遇到return 的話就會結(jié)束執(zhí)行返回false就說明兩個數(shù)組不相等
for(var i=0;i<arr1.length;i++){ //當(dāng)arr1和arr2長度相等時,遍歷arr1和arr2的值進(jìn)行對比
if(a[i]!==b[i]){ //當(dāng)發(fā)生有一項不相等的就終止函數(shù)逛艰,并且返回false躏碳,說明不相等
return false;
}
return true; //如果都滿足上面條件的話,就證明這兩個函數(shù)相等 }}
}
14.類型轉(zhuǎn)換
js中的值的取值類型是非常靈活的散怖,因為js是弱類型語言(https://www.zhihu.com/question/19918532)菇绵,我們從之前的布爾值可以看到這一點肄渗,當(dāng)js需要一個布爾值的時候,你就可以提供任意類型值咬最,js將根據(jù)需要自行轉(zhuǎn)換數(shù)據(jù)類型翎嫡,真值轉(zhuǎn)換成true,假值轉(zhuǎn)換為false.這種轉(zhuǎn)換在其他類型中也同樣適用,如果js期望使用一個字符串永乌,那么它就會把特定的值轉(zhuǎn)換為字符串惑申,其他類型也是如此。例如
console.log(1+“2”);
console.log("7"*"4");
console.log(n-"x");
console.log(1+"object")
結(jié)果大家可以試一下翅雏,這里我們要注意的是圈驼,當(dāng)把特定的值轉(zhuǎn)換為數(shù)字的話,如果轉(zhuǎn)換結(jié)果沒有意義的話將會返回NaN,還有光宇+操作符望几,可以作為數(shù)字加號绩脆,也可以作為字符串連接符,當(dāng)操作數(shù)有一個是為字符串的話橄抹,那它就會當(dāng)作字符串連接符靴迫,而不是加號了
console.log("1" +2);
console.log("1"+"2");
從上面可以看出來,只要+號兩邊的操作符有一個是字符串的話害碾,那+就是字符串連接符了矢劲。
我們參考《javaScript權(quán)威指南》書上的類型轉(zhuǎn)換表可以來看一下哪些數(shù)據(jù)類型之間的轉(zhuǎn)換規(guī)則,其中空單元格表示不必要也沒有執(zhí)行轉(zhuǎn)換.
上表中的轉(zhuǎn)換規(guī)則慌随,我們可以知道芬沉,原始值到原始值的轉(zhuǎn)換相對簡單,轉(zhuǎn)為為布爾值的我們已經(jīng)在之前說過阁猜,真值轉(zhuǎn)換為true丸逸,假值轉(zhuǎn)換為false.轉(zhuǎn)換為字符串的也可以明確可見了。
轉(zhuǎn)為為數(shù)字的:以數(shù)字表示的字符串可以直接轉(zhuǎn)換為數(shù)字剃袍,也可以在開頭和結(jié)尾中帶有空格黄刚。但在開頭和結(jié)尾的任意非空字符都不會被當(dāng)作數(shù)字的一部分,進(jìn)而轉(zhuǎn)換為NaN.
原始值到對象的轉(zhuǎn)換是通過調(diào)用String()民效、Number憔维、Boolean()構(gòu)造函數(shù),轉(zhuǎn)換為它們各自的包裝對(關(guān)于包裝對象可參考上面的內(nèi)容)畏邢。
null和undefined屬于例外业扒,當(dāng)它們用在期望是一個對象的地方都會造成一個類型錯誤(TypeError)異常,而不會執(zhí)行正常轉(zhuǎn)換舒萎,這是因為上面我們說過的程储,null和undefined上是沒有定義任何方法和屬性的,根本就不存在轉(zhuǎn)換為對象的方法。
對象到原始值的轉(zhuǎn)換是有點復(fù)雜的章鲤,現(xiàn)在我們來弄懂對象轉(zhuǎn)換為原始值
對象轉(zhuǎn)換到布爾值是非常簡單的摊灭,只要記得,所有對象都轉(zhuǎn)換為true败徊,因為它們都是真值帚呼,對于new Boolean(false)是一個對象而不是原始值,所以他也轉(zhuǎn)換為true集嵌。
對象到字符串的轉(zhuǎn)換是通過條調(diào)用待轉(zhuǎn)換對象的一個方法來完成的萝挤。當(dāng)然了御毅,js對象有兩個不同的方法來執(zhí)行轉(zhuǎn)換的根欧,并且要注意的是這里提到的字符串和數(shù)字的轉(zhuǎn)換規(guī)則只適用于本地對象。
所有對象繼承了兩個轉(zhuǎn)換方法端蛆。第一個是toString()凤粗,它的作用是返回一個反映這個對象的字符串
var obj={x:1,y:2}
console.log(obj.toString());
var arr=[1,2,3];
console.log(arr.toString());
var fn=function(){alert(1);}
console.log(fn.toString());
var pat=/\d+/.toString();
console.log(pat.toString());
var date=new Date(2017,8,1);
console.log(date.toString());
從上面可以知道,對像返回[object object],數(shù)組是將每個數(shù)組元素轉(zhuǎn)換成一個字符串今豆,并在元素之前添加逗號合并成結(jié)果字符串嫌拣,而函數(shù)是返回這個函數(shù)的實現(xiàn)定義的表示方式(源碼字符串),正則表達(dá)式則將其轉(zhuǎn)換為表示正則表達(dá)式直接量的字符串呆躲,日期對象是返回了一個可讀的日期和時間字符串异逐。
另一個轉(zhuǎn)換對象的函數(shù)valueOf()。應(yīng)用《javaScript權(quán)威指南》中的話:這個方法的任務(wù)并未詳細(xì)定義:如果存在任意原始值插掂,它就默認(rèn)將對象轉(zhuǎn)換為表示它的原始值灰瞻,對象是復(fù)合值,而且大多數(shù)對象無法真正表示一個原始值辅甥,因此默認(rèn)的valueOf()方法簡單的返回對象本身酝润,而不是返回一個原始值。數(shù)組璃弄、函數(shù)和正則表達(dá)式簡單的繼承了這個默認(rèn)的方法要销,調(diào)用這些類型的實力valueOf()方法只是簡單返回對象本身。日期對象定義的valueOf()方法會返回它的一個內(nèi)部表示:1970年1月1日以來的毫秒數(shù)(也就是時間戳)夏块。
通過使用放過講解的toString()和valueOf()方法疏咐,就可以做到對象到字符串和對象到數(shù)字的轉(zhuǎn)換了。但是需要注意的是脐供,在某些特殊的場景中浑塞,js執(zhí)行了完全不同的對象到原始值的轉(zhuǎn)換。這些特殊場景會一一探討患民。
下面我們來總結(jié)下js種對象到字符串的轉(zhuǎn)換步驟
- 如果對象具有toString()方法缩举,則調(diào)用這個方法,如果它返回一個原始值,js將這個值轉(zhuǎn)換為字符串(如果本身不是字符串的話)仅孩,并返回了這個字符串結(jié)果
- 如果對象沒有toString()這個方法托猩,或者這個方法并不返回一個原始值,那么js會調(diào)用valueOf()方法辽慕。如果存在這個方法京腥,則js就調(diào)用它,如果返回的是原始值溅蛉,js會將這個原始值轉(zhuǎn)換為字符串(如果本身不是字符串的話)公浪,并返回這個字符串結(jié)果。
- 否則船侧,js無法從toString()何valueOf()獲得一個原始值欠气,因此這是他會拋出一個類型錯誤異常。對象到數(shù)字的轉(zhuǎn)換過程中镜撩,js同樣做了上面的事情预柒,只是它會首先嘗試使用valueOf()方法。
- 如果對象具有valueOf()方法袁梗,后者返回一個原始值宜鸯,則js將這個原始值轉(zhuǎn)換成數(shù)字(如果需要的話)并返回這個數(shù)字。
- 否則遮怜,如果對象具有toString()方法淋袖,后者會返回一個原始值,則就是會將其轉(zhuǎn)換并返回
- 否則js拋出一個類型錯誤異常锯梁。
現(xiàn)在我們知道了為什么空數(shù)組會被轉(zhuǎn)換成數(shù)字0以及為什么具有單個元素的數(shù)組同樣會轉(zhuǎn)換成一個數(shù)字即碗。數(shù)組繼承了默認(rèn)的valueOf()方法,這個方法返回一個對象而不是原始值涝桅,因此拜姿,數(shù)組到數(shù)字的轉(zhuǎn)換規(guī)則調(diào)用toString()方法,空數(shù)組轉(zhuǎn)換成空字符串冯遂,空字符串轉(zhuǎn)換成數(shù)字0.如果數(shù)組只包含一個數(shù)字元素蕊肥,這個數(shù)字轉(zhuǎn)換成字符串,在轉(zhuǎn)換成數(shù)字蛤肌。
js中的+運算符壁却,如果它的操作書其中一個是對象,則js將使用特殊的方法將對象轉(zhuǎn)換成原始值裸准,而不是使用其他運算符的方法執(zhí)行對象到數(shù)字的轉(zhuǎn)換展东,==相等運算符于此類似,如果將對象與原始值進(jìn)行比較的話炒俱。則轉(zhuǎn)換將會按照兌現(xiàn)到原始值的轉(zhuǎn)換方式進(jìn)行盐肃。
當(dāng)然也有特殊的情況了爪膊,就是日期類對象,Date是js語言核心中唯一預(yù)先定義的類型砸王。它定義了有意義的向字符串和數(shù)字類型的轉(zhuǎn)換推盛。如果使用數(shù)字運算符,比如+進(jìn)行日期對象的轉(zhuǎn)換的話谦铃,日期對象則使用對象到字符串的轉(zhuǎn)換模式耘成,但是,這里的轉(zhuǎn)換和上文講述的并不完全一致:通過valueOf()或toString()返回原始值將被直接使用驹闰,而不會被強制轉(zhuǎn)換成數(shù)字或字符串瘪菌。
這里我們只要了解。除了日期對象的特殊情況嘹朗,進(jìn)行數(shù)字運算符的話师妙,任何對象首先會嘗試調(diào)用valueOf(),然后調(diào)用toString()骡显,不管得到的原始值是否使用疆栏,它都不會進(jìn)一步被轉(zhuǎn)換成數(shù)字或字符串。例如
var a=[1,2,3];
var b=1;
console.log(a+b);
var obj={x:1,y:2};
console.log(b+obj);
顯示類型轉(zhuǎn)換和隱式類型轉(zhuǎn)換
js有時候需要做顯示磚會員惫谤,為了讓代碼變得清晰并且容易閱讀。做顯示轉(zhuǎn)換最簡單的方法就是使用Boolean()珠洗、Number()溜歪、String()或Object()函數(shù),许蓖,它們會作為類型轉(zhuǎn)換函數(shù)并按照之前說的那些規(guī)則做轉(zhuǎn)換
Number('3');String(false);Boolean([]);Object(3);
注意null和undefined沒有toString()和valueOf()方法蝴猪,如果轉(zhuǎn)換成對象的話,會拋出類型錯誤膊爪,但是Object()函數(shù)在這種情況下不會拋出異常:它僅僅簡單的返回一個新創(chuàng)建的類型轉(zhuǎn)換自阱。
var a=Object(null);var b=Object(undefined);console.log(a+" "+b);
js有顯示類型轉(zhuǎn)換,也有隱式類型轉(zhuǎn)換米酬,上面提到過數(shù)字運算符沛豌,比如+、-赃额、*加派、/,還有跳芳!(取反操作符)等等
x+"" //等價與String(x);+x //等價于Number(x);!x //等價與Boolean(x);
Number類定義的toString()方法可以接受表示基(進(jìn)制基數(shù))的可選參數(shù)芍锦,如果不指定參數(shù),則默認(rèn)為十進(jìn)制飞盆。
var num=20;
var a=num.toString(2) //轉(zhuǎn)換為2進(jìn)制
var b=num.toString(8) //轉(zhuǎn)換為8進(jìn)制
var c=num.toString(16) //轉(zhuǎn)換為16進(jìn)制
轉(zhuǎn)換的就到這里了娄琉,下篇我們接著來學(xué)習(xí)js的變量延伸出來的知識了次乓,謝謝觀看,如果錯誤孽水,歡迎指正檬输!
如有錯誤,歡迎批評匈棘,對本文有什么不理解的地方話也可以留言評論交流Iゴ取!主卫!
原創(chuàng)文章by zhengyepan
歡迎訪問我的個人網(wǎng)站zhengyepan.com
歡迎討論交流~