javascript尚學堂百戰程序員-window對象1html bom_第1頁
javascript尚學堂百戰程序員-window對象1html bom_第2頁
javascript尚學堂百戰程序員-window對象1html bom_第3頁
javascript尚學堂百戰程序員-window對象1html bom_第4頁
javascript尚學堂百戰程序員-window對象1html bom_第5頁
免費預覽已結束,剩余26頁可下載查看

下載本文檔

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

文檔簡介

HTMLBOM2課程介紹課程大綱1.頁面加載優化和js文件解析順序2.瀏覽器性能優化:回流和重繪3.window.history對象4.函數的【道岔】:call和apply --以及對函數中this的影響5.閉包6.this總結1.頁面加載優化和js文件解析順序1.1defer1.2async1.3不添加任何屬性的js腳本 在介紹這一節課的內容之前,我們需要先了解一個概念,那就是什么事javascript引擎。

JavaScript引擎:由渲染引擎和javascript解釋器構成 渲染引擎: (1)解析代碼:HTML代碼解析為DOM樹

(2)對象的合成:CSS和DOM合成一棵渲染樹

(3)布局:計算出渲染樹的布局

(4)繪制:將渲染樹繪制到屏幕

(這四步并不一定嚴格按照順序來執行) Javascript解釋器:能夠將js代碼解釋成可以在網頁中實現的工具

1.1defer defer屬性:等待DOM加載完成后才去加載JS腳本

例:第一次彈窗:第二次彈窗:1.2async async屬性:DOM加載和js腳本加載異步執行,同時進行。

async優勢:避免了因DOM文件過大導致的【文件加載阻塞】 async缺陷:無法確定js腳本到底何時執行,并僅對外部js腳本生效

例: 按照我們關于async的說法,此時我們引入的兩個js外部腳本應該是和本地dom異步執行的。也就是說究竟彈窗先彈出哪一個alert都是不確定的。但是事實卻似乎并不是這樣:原因: HTML5規范要求 腳本執行應該按照腳本出現的先后順序執行結果: 腳本的實際執行卻總是按照腳本加載時出現的 順序執行的,每一次的結果都是如左面展示的 順序。1.3不添加任何屬性的js腳本 js腳本在不受任何外界因素影響的時候,實際上就是按照html代碼的加載順序執行的。因此【不添加任何屬性的js腳本】總是會在【引入腳本的節點】加載完畢之前執行。2.瀏覽器性能優化:回流和重繪2.1重繪(repaint)和回流(reflow)2.2引起重繪和回流的原因2.3如何從重繪和回流方面提高瀏覽器性能2.1重繪(repaint)和回流(reflow) 回流(reflow):當頁面中的部分或者全部元素改變寬度和高度、或者位置發生變化、刪除或者增加某個或者某些元素時、某個元素影藏或者顯示時,這時頁面的重新加載被稱為是回流。 重繪(repaint):當頁面的中的可見性發上變化時,我們說頁面發生了重繪。比如:背景顏色嗎,文字顏色等。 通過上述概念我們能得到一個結論:回流必將引起重繪,而重繪不一定引起回流。

ps:重繪的代價是高昂的,因為瀏覽器必須驗證DOM樹上其他節點元素的可見性。

ps:回流更是瀏覽器性能的關鍵因為其變化涉及到部分頁面(或是整個頁面)的布局。一個元素的回流導致了其所有子元素以及DOM中緊隨其后的祖先元素的隨后的回流。 在上面的HTML片段中,對該段落(<p>標簽)回流將會引發強烈的回流,因為它是一個子節點。這也導致了祖先的回流(div.error和body–視瀏覽器而定)。 此外,h5和ol也會有簡單的回流,因為其在DOM中在回流元素之后。在處理能力較低的設備上例如手機,大部分的回流將導致頁面的重新渲染。2.2引起重繪和回流的原因 或許有人會說:既然他們對于頁面的影響是這么的可怕,那么有哪些因素可能導致回流呢?我們記住,然后避免他們不就可以了么? 不幸的是,對于網頁中的很多操作都可能會引發回流,其中甚至包括了一些對css的操作。 例如: 調整窗口大小(Resizingthewindow) 改變字體(Changingthefont) 增加或者移除樣式表(Addingorremovingastylesheet) 內容變化,比如用戶在input框中輸入文字(Contentchanges,suchasausertypingtextinaninputbox) 激活CSS偽類,比如:hover

