自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

JavaScript內(nèi)核之基本概念

開(kāi)發(fā) 前端
本文將聚焦于JavaScript中的基本概念,這些概念與傳統(tǒng)語(yǔ)言有比較大的不同,因此單獨(dú)列出一章來(lái)做專門(mén)描述,理解本章的概念對(duì)書(shū)中后續(xù)章節(jié)的概念,代碼的行為等會(huì)有很大的幫助,讀者不妨花比較大的時(shí)間在本章,即使你對(duì)JavaScript已經(jīng)比較熟悉,也建議通讀本文。

本章主要講述JavaScript中的數(shù)據(jù)類型(基本類型與引用類型),變量(包括變量的作用域),操作符(主要是一些較為常見(jiàn),但是不容易從字面上理解的操作符)。由于JavaScript中的“一切皆對(duì)象”,在掌握了這些基本的概念之后,讀者就可以較為輕松的理解諸如作用域,調(diào)用對(duì)象,閉包,currying等等較難理解的概念了。

數(shù)據(jù)類型

有程序設(shè)計(jì)經(jīng)驗(yàn)的讀者肯定知道,在C或者Java這樣的語(yǔ)言中,數(shù)據(jù)是有類型的,比如用以表示用戶名的屬性是字符串,而一個(gè)雇員的年齡則是一個(gè)數(shù)字,表示UI上的一個(gè)開(kāi)關(guān)按鈕的數(shù)據(jù)模型則為布爾值等等,對(duì)數(shù)字可能還可以細(xì)分為浮點(diǎn)數(shù),整型數(shù),整型數(shù)又可能分為長(zhǎng)整型和短整型,總而言之,它們都表示語(yǔ)言中的數(shù)據(jù)的值的類型。

JavaScript中的數(shù)據(jù)類型分為兩種:基本數(shù)據(jù)類型和對(duì)象類型,其中對(duì)象類型包含對(duì)象,數(shù)組,以及函數(shù)(事實(shí)上,函數(shù),數(shù)組等也都是對(duì)象,這個(gè)在后邊的章節(jié)詳述)。

1.1.1 基本數(shù)據(jù)類型

在JavaScript中,包含三種基本的數(shù)據(jù)類型,字符串(String),數(shù)值(Number),布爾值(boolean),下面是一些簡(jiǎn)單的例子:

  1. <strong>var str = "Hello, world";//字符串  
  2. var i = 10;//整型數(shù)  
  3. var f = 2.3;//浮點(diǎn)數(shù)  
  4.    
  5. var b = true;//布爾值</strong> 

我們可以分別查看變量的值及變量的類型:

  1. print(str);  
  2. print(i);  
  3. print(f);  
  4. print(b);  
  5.    
  6. print(typeof str);  
  7. print(typeof i);  
  8. print(typeof f);  
  9. print(typeof b); 

注意,在此處使用的print()函數(shù)為rhino解釋器的頂層對(duì)象的方法,可以用來(lái)打印字符串,通常情況下,在客戶端,程序員多使用alert()進(jìn)行類似的動(dòng)作,alert()是瀏覽器中JavaScript解釋器的頂層對(duì)象(window)的一個(gè)方法。

  1. Hello, world  
  2. 10  
  3. 2.3  
  4. true 
  5.    
  6. string  
  7. number  
  8. number  
  9. Boolean 

在JavaScript中,所有的數(shù)字,不論是整型浮點(diǎn),都屬于“數(shù)字”基本類型。typeof是一個(gè)一元的操作符,在本章的另外一個(gè)小節(jié)會(huì)專門(mén)講到。

1.1.2 對(duì)象類型

這里提到的對(duì)象不是對(duì)象本身,而是指一種類型,我們?cè)诘谌聲?huì)對(duì)對(duì)象進(jìn)行詳細(xì)的討論,此處的對(duì)象包括,對(duì)象(屬性的集合,即鍵值的散列表),數(shù)組(有序的列表),函數(shù)(包含可執(zhí)行的代碼)。

