日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
沒那么簡(jiǎn)單 那些應(yīng)該吃透的JavaScript概念

文章的目的是讓更多的程序員深入理解JavaScript的一些概念,其實(shí)關(guān)于這些,我們?cè)诳梢栽诰W(wǎng)上看到很多類似的內(nèi)容,所以現(xiàn)在該是向深入理解的方向靠攏的時(shí)候了。

成都創(chuàng)新互聯(lián)始終堅(jiān)持【策劃先行,效果至上】的經(jīng)營(yíng)理念,通過多達(dá)10余年累計(jì)超上千家客戶的網(wǎng)站建設(shè)總結(jié)了一套系統(tǒng)有效的網(wǎng)絡(luò)營(yíng)銷推廣解決方案,現(xiàn)已廣泛運(yùn)用于各行各業(yè)的客戶,其中包括:成都加固等企業(yè),備受客戶贊美。

推薦閱讀:揭開JavaScript閉包的真實(shí)面目

一,function

從一開始接觸到j(luò)s就感覺好靈活,每個(gè)人的寫法都不一樣,比如一個(gè)function就有N種寫法。如:functionshowMsg(){},varshowMsg=function(){},showMsg=function(){}。似乎沒有什么區(qū)別,都是一樣的嘛,真的是一樣的嗎,大家看看下面的例子:

 
 
 
  1. //函數(shù)定義:命名函數(shù)(聲明式),匿名函數(shù)(引用式)  
  2. //聲明式,定義代碼先于函數(shù)執(zhí)行代碼被解析  
  3. functiont1(){  
  4. dwn("t1");  
  5. }  
  6. t1();  
  7. functiont1(){  
  8. dwn("newt1");  
  9. }  
  10. t1();  
  11. //引用式,在函數(shù)運(yùn)行中進(jìn)行動(dòng)態(tài)解析  
  12. vart1=function(){  
  13. dwn("newnewt1");  
  14. }  
  15. t1();  
  16. vart1=function(){  
  17. dwn("newnewnewt1");  
  18. }  
  19. t1();  
  20. //以上輸出:newt1,newt1,newnewt1,newnewnewt1 

可能想著應(yīng)該是輸出t1,newt1,newnewt1,newnewnewt1,結(jié)果卻并不是這樣,應(yīng)該理解這句話:聲明式,定義代碼先于函數(shù)執(zhí)行代碼被解析。如果深入一步,應(yīng)該說是scope鏈問題,實(shí)際上前面兩個(gè)方法等價(jià)于window.t1,可以理解為t1是window的一個(gè)公有屬性,被賦了兩次值,以最后一次賦值為最終值。而后面兩個(gè)方法,可以理解為是t1是個(gè)變量,第四個(gè)方法的var去掉之后的結(jié)果仍然不會(huì)改變。

然而,當(dāng)?shù)谒膫€(gè)方法改成functiont1(){}這樣的聲明式時(shí),結(jié)果變成了newnewnewt1,newnewnewt1,newnewt1,newnewt1。前面兩個(gè)按照我的理解可以很好的理解為什么是這個(gè)答案,第三個(gè)也可以理解,但是最后一個(gè)輸出讓我比較糾結(jié),希望有高手出現(xiàn)解答一下。另外匿名函數(shù)還有(function(){...})()這樣的寫法,最后一個(gè)括號(hào)用于參數(shù)輸入還有vart1=newfunction(){..}這樣的聲明,實(shí)際上t1已經(jīng)是一個(gè)對(duì)象了。

 
 
 
  1. vart2=newfunction()  
  2. {  
  3. vartemp=100;//私有成員  
  4. this.temp=200;//公有成員,這兩個(gè)概念會(huì)在第三點(diǎn)以后展開說明  
  5. returntemp+this.temp;  
  6. }  
  7.  
  8. alert(typeof(t2));//object  
  9. alert(t2.constructor());//300  
  10. 除此之外,還有使用系統(tǒng)內(nèi)置函數(shù)對(duì)象來構(gòu)建一個(gè)函數(shù),例:  
  11. vart3=newFunction('vartemp=100;this.temp=200;returntemp+this.temp;');//這個(gè)位置加不加new結(jié)果都一樣,WHY  
  12. alert(typeof(t3));//function  
  13. alert(t3());//300 

二,創(chuàng)建對(duì)象