(IE中為兄弟結點偽類的激活)(ActivationofCSSpseudoclassessuchas:hover(inIEtheactivationofthepseudoclassofasibling)) 操作class屬性(Manipulatingtheclassattribute) 腳本操作DOM(AscriptmanipulatingtheDOM) 計算offsetWidth和offsetHeight屬性(CalculatingoffsetWidthandoffsetHeight) 設置style屬性的值(Settingapropertyofthestyleattribute)2.3如何從重繪和回流方面提高瀏覽器性能1.不要一項一項的去改變樣式,盡可能一口氣寫完。(可以寫在一起,不要被打斷就行)最好使用.style或者.style.cssText2.讀寫DOM也盡量也放在一起3.使用文檔碎片varlinshi=document.createDocumentFragment();4.使用fixed或者absolute可以減少回流和重繪5.使用

window.requestAnimationFrame(function(){

for(vari=0;i<div.length;i++){

div[i].style.background="red";

}

}) 把發生重繪的代碼推遲到下一次重繪發生時一起執行3.window.history對象 window.history對象表示整個瀏覽器的頁面棧對象。在對象中提供了一些屬性和方法來幫助更好的控制整個瀏覽器中頁面的訪問。 (1)window.history.back() 跳轉到棧中的上一個頁面 (2)window.history.forward() 跳轉到棧中的下一個頁面 (3)window.history.go(num) 跳轉到棧中的指定頁面 (4)window.history.length 棧中頁面的數量ps:通過window.history對象中提供的方法進行的頁面跳轉并不會向棧中添加新的頁面。 而通過window.location.href或者通過a標簽進行的跳轉,則會向棧中添加新的頁面。window.history棧對象第一個添加的頁面當前頁第三個添加的頁面window.history.forward()window.history.back()第四個添加的頁面第五個添加的頁面window.history.go(3)window.history.go(-1)window.history.length=54.函數的【道岔】:call和apply--以及對函數中this的影響什么是道岔? 火車在行進途中遇到路口后,決定火車應該向那個方向執行的裝置被稱為【道岔】

我們可以將函數類比為火車, 而今天介紹的call和apply就好比為控制火車行進方向的【道岔】

語法:

call: 函數.call(函數實際的調用者,函數參數1,函數參數2,...) apply: 函數.apply(函數實際的調用者,【函數參數1,函數參數2,...】) 他們所表達的含義是: 函數的實際調用者是call或者apply的第一個參數。 而后的參數是這個要執行的函數的參數。先來看一段很簡單的代碼:

varname='window' functionshow(){

console.log();

}

show();很顯然這段代碼的執行結果會在控制臺中打印一個window。但是為什么會得到這樣一個結果呢?再來看一段代碼:

varname='window';

functionshow(){

console.log();

}

varfrank={

name:'frank'

};

show.call(window);

show.call(frank);這段代碼又會在控制臺中輸出什么內容呢?varname='quanJuBianLiang';

varobj1={

name:'obj1Name',

getName:function(x,y){

console.log();

console.log(x);

console.log(y);

}

};

varobj2={name:'obj2Name'};

functiongetName(x,y){

console.log('------------一次輸出------------');

console.log('this:'+this);

console.log(':'+);

console.log('參數x:'+x)

console.log('參數y:'+y);

}getName.call(window,'call1','call2');

getName.call(obj2,'call3','call4');

getName.apply(obj1,['apply1','apply2']);

getName.apply(obj2,['apply3','apply4']);這段代碼在執行的時候又會得到怎樣的結果?通過以上幾段代碼,我們可以得到有關apply和call的一些結論: call函數結論:

(1)call函數能夠改變函數的實際調用者,也就是函數中this的指向。

(2)call函數中第一個參數必須寫,而其余參數可以不寫。

(3)call函數傳遞參數的時候,用逗號分隔每一個參數

apply函數結論:

(1)apply函數能夠改變函數的實際調用者,也就是函數中this的指向