對(duì)象類型是一種復(fù)合的數(shù)據(jù)類型,其基本元素由基本數(shù)據(jù)類型組成,當(dāng)然不限于基本類型,比如對(duì)象類型中的值可以是其他的對(duì)象類型實(shí)例,我們通過(guò)例子來(lái)說(shuō)明:

  1. <strong>var str = "Hello, world";  
  2. var obj = new Object();  
  3. obj.str = str;  
  4. obj.num = 2.3;  
  5.    
  6. var array = new Array("foo""bar""zoo");  
  7.    
  8. var func = function(){  
  9.     print("I am a function here");  
  10. }</strong> 

可以看到,對(duì)象具有屬性,如obj.str, obj.num,這些屬性的值可以是基本類型,事實(shí)上還可以更復(fù)雜,我們來(lái)看看他們的類型:

  1. print(typeof obj);  
  2. print(typeof array);  
  3. print(typeof func);  
  4.    
  5. //將打印出  
  6. object  
  7. object  
  8. function 

讀者可能會(huì)對(duì)print(typeof array)打印出object感到奇怪,事實(shí)上,對(duì)象和數(shù)組的界限并不那么明顯(事實(shí)上它們是屬于同一類型的),但是他們的行為卻非常不同,本書(shū)的后續(xù)章節(jié)將兩個(gè)重要的數(shù)據(jù)類型做了分別介紹。

2.1.3 兩者之間的轉(zhuǎn)換

類似與Java中基本數(shù)據(jù)類型的自動(dòng)裝箱拆箱,JavaScript也有類似的動(dòng)作,基本數(shù)據(jù)類型在做一些運(yùn)算時(shí),會(huì)臨時(shí)包裝一個(gè)對(duì)象,做完運(yùn)算后,又自動(dòng)釋放該對(duì)象。我們可以通過(guò)幾個(gè)例子來(lái)說(shuō)明:

  1. <strong>var str = "JavaScript Kernal";  
  2. print(str.length);//打印17</strong> 

str為一個(gè)字符串,通過(guò)typeof運(yùn)算符可知其type為”string”,而:

  1. <strong>var str2 = new String("JavaScript Kernal");  
  2. print(typeof str2);</strong> 

可知,str2的type為”object”,即這兩者并不相同,那么為什么可以使用str.length來(lái)的到str的長(zhǎng)度呢?事實(shí)上,當(dāng)使用str.length時(shí),JavaScript會(huì)自動(dòng)包裝一個(gè)臨時(shí)的String對(duì)象,內(nèi)容為str的內(nèi)容,然后獲取該對(duì)象的length屬性,最后,這個(gè)臨時(shí)的對(duì)象將被釋放。

而將對(duì)象轉(zhuǎn)換為基本類型則是通過(guò)這樣的方式:通過(guò)調(diào)用對(duì)象的valueOf()方法來(lái)取得對(duì)象的值,如果和上下文的類型匹配,則使用該值。如果valueOf取不到值的話,則需要調(diào)用對(duì)象的toString()方法,而如果上下文為數(shù)值型,則又需要將此字符串轉(zhuǎn)換為數(shù)值。由于JavaScript是弱類型的,所以JavaScript引擎需要根據(jù)上下文來(lái)“猜測(cè)”對(duì)象的類型,這就使得JavaScript的效率比編譯型的語(yǔ)言要差一些。

valueOf()的作用是,將一個(gè)對(duì)象的值轉(zhuǎn)換成一種合乎上下文需求的基本類型,toString()則名副其實(shí),可以打印出對(duì)象對(duì)應(yīng)的字符串,當(dāng)然前提是你已經(jīng)“重載”了Object的toString()方法。

事實(shí)上,這種轉(zhuǎn)換規(guī)則會(huì)導(dǎo)致很多的問(wèn)題,比如,所有的非空對(duì)象,在布爾值環(huán)境下,都會(huì)被轉(zhuǎn)成true,比如:

  1. <strong>function convertTest(){  
  2. if(new Boolean(false) && new Object() &&  
  3.  new String("") && new Array()){  
  4.        print("convert to boolean")  
  5.     }    
  6. }  
  7.    
  8. convertTest();//convert to Boolean</strong> 