首先我們理解一下面向?qū)ο缶幊蹋∣bject-OrientedProgramming,OOP),使用OOP技術(shù),常常要使用許多代碼模塊,每個(gè)模塊都提供特定的功能,每個(gè)模塊都是孤立的,甚至與其它模塊完全獨(dú)立。這種模塊化編程方法提供了非常大的多樣性,大大增加了代碼的重用機(jī)會(huì)??梢耘e例進(jìn)一步說明這個(gè)問題,假定計(jì)算機(jī)上的一個(gè)高性能應(yīng)用程序是一輛一流賽車。如果使用傳統(tǒng)的編程技巧,這輛賽車就是一個(gè)單元。

如果要改進(jìn)該車,就必須替換整個(gè)單元,把它送回廠商,讓汽車專家升級(jí)它,或者購(gòu)買一個(gè)新車。如果使用OOP技術(shù),就只需從廠商處購(gòu)買新的引擎,自己按照說明替換它,而不必用鋼鋸切割車體。不過大部分的論點(diǎn)是,JavaScript并不是直接的面向?qū)ο蟮恼Z(yǔ)言,但是通過模擬可以做到很多面向?qū)ο笳Z(yǔ)言才能做到的事,如繼承,多態(tài),封裝,JavaScript都能干。

 
 
 
  1. //以下三種構(gòu)造對(duì)象的方法  
  2. //newObject,實(shí)例化一個(gè)Object  
  3. vara=newObject();  
  4. a.x=1,a.y=2;  
  5. //對(duì)象直接量  
  6. varb={x:1,y:2};  
  7. //定義類型  
  8. functionPoint(x,y){//類似于C#中的類  
  9. this.x=x;  
  10. this.y=y;  
  11. }  
  12. varp=newPoint(1,2);//實(shí)例化類 

第一種方法通過構(gòu)造基本對(duì)象直接添加屬性的方法來實(shí)現(xiàn),第二種和第一種差不多,可以看成是第一種方法的快捷表示法。第三種方法中,可以以”類“為基礎(chǔ),創(chuàng)造多個(gè)類型相同的對(duì)象。

#p#

三,對(duì)象屬性的封裝(公有和私有)

以例子來說明:

 
 
 
  1. functionList(){  
  2. varm_elements=[];//私有成員,在對(duì)象外無法訪問  
  3. m_elements=Array.apply(m_elements,arguments);  
  4. //此處模擬getter,使用時(shí)alist.length;  
  5. //等價(jià)于getName()方式:this.length=function(){returnm_elements.length;},使用時(shí)alist.length();  
  6. //公有屬性,可以通過"."運(yùn)算符或下標(biāo)來訪問  
  7. this.length={  
  8. valueOf:function(){  
  9. returnm_elements.length;  
  10. },  
  11. toString:function(){  
  12. returnm_elements.length;  
  13. }  
  14. }  
  15. //公有方法,此方法使用得alert(alist)相當(dāng)于alert(alist.toString())  
  16. this.toString=function(){  
  17. returnm_elements.toString();  
  18. }  
  19. //公有方法  
  20. this.add=function(){  
  21. m_elements.push.apply(m_elements,arguments);  
  22. }  
  23. //私有方法如下形式,這里涉及到了閉包的概念,接下來繼續(xù)說明  
  24. //varadd=function()或functionadd()  
  25. //{  
  26. //m_elements.push.apply(m_elements,arguments);  
  27. //}  
  28. }  
  29. varalist=newList(1,2,3);  
  30. dwn(alist);//=alert(alist.toString()),輸出1,2,3  
  31. dwn(alist.length);//輸出3  
  32. alist.add(4,5,6);  
  33. dwn(alist);//輸出1,2,3,4,5,6  
  34. dwn(alist.length);//輸出6 

四,屬性和方法的類型

