入門(mén)就《JavaScript+DOM編程藝術(shù)》
網(wǎng)站建設(shè)哪家好,找成都創(chuàng)新互聯(lián)!專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、小程序設(shè)計(jì)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶(hù)創(chuàng)新互聯(lián)還提供了平利免費(fèi)建站歡迎大家使用!
這個(gè)階段處于對(duì)JS有基本認(rèn)識(shí),包括語(yǔ)法和數(shù)據(jù)類(lèi)型概念, 還包括JS的組成以及DOM的基本操作。
對(duì)JS有一定認(rèn)識(shí)和理解的時(shí)候就《JavaScript高級(jí)程序設(shè)計(jì)》
這個(gè)階段處于對(duì)JS的探索階段,要了解JS的各種性能、不同終端和解釋器的兼容性、以及原型鏈、封裝和繼承概念等。
對(duì)JS已經(jīng)有自己的理解和思想了就《JavaScript 權(quán)威指南》,可以把這本書(shū)當(dāng)JS字典用
這個(gè)階段就是突破階段了, 會(huì)形成自己的編碼風(fēng)格和思想,處于架構(gòu)層次的突破階段。
一、什么是閉包?\x0d\x0a“官方”的解釋是:所謂“閉包”,指的是一個(gè)擁有許多變量和綁定了這些變量的環(huán)境的表達(dá)式(通常是一個(gè)函數(shù)),因而這些變量也是該表達(dá)式的一部分。\x0d\x0a相信很少有人能直接看懂這句話(huà),因?yàn)樗枋龅奶珜W(xué)術(shù)。我想用如何在Javascript中創(chuàng)建一個(gè)閉包來(lái)告訴你什么是閉包,因?yàn)樘^(guò)閉包的創(chuàng)建過(guò)程直接理解閉包的定義是非常困難的。看下面這段代碼: \x0d\x0afunction a(){\x0d\x0a var i=0;\x0d\x0a function b(){\x0d\x0a alert(++i);\x0d\x0a }\x0d\x0a return b;\x0d\x0a}\x0d\x0avar c = a();\x0d\x0ac();\x0d\x0a這段代碼有兩個(gè)特點(diǎn):\x0d\x0a1、函數(shù)b嵌套在函數(shù)a內(nèi)部;\x0d\x0a2、函數(shù)a返回函數(shù)b。\x0d\x0a這樣在執(zhí)行完var c=a()后,變量c實(shí)際上是指向了函數(shù)b,再執(zhí)行c()后就會(huì)彈出一個(gè)窗口顯示i的值(第一次為1)。這段代碼其實(shí)就創(chuàng)建了一個(gè)閉包,為什么?因?yàn)楹瘮?shù)a外的變量c引用了函數(shù)a內(nèi)的函數(shù)b,就是說(shuō):\x0d\x0a\x0d\x0a當(dāng)函數(shù)a的內(nèi)部函數(shù)b被函數(shù)a外的一個(gè)變量引用的時(shí)候,就創(chuàng)建了一個(gè)閉包。\x0d\x0a\x0d\x0a我猜想你一定還是不理解閉包,因?yàn)槟悴恢篱]包有什么作用,下面讓我們繼續(xù)探索。\x0d\x0a\x0d\x0a二、閉包有什么作用?\x0d\x0a簡(jiǎn)而言之,閉包的作用就是在a執(zhí)行完并返回后,閉包使得Javascript的垃圾回收機(jī)制GC不會(huì)收回a所占用的資源,因?yàn)閍的內(nèi)部函數(shù)b的執(zhí)行需要依賴(lài)a中的變量。這是對(duì)閉包作用的非常直白的描述,不專(zhuān)業(yè)也不嚴(yán)謹(jǐn),但大概意思就是這樣,理解閉包需要循序漸進(jìn)的過(guò)程。\x0d\x0a在上面的例子中,由于閉包的存在使得函數(shù)a返回后,a中的i始終存在,這樣每次執(zhí)行c(),i都是自加1后alert出i的值。\x0d\x0a\x0d\x0a那 么我們來(lái)想象另一種情況,如果a返回的不是函數(shù)b,情況就完全不同了。因?yàn)閍執(zhí)行完后,b沒(méi)有被返回給a的外界,只是被a所引用,而此時(shí)a也只會(huì)被b引 用,因此函數(shù)a和b互相引用但又不被外界打擾(被外界引用),函數(shù)a和b就會(huì)被GC回收。(關(guān)于Javascript的垃圾回收機(jī)制將在后面詳細(xì)介紹)\x0d\x0a\x0d\x0a三、閉包內(nèi)的微觀世界\x0d\x0a如 果要更加深入的了解閉包以及函數(shù)a和嵌套函數(shù)b的關(guān)系,我們需要引入另外幾個(gè)概念:函數(shù)的執(zhí)行環(huán)境(excution context)、活動(dòng)對(duì)象(call object)、作用域(scope)、作用域鏈(scope chain)。以函數(shù)a從定義到執(zhí)行的過(guò)程為例闡述這幾個(gè)概念。\x0d\x0a\x0d\x0a1、當(dāng)定義函數(shù)a的時(shí)候,js解釋器會(huì)將函數(shù)a的作用域鏈(scope chain)設(shè)置為定義a時(shí)a所在的“環(huán)境”,如果a是一個(gè)全局函數(shù),則scope chain中只有window對(duì)象。\x0d\x0a2、當(dāng)函數(shù)a執(zhí)行的時(shí)候,a會(huì)進(jìn)入相應(yīng)的執(zhí)行環(huán)境(excution context)。\x0d\x0a3、在創(chuàng)建執(zhí)行環(huán)境的過(guò)程中,首先會(huì)為a添加一個(gè)scope屬性,即a的作用域,其值就為第1步中的scope chain。即a.scope=a的作用域鏈。\x0d\x0a4、然后執(zhí)行環(huán)境會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象(call object)?;顒?dòng)對(duì)象也是一個(gè)擁有屬性的對(duì)象,但它不具有原型而且不能通過(guò)JavaScript代碼直接訪問(wèn)。創(chuàng)建完活動(dòng)對(duì)象后,把活動(dòng)對(duì)象添加到a的作用域鏈的最頂端。此時(shí)a的作用域鏈包含了兩個(gè)對(duì)象:a的活動(dòng)對(duì)象和window對(duì)象。\x0d\x0a5、下一步是在活動(dòng)對(duì)象上添加一個(gè)arguments屬性,它保存著調(diào)用函數(shù)a時(shí)所傳遞的參數(shù)。\x0d\x0a6、最后把所有函數(shù)a的形參和內(nèi)部的函數(shù)b的引用也添加到a的活動(dòng)對(duì)象上。在這一步中,完成了函數(shù)b的的定義,因此如同第3步,函數(shù)b的作用域鏈被設(shè)置為b所被定義的環(huán)境,即a的作用域。\x0d\x0a\x0d\x0a到此,整個(gè)函數(shù)a從定義到執(zhí)行的步驟就完成了。此時(shí)a返回函數(shù)b的引用給c,又函數(shù)b的作用域鏈包含了對(duì)函數(shù)a的活動(dòng)對(duì)象的引用,也就是說(shuō)b可以訪問(wèn)到a中定義的所有變量和函數(shù)。函數(shù)b被c引用,函數(shù)b又依賴(lài)函數(shù)a,因此函數(shù)a在返回后不會(huì)被GC回收。\x0d\x0a\x0d\x0a當(dāng)函數(shù)b執(zhí)行的時(shí)候亦會(huì)像以上步驟一樣。因此,執(zhí)行時(shí)b的作用域鏈包含了3個(gè)對(duì)象:b的活動(dòng)對(duì)象、a的活動(dòng)對(duì)象和window對(duì)象,如下圖所示:\x0d\x0a\x0d\x0a如圖所示,當(dāng)在函數(shù)b中訪問(wèn)一個(gè)變量的時(shí)候,搜索順序是先搜索自身的活動(dòng)對(duì)象,如果存在則返回,如果不存在將繼續(xù)搜索函數(shù)a的活動(dòng)對(duì)象,依 次查找,直到找到為止。如果整個(gè)作用域鏈上都無(wú)法找到,則返回undefined。如果函數(shù)b存在prototype原型對(duì)象,則在查找完自身的活動(dòng)對(duì)象 后先查找自身的原型對(duì)象,再繼續(xù)查找。這就是Javascript中的變量查找機(jī)制。\x0d\x0a\x0d\x0a四、閉包的應(yīng)用場(chǎng)景\x0d\x0a1、保護(hù)函數(shù)內(nèi)的變量安全。以最開(kāi)始的例子為例,函數(shù)a中i只有函數(shù)b才能訪問(wèn),而無(wú)法通過(guò)其他途徑訪問(wèn)到,因此保護(hù)了i的安全性。\x0d\x0a2、在內(nèi)存中維持一個(gè)變量。依然如前例,由于閉包,函數(shù)a中i的一直存在于內(nèi)存中,因此每次執(zhí)行c(),都會(huì)給i自加1。\x0d\x0a以上兩點(diǎn)是閉包最基本的應(yīng)用場(chǎng)景,很多經(jīng)典案例都源于此。\x0d\x0a\x0d\x0a五、Javascript的垃圾回收機(jī)制\x0d\x0a在Javascript中,如果一個(gè)對(duì)象不再被引用,那么這個(gè)對(duì)象就會(huì)被GC回收。如果兩個(gè)對(duì)象互相引用,而不再被第3者所引用,那么這兩個(gè)互相引用的對(duì)象也會(huì)被回收。因?yàn)楹瘮?shù)a被b引用,b又被a外的c引用,這就是為什么函數(shù)a執(zhí)行后不會(huì)被回收的原因。
開(kāi)始切入正題之前,有必要告知大家一下,這篇文章可能有一些深度,初學(xué)者可能理解會(huì)有些吃力。我會(huì)盡量把復(fù)雜問(wèn)題簡(jiǎn)單化,爭(zhēng)取讓每個(gè)閱讀的童鞋們都能看得懂。希望你對(duì)element-ui,vue-router,KeepAlive組件有一點(diǎn)了解?,F(xiàn)在,我們開(kāi)始吧。
熟悉element-ui的童鞋們都知道,ElMenuItem和ElSubMenu都需要一個(gè)index屬性,該屬性必須是唯一的?,F(xiàn)在,我們想把路由配置直接應(yīng)用于ElMenu,該如何確保index的唯一性呢?我們需要有一個(gè)生成唯一index的函數(shù)。如下是genKey函數(shù)的定義,是不是很簡(jiǎn)單?
現(xiàn)在,我們創(chuàng)建addRouteMetaKey函數(shù),該函數(shù)對(duì)路由樹(shù)進(jìn)行遞歸遍歷,為每一個(gè)路由配置的meta屬性動(dòng)態(tài)添加key字段。這個(gè)函數(shù)很簡(jiǎn)單,屬于最基礎(chǔ)的遞歸使用例子,我就不做太多解釋了。
提示 :數(shù)組的forEach方法不是純函數(shù),因?yàn)樗懈弊饔?,所以forEach方法不能稱(chēng)之為函數(shù)式編程工具。
通過(guò)addRouteMetaKey函數(shù),我們可以把路由的meta.key作為index的值了。
現(xiàn)在,我們想實(shí)現(xiàn)另一個(gè)功能,就是 基于標(biāo)簽頁(yè)的路由組件緩存控制 。使用過(guò)Vuejs KeepAlive組件的童鞋們,應(yīng)該多多少少都遇到一些坑吧?在我們的項(xiàng)目中,有一個(gè)頂部標(biāo)簽頁(yè)導(dǎo)航,每個(gè)tab項(xiàng)對(duì)應(yīng)一個(gè)url,以每個(gè)url對(duì)應(yīng)路由的title作為tab項(xiàng)標(biāo)題,當(dāng)切換tab的時(shí)候加載緩存中的url對(duì)應(yīng)的路由組件,關(guān)閉tab項(xiàng),下次打開(kāi)該路由url,重新掛載對(duì)應(yīng)的路由組件,而不是從緩存中加載。
當(dāng)路由層級(jí)不確定的時(shí)候,KeepAlive會(huì)變的難以手動(dòng)控制。所以,我 劍走偏鋒,嘗試了一種簡(jiǎn)單的解決方案 ,實(shí)踐證明: 這是非常有效的 。我的方案就是把無(wú)限層級(jí)的路由樹(shù)轉(zhuǎn)化為一維數(shù)組。通過(guò)為meta添加必要的字段,進(jìn)行頁(yè)面結(jié)構(gòu)個(gè)性化定制。
我們需要把每層路由配置的path轉(zhuǎn)化為全路徑,所以需要一個(gè)函數(shù):getRouteFullPath,該函數(shù)定義如下:
getRouteFullPath函數(shù)中使用到的joinPath函數(shù)用于將多個(gè)路徑字符串拼接為1個(gè)完整的路徑,定義如下:
現(xiàn)在,我們把路由樹(shù)轉(zhuǎn)化為一維數(shù)組。我們定義toFlatRoutes函數(shù),該函數(shù)使用了數(shù)組的reduce方法對(duì)路由樹(shù)進(jìn)行聚合遞歸,將路由配置中的path屬性的值替換為全路徑,還順便給路由配置添加了name屬性,返回一個(gè)新的一維路由配置數(shù)組。 這是函數(shù)式編程和遞歸結(jié)合的一個(gè)例子。
以上,我們解決了KeepAlive的緩存控制問(wèn)題;現(xiàn)在,我們又有了一個(gè)新的用戶(hù)體驗(yàn)上的需求,就是我們想根據(jù)url對(duì)應(yīng)的路由,自動(dòng)展開(kāi)該路由meta.key所屬的側(cè)邊菜單;我們通過(guò)查閱element-ui文檔得知,ElMenu有一個(gè)open方法,接收index作為參數(shù),展開(kāi)index對(duì)應(yīng)的菜單。
現(xiàn)在的問(wèn)題是,我們的路由對(duì)應(yīng)的index是ElMenuItem的,而路由樹(shù)已經(jīng)被我們轉(zhuǎn)化為了一維數(shù)組,通過(guò)路由的matched字段是得不到我們想要的菜單index的。所以, 我們需要遍歷原始路由樹(shù) 。
如下代碼,我們定義getMenuKey函數(shù),該函數(shù)接收的參數(shù)為route對(duì)象。如果路由存在,我們進(jìn)行查找。首先進(jìn)行簡(jiǎn)單查找,如果找到一個(gè)菜單menu,則返回該菜單的meta.key;如果簡(jiǎn)單查找無(wú)果,則對(duì)路由樹(shù)進(jìn)行遞歸查找; 這是函數(shù)式編程和遞歸結(jié)合的另一個(gè)例子。
現(xiàn)在,我們大功告成了;以上就是本節(jié)的知識(shí)點(diǎn),童鞋們理解了嗎?只要我們熟悉遞歸的使用,其實(shí)操作樹(shù)很簡(jiǎn)單。如果大家還有不懂的,可以評(píng)論區(qū)問(wèn)我。感謝閱讀!
《深入理解JavaScript》AxelRauschmayer電子書(shū)網(wǎng)盤(pán)下載免費(fèi)在線(xiàn)閱讀
鏈接:
密碼:2mhi
書(shū)名:深入理解JavaScript
作者名:AxelRauschmayer
豆瓣評(píng)分:8.2
出版社:人民郵電出版社
出版年份:2015-12
頁(yè)數(shù):413
內(nèi)容介紹:
avaScript是目前Web開(kāi)發(fā)領(lǐng)域非常流行的一種編程語(yǔ)言,得到眾多IT從業(yè)人員和編程愛(ài)好者的關(guān)注。本書(shū)是一本全面、深入介紹JavaScript語(yǔ)言的學(xué)習(xí)指南。本書(shū)共分四個(gè)部分,第1部分幫助讀者快速入手,掌握基本的JavaScript編程要點(diǎn);第2部分介紹JavaScript的發(fā)展和技術(shù)背景;第3部分深入探索JavaScript,介紹了語(yǔ)法、值、運(yùn)算符、布爾類(lèi)型、數(shù)字、字符串、語(yǔ)句、異常捕獲、函數(shù)、變量、對(duì)象與繼承、數(shù)組、正則表達(dá)式、Date、Math、JSON、標(biāo)準(zhǔn)全局變量、編碼和JavaScript、ECMAScript 5的新特性等內(nèi)容;第4部分介紹技巧、工具和類(lèi)庫(kù),幫助讀者更好地運(yùn)用JavaScript進(jìn)行編程。本書(shū)內(nèi)容由淺入深,非常適合想要快速學(xué)習(xí)JavaScript編程或者深入鉆研JavaScript的讀者參考。
作者介紹:
Dr.Axel Rauschmayer 專(zhuān)攻JavaScript和Web開(kāi)發(fā)領(lǐng)域。他在2ality.com寫(xiě)博客,教Ecmanauten,編輯JavaScript Weekly周刊,組織MunichJS用戶(hù)組。Axel從1985年開(kāi)始編程,1995年開(kāi)始開(kāi)發(fā)web應(yīng)用。 ?
本文標(biāo)題:javascript探索,javascript search
分享網(wǎng)址:http://jinyejixie.com/article2/dssidoc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、網(wǎng)站設(shè)計(jì)公司、服務(wù)器托管、小程序開(kāi)發(fā)、響應(yīng)式網(wǎng)站、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)