初學(xué)者容易被JavaScript中的類型轉(zhuǎn)換規(guī)則搞暈掉,很多情況下會(huì)覺(jué)得那種寫(xiě)法看著非常別扭,其實(shí)只需要掌握了規(guī)則,這些古怪的寫(xiě)法會(huì)大大的提高代碼的性能,我們通過(guò)例子來(lái)學(xué)習(xí)這些規(guī)則:

  1. <strong>var x = 3;  
  2. var y = x + "2";// => 32  
  3. var z = x + 2;// => 5  
  4.    
  5. print(y);  
  6. print(z);</strong> 

通??梢栽贘S代碼中發(fā)現(xiàn)這樣的代碼:

  1. <strong>if(datamodel.item){  
  2.     //do something...  
  3. }else{  
  4.     datamodel.item = new Item();  
  5. }</strong> 

這種寫(xiě)法事實(shí)上具有更深層次的含義:

應(yīng)該注意到,datamodel.item是一個(gè)對(duì)象(字符串,數(shù)字等),而if需要一個(gè)boolean型的表達(dá)式,所以這里進(jìn)行了類型轉(zhuǎn)換。在JavaScript中,如果上下文需要boolean型的值,則引擎會(huì)自動(dòng)將對(duì)象轉(zhuǎn)換為boolean類型。轉(zhuǎn)換規(guī)則為,如果該對(duì)象非空,則轉(zhuǎn)換為true,否則為false.因此我們可以采取這種簡(jiǎn)寫(xiě)的形式。

而在傳統(tǒng)的編程語(yǔ)言(強(qiáng)類型)中,我們則需要:

  1. <strong>if(datamodel.item != null){  
  2.     //do something...  
  3. }else{  
  4.     datamodel.item = new Item();  
  5. }</strong> 

#p#

2.1.4類型的判斷

前面講到JavaScript特性的時(shí)候,我們說(shuō)過(guò),JavaScript是一個(gè)弱類型的語(yǔ)言,但是有時(shí)我們需要知道變量在運(yùn)行時(shí)的類型,比如,一個(gè)函數(shù)的參數(shù)預(yù)期為另一個(gè)函數(shù):

  1. <strong>function handleMessage(message, handle){  
  2.     return handle(message);  
  3. }</strong> 

當(dāng)調(diào)用handleMessage的函數(shù)傳遞的handle不是一個(gè)函數(shù)則JavaScript引擎會(huì)報(bào)錯(cuò),因此我們有必要在調(diào)用之前進(jìn)行判斷:

  1. <strong>function handleMessage(message, handle){  
  2.     if(typeof handle == "function"){  
  3.        return handle(message);   
  4.     }else{  
  5.        throw new Error("the 2nd argument should be a function");  
  6.     }  
  7. }</strong> 

但是,typeof并不總是有效的,比如下面這種情況:

  1. <strong>var obj = {};  
  2. var array = ["one""two""three""four"];  
  3.    
  4. print(typeof obj);//object  
  5. print(typeof array); //object</strong> 

運(yùn)行結(jié)果顯示,對(duì)象obj和數(shù)組array的typeof值均為”object”,這樣我們就無(wú)法準(zhǔn)確判斷了,這時(shí)候,可以通過(guò)調(diào)用instanceof來(lái)進(jìn)行進(jìn)一步的判斷:

  1. print(obj instanceof Array);//false  
  2. print(array instanceof Array);//true 

第一行代碼返回false,第二行則返回true。因此,我們可以將typeof操作符和instanceof操作符結(jié)合起來(lái)進(jìn)行判斷。

2.2 變量

變量,即通過(guò)一個(gè)名字將一個(gè)值關(guān)聯(lián)起來(lái),以后通過(guò)變量就可以引用到該值,比如:

  1. <strong>var str = "Hello, World";  
  2. var num = 2.345;</strong> 