JavaScript里,對(duì)象的屬性和方法支持4種不同的類型:privateproperty(私有屬性),dynamicpublicproperty(動(dòng)態(tài)公有屬性),staticpublicproperty/prototypeproperty(靜態(tài)公有屬性或原型屬性),staticproperty(靜態(tài)屬性或類屬性)。私有屬性對(duì)外界完全不具備訪問性,可以通過內(nèi)部的getter和setter(都是模擬);動(dòng)態(tài)公有屬性外界可以訪問,每個(gè)對(duì)象實(shí)例持有一個(gè)副本,不會(huì)相互影響;原型屬性每個(gè)對(duì)象實(shí)例共享唯一副本;類屬性不作為實(shí)例的屬性,只作為類的屬性。以下是例子:

 
 
 
  1. //動(dòng)態(tài)公有類型,靜態(tài)公有類型(原型屬性)  
  2. functionmyClass(){  
  3. varp=100;//privateproperty  
  4. this.x=10;//dynamicpublicproperty  
  5. }  
  6. myClass.prototype.y=20;  
  7. //要想成為高級(jí)JavaScript階段,prototype和閉包必須得理解和適當(dāng)應(yīng)用  
  8. myClass.z=30;//staticproperty  
  9.  
  10. vara=newmyClass();  
  11. dwn(a.p)//undefined  
  12. dwn(a.x)//10  
  13. dwn(a.y)//20  
  14. a.x=20;  
  15. a.y=40;  
  16. dwn(a.x);//20  
  17. dwn(a.y);//40  
  18. delete(a.x);//刪除對(duì)象a的屬性x  
  19. delete(a.y);//刪除對(duì)象a的屬性y  
  20. dwn(a.x);//undefined  
  21. dwn(a.y);//20靜態(tài)公有屬性y被刪除后還原為原型屬性y  
  22. dwn(a.z);//undefined類屬性無法通過對(duì)象訪問  
  23. dwn(myClass.z); 

五,原型(prototype)

這里只講部分,prototype和閉包都不是幾句話都能講清楚的,如果這里可以給你一些啟蒙,則萬幸矣。習(xí)語(yǔ)”照貓畫虎“,這里的貓就是原型,虎是類型,可以表示成:虎.prototype=某只貓or虎.prototype=new貓()。因?yàn)樵蛯傩悦總€(gè)對(duì)象實(shí)例共享唯一副本,所以當(dāng)實(shí)例中的一個(gè)調(diào)整了一個(gè)原型屬性的值時(shí),所有實(shí)例調(diào)用這個(gè)屬性時(shí)都將發(fā)生變化,這點(diǎn)需要注意,以下是原型關(guān)系的類型鏈:

 
 
 
  1. functionClassA(){  
  2. }  
  3. ClassA.prototype=newObject();  
  4. functionClassB(){  
  5. }  
  6. ClassB.prototype=newClassA();  
  7. functionClassC(){  
  8. }  
  9. ClassC.prototype=newClassB();  
  10. varobj=newClassC();  
  11. dwn(objinstanceofClassC);//true  
  12. dwn(objinstanceofClassB);//true  
  13. dwn(objinstanceofClassA);//true  
  14. dwn(objinstanceofObject);//true  
  15. 帶默認(rèn)值的Point對(duì)象:  
  16. functionPoint2(x,y){  
  17. if(x)this.x=x;  
  18. if(y)this.y=y;  
  19. }  
  20. //設(shè)定Point2對(duì)象的x,y默認(rèn)值為0  
  21. Point2.prototype.x=0;  
  22. Point2.prototype.y=0;  
  23. //p1是一個(gè)默認(rèn)(0,0)的對(duì)象  
  24. varp1=newPoint2();//可以寫成varp1=newPoint2也不會(huì)出錯(cuò),WHY  
  25. //p2賦值  
  26. varp2=newPoint2(1,2);  
  27. dwn(p1.x+","+p1.y);//0,0  
  28. dwn(p2.x+","+p2.y);//1,2  
  29. delete對(duì)象的屬性后,原型屬性將回到初始化的狀態(tài):  
  30. functionClassD(){  
  31. this.a=100;  
  32. this.b=200;  
  33. this.c=300 
  34. }  
  35. ClassD.prototype=newClassD();//將ClassD原有的屬性設(shè)為原型,包括其值  
  36. ClassD.prototype.reset=function(){//將非原型屬性刪除  
  37. for(vareachinthis){  
  38. deletethis[each];  
  39. }  
  40. }  
  41. vard=newClassD();  
  42. dwn(d.a);//100  
  43. d.a*=2;  
  44. d.b*=2;  
  45. d.c*=2;  
  46. dwn(d.a);//200  
  47. dwn(d.b);//400  
  48. dwn(d.c);//600  
  49. d.reset();//刪掉非原型屬性,所有回來原型  
  50. dwn(d.a);//100  
  51. dwn(d.b);//200  
  52. dwn(d.c);//300 

