javascript的數(shù)據(jù)分為兩類:原始類(primitive type)和對象類型(object type)
javascript中的原始類包括數(shù)字,字符串,布爾值,本章會有單獨(dú)的章節(jié)專門講述javascript的數(shù)字、字符串、布爾值。javascript還有兩個特殊的原始值,null(空)和Undefined(未定義),他們不是數(shù)字、字符串、布爾值。它們分別代表了各自特殊類型的唯一成員。
javascript除了數(shù)字、字符串、布爾值、null、undefined之外就是對象了。對象 (object)是屬性(property)的集合。每個屬性都由"名/值對"(值可以是原始值,比如數(shù)字,字符串,也可以是對象)構(gòu)成。其中一個比較特殊的對象(全局對象(global object)會在第五小姐介紹,第六小節(jié)將更詳細(xì)的描述)
普通的javascript對象是“命名值”的無需集合。javascript同樣定義了一種特殊對象--數(shù)組(array),表示帶編號的值的有序集合。javascript為數(shù)組定義了專用的語法。使數(shù)組擁有一些和普通對象不同的特有的行為屬性。
javascript還定義了一種特殊的對象--函數(shù)。函數(shù)是具有與它想關(guān)聯(lián)的可執(zhí)行代碼的對象,通過調(diào)用函數(shù)來運(yùn)行科執(zhí)行代碼,并返還運(yùn)算結(jié)果。和數(shù)組一樣,函數(shù)行為特征和其它對象都不一樣。javascript為使用函數(shù)定義了專用語法。對javascript函數(shù)來講。最重要的是,他們都是真值,并且javascript可以講他們當(dāng)做普通對象來對待。
如果函數(shù)初始化(使用new運(yùn)算符)一個新建對象,我們稱之為構(gòu)造函數(shù)(constructor)。每個構(gòu)造函數(shù)定義了一類(class)對象--構(gòu)造函數(shù)初始化對象組成的集合。類可以看做對象類型的子類型。除了數(shù)組(array)類和函數(shù)(function)類之外,javascript還定義了其它三種由用的類。日期(date)定義了代表日期的對象。正則(regExp)定義了正則表達(dá)式的對象。錯誤(error)類定義了那行表示javascript程序中運(yùn)行時錯誤和語法錯誤對象??梢酝ㄟ^定義自己的構(gòu)造函數(shù)來定義需要的類。
javascript解釋器有自己的內(nèi)存管理機(jī)制,可以自動對內(nèi)存進(jìn)行垃圾回收(garbagecollection)。這意味著程序程序可以按需創(chuàng)建對象,程序員則不必?fù)?dān)心這些對象的銷毀了內(nèi)存回收。當(dāng)不再有任何一個引用指向一個對象,解釋器就知道這個對象沒有用了,然后會自動回收它所占用的內(nèi)存資源。
javascript是一種面向?qū)ο蟮恼Z言。不嚴(yán)格的講,這意味著我們不用全局的定義函數(shù)去操作不同類型的值,數(shù)據(jù)類型本身可以定義方法(method)來使用值,例如要對數(shù)組a中的元素進(jìn)行排序,不必要將a傳入sort()函數(shù),而是調(diào)運(yùn)a的一個方法sort()
a.sort(); //sort(a)面向?qū)ο蟮陌姹?br /> 從技術(shù)上來將,只有javascript對象才能擁有方法。然而,數(shù)字,字符串,布爾值也擁有自己的方法。在javascript中,只有null和undefined是無法擁有方法的值。
javascript的類型可以分為原始類型和對象類型,可分為可以擁有方法的類型和不能擁有方法的類型。同樣可分為可變(mutable)和不可變(immutable)類型??勺冾愋偷闹凳强梢孕薷牡模瑢ο蠛蛿?shù)組屬于可變類型:javascript程序可以改變對象的屬性值和數(shù)組元素的值。
數(shù)字、布爾值、null和undefined屬于不可改變的類型。比如,修改一個數(shù)組的內(nèi)容本身就說不通。字符串可以看做是字符組成的數(shù)組,你可以認(rèn)為它是可以變的。然而在javascript中,字符串是不可變的??梢栽L問字符串任意位置的文本,但javascript并未提供修改一直字符串文本內(nèi)容的方法。
javascript可以自由地進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換。比如,如果在程序期望使用字符串的地方使用了數(shù)字,javascript會自動將數(shù)字轉(zhuǎn)換為字符串。如果期望在使用布爾值的地方使用了非布爾值,javascript也會相應(yīng)的轉(zhuǎn)換。javascript中對靈活的類型抓換規(guī)則對“判斷相等”(equality)
javascript的變量是無類型的(untyped),變量可以被賦予人和類型的值,使用var關(guān)鍵字來聲明(declare)變量。javascript采用語法作用域,不在任何函數(shù)內(nèi)聲明的變量稱為全局變量(global variable),它在javascript的程序 中任何地方都是可見的。
1.數(shù)字
和其它編程語言不同,javascript不區(qū)分整數(shù)數(shù)值和浮點(diǎn)數(shù)數(shù)值。javascript中的數(shù)值均用浮點(diǎn)數(shù)數(shù)值來表示。當(dāng)一個數(shù)字直接出現(xiàn)在javascript程序中,我們陳之為數(shù)字直接量(numeric literal),javascript支持多種格式的數(shù)字直接量。(注意:在任何數(shù)字前直接添加負(fù)號(-)可以得到它們的負(fù)值)但負(fù)號是一元求反運(yùn)算符。,并不是數(shù)字直接量語法的組成部分。)
i整數(shù)型直接量
javascript中用一個數(shù)組序列表示一個十進(jìn)制的整數(shù)
除了十進(jìn)制的整數(shù)直接量,javascript同樣識別十六機(jī)制(16)為基數(shù)的的值。所謂十六進(jìn)制是以“0X”或者"0x"為前綴,其后緊跟十六進(jìn)制數(shù)串的直接量。十六進(jìn)制數(shù)值是0-9的數(shù)字和a(A)-f(F)之間的字母構(gòu)成。a-f的字母對于的表述數(shù)字10-15下面是十六進(jìn)制整型直接量的例子
代碼如下:
0xff //15*16+15=255
0xCAFE911
盡管ECMAScript不支持八進(jìn)制直接量,但javascript的某些實(shí)現(xiàn)可以允許采用八進(jìn)制(基數(shù)為8)形式表示整數(shù)。八進(jìn)制直接量以數(shù)字0開始,其后跟隨著一個0-7之間數(shù)字組成的序列。
代碼如下:
0377 // 3*64 +7*8 +7 =255(十進(jìn)制)
由于某些javascript的實(shí)現(xiàn)支持八進(jìn)制的之間量,而有些不支持,因此最好不要使用以0為前綴的整數(shù)之間量,畢竟我們也無法得知當(dāng)前javascript的實(shí)現(xiàn)是否支持八進(jìn)制的解析。在ECMAScript6的嚴(yán)格模式下,八進(jìn)制的直接量是明令禁止的。
ii.浮點(diǎn)型直接量
浮點(diǎn)型直接量可以含有小數(shù)點(diǎn),它們采用的是傳統(tǒng)的實(shí)數(shù)寫法。一個實(shí)數(shù)由整數(shù)部分,小數(shù)點(diǎn)和小數(shù)部分組成。
此外,還可以使用指數(shù)計(jì)數(shù)法表示浮點(diǎn)型直接量。即在實(shí)數(shù)后跟字母E或e,后面再跟正負(fù)號,其后再加一個整型的指數(shù)。這種計(jì)數(shù)方法表示的數(shù)值,是有前面的實(shí)數(shù)乘以10的指數(shù)冪。
可以使用更簡潔的語法來表示
代碼如下:
[digits][.digits][(E|e)[(+|-)]digits]
3.14
2345.455
.33333333333333333
6.02e23 //6.02*10的23次方
1.255454E-23 //1.255454*10的負(fù)23次方
iii.javascript中的算術(shù)運(yùn)算
javascript程序是使用語言本省提供的算術(shù)運(yùn)算符來進(jìn)行數(shù)字運(yùn)算的的。這些運(yùn)算符包含+ - * /和求余(整除后的余數(shù))運(yùn)算符%
除了基本的運(yùn)算符之外,javascript還支持更加復(fù)雜的算術(shù)運(yùn)算,這個線復(fù)雜的運(yùn)算通過作為Math對象的屬性定義的函數(shù)和常量實(shí)現(xiàn)。
代碼如下:
Math.pow(2, 53) //=>9007199254740992 document.write(Math.pow(2,53) )
Math.round(.6) //=>1.0 四舍五入
Math.ceil(.6) //=>1.0向上求整
Math.floor(.6) //=>0.0向下求整
Math.abs(-5) //=>5 求絕對值
Math.max(x, y, z) //返回最大值
Math.min(x, y, z) //返回最小值
Math.random() //生成一個大于0小于1的偽隨機(jī)數(shù)
Math.PI //圓周率π
Math.E //e:自然對數(shù)的底數(shù)
Math.sqrt(3) //3的平方根
Math.pow(3, 1 / 3) //3的立方根
Math.sin(0) //三角函數(shù),還有Math.cos,Math.atan等
Math.log(10) //=>2.302585092994046 以10為底的自然對數(shù)
Math.log(512) / Math.LN2 //以2為底的512的對數(shù)
Math.log(100) / Math.LN10 //以10為底的100的對數(shù)
Math.exp(3) //e的三次冪
javascript中的算術(shù)運(yùn)算在溢出(overflow)、下溢(underflow)或被零整除時不會報錯。但數(shù)字運(yùn)算結(jié)果超過了javascript中所能表示的數(shù)字上線(溢出),結(jié)果為一個特殊的無窮大的值(infinty)值,在javascript中以infinty表示。同樣地,當(dāng)負(fù)數(shù)的值超過了javascript所能表達(dá)的負(fù)數(shù)范圍,結(jié)果為負(fù)無窮大,在javascript中以-Infinty表示。無窮大值的行為特性和我們所期望的是一致的:基于它們的加減乘除運(yùn)算結(jié)果是無窮大(保留正負(fù)號)
下溢(underflow)是當(dāng)運(yùn)算結(jié)果無線接近于零并比 javascript能表示的最小值還小的時候發(fā)生的一種情形。當(dāng)一個負(fù)數(shù)發(fā)生下溢時,javascript返回一個特殊的值,“負(fù)零”,這個(負(fù)零)幾乎和正常的零完全一樣。javascript程序員很少用到負(fù)零。
javascript預(yù)定義了全局變量Infinaty和NaN,用來表達(dá)正無窮大河非數(shù)字值,在ECMAScipt3中,這兩個值是可以讀寫的。ECMAScript5修正了這個問題,將他們定義為只讀的。ECMAScipt3中的Number對象定義的屬性值也是只讀的,這里有一些例子:
代碼如下:
Infinity //將一個可讀/寫的變量初始化為infinty
Number.POSITIVE_INFINITY //同樣的值,只讀
1 / 0 //這也是同樣的值
Number.MAX_VALUE + 1 //計(jì)算結(jié)果還是Infinity
Number.NEGATIVE_INFINITY //表示了負(fù)無窮大
-Infinity
-1/0
-Number.MAX_VALUE -1
NaN //將一個可讀/寫的變量初始化為NaN
Number.NaN //同樣的值,但是只讀
0/0 //計(jì)算結(jié)果還是NaN
Number.MIN_VALUE/2 //發(fā)生下溢。計(jì)算結(jié)果為0
-Number.MIN_VALUE/2 //負(fù)零
-1/Infinity //負(fù)零
-0 //負(fù)零
javascript中的非數(shù)字值有一點(diǎn)特殊,它和人和值都不相等,包括自身。也就是說沒法通過x==NaN來判斷x是否為NaN。相反,應(yīng)當(dāng)使用x!=x來判斷,當(dāng)且僅當(dāng)x為NaN的時候,表達(dá)式的結(jié)果為true.函數(shù)isNaN()作用與此相似,如果參數(shù)是NaN或者是一個非數(shù)字值(比如字符串和對象),則返回true。javascript中有一個類似的函數(shù)isFinite(),在參數(shù)不是NaN、Infinty或-Infinity的時候返回true.
負(fù)零值同樣有些特殊,它和正負(fù)零是相等的(甚至使用javascript的嚴(yán)格相等測試來判斷)、這意味這兩個值幾乎是一模一樣的,除了作為除數(shù)之外:
代碼如下:
var zero = 0;
var negz = -0;
zero === negz //=>true 正負(fù)零值相等
1/zero === 1/negz //false 正無窮大和負(fù)無窮大不等
iiii.二進(jìn)制浮點(diǎn)數(shù)和四舍五入錯誤
實(shí)數(shù)有無數(shù)個,但javascript通過浮點(diǎn)數(shù)的形式只能表示有限的個數(shù)(確切的說有18 437 736 874 454 810 627個),也就是說,當(dāng)javascript中使用實(shí)數(shù)的時候,常常只是真實(shí)值的一個近似的表示。
javascript采用了IEEE-754浮點(diǎn)數(shù)表示法(幾乎所有的現(xiàn)代編程語言采用)。這是一種二進(jìn)制表示法,可以精確的表示分?jǐn)?shù),比如1/2 1/8 和1/1024,遺憾的是,我們常采用的分?jǐn)?shù),特別是金融計(jì)算方面,都是以十進(jìn)制分?jǐn)?shù)1/10 ,1/100等。二進(jìn)制表示法并不能表示類似0.1這樣簡單的數(shù)字。
javascript中的數(shù)字具有足夠的精度。并可以接近0.1.但事實(shí)上,數(shù)字不能精確表述帶來了一些問題。
代碼如下:
var x = .3 - .2;
var y = .2 - .1;
alert(x == y) //=>false 兩值不相等
x == .1 //=>false .3-.2 不等于.1
y == .1 //=>true .2-.1等于1
由于舍入誤差,0.3和0.2之間的近似差值實(shí)際上并不等于0.2和0.1之間的近似差值(在真實(shí)模擬環(huán)境中,0.3-0.2=0.099 999 999 999 999 98).這個問題不只在javascript中存在,理解這一點(diǎn)十分重要:在任何使用二進(jìn)制浮點(diǎn)數(shù)的編程語言中都會有這個問題。同樣需要注意的是,上述代碼中x和y的值非常接近彼此和最終的正確值。這種計(jì)算結(jié)果可以勝任大多數(shù)的計(jì)算任務(wù)。這個問題也是只有比較兩個值是否相等的時候才才會出現(xiàn)。
javascript的未來版或許支持十進(jìn)制數(shù)字類型以避免這個問題,在這之前你可能更愿意使用大整數(shù)進(jìn)行重要的金融計(jì)算。例如,要使用整數(shù)“分”,而不要使用小數(shù)“元”進(jìn)行基于貨幣單位的運(yùn)算。
iiiii.日期和時間
javascript語言核心包含Date()構(gòu)造函數(shù),原來創(chuàng)建日期和時間的對象,這些日期對象的方法為日期計(jì)算提供了簡單的API,日期對象不能像數(shù)字那樣是基本數(shù)據(jù)類型。
代碼如下:
var zhen = new Date(2011, 0, 1); //2011年1月1日
var later = new Date(2011, 0, 1, 17, 10, 30); //同一天
var now = new Date(); //當(dāng)前的日期和時間
var elapsed = now - zhen; //日期減法。計(jì)算時間間隔的毫秒數(shù)
later.getFullYear(); //=>2011
later.getMonth(); //=>0 從0開始計(jì)數(shù)的月份
later.getDate(); //=>1 從1開始計(jì)數(shù)的天數(shù)
later.getDay(); //=>5 得到星期幾。 0代表星期日,5代表星期1
later.getHours() //=>當(dāng)?shù)貢r間
later.getUTCHours() //使用UTC表示小時的時間,基于時區(qū)。
2.文本
字符串(string)是一組16位值組成的不可變的有序序列,每個字符通常來自于Unicode字符集。javascript通過字符串類型來表示文本。字符串的長度(length)是其所含的16位值的個數(shù)。javascript字符串(和其數(shù)組)的索引從0開始。空字符串的(empty string)長度為0,javascript中并沒有表示單個字符的“字符型”。要表示一個16位值,只需要將其賦值給字符串變量即可。這個字符串的長度為1。
字符集,內(nèi)碼和javascript字符串
javascript采用UTF-16編碼的Unicode字符集,javascript字符串是由一組無序號的16位值組成的序列。最常用的Unicode字符都是通過16位的內(nèi)碼表示,并代表字符串中的單個字符,那行不能表示為16位的Unicode字符則遵循UTF-16編碼規(guī)則----用兩個16位值組成一個序列(亦稱為“代理項(xiàng)對”)表示。這意味著一個長度為2的javascript字符串(兩個16位值)可能表示一個Unicode字符。
代碼如下:
var p ="π" ; //π由16位內(nèi)碼表示0x03c0
var e = "e"; //e由17位內(nèi)碼表示0x1d452
p.length // =>1 p包含一個16位的值
e.length // =>2 e通過UTF-16編碼后包含兩個值:"\ud835\udc52"
javascript定義的各式字符串操作方法均作用于16位值,而非字符,且不會對代理項(xiàng)對做單獨(dú)處理。同樣javascript不會對字符串做標(biāo)準(zhǔn)化的加工。甚至不能保證字符串是合法的UTF-16格式
i字符串直接量
在javascript程序中的字符串直接量,是由單引號或雙引號括起來的字符序列,由單引號定界的字符串中可以包含雙引號,由雙引號定界的字符串中也可以包含單引號。這里有幾個字符串直接量的例子。
代碼如下:
"" //空字符串,0個字符
'testing'
"3.14"
'name="myform"'
"wouldn't you prefer O'Reily's book?"
ECMAScript3中,字符串直接量必須寫在一行中,而在ECMAScript5中,字符串的直接量可以拆分為數(shù)行,每行必須以反斜線(\)結(jié)束,反斜線和行結(jié)束符都不是字符串直接量的內(nèi)容。如果希望在一起,則可以使用 轉(zhuǎn)義字符。
需要注意的是,當(dāng)使用單引號定界字符串時,需要格外小心英文中的縮寫和所有格式寫法,英文撇號和單引號是同一個字符,所以必須使用反斜線(\)來轉(zhuǎn)義。
ii轉(zhuǎn)義字符
在javascript字符串中,反斜線()有著特殊的用途,反斜線后加一個字符,就不再表示他們的字面含義了,比如\n 就是一個轉(zhuǎn)義字符,它表示一個換行符。
代碼如下:
\o //NUL字符
\b //退格符
\t //水平制表符
\n //換行符
\v //垂直制表符
\f //換頁符
\r //回車符
\" //雙引號
\\ 反斜線
\xXX 由兩位十六進(jìn)制指定的Latin-1字符
\xXXXX 由四位十六進(jìn)制XXXX指定的Unicode字符
iii字符串的使用
javascript的內(nèi)置功能之一就是字符串連接。將運(yùn)算符+用于字符串,表示字符串連接。例如
代碼如下:
var msg = "hello" + "world"; //生成字符串hello world
要確定一個字符串的長度——其所包含的16位值的個數(shù),可以使用length屬性,比如字符串s的長度。
s.length
除了length屬性,字符串還提供很多可以調(diào)用的方法。
代碼如下:
var s = "hello,world";
s.charAt(0); //"h"第一個字符
s.charAt(s.length - 1) //"d"最后一個字符
s.substring(1, 4) //"ell" 2-4個字符
s.slice(1, 4) //ell 同上
s.slice(-3) // 最后出現(xiàn)的3個字符
s.indexOf(l ")//2字符l 第一次出現(xiàn)的位置
s.lastIndexOf("l") //10 字符l最后一次出現(xiàn)的位置
s.indexOf("l",3)//在位置3之后,l字符首次出現(xiàn)的位置
s.split(",") //=> ["hello","world"]分隔成子串
s.replace("h","H")// =>"Hllo,world"全文字符替換
s.toUpperCase() //=>"HELLO,WORLD"
在javascript中,字符串是固定不變的,類似replace()和toUpperCase()方法都返回了新的字符串,原來的字符本身沒有發(fā)生變化。
在ECMAScript中,字符可以當(dāng)做只讀數(shù)組,除了使用charAt()方法,也可以使用方括弧來訪問字符串中的單個字符。(16位值)
代碼如下:
s = "hello,world"
s[0] //=>"h"
s[s.length-1] //=>"d"
Foxfire很久之前就支持這樣方法的字符串索引,多數(shù)現(xiàn)代瀏覽器(IE除外)也緊跟Mozailla的腳步,在ECMAScript成型之前就完成了這一特性
iiii模式匹配
javascript定義了RegExp()構(gòu)造函數(shù),用來創(chuàng)建表示文本模式匹配的對象,這些模式被稱為“正則表達(dá)式”(regular expression),javascript彩陽Perl中的正則表達(dá)語法。String和RegExp對象均定義了利用正則表達(dá)式進(jìn)行模式匹配和查找與替換的函數(shù)。
RegExp對象并不是語言中的基本數(shù)據(jù)類型,和Date一樣,它只是一種具有實(shí)用API的特殊對象。正則表達(dá)式的語法很復(fù)雜,API也很豐富。在第10章節(jié)會詳細(xì)介紹。RegExp是一種強(qiáng)大和常用的文本處理工具,此處只是一個概述。
盡管RegExp并不是語言中的基本數(shù)據(jù)類型,但是他們依然具有直接量的寫法,可以直接在javascript中使用。在兩條斜線之間的文本構(gòu)成了一個正則表達(dá)式的直接量。第二條斜線之后也可以跟隨一個或多個字母。用來修飾匹配模式的含義。例如:
代碼如下:
/^HTML/ //匹配以HTML開始的字符串
/[1-9][0-9]*/ //匹配一個非零數(shù)字,后面是任意個數(shù)字
/\bjavascript\b/i/ //匹配單詞javascript,并忽略大小寫
RegExp對象定義了很多有用的方法,字符串同樣具有可以接受RegExp參數(shù)的方法。例如:
代碼如下:
var text = "testing:1,2,3"; //文本示例
var pattern = /\d+/g / //匹配所有包含一個或多個數(shù)字的實(shí)例
pattern.test(text) // =>true:匹配成功
text.search(pattern) //=>9 :首次匹配成功的位置
text.match(pattern) //=> ["1","2","3"]所有匹配組成數(shù)組
text.repeat(pattern,"#"); //=>"testing:#,#,#"
text.split(/\D+/); //=>["","1","2","3"]:用非數(shù)字字符截取字符串
3.布爾值
布爾值指代真或假,開或關(guān),這個類型只有兩個值,保留字true或false
javascript中的比較語句的結(jié)果通常都是布爾值。例如
a==4
這段代碼用來檢測變量的a的值是否等于4.如果等于,則值為true,如果不等值為false
布爾值通常用于javascript的控制語句中,例如javascript中的if/else語句,如果布爾值為true執(zhí)行第一段邏輯,如果為false執(zhí)行另一段代碼,例如
代碼如下:
if (a == 4)
b = b + 1;
else
a = a + 1;
任意javascript的值都可以轉(zhuǎn)化為布爾值,下面這些值都被轉(zhuǎn)化為false
代碼如下:
undefined
null
0
-0
NaN
""http://空字符串
所有其它值,包括所有對象(數(shù)組)都會被轉(zhuǎn)換為true,false和上面6個可以轉(zhuǎn)化為false的值有時候稱為“假值”,javascript期望使用一個布爾值時,假值會被當(dāng)做false,真值會被當(dāng)做true
來看一個例子,加上變量o是一個對象或是null,可以通過一條if語句來檢測o是否是非null值。
if(o!==null)...
不等操作符“!==”將o和null比較,并得出結(jié)果為 true或false??梢韵群雎赃@里的比較語句,null是一個假值,對象是一個真值。
if(o)...
對于第一種情況,只要當(dāng)o不是null時才會執(zhí)行if后的代碼,第二種情況的限制沒有那么嚴(yán)格。只有o不是false或任何假值(比如null或unfined)時才執(zhí)行這個if。
布爾值包含toString()方法,因此可以使用這個方法將字符串轉(zhuǎn)換為 “true”或"false",但它不包含其他有用的方法,除了這個不重要的API,還有三個重要的布爾值運(yùn)算符。
&&運(yùn)算符,||運(yùn)算符和一元操作符“!”執(zhí)行了布爾非(NOT)操作,如果真值返回false,假值返回true,比如
代碼如下:
if ((x == 0 && y == 0) || !(z == 0)) {
//x和y都是零或z是非零
}
4.null和undefined
null是javascript語言的關(guān)鍵字,它表示一個特殊值“空值”,對于null執(zhí)行typeof()運(yùn)算,返回object.也就是說,可以將null認(rèn)為是一個特殊的對象值,含義是"非對象"。但實(shí)際上,通常認(rèn)為null是它自由類型的唯一一個成員。它可以表示數(shù)字,字符串,和對象是“無值”的。大多數(shù)編程語言和javascript一樣含有null,你可以對null或者nil很熟。
javascript還有第二個值表示值的空缺。用來表示更深層次的“空值”。它是一種變量的一種取值。表示變量的沒有初始化。如果要查詢對象屬性或數(shù)組元素的值是返回undefined則表明這個屬性或者元素不存在。undefined是預(yù)定義的全局變量(它和null不一樣,它不是關(guān)鍵字),它的值就是未定義。如果使用typeof來測試undefined類型,則返回“undefined”,表明這個值是這個類型的唯一成員。
盡管null和undefined是不同的,但它們都表示“值的空缺”,兩者往往可以互換。判斷相等的運(yùn)算符“==”認(rèn)為兩者是相等的(要使用嚴(yán)格相等運(yùn)算符"==="來區(qū)分它們)。在希望值是布爾類型的地方它們的值都是假值。和false類似。null和undefined都是不包含任何屬性和方法。實(shí)際上,使用"."和"[]"來存取這兩個值的成員或方法,都會產(chǎn)生一個類型錯誤。
你或許認(rèn)為undefined是表示系統(tǒng)級的,出乎意料的活類似錯誤的值的空缺,而null是表示程序級的,正常或在意料之中的值的空缺,如果你想將它們復(fù)制變量或者屬性,或?qū)⑺鼈冏鳛閰?shù)傳入函數(shù),null是最佳的選擇。
5.全局對象
前幾節(jié)討論了javascript的元素類型和原始值。對象類型——對象、數(shù)組和函數(shù)/但有一類非常重要的對象,不得現(xiàn)在就必須將清楚:全局對象
全局對象(global object)在javascript中有著重要的用途。全局對象的屬性是全局定義的符號。javascript程序可以直接使用。當(dāng)javascript解釋器啟動時,它將新建一個新的全局對象,并給它一組定義的初始屬性。
全局屬性 比如undefined Infinty和NaN
全局函數(shù) 比如isNaN()、parseInt()和eval()
構(gòu)造函數(shù),比如Date()、RegExp()、String()、Object()和Array()
全局對象,比如Math 和JSON
全局對象的初始屬性并不是保留字,但他們應(yīng)當(dāng)當(dāng)做保留字來對待。
在代碼的最頂級——不在任何函數(shù)內(nèi)的javascript代碼,可以通過javascript關(guān)鍵字來引用全局對象。
var global = this; //定義一個引用全局對象的全局變量。
在客戶端javascript中,window對象充當(dāng)了全局對象,這個全局window對象有一個熟悉window引用其本身,它可以代替this來引用全局對象,window定義了全局核心屬性。但也征對web瀏覽器和和互動javascript定義了一部分其他全局屬性。
當(dāng)初次創(chuàng)建時,全局對象定義了javascript中所有的預(yù)定義全局值,這個特殊對象同樣包含了為程序定義的全局值。如果代碼聲明了一個全局變量。這個全局變量就是全局對象的一個屬性。
6.包裝對象
javascript對象是一種復(fù)合值:它是屬性或已命名值的集合。通過"."來引用屬性值,當(dāng)屬性值是一個函數(shù)的時候,陳其為方法,通過o.m()來調(diào)運(yùn)對象o中的方法。
我們看到字符串也同樣具有屬性和方法。
代碼如下:
var s ="hello world";
var word = s.substring(s.indexOf("")+1,s.length);//使用字符串的屬性。
document.write(word) //"ello world"
字符串既然不是對象,為什么它有屬性呢?只要引用了字符串s的屬性,javascript就會將字符串的值通過調(diào)用new String(s)的方式轉(zhuǎn)換成對象,這個對象繼承了字符串的方法。并被用來處理屬性引用。一旦新的屬性引用出來。一但引用結(jié)束,這個新創(chuàng)建的對象就會被銷毀。(實(shí)際上并不一定創(chuàng)建或銷毀這個臨時對象,然而這個過程看起來是這樣的。)
如同字符串一樣,數(shù)字和布爾值也具有各自的方法,通過Number()和Boolean()構(gòu)造函數(shù)創(chuàng)建一個臨時對象。這些方法的調(diào)用均是來自于這個臨時對象。(null和undefined沒有包裝過對象,訪問他們的屬性會有一個類型錯誤)
看如下 代碼,思考他們的執(zhí)行過程
代碼如下:
var s = "test";
s.len = 4; //給它設(shè)置一個屬性
var t = s.len //查找這個屬性
當(dāng)運(yùn)行這段代碼時,t的值是undefined,第二行代碼創(chuàng)建一個臨時字符串對象,并給len的值為4,隨即銷毀這個對象,第三行用過原始(沒有被修改的)的字符串創(chuàng)建一個新的字符串對象,并嘗試讀取len 的屬性。
這個屬性自然不存在,表示結(jié)果undefined,這段代碼說明了讀取字符串、數(shù)組和布爾值的屬性值(或方法)時,表現(xiàn)的像對象一樣,但如果你試圖給其屬性賦值。則會忽略這個操作;修改只是發(fā)生在臨時對象身上。而這個臨時對象并未保留下來。
需要注意的是,可以通過String(),Number(),Boolean()構(gòu)造函數(shù)來顯示創(chuàng)造包裝對象:
代碼如下:
var s = "test",
n = 1,
b = true;
var S = new String(s);
var N = new Number(n);
var B = new Boolean(b);
javascript會在必要的時候?qū)b轉(zhuǎn)換為原始值,因此上段代碼中的對象S N B常?!豢偸恰憩F(xiàn)的值和s n b一樣,"=="等于運(yùn)算符將原始值和其包裝對象視為相等。
但"==="全籌運(yùn)算符將它們視為不等,通過typeof運(yùn)算符可以看到原始值和其包裝的對象的不同。
7.不可變的原始值和可變的對象引用。
javascript的原始值(undefined null 布爾值 數(shù)字和字符串)與對象(包括數(shù)組和函數(shù))有著根本的區(qū)別,原始值是不可更改的;任何方法都無法(或突變)一個原始值。對數(shù)字和布爾值來說顯然如此———改變數(shù)字的值本身就說不通,而對字符串來說就不那么明顯,因?yàn)樽址雌饋碛勺址M成的數(shù)組。我們期望可以通過指定的索引來修改字符串中的字符。實(shí)際上javascript是禁止這樣做的。字符串中所有的方法看上去返回了一個修改后的字符串,實(shí)際上是返回一個新的字符串。
代碼如下:
var s = "hello world";
s.toUpperCase(); //返回"HELLO WORLD"并沒更改s的值
s //=> "hello world" 原始的字符串并未改變
原始值的比較是值的比較,只有在他們的值相當(dāng)時它們在才相等。這對數(shù)字、布爾值、null和undefined來說聽起來有點(diǎn)難,并沒有其他辦法來比較他們。同樣,對于字符串來說則不那么明顯;如果比較兩個單獨(dú)的字符串,當(dāng)且僅當(dāng)他們的長度相等且每個索引的字符都相等時,javascript的才認(rèn)為相等。
代碼如下:
var o = {x:1} //定義一個對象
o.x = 2 //通過修改對象的屬性來改變對象
o.y = 3 //再次更改這個對象,給它增加一個新屬性
var a =[1,2,3] //數(shù)組也是可以修改的
a[0]=0; //更改數(shù)組中的一個元素
a[3]=4; 給數(shù)組增加一個新元素
對象的比較并非值的比較:即使兩個對象包含同樣的屬性及相同的值,他們也是不相等的,各個索引元素完全相等的兩個數(shù)組也不相等
代碼如下:
var o ={x:1}, p={x:1}//兩個具有相同屬性的兩個對象
o === p ;//=>false 兩個單獨(dú)的對象永不相等( o == p ; =>false)
var a =[],b=[]; //兩個單獨(dú)的空數(shù)組
a === b ; //=>false兩個單獨(dú)的數(shù)組永不相等
我們通常將對象稱為引用類型(reference type),以此來和javascript的基本類型區(qū)分開來。依照術(shù)語的叫法,對象都是引用(reference),對象的比較均是引用的比較;當(dāng)且當(dāng)它們應(yīng)用同一個基對象時,它們才相等。
代碼如下:
var a = []; //定義一個引用空數(shù)組的變量a
var b = a; //變量b引用同一個數(shù)組
b[0] = 1;
a[0] //=>1 變量a也會修改
a === b //=>true a和b引用同一個數(shù)組,因此他們相等。
就像你剛才看到的如上代碼,將對象(或數(shù)組)賦值給一個變量,僅僅是賦值的引用值:對象本身并沒有復(fù)制一次。
如果你想得到一個對象或數(shù)組的副本,則必須顯式復(fù)制對象的每個屬性或數(shù)組的每個元素。下面的這個例子則是通過循環(huán)來完成對數(shù)組的復(fù)制。
代碼如下:
var a = ['a', 'b', 'c']; //待復(fù)制的數(shù)組
var b = []; //復(fù)制到目標(biāo)的空數(shù)組
for (var i = 0; i < a.length; i++) { //遍歷a[]中的每個元素
b[i] = a[i]; //將元素復(fù)制到b中。
}
同樣的,如果我們想比較兩個單獨(dú)或者數(shù)組,則必須比較他們的屬性或元素。下面這段代碼定義了一個比較練個數(shù)組的函數(shù)。
代碼如下:
function equalArrays(a, b) {
if (a.length != b.length) return false; //兩個長度不相同的數(shù)組不相等
for (var i = 0; i < a.length; i++) //循環(huán)遍歷所有元素
if (a[i] !== b[i]) return false; //如果有任意元素不等,則數(shù)組不相等
return true; // 否則他們相等
}
8.類型轉(zhuǎn)化
javascript中的取值型非常靈活,我們已經(jīng)從布爾值看到了這一點(diǎn):當(dāng)javascript期望使用一個布爾值時候,你可以提供任意類型值。javascript將根據(jù)需要自行轉(zhuǎn)換類型。一些值(真值)為true,其它值(假值)轉(zhuǎn)化為false.這在其它類型中同樣適用。如果javascript期望使用一個字符串,它把給定的值轉(zhuǎn)換為字符串。如果javascript期望使用一個數(shù)組,它把給定的值轉(zhuǎn)換為數(shù)字(如果轉(zhuǎn)化結(jié)果無意義的話將返回NaN),一些例子如下:
代碼如下:
10 + "object" //=> "10object";
"7" * "4" // =>28 兩個字符串均轉(zhuǎn)化為數(shù)字
var n = 1 - "x" // =>NaN字符串x無法轉(zhuǎn)換為數(shù)字
n + " objects" // =>"NaN objects":NaN轉(zhuǎn)換為字符串"NaN"
下表說明了在javascript中如何進(jìn)行類型轉(zhuǎn)化。粗體突出了那些讓你倍感意外的類型轉(zhuǎn)化??諉卧癖硎静槐匾矝]有執(zhí)行的轉(zhuǎn)換。
值 | 轉(zhuǎn)換為字符串 | 數(shù)字 | 布爾值 | 對象 |
undefined null |
"undefined" "null" |
NaN 0 |
false false |
throws TypeError throws TypeError |
true false |
"ture" "false" |
1 0 |
new Boolean(true) new Boolean(false) |
|
""(空字符串) "1.2"(非空,數(shù)字) "one"(非空,非數(shù)字) |
0 1.2 NaN |
false true true |
new String("") new String("1.2") new String("one") |
|
0 -0 NaN Infinty -Infinty 1(無窮大,非零) |
"0" "0" "NaN" "Infinity" "-Infinity" "1" |
false false false true true true |
new Number(0); new Number(-0); new Number(NaN) new Number(Infinty) new Number(-Infinty) new Number(1) |
|
{}(任意對象) [](任意數(shù)組) [9](1個數(shù)字元素) ['a'](其它數(shù)組) function(){}(任意函數(shù)) |
參考本小節(jié)第三節(jié)內(nèi)容 "" "9" 使用join()方法 參考本小節(jié)第三節(jié)內(nèi)容 |
參考本小節(jié)第三節(jié)內(nèi)容 0 9 NaN NaN |
true true true true true |
上表提到的原始值到原始值的轉(zhuǎn)換行對簡單,我們已經(jīng)在第本文第三小節(jié)討論過轉(zhuǎn)換為布爾值的情況了。所有原始值轉(zhuǎn)換為字符串的情形也已經(jīng)明確定義。轉(zhuǎn)換為數(shù)字的情形比較微妙。那些以數(shù)字表示的字符串可以直接轉(zhuǎn)化為數(shù)字,也允許在開始和結(jié)尾處帶有空格。但在開始和結(jié)尾處的任意非空字符都不會被當(dāng)成數(shù)字量的一部分,進(jìn)而造成字符串為數(shù)字的結(jié)果為NaN。有一些數(shù)字轉(zhuǎn)換看起來讓人奇怪:true轉(zhuǎn)換為1,false、空字符串""轉(zhuǎn)換為0.
原始值到對象的轉(zhuǎn)換也非常簡單,原始值
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com