當(dāng)我們下一次要引用”Hello, Wrold”這個(gè)串進(jìn)行某項(xiàng)操作時(shí),我們只需要使用變量str即可,同樣,我們可以用10*num來(lái)表示10*2.345。變量的作用就是將值“存儲(chǔ)”在這個(gè)變量上。

2.2.1基本類型和引用類型

在上一小節(jié),我們介紹了JavaScript中的數(shù)據(jù)類型,其中基本類型如數(shù)字,布爾值,它們?cè)趦?nèi)存中都有固定的大小,我們通過(guò)變量來(lái)直接訪問(wèn)基本類型的數(shù)據(jù)。而對(duì)于引用類型,如對(duì)象,數(shù)組和函數(shù),由于它們的大小在原則上是不受任何限制的,故我們通過(guò)對(duì)其引用的訪問(wèn)來(lái)訪問(wèn)它們本身,引用本身是一個(gè)地址,即指向真實(shí)存儲(chǔ)復(fù)雜對(duì)象的位置。

基本類型和引用類型的區(qū)別是比較明顯的,我們來(lái)看幾個(gè)例子:

  1. <strong>var x = 1;//數(shù)字x,基本類型  
  2. var y = x;//數(shù)字y,基本類型  
  3. print(x);  
  4. print(y);  
  5.    
  6. x = 2;//修改x的值  
  7.    
  8. print(x);//x的值變?yōu)?  
  9. print(y);//y的值不會(huì)變化</strong> 

運(yùn)行結(jié)果如下:

1

1

2

1

這樣的運(yùn)行結(jié)果應(yīng)該在你的意料之內(nèi),沒(méi)有什么特別之處,我們?cè)賮?lái)看看引用類型的例子,由于數(shù)組的長(zhǎng)度非固定,可以動(dòng)態(tài)增刪,因此數(shù)組為引用類型:

  1. <strong>var array = [1,2,3,4,5];  
  2. var arrayRef = array;  
  3.    
  4. array.push(6);  
  5. print(arrayRef);</strong> 

引用指向的是地址,也就是說(shuō),引用不會(huì)指向引用本身,而是指向該引用所對(duì)應(yīng)的實(shí)際對(duì)象。因此通過(guò)修改array指向的數(shù)組,則arrayRef指向的是同一個(gè)對(duì)象,因此運(yùn)行效果如下:

1,2,3,4,5,6

2.2.2變量的作用域

變量被定義的區(qū)域即為其作用域,全局變量具有全局作用域;局部變量,比如聲明在函數(shù)內(nèi)部的變量則具有局部作用域,在函數(shù)的外部是不能直接訪問(wèn)的。比如:

  1. <strong>var variable = "out";  
  2.    
  3. function func(){  
  4.     var variable = "in";  
  5.     print(variable);//打印”in”  
  6. }  
  7.    
  8. func();  
  9. print(variable);//打印”out”</strong> 

應(yīng)該注意的是,在函數(shù)內(nèi)var關(guān)鍵字是必須的,如果使用了變量而沒(méi)有寫(xiě)var關(guān)鍵字,則默認(rèn)的操作是對(duì)全局對(duì)象的,比如:

  1. <strong>var variable = "out";  
  2.    
  3. function func(){  
  4.     variable = "in";//注意此variable前沒(méi)有var關(guān)鍵字  
  5.     print(variable);  
  6. }  
  7.    
  8. func();  
  9. print(variable);//全局的變量variable被修改</strong> 

由于函數(shù)func中使用variable而沒(méi)有關(guān)鍵字var,則默認(rèn)是對(duì)全局對(duì)象variable屬性做的操作(修改variable的值為in),因此此段代碼會(huì)打?。?/p>

in

in

#p#

2.3運(yùn)算符

運(yùn)算符,通常是容易被忽略的一個(gè)內(nèi)容,但是一些比較古怪的語(yǔ)法現(xiàn)象仍然可能需要用到運(yùn)算符的結(jié)合率或者其作用來(lái)進(jìn)行解釋,JavaScript中,運(yùn)算符是一定需要注意的地方,有很多具有JS編程經(jīng)驗(yàn)的人仍然免不了被搞得暈頭轉(zhuǎn)向。

