Javascript深層原理探討(進階版本)_第1頁
Javascript深層原理探討(進階版本)_第2頁
Javascript深層原理探討(進階版本)_第3頁
已閱讀5頁,還剩15頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

PAGE120頁原始值和引用值在ECMAScript中,變量可以存放兩種類型的值,即原始值和引用值。原始值指的就是代表原始數(shù)據(jù)類型(基本數(shù)據(jù)類型)類型所表示的值。,等等棧和堆與原始值與引用值對應存在兩種結(jié)構(gòu)的內(nèi)存即棧和堆JavaScript中,引用值是存放在堆中的。變量r為基本數(shù)據(jù)類型,它們的值,直接存放在棧中r為復合數(shù)據(jù)類型,他們的引用變量存儲在棧中,指向,對象是一個復雜的結(jié)構(gòu),并且可以自由擴展,如:數(shù)組可以無限擴充,對象可以自由添加屬性。將他們棧中取得實際值的成本。所以簡單數(shù)據(jù)類型的值直接存放在棧中。NullUndefined的比較ECMAScriptUndefinedNullundefined和nullundefinednullECMAScript把它們定義為相等的。盡管這兩個值相等d是聲明了變量但未對其初始化時賦予該變量的值l則用于表示尚未存在的對象。dl代表沒有賦值的引用數(shù)據(jù)類型。null參與數(shù)值運算時其值會自動轉(zhuǎn)換為0,undefined參與任何數(shù)值計算時,其結(jié)果一定是NaN。,但是undefinedTypeof運算符無法區(qū)分這兩種值,var?undefined?)//codehere未定義(undefined)未初始化兩種情況的。PAGE220頁JavaScriptJavaScript全局觀JavaScript核心包括一下三部分:核心文檔對象模型和XML應用程序接口。關(guān)于ECMAScriptt是一種由歐洲計算機制造商協(xié)會)通過2標準化的腳本程序設計語言。ECMAScript的工作是定義語法和對象JavaScript實現(xiàn)了ActionScriptOpenViewScriptEase同樣也實現(xiàn)了ECMAScriptECMAScript、、Function等等。ECMA-262ECMAScriptWeb瀏覽器沒有依賴關(guān)系。其實上它就是一套定義了語法規(guī)則的接口,然后由不同的瀏覽器對其進行實現(xiàn),最后我們輸寫遵守語法規(guī)則的程序,完成應用開發(fā)需求。關(guān)于DOM文檔對象模型ttl定義了訪問和處理文檔的標準方法ML和L)可知由兩個部分組成:XMLDOMDOMCoreHTMLDOM。DOMCoreDOM(還包括屬性,注釋,文本之類)DOMCORE在解析文檔時,會將所有的元素、屬性、文本、注釋等等視為一個節(jié)點對象(象的對象多態(tài)、向上轉(zhuǎn)型"DOM樹"DOMHTML的核心概念是HTMLElement,DOMHTML會將文檔中的元素(這里的元素特指<body>這種tag,不包括注釋,屬性,文本)都視為HTMLElement。而元素的屬性,則為HTMLElement的屬性。DOMCoreDOMhtmlhtml文檔可以用DOMhtml進行操作,針對Xhtml可以用DOM。PAGE720DOM模型示例:關(guān)于BOMBOM解析:BOM是browserobjectmodel的縮寫,簡稱瀏覽器對象模型BOM提供了獨立于內(nèi)容而與瀏覽器窗口進行交互的對象由于BOMwindowBOMBOM模型示例:基本的數(shù)據(jù)類型"基本的數(shù)據(jù)類型"與"基本數(shù)據(jù)類型"的概念不一樣:1.2.(一