#p#

六,繼承

如果兩個(gè)類都是同一個(gè)實(shí)例的類型,那么它們之間存在著某種關(guān)系,我們把同一個(gè)實(shí)例的類型之間的泛化關(guān)系稱為繼承。C#和JAVA中都有這個(gè),具體的理解就不說了。在JavaScript中,并不直接從方法上支持繼承,但是就像前面說的,可以模擬。

方法可以歸納為四種:構(gòu)造繼承法,原型繼承法,實(shí)例繼承法和拷貝繼承法。融會(huì)貫通之后,還有混合繼續(xù)法,這是什么法,就是前面四種挑幾種混著來。以下例子來源于王者歸來,其中涉及到了apply,call和一些Array的用法,有興趣的可以自己在園子里搜索一下。

1,構(gòu)造繼續(xù)法例子:

 
 
 
  1. //定義一個(gè)Collection類型  
  2. functionCollection(size)  
  3. {  
  4. this.size=function(){returnsize};//公有方法,可以被繼承  
  5. }  
  6.  
  7. Collection.prototype.isEmpty=function(){//靜態(tài)方法,不能被繼承  
  8. returnthis.size()==0;  
  9. }  
  10. //定義一個(gè)ArrayList類型,它"繼承"Collection類型  
  11. functionArrayList()  
  12. {  
  13. varm_elements=[];//私有成員,不能被繼承  
  14. m_elements=Array.apply(m_elements,arguments);  
  15.  
  16. //ArrayList類型繼承Collection  
  17. this.base=Collection;  
  18. this.base.call(this,m_elements.length);  
  19.  
  20. this.add=function()  
  21. {  
  22. returnm_elements.push.apply(m_elements,arguments);  
  23. }  
  24. this.toArray=function()  
  25. {  
  26. returnm_elements;  
  27. }  
  28. }  
  29.  
  30. ArrayList.prototype.toString=function()  
  31. {  
  32. returnthis.toArray().toString();  
  33. }  
  34. //定義一個(gè)SortedList類型,它繼承ArrayList類型  
  35. functionSortedList()  
  36. {  
  37. //SortedList類型繼承ArrayList  
  38. this.base=ArrayList;  
  39. this.base.apply(this,arguments);  
  40.  
  41. this.sort=function()  
  42. {  
  43. vararr=this.toArray();  
  44. arr.sort.apply(arr,arguments);  
  45. }  
  46. }  
  47.  
  48. //構(gòu)造一個(gè)ArrayList  
  49. vara=newArrayList(1,2,3);  
  50. dwn(a);  
  51. dwn(a.size());//a從Collection繼承了size()方法  
  52. dwn(a.isEmpty);//但是a沒有繼承到isEmpty()方法  
  53.  
  54. //構(gòu)造一個(gè)SortedList  
  55. varb=newSortedList(3,1,2);  
  56. b.add(4,0);//b從ArrayList繼承了add()方法  
  57. dwn(b.toArray());//b從ArrayList繼承了toArray()方法  
  58. b.sort();//b自己實(shí)現(xiàn)的sort()方法  
  59. dwn(b.toArray());  
  60. dwn(b);  
  61. dwn(b.size());//b從Collection繼承了size()方法 

2,原型繼承法例子

 
 
 
  1. //定義一個(gè)Point類型  
  2. functionPoint(dimension)  
  3. {  
  4.  
  5. this.dimension=dimension;  
  6. }  
  7.  
  8. //定義一個(gè)Point2D類型,"繼承"Point類型  
  9. functionPoint2D(x,y)  
  10. {  
  11. this.x=x;  
  12. this.y=y;  
  13. }  
  14. Point2D.prototype.distance=function()  
  15. {  
  16. returnMath.sqrt(this.x*this.x+this.y*this.y);  
  17. }  
  18. Point2D.prototype=newPoint(2);//Point2D繼承了Point  
  19.  
  20. //定義一個(gè)Point3D類型,也繼承Point類型  
  21. functionPoint3D(x,y,z)  
  22. {  
  23. this.x=x;  
  24. this.y=y;  
  25. this.z=z;  
  26. }  
  27. Point3D.prototype=newPoint(3);//Point3D也繼承了Point  
  28.  
  29. //構(gòu)造一個(gè)Point2D對(duì)象  
  30. varp1=newPoint2D(0,0);  
  31. //構(gòu)造一個(gè)Point3D對(duì)象  
  32. varp2=newPoint3D(0,1,2);  
  33. dwn(p1.dimension);  
  34. dwn(p2.dimension);  
  35. dwn(p1instanceofPoint2D);//p1是一個(gè)Point2D  
  36. dwn(p1instanceofPoint);//p1也是一個(gè)Point  
  37. dwn(p2instanceofPoint);//p2是一個(gè)Point 