(2)apply函數中第一個參數必須寫,而其余參數可以不寫

(3)apply函數傳遞參數的時候,參數采用數組方式傳遞小技巧

之前我們提到過,Math.max方法可以將參數中的最大值檢索出來,

但是缺點是參數必須一個一個寫,而不能直接傳遞一個數組作為方法的參數。

但是我們可以通過apply方法,將Math.max的實際執行者交給window對象。

然后參數直接給定一個數組。即可直接查找。 vararr=[1,23,2,43,54,6,57,65,76]; varmax=Math.max.apply(null,arr); console.log(max);

console.log(Math.max.apply(null,[1,23,2,43,54,6,57,65,76]));5.閉包5.1變量作用域5.2如何在函數外部讀取局部變量5.3閉包5.4閉包的用途5.5閉包注意事項5.6思考題5.1變量作用域 閉包在js中是一個非常使用的模塊,不過我們在學習閉包之前,需要先了解javascript的作用域方面的知識。 javascript中變量作用域只有兩種: 全局作用域 函數作用域(局部作用域)

javascript語言特殊之處就在于,在函數內部能夠直接讀取全局變量 varnum=999;

functionfunc(){ console.log(num); }

func();

//999那么反過來說,在函數外部自然無法讀取函數內的局部變量。

functionfunc(){

varnum=999;

}

console.log(num);

//error這里有一個地方需要注意,函數內部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量!5.2如何在函數外部讀取局部變量

出于很多原因,的確在很多時候需要在函數之外讀取函數內部的局部變量。 但是剛才也說過了,正常情況下js中是不允許這種訪問的。 所以我們需要一種變通的方法,來幫助我們在函數之外訪問函數內部的局部變量。 但是什么辦法能實現這個功能呢? 讓我們先把這個問題放在一邊,來看下面的一段代碼

functionfunc(){ num=999; functionfunc2(){

console.log(num);

}

} 在這段代碼中func中的所有局部變量對func2來說都是可見的,因為func2被包括在了func函數之內,但是反過來則不行。這就是js中獨有的【鏈式作用域(chainscope)】結構 既然剛才的代碼中func2可以讀取func中的局部變量,那么只要把func2作為返回值,不就可以在func外部讀取它的內部變量了么?

functionfunc(){

num=999;

functionfunc2(){

console.log(num);

}

returnfunc2;

}

varresult=func();

result();

看來似乎可以實現,實際運行來測試一下吧!

ps:在這里func2函數的函數名實際上并沒有什么用。5.3閉包

實際上上一節中我們所寫的func2就是一個閉包。我們把上一節課的代碼稍稍整理一下可以得到下列的代碼: functionfunc(){

num=999;

returnfunction(){console.log(num);}

}

func()();

在上述案例中,我們正是通過閉包將函數內部的局部變量傳遞到了函數外部。 所以在本質上,閉包就是將函數內部和函數外部連接起來的一座橋梁。5.4閉包的用途

閉包在js中可以使用在很多地方,但是閉包最常見的用途會使用在如下兩個方面:

(1)通過閉包,可以在函數外部讀取函數內局部變量的值 (2)讓局部變量始終生存在內存當中,避免被垃圾回收機制殺死 很顯然對于第一個用途我們剛剛已經說過了,但是對于第二個用途我們又應當如何理解呢? 請觀察下列代碼: functionfunc(){

varnum=999;

nAdd=function(){num+=1;}

returnfunction(){console.log(num);};

}

varresult=func();

result();

nAdd();

result();5.5閉包的注意事項

(1)由于閉包會使得函數中的變量都被保存在內存中,內存消耗很大。 所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。

解決方法是:在退出函數之前,將不使用的局部變量全部刪除。

(2)閉包會在父函數外部,改變父函數內部變量的值。 所以如果把父函數當作對象(object) 那么閉包就好比是對象的公用方法(PublicMethod) 而內部變量則就是對象的私有屬性(privatevalue) 這時一定要小心,不要隨便改變父函數內部變量的值。

(3)由于閉包的實際調用者都是window,因此所有閉包中的this均指向了window。 如果非要在函數中通過this來調用函數中的變量,則記得使用apply或者call變更閉

溫馨提示

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

評論

0/150

提交評論