我們?cè)谶@一節(jié)主要講解這樣幾個(gè)運(yùn)算符:

2.3.1中括號(hào)運(yùn)算符([])

[]運(yùn)算符可用在數(shù)組對(duì)象和對(duì)象上,從數(shù)組中按下標(biāo)取值:

  1. <strong>var array = ["one""two""three""four"];  
  2. array[0]</strong> 

而[]同樣可以作用于對(duì)象,一般而言,對(duì)象中的屬性的值是通過(guò)點(diǎn)(.)運(yùn)算符來(lái)取值,如:

  1. <strong>var object = {  
  2.     field : "self",  
  3.     printInfo : function(){  
  4.        print(this.field);  
  5.     }  
  6. }  
  7.    
  8. object.field;  
  9. object.printInfo();</strong> 

但是考慮到這樣一種情況,我們?cè)诒闅v一個(gè)對(duì)象的時(shí)候,對(duì)其中的屬性的鍵(key)是一無(wú)所知的,我們?cè)趺赐ㄟ^(guò)點(diǎn)(.)來(lái)訪問(wèn)呢?這時(shí)候我們就可以使用[]運(yùn)算符:

  1. <strong>for(var key in object){  
  2.     print(key + ":" + object[key]);  
  3. }</strong> 

運(yùn)行結(jié)果如下:

  1. field:slef  
  2. printInfo:function (){  
  3.        print(this.field);  

2.3.2點(diǎn)運(yùn)算符(.)

點(diǎn)運(yùn)算符的左邊為一個(gè)對(duì)象(屬性的集合),右邊為屬性名,應(yīng)該注意的是右邊的值除了作為左邊的對(duì)象的屬性外,同時(shí)還可能是它自己的右邊的值的對(duì)象:

  1. <strong>var object = {  
  2.     field : "self",  
  3.     printInfo : function(){  
  4.        print(this.field);  
  5.     },  
  6.     outter:{  
  7.        inner : "inner text",  
  8.        printInnerText : function(){  
  9.            print(this.inner);  
  10.        }  
  11.     }  
  12. }  
  13.    
  14. object.outter.printInnerText();</strong> 

這個(gè)例子中,outter作為object的屬性,同時(shí)又是printInnerText()的對(duì)象。

2.3.3 == 和 === 以及 != 和 !==

運(yùn)算符==讀作相等,而運(yùn)算符===則讀作等同。這兩種運(yùn)算符操作都是在JavaScript代碼中經(jīng)常見(jiàn)到的,但是意義則不完全相同,簡(jiǎn)而言之,相等操作符會(huì)對(duì)兩邊的操作數(shù)做類型轉(zhuǎn)換,而等同則不會(huì)。我們還是通過(guò)例子來(lái)說(shuō)明:

  1. print(1 == true);  
  2. print(1 === true);  
  3. print("" == false);  
  4. print("" === false);  
  5.    
  6. print(null == undefined);  
  7. print(null === undefined); 

運(yùn)行結(jié)果如下:

  1. <strong>true 
  2. false 
  3. true 
  4. false 
  5. true 
  6. false</strong> 

相等和等同運(yùn)算符的規(guī)則分別如下:

相等運(yùn)算符

如果操作數(shù)具有相同的類型,則判斷其等同性,如果兩個(gè)操作數(shù)的值相等,則返回true(相等),否則返回false(不相等).

如果操作數(shù)的類型不同,則按照這樣的情況來(lái)判斷:

◆  null和undefined相等

◆ 其中一個(gè)是數(shù)字,另一個(gè)是字符串,則將字符串轉(zhuǎn)換為數(shù)字,在做比較

◆  其中一個(gè)是true,先轉(zhuǎn)換成1(false則轉(zhuǎn)換為0)在做比較

◆ 如果一個(gè)值是對(duì)象,另一個(gè)是數(shù)字/字符串,則將對(duì)象轉(zhuǎn)換為原始值(通過(guò)toString()或者valueOf()方法)

◆ 其他情況,則直接返回false

等同運(yùn)算符

如果操作數(shù)的類型不同,則不進(jìn)行值的判斷,直接返回false

如果操作數(shù)的類型相同,分下列情況來(lái)判斷:

◆ 都是數(shù)字的情況,如果值相同,則兩者等同(有一個(gè)例外,就是NaN,NaN與其本身也不相等),否則不等同

◆ 都是字符串的情況,與其他程序設(shè)計(jì)語(yǔ)言一樣,如果串的值不等,則不等同,否則等同

◆ 都是布爾值,且值均為true/false,則等同,否則不等同

◆ 如果兩個(gè)操作數(shù)引用同一個(gè)對(duì)象(數(shù)組,函數(shù)),則兩者完全等同,否則不等同

◆ 如果兩個(gè)操作數(shù)均為null/undefined,則等同,否則不等同

比如:

  1. <strong>var obj = {  
  2.     id : "self",  
  3.     name : "object" 
  4. };  
  5.    
  6. var oa = obj;  
  7. var ob = obj;  
  8.    
  9. print(oa == ob);  
  10. print(oa === ob);</strong> 

會(huì)返回:

true

true

再來(lái)看一個(gè)對(duì)象的例子:

  1. <strong>var obj1 = {  
  2.     id : "self",  
  3.     name : "object",  
  4.     toString : function(){  
  5.        return "object 1";  
  6.     }  
  7. }  
  8.    
  9. var obj2 = "object 1";  
  10.    
  11. print(obj1 == obj2);  
  12. print(obj1 === obj2);</strong> 

返回值為:

true

false

obj1是一個(gè)對(duì)象,而obj2是一個(gè)結(jié)構(gòu)與之完全不同的字符串,而如果用相等操作符來(lái)判斷,則兩者是完全相同的,因?yàn)閛bj1重載了頂層對(duì)象的toString()方法。