以上兩種方法是最常用。

3,實(shí)例繼承法例子

在說此法例子之前,說說構(gòu)造繼承法的局限,如下:

 
 
 
  1. functionMyDate()  
  2. {  
  3. this.base=Date;  
  4. this.base.apply(this,arguments);  
  5. }  
  6. vardate=newMyDate();  
  7. alert(date.toGMTString);//undefined,date并沒有繼承到Date類型,所以沒有toGMTString方法 

核心對(duì)象的某些方法不能被構(gòu)造繼承,原因是核心對(duì)象并不像我們自定義的一般對(duì)象那樣在構(gòu)造函數(shù)里進(jìn)行賦值或初始化操作換成原型繼承法呢?,如下:

 
 
 
  1. functionMyDate(){}  
  2. MyDate.prototype=newDate();  
  3. vardate=newMyDate();  
  4. alert(date.toGMTString);//'[object]'不是日期對(duì)象,仍然沒有繼承到Date類型! 

現(xiàn)在,換成實(shí)例繼承法:

 
 
 
  1. functionMyDate()  
  2. {  
  3. varinstance=newDate();//instance是一個(gè)新創(chuàng)建的日期對(duì)象  
  4. instance.printDate=function(){  
  5. document.write("

    "+instance.toLocaleString()+"

    ");  
  6. }//對(duì)instance擴(kuò)展printDate()方法  
  7. returninstance;//將instance作為構(gòu)造函數(shù)的返回值返回  
  8. }  
  9. varmyDate=newMyDate();  
  10. dwn(myDate.toGMTString());//這回成功輸出了正確的時(shí)間字符串,看來myDate已經(jīng)是一個(gè)Date的實(shí)例了,繼承成功  
  11. myDate.printDate();//如果沒有returninstance,將不能以下標(biāo)訪問,因?yàn)槭撬接袑?duì)象的方法 

4,拷貝繼承法例子

 
 
 
  1. Function.prototype.extends=function(obj)  
  2. {  
  3. for(vareachinobj)  
  4. {  
  5. this.prototype[each]=obj[each];  
  6. //對(duì)對(duì)象的屬性進(jìn)行一對(duì)一的復(fù)制,但是它又慢又容易引起問題  
  7. //所以這種“繼承”方式一般不推薦使用  
  8. }  
  9. }  
  10. varPoint2D=function(){  
  11. //……  
  12. }  
  13. Point2D.extends(newPoint())  
  14. {  
  15. //……  

這種繼承法似乎是用得很少的。

5,混合繼承例子

 
 
 
  1. functionPoint2D(x,y)  
  2. {  
  3. this.x=x;  
  4. this.y=y;  
  5. }  
  6. functionColorPoint2D(x,y,c)  
  7. {  
  8. Point2D.call(this,x,y);//這里是構(gòu)造繼承,調(diào)用了父類的構(gòu)造函數(shù)  
  9. //從前面的例子看過來,這里等價(jià)于  
  10. //this.base=Point2D;  
  11. //this.base.call(this,x,y);  
  12. this.color=c;  
  13. }  
  14. ColorPoint2D.prototype=newPoint2D();//這里用了原型繼承,讓ColorPoint2D以Point2D對(duì)象為原型 

【編輯推薦】

  1. 深入淺出JavaScript內(nèi)存泄漏
  2. 拔開云霧見明月 透析JavaScript定時(shí)機(jī)制
  3. 揭開JavaScript閉包的真實(shí)面目
  4. JavaScript中的函數(shù)式編程實(shí)踐
  5. 三大秘訣助你輕松搞定JavaScript

網(wǎng)頁(yè)題目:沒那么簡(jiǎn)單 那些應(yīng)該吃透的JavaScript概念
分享路徑:http://www.5511xx.com/article/dpodgdd.html