"基本的數(shù)據(jù)類型"指的是最常用的數(shù)據(jù)類型"基本數(shù)據(jù)類型"指的是原始類型(儲存在內(nèi)存中的方式)原始類型(簡單數(shù)據(jù)類型、基本數(shù)據(jù)類型)Undefined類型:表示聲明了變量但未對其初始化時賦予該變量的值undefined為Undefined類型下的唯一的一個值。NullNullnull。Boolean類型:有兩個值true主要用于條件判斷,控制執(zhí)行流程。Number類型:代表數(shù)字(32的整數(shù),也包括64位的浮點數(shù))String類型:用于代表字符串。(二)對象一個無序?qū)傩缘募?,這些屬性的值為簡單數(shù)據(jù)類型、對象或者函數(shù)。這里對象并不特指全局對(三)函數(shù)、、等內(nèi)部屬性。函數(shù)作為函數(shù)調(diào)用與構(gòu)造器(使用new關(guān)鍵字創(chuàng)建實例對象)的處理機制不一樣(Function對象除外)。內(nèi)部方法[[Construct]]用于實現(xiàn)作為構(gòu)造器的邏輯,方法[[Call]]實現(xiàn)作為函數(shù)調(diào)用的邏輯。這里的函數(shù)并不特指全局對象Function。內(nèi)置數(shù)據(jù)類型(內(nèi)置對象)Function:函數(shù)類型的用戶接口。Object:對象類型的用戶接口。BooleanNumberString分別為這三種簡單數(shù)值類型的對象包裝器,對象包裝在概念上有點類C#/Java。,ArrayRegExp:可以把它們看作是幾種內(nèi)置的擴展數(shù)據(jù)類型。注:它們JavaScript是暴露給開發(fā)者對這些內(nèi)置數(shù)據(jù)類型進行操作的接口后面隱藏了具體的實現(xiàn)機制。數(shù)據(jù)類型實現(xiàn)模型描述標準注解:Build-in***dataJS(提供,這些結(jié)構(gòu)我們基本上無法直接操作。Build-in***objectJSNumberStringBoolean等這些對象,這是JS將內(nèi)部實現(xiàn)的數(shù)據(jù)類型暴露給開發(fā)者使用的接口。Build-in***:JS內(nèi)置的一些構(gòu)造器,用來構(gòu)造相應類型的對象實例。它們被包裝成函數(shù)對象暴露出來可理解:datastructure:存儲在內(nèi)存中的數(shù)據(jù)object:對于存儲在內(nèi)存中的數(shù)據(jù)的一種包裝(也存放在內(nèi)存中),提供各種接口以供程序語言對存儲在內(nèi)存中的數(shù)據(jù)進行操作。constructor:將存儲在內(nèi)存中的數(shù)據(jù)包裝的方法。關(guān)于簡單數(shù)據(jù)類型的對象化一個細微的地方,下面描述對于Boolean,String和Number這三種簡單數(shù)值類型都適用,以Number為例說明。JS規(guī)范要求:var這樣的代碼,直接返回基本數(shù)據(jù)類型,就是說返回的對象不是派生NumberObjectnum1instanceofObjectnew關(guān)鍵字創(chuàng)建則返回Number類型,例如varnum2=newNumber(123)num2instanceofNumber。Number當作函數(shù)調(diào)用,返回結(jié)果會轉(zhuǎn)換成簡單數(shù)值類型。示例代碼:varnum1=newNumber(123);num1instanceofNumber//result:truenum1instanceofObject//result:truenum1=Number(num1);num1instanceofNumber//result:falsenum1instanceofObject//result:falsevarnum2=123;num2instanceofNumber//result:falsenum2instanceofObject//result:false結(jié)論:雖然我們得到了一個簡單數(shù)值類型,但它看起來仍然是一JSObject對象,具有Object以及相應類型的所有屬性和方法,使用上基本沒有差別,唯一不同之處是instanceof的測試結(jié)果。由此也就產(chǎn)生了一個概念"LiteralSyntax"LiteralSyntax-字面量定義方法可以理解為在定義一個變量的同時初始化賦值。1、簡單數(shù)據(jù)類型:i=100;//vari=newNumber(100);布爾值:varb=true;//替代varb=newBoolean(true);字符:varstr='thisisastring.';//替代varstr=newString('thisisastring');2、復合數(shù)據(jù)類型數(shù)組:vararr=['笨蛋的座右銘',25]obj={name:',age:25}reg/\d+/;Json:varobj={name:測試,age:25,Type:25,c1c2c3c4getname:function(){//code}原型繼承原理什么是prototype?JavaScript中對象的在JavaScript中,另外一種重要的抽象關(guān)系是類。這種關(guān)系是一種更高層次的抽象關(guān)系,它恰好和類型與實例的抽象關(guān)系構(gòu)成了一個三層的鏈。實例、類型、原型實例://Animal對象類型functionAnimal(name){=name;}//Animal對象原型對象={id:"Animal",sleep:function(){alert("sleep");}}//Animal實例Vardog=newAnimal();其對應的簡易內(nèi)存分配結(jié)構(gòu)圖:PAGE820頁prototype與[[prototype]][[prototype]]與prototype與[[prototype]]prototype屬性,它代表了對象的原型)所創(chuàng)建出來對象原型。屬性指向于它所對應的原型對象,由此便構(gòu)成了一種鏈表的結(jié)構(gòu),這就是原型鏈的概念。JavaScript對象應當都通過鏈關(guān)聯(lián)起來,最頂層是Object類型。鏈的根為的內(nèi)部屬性為null.constructor實現(xiàn)原理constructor指的就是對象的構(gòu)造函數(shù)。在JavaScript的屬性,用于引用原型對象。此原型對象又有名的屬性,它反過來引用函數(shù)本身。這是一種循環(huán)引用。constructor是Functionprototype鏈中的一個屬性。constructorconstructor屬性。示例代碼:functionAnimal(){}functionPerson(){}Ptotype=newAnimal();varperson=newPerson();alert(person.constructor);//AnimalPtotypenewprototype指向的是Animal的實例,所以personconstructor為Animal這個構(gòu)造函數(shù)。instanceof原理instanceof可以判斷一個對象是不是某個類或其子類的實例。instanceof檢測一個對象A是不是另一個對象BBA的鏈上。如果在,則返回如果不在則返回。不過有一個特殊的情況,當對象B的prototype為null將會報錯(類似于空指針異常)。PAGE1020頁函數(shù)對象的創(chuàng)建過程函數(shù)對象的創(chuàng)建過程函數(shù)就是對象,代表函數(shù)的對象就是函數(shù)對象。函數(shù)對象是由Function這個函數(shù)對象構(gòu)造出來的。Function對象本身也是一個函數(shù),因此它也一個函數(shù)對象。函數(shù)對象詳細創(chuàng)建步驟如下:創(chuàng)建一個build-inobjectfnfn屬性,處理函數(shù)調(diào)用的邏輯。屬性,它是內(nèi)部實現(xiàn)的一個方法,處理邏輯參考對象創(chuàng)建過程。fn.length0new同樣的邏輯創(chuàng)建一個ObjectfnProtofnPtotypefnProto116的區(qū)別為,步驟1Object(build-inobject、null或者內(nèi)部初始化值,即我們可以理解為不指向任何對對(、)。是一個Object鏈將指向。函數(shù)對象構(gòu)造過程的分析函數(shù)對象構(gòu)造過程的分析functionAnimal(){};和vardog=newAnimal();上述兩行簡單的語句的實際構(gòu)造過程可以等價于以下的代碼:functionAnimal(){};等價于:{Atotype={constructor:Animal};}vardog=newAnimal等價于:vardogvaro={};Animal.Animal.call(o);Returno;})();PAGE1120頁FunctionObject關(guān)系FunctionObjectFunctionObject關(guān)系橙色線為類的實例綠色線為類的prototype的實例黑色線為類的constructor的prototype的實例由上圖可以得出下列結(jié)論:FunctionObject各為自身的實例。ObjectFunction進行構(gòu)造的,而Function則由自己構(gòu)造自己。Function的原型對象是Object的實例。FuctionObject的總結(jié):Functionnn是最頂層的構(gòu)造器。它構(gòu)造了系統(tǒng)中所有的對象,包括用戶自定義對象,系統(tǒng)內(nèi)置對象,甚至包括它自已。這也表Function(的能力)。這也間接決定了Function的和邏輯相同。ObjectObjectObject構(gòu)造出來的。PAGE1420頁對象模型JavaScript的對象模型如下圖所示:(紅色虛線表示隱式Prototype鏈)總結(jié):圖中有好幾個地方提到build-in:指向系統(tǒng)內(nèi)置的函數(shù)構(gòu)造器nn);nn構(gòu)造。obj1,obj2...objn范指用類似這樣的代碼創(chuàng)建的對象:functionfn1(){}varobj1=newfn1();這些對象沒有本地constructor方法,但它們將從Prototypeconstructor方法,即本身了。obj1obj2...objnvarobj1=newvarvarobj1=newNumber(123);或obj1=/\w+/;等等。所以這些對象Prototype鏈的指向、從Prototype鏈繼承而來的constructor的值(指它們build-inNumberbuild-inObjectconstructor)等依賴于具體的對象類型。另外注意的是,varobj=new這樣創(chuàng)建的對象,它的類型仍然是鏈上獲得繼承的constructorbuild-inOtotype。所有函數(shù)的PrototypeFunction設計為具有自舉性。,鏈只有唯一的一個終結(jié)點。中可以訪問到。(userdefined,即它的隱式鏈指向Ototype,所以圖中就這樣表示了,但并不代表總是這樣,當用戶設置了自定義函數(shù)的prototype屬性之后,情況就不同了。屬性訪問原則使用pName訪問一個對象的屬性時,按照下面的步驟進行處(假設obj的內(nèi)屬性名proto ):如果objpropName屬性,返回屬性的值,否則如果obj. proto 為null,返回否則返回obj. proto .propName調(diào)用對象的方法跟訪問屬性搜索過程一樣,因為方法的函數(shù)對象就是對象的一個屬性值。提示:上面步驟中隱含了遞歸過程,步3中obj. proto 是另外一個對象,同樣將采1,2,3這樣的步驟來搜索propName屬性。這就是基于Prototype的繼承和共享的方法fn2來自概念上即object2重寫了object3的方法fn2。)本地屬性與繼承屬性e:propName設置為不能設值,則返回如果pName不存在,則為objpropNpName的值設為value也是一個普通對象,就是說它是一個普通的實例化的對象,而不是純粹抽象的數(shù)據(jù)結(jié)構(gòu)描述。所以就有了這個本地屬性與繼承屬性的問題。objobj共享屬性,還可能向其它對象共享屬性,修改它可能影響其它對象。執(zhí)行模型Javascript執(zhí)行模型指的是一段javascript腳本從載入瀏覽器到顯示執(zhí)行都經(jīng)過了哪些流程。Javascript執(zhí)行模型可簡要總結(jié)如下:step1.讀入第一個代碼段step2.做語法分析,有錯則報語法錯誤(比如括號不匹配等),step5step3.varfunction定義做預解析")step4.(調(diào)用函數(shù)、進入eval),有錯則報錯(比如變量未定義)step5.step2step6.結(jié)束執(zhí)行環(huán)境(ExecutionContext)JavaScriptJavaScript運行時作用域、生存期等方面的處理。JavaScript代碼分三種類型:GlobalCodejs文件、嵌入在HTML頁面中的js代碼等。EvalCode,即使用函數(shù)動態(tài)執(zhí)行的JS代碼。FunctionCodeJS代碼。JavaScript代碼具有不同的Execution。JSJavaScript函數(shù)時,該函數(shù)就會進入相應的執(zhí)行環(huán)境。如果又調(diào)用了另外一個函數(shù)(或者遞歸地調(diào)用同一個函數(shù)),JavaScript代碼就構(gòu)成了一個執(zhí)行環(huán)境棧。VariableObject的對象。針對于函數(shù)執(zhí)行環(huán)境,函數(shù)對應的每一個參數(shù)、局部變量、內(nèi)部方法都會在VariableObject上創(chuàng)建一個屬性,屬性名為變量名,屬性值為變量值。針對于全局執(zhí)行環(huán)境,具有相同的行為。但是要強調(diào)的VaribleObjectGlobalObject,可以簡單的理解為window對象。全局執(zhí)行環(huán)境JSJavaScriptScopeChain代碼的、常規(guī)的頂級函數(shù)聲明。而且,在變量實例化過程中全局對象就是可變對象,這就是為什么全局性聲明的函數(shù)是全局對象屬性的原因。全局性聲明的變量同樣如此全局執(zhí)行環(huán)境會使用this對象來引用全局對象。PAGE1520頁Eval執(zhí)行環(huán)境構(gòu)建Eval(Variable就是調(diào)用eval(Variable。在全局執(zhí)行環(huán)境中調(diào)用eval(Variable(Variable就是函數(shù)的活動對象(ActivationEval執(zhí)行環(huán)境eval調(diào)用中可以訪問函數(shù)fn的參數(shù)、局部變量;在evalfnVaribleObject是同一個對象。進入EvalCode執(zhí)行時會創(chuàng)建一個新的ScopeChain,內(nèi)容與當前執(zhí)行上下文的ScopeChain完全一樣。函數(shù)執(zhí)行環(huán)境在創(chuàng)建執(zhí)行環(huán)境的過程中,會按照定義的先后順序完成一系列操:'(Activation。活動對象是規(guī)范中規(guī)定的另外一種機制JavaScript代碼直接引用活動對象。著h和e“arguments的屬性,該屬性引對象。接著,為執(zhí)行環(huán)境分配作用域。作用域由對象列表(鏈)組成。ECMA262'''(Variable的過程。此時會將函數(shù)的形式參數(shù)創(chuàng)建為可變對象的命名屬性,如果調(diào)用函數(shù)時傳遞的參數(shù)與形式參數(shù)一致,則將相應參數(shù)的值賦給這些命名屬性(ndefined值)'undefined值.this(thiswindow)關(guān)于作用域和作用域鏈在訪問變量時,就必須存在一個可見性的問題,這就是作用域)。更深入的說,當訪問一個變量或調(diào)用一個函數(shù)時t引擎將不同執(zhí)行位置上的VariableObject按照規(guī)則構(gòu)建一個鏈表,在訪問一個變量時,先在鏈表的第一VariableObject上查找,如果沒有找到則繼續(xù)在第二個et上查找,直到搜索結(jié)束。這也就形成了作用域鏈e)的概念。ScopeChain/VariableObject/ActivationVariableObject也叫做n因為有一些差異存在,所以規(guī)范中重新取一個名字以示區(qū)別lle中叫e,tionCode中就叫做ActivationObject)ActivationObjectarguments對象并設置為ntennt并不是內(nèi)存釋放,。PAGE1820頁執(zhí)行環(huán)境棧和作用域鏈的關(guān)系示例:<scriptfunctionFn1(){functionFn2(){alert(document.body.tagName);//BODY//othercode...}Fn2();}</script>this關(guān)鍵字處理GlobalCodethis關(guān)鍵字為Globalthisfn1thisEvalCodethisVariable。提供一個讓用戶自己指定thisapply:,,或者,,都是將1作為s關(guān)鍵字,調(diào)用執(zhí)行1函數(shù),后面的參數(shù)都作為函數(shù)11為l或l將作為s關(guān)鍵字的值1不是tyl方法必須一個一個參數(shù)的給。作用域分配與變量訪問規(guī)則在ECMAScriptunction構(gòu)造[[scope]]屬性,這個屬性也由對象列表(鏈)組成。這個內(nèi)部[[scope]]屬性引用的就是用域鏈上尋找變量的過程。示例代碼:<scriptfunctionouter(){vari=10;functioninner(){varj=100;alert(j);//100alert(i);//10alert(adf);}inner();}outer();</script>執(zhí)行過程如下:1.載入代碼,創(chuàng)建全局執(zhí)行環(huán)境,在可變對中添加outer此時作用域鏈中只有window.2.outer變量,成功調(diào)用。創(chuàng)建,設置值為添加變量并將活動對象壓.并將函數(shù)對象的屬性指向活動對象。此時作用域鏈為outer+window.i時,會在函數(shù)對象的inner變量。找到后成功調(diào)用。innerinner的[[scope]]屬性指向活動對象inner.此時作用域鏈為:inner的活動對象+outer的活動對象+window.執(zhí)行代碼為j賦值,當訪問、jadf時,沒有在作用域中尋找到,訪問出錯。閉包原理ECMAScript允許使用內(nèi)部函數(shù)--即函數(shù)定義和函數(shù)表達式位于另一個函數(shù)的函數(shù)體內(nèi)。而且,這些內(nèi)部函數(shù)可以訪問它們所在的外部函這些局部變量、參數(shù)和函數(shù)聲明(最初時)的值是外部函數(shù)返回時的值,但也會受到內(nèi)部函數(shù)的影響。示例代碼:<scriptvarincrement=(function(){varid=0;returnfunction(){return++id;}})()alert(increment());//1alert(increment());//2</script>的語句時,按理說變量id在執(zhí)行完第一個語句后就應該銷毀了,JavaScriptidid的初始值是10。PAGE1920頁函數(shù)形式參數(shù)與arguments實例代碼:functionsay(msg,other,garbage){alert(arguments[1]);//worldvar='nicetomeetyou!';varmsg;alert(arguments.length);alert(msg);//helloalert(other);//nicetomeetyou!alert(arguments[1]);//nicetomeetyou!alert(garbage);//undefined}say('hello','world');簡單的內(nèi)存圖注:虛線表示的是曾經(jīng)引用的指向。Javascript函數(shù)有形式參數(shù)和實際參數(shù)。形式參數(shù)是定義方法時所明確指定的參數(shù)t語言的靈活性t不要求方法調(diào)用時。javascript實際調(diào)用時所傳遞的參數(shù)就是實際參數(shù)arguments指的就是實際參數(shù)。sayarguments.length的值為2,接著我們來看一下arguments會將所有的實際參數(shù)都當作對象來看待,對于基本數(shù)據(jù)類型的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論