而!=不等和!==不等同,則與==/!==相反。因此,在JavaScript中,使用相等/等同,不等/不等同的時(shí)候,一定要注意類型的轉(zhuǎn)換,這里推薦使用等同/不等同來(lái)進(jìn)行判斷,這樣可以避免一些難以調(diào)試的bug。

原文:http://abruzzi.iteye.com/blog/632010

【編輯推薦】

  1. JavaScript概述
  2. 5個(gè)有趣的JavaScript代碼片段分享
  3. JavaScript來(lái)實(shí)現(xiàn)的超炫組織結(jié)構(gòu)圖
  4. JavaScript與生俱來(lái)的10個(gè)設(shè)計(jì)缺陷
  5. JavaScript網(wǎng)頁(yè)開(kāi)發(fā)指南
責(zé)任編輯:陳貽新 來(lái)源: abruzzi
相關(guān)推薦

2010-06-07 19:48:30

UML

2011-07-21 15:28:30

java

2011-03-28 11:05:17

ODBC

2014-04-16 15:11:19

Spark

2012-09-11 14:39:03

Moosefs

2009-03-20 11:46:10

MGCP協(xié)議網(wǎng)關(guān)

2020-12-31 05:31:01

數(shù)據(jù)結(jié)構(gòu)算法

2010-06-24 13:26:53

FTP協(xié)議

2009-12-21 10:27:52

WCF基本概念

2009-12-29 18:29:09

Silverlight

2010-02-23 16:32:29

WCF服務(wù)

2017-04-07 10:19:22

交易支付概念

2023-06-14 00:21:52

2017-02-28 16:03:46

支付清結(jié)算交易

2010-08-23 16:58:17

DHCP協(xié)議

2009-08-18 10:34:31

Java入門(mén)基本概念

2010-07-07 15:17:40

LDAP協(xié)議

2010-07-12 09:43:38

Symbian開(kāi)發(fā)

2012-12-03 17:12:10

HDFS

2011-08-04 17:01:16

iPhone游戲開(kāi)發(fā) Cocos2d
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)