1. 程式人生 > >Javascript效能優化閱讀筆記

Javascript效能優化閱讀筆記

第一章 載入和執行

大多數瀏覽器都是用單一程序處理UI介面的重新整理和JavaScript的指令碼執行,所以同一時間只能做一件事,Javascript執行過程耗時越久,瀏覽器等待響應的時間就越長。

所以,HTML頁面在遇到

無阻塞的指令碼

儘管減少Javascript檔案的大小並限制HTTP請求次數僅僅只是第一步,下載單個較大的Javascript指令碼執行也許要鎖死大量的事件,所以無阻塞的指令碼的意義在於頁面載入完成之後再下載指令碼

延遲的指令碼

<script defer>
這是告知,延遲指令碼內的內容不會更改DOM,只有IE 4+和Firefox 3.5+瀏覽器支援。

defer意味著指令碼會先下載,但只有到DOM載入完成之前才會執行,不與頁面的其他資源衝突,可並行

動態指令碼元素

XMLHttpRequest指令碼注入

這種方法的優點是,可以下載Javascript程式碼但不立即執行,而且幾乎適用所有主流瀏覽器。

侷限性在於Javascript檔案必須與所請求的頁面處於相同的域,所以Javascript檔案不能從CDN下載。

推薦的無阻塞模式

向頁面中新增大量的JavaScript的推薦做法只需兩步:先新增動態載入所需要的程式碼,再載入初始化頁面所需要的程式碼。

前者程式碼精簡,執行很快。

<script type
="text/javascript">
function loadScript(url, callback) { var script = document.createElement("script"); script.type = "text/javascript"; if (script.readyState) { script.onreadstatechange = function() { if (script.readyState == "loaded" || script.readyState = "complete"
) { script.onreadystatechange = null; callback(); } } } else { script.onload = function() { callback() } } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); } loadScript("the-rest.js", function() { Application.init(); });
</script>

第二章 資料存取

資料的儲存位置不同,程式碼執行時的資料檢索速度也不同。

對於Javascript來說,有下面四種基礎的資料存取位置。

字面量
字面量只代表自身,不儲存在特定位置。JS中的字面量有:字串、數字、布林值、物件、陣列、函式、正則表示式,以及特殊的null和undefined值。

本地變數
開發人員使用關鍵字var定義的資料儲存單元。

陣列元素
儲存在JS陣列物件內部,以數字作為索引。

物件成員
儲存在JS物件內部,以字串作為索引。

管理作用域

作用域概念對於理解Javascript至關重要,不僅在效能方面,還在功能方面。

作用域鏈和標識解析

每個函式都是Function的例項,Function物件與其他物件一樣,擁有可以編寫的屬性以及,一系列只供JavaScript引擎儲存的內部屬性,其中一個是[[scope]]。

[[scope]]包含了一個函式被建立的作用域中物件的集合。

在函式執行過程中,每遇到一個變數,都會經歷一次識別符號解析過程以及從哪裡獲取儲存資料。如果當前執行環境(作用域頭)找不到該變數,就搜尋下一個作用域,如果都找不到則為undefined。

識別符號解析的效能

識別符號所在的位置越深,讀寫速度也就越慢。所以,讀取區域性變數時最快的,而讀取全域性變數時最慢的。

對此有個經驗法則:如果某個跨作用域的值在函式中被引用一次以上,那麼就把它儲存到區域性變數裡

改變作用域鏈

一般來說,一個執行環境的作用域鏈是不會改變的。但是,有兩個語句可以在執行時臨時改變作用域鏈。

一個是with語句,另一個是try-catch語句。

with(context),with語句有一個問題,那就是with()裡的引數作為作用域鏈頭後,函式的區域性變數都會變成第二個作用域鏈物件中,這樣每次訪問都得訪問兩次。

try-catch的catch子句也有這種效果,它把一個異常物件推到作用域鏈首部,但是子句執行完畢,作用域鏈就會返回之前的狀態。

動態作用域

with、try-catch和eval()都是動態作用域。

閉包、作用域和記憶體

閉包是JS最強大的特性之一,它允許函式訪問區域性作用於之外的資料。

通常執行環境一銷燬,活動物件也應該銷燬,但是因為閉包中,對活動物件的引用依舊存在,所以活動物件並不會被銷燬,因此也需要更高的記憶體開銷。

物件成員

原型

JS物件基於原型,例項屬性proto指向原型物件且只對開發者可見。

hasOwnProperty()區分原型屬性和例項屬性。

原型鏈

不多解釋。

巢狀成員

不太常見的寫法:window.location.href,巢狀成員會導致JS引擎搜尋所有物件成員。巢狀得越深,讀取速度就會越慢。

快取物件成員值

不多解釋

小結

在JS中,資料儲存的位置會對程式碼整體效能產生重大的影響。資料儲存有4種方法:字面量、變數、陣列項和物件成員。它們有著各自的效能特點。

  • 訪問字面量和區域性變數的速度最快,相反,訪問陣列元素和物件成員相對較慢。
  • 訪問區域性變數比訪問跨作用域變數更快。變數在作用域鏈中的位置越深,訪問時間越長。
  • 避免使用動態作用域鏈
  • 巢狀的物件成員會明顯影響效能,少用
  • 屬性或方法在原型鏈中位置越深,訪問速度越慢
  • 可把常用元素儲存在區域性變數中改善效能

第三章 DOM程式設計

首先必須先明確一點:用指令碼進行DOM操作的代價非常昂貴。

DOM相當於瀏覽器HTML文件,XML文件與JS的程式介面(API),與語言無關。所以DOM與JS之間的交流消耗費用也就越高。

DOM訪問與修改

通用的經驗法則:減少訪問DOM的次數,把運算儘量留在ECMAScript這端來處理。

innerHTML與DOM方法的對比

innerHTML非標準但是支援性良好,在老瀏覽器中innerHTML比DOM更加高效,但是innerHTML最好與陣列結合起來使用。這樣效率會更高。

節點克隆

element.cloneNode()方法克隆節點。

HTML集合

HTML集合是包含了DOM節點引用的類陣列物件。以下方法的返回值就是一個集合。

類陣列物件沒有push.slice等方法,但是有length屬性且可遍歷。

HTML集合與文件時刻保持連線,所以需要最新的訊息需要時刻查詢。

昂貴的集合

在迴圈語句中讀取陣列的length是不推薦的做法,最好是把陣列的長度儲存在一個區域性變數中。

訪問集合時使用區域性變數

第一優化原則是把集合儲存在區域性變數中,並把length快取在迴圈外部,然後用區域性變數替代這些需要多次讀取的元素。

舉個例子:

// 較慢
function collectionGlobal() {

    var coll = document.getElementsByTagName('div'),
    len = coll.length,
    name = '';

    for (var count = 0; count < len; count++) {
        name = document.getElementsByTagName('div')[count].nodeName;
        name = document.getElementsByTagName('div')[count].nodeType

    }
}

// 很快
function collectionGlobal() {

    var coll = document.getElementsByTagName('div'),
    len = coll.length,
    name = '',
    el = null;

    for (var count = 0; count < len; count++) {
        el = coll[count];
        name = el.nodeName;
        name = el.nodeType

    }
}

遍歷DOM

獲取DOM元素

通常你需要從某一個DOM元素開始,操作周圍的元素,或者遞迴查詢所有子節點。你可以使用childNodes得到元素集合,或者用nextSibling來獲取每個相鄰元素。

元素節點

DOM元素屬性諸如childNodes,firstChild和nextSibling並不區分元素節點和其他型別節點,如果要過濾的話,其實是不必要的DOM操作。

現在能區分元素節點和其他節點的DOM屬性如下:

屬性名 被替代的屬性
children childNodes
childElementCount childNodes.length
firstElementChild firstChild
lastElementChild lastChild
nextElementSibling nextSibling
previousElementSibling previousSibling

children屬性的支援率較高。

選擇器API

document.querySelectorAll(‘#menu a’);
document.querySelector(”) 選擇匹配的第一個節點

重繪與重排(Repaints and Reflows)

瀏覽器下載完頁面中的所有元件,之後會解析並生成兩個內部資料結構:

DOM樹
表示頁面結構

渲染樹
表示DOM節點如何顯示

DOM樹中所有需要顯示的節點在渲染樹中至少存在一個對應的節點(隱藏的DOM元素在渲染樹中沒有對應的節點)。

一旦DOM樹與渲染樹構建完成,瀏覽器就開始繪製頁面元素。

重排

當DOM的變化影響了元素的幾何屬性(寬和高)——比如改變邊框寬度或給段落增加文字,導致行數增加——瀏覽器需要重新計算元素的幾何屬性,同樣其他元素的集合屬性位置也會因此受到影響。瀏覽器會使渲染樹中受到影響的部分失效,並重新構造渲染樹,這個過程被稱為重排。

重繪

完成重排後,瀏覽器會重新繪製受影響的部分到螢幕中,這個過程被稱為重繪。有些樣式的改變,比如背景的變化不影響到佈局,所以只會重繪。

渲染樹變化的排隊和重新整理

由於每次重排都會產生計算消耗,大多數瀏覽器通過佇列化修改並批量執行來優化重排過程。然而,你可能會不自覺得強制重新整理佇列並要求計劃任務立刻執行。獲取佈局資訊的操作會導致列隊重新整理,比如:
- offsetTop,offsetLeft…
- scrollTop,scrollLeft…
- clientTop,clientLeft…
- getComputedStyle()
因為以上方法要求返回最新的佈局資訊,所以瀏覽器不得不把“待處理變化”觸發重排。

最小化重繪和重排

  • el.style.cssText = "";修改樣式資訊。
  • 修改css的class名稱 el.className = "";

批量修改DOM

當你需要對DOM元素進行一系列操作時,可以通過以下步驟來減少重繪和重排的次數:
1.使元素脫離文件流
2.對其應用多重改變
3.把元素帶回文件

有三種方法可以使DOM脫離文件:
- 隱藏元素,應用修改,重新顯示
- 使用文件片段在當前DOM之外構建一個子樹,再把它拷貝迴文檔
- 將原始元素拷貝到一個脫離文件的節點中,修改副本,完成後再替換原始元素

舉個例子:

<ul id="mylist">
    <li><a></a></li>
    <li><a></a></li>
    <li><a></a></li>
</ul>

// 假設要將更多的資料插入到這個列表中
var data = [
    {
        "name": "Nicholas",
        "url": "...."
    }
]

// 用來更新指定節點資料的通用函式
function appendDataToElement(appendToElement, data) {
    var a, li;
    for (var i = 0, max = data.length; i < max; i++) {
        a = document.createElement('a');
        a.href = data[i].url;
        a.appendChild(document.createTextNode(data[i].name));
        li = document.createElement('li');
        li.appendChild(a);
        appendToElement.appendChild(li);
    }
}

// 不考慮重排
var ul = document.getElementById('mylist');
appendDataToElement(ul, data);

// 第一種方法
var ul = document.getElementById('mylist');
ul.style.display = 'none';
appendDataToElement(ul, data);
ul.style.display = 'block';

// 第二種方法(推薦)
var fragment = document.createDocumentFragment();
appendDataToElement(fragment, data);
document.getElementById('mylist').appendChild(fragment);

// 第三種方法
var old = document.getElementById('mylist');
var clone = old.cloneNode(true);
appendDataToElement(clone, data);
old.parentNode.replaceChild(clone, old);

快取佈局資訊

對於需要操作佈局資訊的地方,最好用一個區域性變數來快取,不然查詢一次就會重新整理一次渲染佇列並應用所有變更。

讓元素脫離動畫流

一般而言動畫的展開與隱藏會影響大量元素的重排,使用一下步驟可以避免頁面中大部分重排。

  • 使用絕對位置定位頁面上的動畫元素,使其脫離文件流。
  • 讓元素動起來。當它擴大時,會臨時覆蓋部分頁面,但這只是頁面一個小區域的重繪。
  • 當動畫結束時恢復定位,從而只會下移一次文件的其他元素。

IE和:hover

儘量避免使用hover。

事件委託

繫結的事件越多,代價也越大,要麼加重了頁面負擔,要麼是增加了執行期的執行時間。
在父元素繫結個事件,利用冒泡。

小結

訪問和操作DOM是現代Web應用的重要部分。但每次穿越連線ECMAScript和DOM兩個島嶼之間的橋樑,都會被收取“過橋費”。
- 最小化DOM訪問次數,儘可能在JavaScript端處理。
- 如果需要多次訪問某個DOM節點,請使用區域性變數儲存它的引用。
- 小心處理HTML集合,因為它實時連線著底層文件。把集合的長度快取到一個變數中,並在迭代中使用它,如果需要經常操作集合,建議把它拷貝到一個數組中。
- 如果可能的話,使用速度更快的API
- 要留意重繪和重排,批量修改樣式時,“離線”操作DOM樹,使用快取,減少訪問佈局資訊的次數
- 動畫中使用絕對定位,使用拖放代理
- 使用事件委託來減少事件處理器的數量

第四章 演算法和流程控制

程式碼的數量不是影響程式碼執行速度的必然因素,程式碼的組織結構和解決具體問題的思路才是。

迴圈

大多數程式語言中,程式碼執行時間都消耗在迴圈中。

迴圈的型別

for迴圈
while迴圈
do-while迴圈
for-in迴圈

迴圈效能

不斷引發迴圈效能爭論的源頭是迴圈型別的選擇。在JS提供的四種迴圈型別中,只有for-in明顯比其他的慢。

優化迴圈的第一步就是減少物件成員和陣列項的查詢次數。比如把陣列長度賦值給一個區域性變數

第二步是顛倒陣列的順序,同樣可以提升迴圈效能。

第三步是減少迭代次數,達夫裝置。
達夫裝置實際上是把一次迭代操作展開成多次迭代操作。

思路是,每次迴圈中最多可呼叫8次process(),如果有餘數,則表示第一次process()執行幾次。

var iterations = Math.floor(items.length / 8),
    startAt = items.length % 8,
    i = 0;

do {
    switch(startAt) {
        case 0: process(items[i++]);
        ...
        ...
        case 8: process(items[i++]);
    }
    startAt = 0;
} while (--iterations);

達夫裝置對於1000次以上的迴圈有很大的提升。

基於函式的迭代

Array.forEach(function(value, index, array){
    process(value);
})

條件語句

if-else對比switch

條件數量少時用if-else,多時用switch。

優化if-else

目標:最小化到達正確分之前所需判斷的條件數量。

最簡單的優化方法是確保最可能出現的條件放在首位。

還有一種是增加if-else的巢狀,儘可能減少判斷次數。

查詢表

當有大量離散值需要測試時,或者條件語句數量很大時,JS可以通過陣列和普通物件來構建查詢表,速度要快得多。

switch(value) {
    case 0:
        return result0;
    case 1:
        return result1;
}

var results = [results0, results1]

return results[index]

遞迴

階乘就是用遞迴實現的,但是遞迴的問題在於終止條件不明確或缺少終止條件會導致函式長時間執行,而且可能會遇到瀏覽器的“呼叫棧大小限制”。

呼叫棧限制

瀏覽器有棧限制。

遞迴模式

有兩種遞迴模式。直接遞迴和隱伏模式。

迭代

任何遞迴能實現的演算法同樣可以用迭代來實現。

Memoization

把計算結果快取,執行前先判斷。

functiom memfactorial(n) {
    if (!memfactorial.cache) {
        memfactorial.cache = {
            "0": 1,
            "1": 1
        }
    }

    if (!memfactorial.cache.hasOwnProperty(n)) {
        memfactorial.cache[n] = n * memfactorial(n-1)
    }

    return memfactorial.cache[n];
}

小結

  • for/while/do-while迴圈效能特性相當,並沒有一種迴圈型別明顯快於或慢於其他型別。
  • 避免使用for-in迴圈,除非你需要遍歷一個屬性數量未知的物件
  • 改善迴圈效能的最佳方式是減少每次迭代的運算量和減少迴圈迭代次數。
  • 通常來說,switch總是比if-else快,但並不總是最佳決絕方案。
  • 再判斷條件較多時,使用查詢表比if-else和switch快
  • 瀏覽器的呼叫棧大小限制了遞迴演算法在JavaScript中的應用;棧溢位錯誤會導致其他程式碼中斷執行。
  • 如果你遇到棧溢位錯誤,可將方法改為迭代演算法,或使用Memoization來避免重複計算。

執行的程式碼量數量越大,使用這些策略所帶來的效能提升也就越明顯。

第六章 快速響應的使用者介面

瀏覽器UI執行緒

UI執行緒把一個個JS或者UI渲染任務放到佇列中逐個執行,最理想的情況就是佇列為空,這樣任務可以即刻執行。

瀏覽器限制

瀏覽器對JS任務的執行時間有限制,從棧大小限制和執行時間兩方面來限制。

多久才算“太久”

“如果JS運行了整整幾秒鐘,那麼很可能是你做錯了什麼….”
單個JS檔案的操作總時間不能超過100毫秒。

使用定時器讓出事件片段

如果100毫秒內不能解決JS任務,那麼就把執行緒讓出來執行UI渲染。

定時器基礎

setTimeout()和setInterval()會告訴JS引擎等待一段時間,然後新增一個JS任務到UI佇列。

定時器的精度

定時器不可用於測量實際時間,有幾毫秒的偏差。

使用定時器處理陣列

如果第四章的迴圈優化還是沒有將JS任務縮短到100毫秒以內,那麼下一步的優化步驟就是定時器。

分割任務

可以的話,將一個大任務分割成無數小任務。

記錄程式碼執行時間

不超過50毫秒的JS任務是非常好的使用者體驗,但是有時候一次性只執行一個任務,這樣執行效率反而不高。

定時器與效能

多個重複的定時器同時建立往往會出現效能問題。間隔在1s或者1s以上的重複定時器不會影響Web應用得響應速度。

Web Workers

Web Workers是HTML5最初的一部分,它的出現意味著JS任務可以單獨分離出去而不佔用瀏覽器的UI渲染。

Worker執行環境

Web Workers不能處理UI程序,這就意味著它不能接觸很多瀏覽器的資源。

Web Workers的執行環境由如下部分組成:
- navigator物件,包括appName、appVersion、user Agent和platform。
- 一個location物件,(與window.location同,但是隻讀)
- 一個self物件,指向全域性worker物件。
- 一個importScripts()方法,用來載入Worker所用到外部JS檔案
- 所有的ECMAScript物件
- XMLHttpRequest構造器
- setTimeout()和setInterval()方法
-一個close()方法,它能立刻停止Worker執行

var worker = new Worker("code.js")

與Worker通訊

Worker與網頁程式碼通過事件介面進行通訊,網頁程式碼通過postMessage()方法給Worker傳遞資料,它接收一個引數,即需要傳給Worker的資料。此外,Worker還有一個用來接收資訊的onmessage事件處理器。

var worker = new Worker('code.js')
worker.onmessage = function(event) {
    process(event.data)
}
worker.postMessage('data')

//code.js
self.onmessage = function(event) {
    self.postMessage("Hello" + event.data)
}

載入外部檔案

importScripts()阻塞

實際應用

var worker = new Worker("jsonparser.js");

worker.onmessage = function(event) {
    var jsonData = event.data
    evaluateData(jsonData)
}

worker.postMessage(jsonText)

self.onmessage = function(event) {
    var jsonText = event.data

    var jsonData = JSON.parse(jsonText)

    self.postMessage(jsonData)
}

小結

  • 任何JavaScript任務都不應當執行超過100毫秒,過長的執行時間會導致UI更新出現明顯的延遲,從而對使用者體驗產生負面影響。
  • 定時器可以用來安排程式碼延遲執行,把一個大任務分割成多個小任務,不影響UI渲染
  • Web Worker是新版瀏覽器支援的特性

第七章 Ajax

Ajax可以通過延遲和非同步載入大資源。

資料傳輸

Ajax從最基本的層面來說,是一種與伺服器通訊而無需過載頁面的方法,資料可以從伺服器獲取或傳送給伺服器。

請求資料

有五種常用技術用於向伺服器請求資料:
- XMLHttpRequest(XHR)
- Dynamic script tag insertion 動態指令碼注入
- iframes
- Comet
- Multipart XHR

XHR

var url = '/data.php';
var params = [
        'id=934875',
        'limit=20'
    ];

var req = new XMLHttpRequest();

req.onreadystatechange = function() {
    if (req.readystate === 4) {

    }
}

req.open('get', url + '?' + params.join('&'), true)

req.setRequestHeader('X-Requested-with', 'XMLHttpRequst');

req.send(null)

XHR的get請求是冪等行為,即一次請求和多次請求並不會有副作用。

動態指令碼注入
這個與XHR不同的地方在於它不用在意跨域問題。

var scriptElement = document.createElement('script');

scriptElement.src = '';

document.getElementsByTagName('head')[0].appendChild(scriptElement)

不能設定頭資訊,引數傳遞也只能用GET,不能設定請求的超時處理。

因為響應訊息作為指令碼標籤的原始碼,它必須是可執行的JS程式碼。

Multipart XHR
MXHR允許客戶端只用一個HTTP請求就可以從服務端向客戶端傳送多個資源。它通過在服務端將資源打包成一個由雙方約定的字串分割的長字串併發送到客戶端,然後用JS程式碼處理這個長字串,並根據它的mime-type型別和傳入的其他“頭資訊”解析出每個資源。

傳送資料

資料格式

唯一需要比較的標準就是速度。

XML

需要解析結構,才能讀取值。

JSON

JSON-P JSON填充,在動態指令碼注入時必須放在回撥函式裡,不然就會被當做另外一個JS檔案執行(所以也要尤其注意指令碼攻擊。)

HTML

Ajax效能指南

快取資料

最快的Ajax請求就是沒有請求。有兩種主要的方法可以避免傳送不必要的請求:
- 在服務端,設定HTTP頭資訊以確保響應會被瀏覽器快取
- 在客戶端,把獲取到的資訊儲存到本地,從而避免再次請求。

設定HTTP頭資訊
如果你希望Ajax響應能夠被瀏覽器快取,那麼你必須使用GET方式發出請求。但這還不夠,你還必須在相應中傳送正確的HTTP頭資訊。

Expires頭資訊會告訴瀏覽器應該快取響應多久,它的值是一個日期,過期之後,對該URL的任何請求都不再從快取中獲取,而是會重新訪問伺服器。

本地資料儲存
可以把響應文字儲存到一個物件中,以URL為鍵值做索引。

var localCache = {};

function xhrRequest(url, callback) {

    // 檢查此URL的本地快取
    if (localCache[url]) {
        callback.success(localCache[url]);
        return;
    }

    // 此URL對應的快取沒有找到,則傳送請求
    var req = createXhrObject();
    req.onerror = function() {
        callback.error();
    }
    req.onreadystatechange = function() {
        ...
        localCache[url] = req.responseText;
        callback.success(req.responseText)
    }

    req.open("GET", url, true)
    req.send(null)
}

瞭解Ajax類庫的侷限

瀏覽器之間有些差異,不過大多數類庫都有封裝。

小結

  • 減少請求數,可通過合併JavaScript和CSS檔案,或使用MXHR
  • 縮短頁面的載入時間,頁面主要內容載入完成後,用Ajax獲取次要檔案
  • 程式碼錯誤不會輸出給使用者
  • 知道何時使用類庫,何時編寫自己的底層Ajax程式碼

第八章 程式設計實踐

避免雙重求值(Double Evaluation)

JS和其他很多指令碼語言一樣,允許你在程式中提取一個包含程式碼的字串,然後動態執行。

有四種標準方法可以實現:eval(),Function(),setTimeout(),setInterval()。

在JS程式碼中執行另外一段JS程式碼就會造成雙重求值,所以eval和Function不推薦使用,setTimeout和setInterval的第一個引數最好是回撥函式。

使用Object/Array 直接量

使用直接量建立Object/Array

避免重複工作

延遲載入

當一個函式在頁面中不會被立即呼叫時,延遲載入時最好的選擇,即如果需要針對不同的瀏覽器寫不同的程式碼,在第一次就判斷用的是哪種,然後在內部重寫函式。

條件預載入

var addHandler = document.body.addEventListener ? function1 : function2

使用速度快的部分

位操作

原生方法

小結

  • 通過避免使用eval()和Function()構造器來避免雙重求值帶來的效能消耗。同樣的,給setTimeout()和setInterval()傳遞函式而不是字串作為引數。
  • 儘量使用直接量建立物件和陣列
  • 避免做重複的工作。當需要檢測瀏覽器時,可以使用延遲載入或條件預載入。
  • 進行數學計算時,考慮使用直接運算元字的二進位制形式的位運算。
  • 儘量使用原生方法

相關推薦

Javascript效能優化閱讀筆記

第一章 載入和執行 大多數瀏覽器都是用單一程序處理UI介面的重新整理和JavaScript的指令碼執行,所以同一時間只能做一件事,Javascript執行過程耗時越久,瀏覽器等待響應的時間就越長。 所以,HTML頁面在遇到 無阻塞的指令碼 儘管減少Jav

Javascript權威指南閱讀筆記--第3章類型、值和變量(1)

分享圖片 自動 局部變量 清理 ace defined define 原型 未在   之前一直有個想法,好好讀完JS權威指南,便於自己對於JS有個較為全面的了解。畢竟本人非計算機專業出生,雖然做著相關行業的工作,但總覺得對於基礎的掌握並沒有相關專業學者紮實,正好因為辭職待業

效能優化相關筆記摘要

前言 新的專案中,碰到一片從前很少接觸過的效能調優的區域,學習了以下內容,做此摘要和記錄。 本文的思路先講下系統性能的定義和測試,之後講如何定位效能瓶頸以及如何優化的方法。 一、系統性能定義 總體來說,系統性能就是兩個事: Throughput ,吞吐量。也就是每秒鐘可以處

JavaScript效能優化方案(事件委託詳解)

事件處理程式過多導致效能下降 在 JavaScript 中,新增到頁面上的事件處理程式數量會直接關係到頁面的整體執行效能。導致這一問題的原因是多方面的。首先,每個函式都是物件,都會佔用記憶體;記憶體中物件越多,效能就越差。其次,必須事先指定所有事件處理程式所造成的 DOM 訪問次數,也會

JavaScript 效能優化的小知識總結

前言 原創地址 一直在學習 javascript,也有看過《犀利開發 Jquery 核心詳解與實踐》,對這本書的評價只有兩個字犀利,可能是對 javascript 理解的還不夠透徹異或是自己太笨,更多的是自己不擅於思考懶得思考以至於裡面說的一些精髓都沒有太深入的理

JavaScript 效能優化技巧分享

JavaScript 作為當前最為常見的直譯式指令碼語言,已經廣泛應用於 Web 應用開發中。為了提高Web應用的效能,從 JavaScript 的效能優化方向入手,會是一個很好的選擇。 本文從載入、上下文、解析、編譯、執行和捆綁等多個方面來講解 JavaScript 的效能優化技巧,以便讓更多的前端開發人

Java程式效能優化 讀書筆記(六)設計模式:觀察者模式

一、觀察者模式 觀察者模式定義了物件間的一種一對多依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並被自動更新。它將觀察者和被觀察者的物件分離開。提高了應用程式的可維護性和重用性。觀察者模式又稱為釋出/訂閱(Publish/Subscribe)模式。 觀

java程式效能優化讀書筆記-垃圾回收

衡量系統性能的點 執行速度:即響應時間 記憶體分配:記憶體分配是否合理,是否過多消耗記憶體或者存在記憶體洩露 啟動時間:程式從啟動到正常處理業務需要的時間 負載承受能力:當系統壓力上升,系統執行速度和響應時間上升曲線是否平緩 系統調優層次 系統設計調優 程式碼調優

JavaScript效能優化之搖樹

作者|Jeremy Wagner譯者|薛命燈 現代 Web 應用程式可能會變得非常巨大,特別是它們的 JavaScript 部分。HTTP Archive 網站的資料顯示,截至 2018 年中,傳輸到移動裝置上的 JavaScript 檔案中值大約為 350 KB。而這只是傳輸大小,JavaScript 在

Sql server 2008查詢效能優化學習筆記

一、在調整過程中,必須檢查各種可能影響基於Sqlserver的應用程式效能的硬體和軟體因素。你應該在效能分析中問自己以下的問題: 1.相同伺服器上有沒有執行其他的資源密集型應用? 2.硬體子系統是否能承受最大的工作負荷? 3.Sql server 是否被正確配置? 4.Sq

《嵌入式Linux記憶體使用與效能優化筆記

這本書有兩個關切點:系統記憶體(使用者層)和效能優化。 這本書和Brendan Gregg的《Systems Performance》相比,無論是技術層次還是更高的理論都有較大差距。但是這不影響,快速花點時間簡單過一遍。 然後在對《Systems Performance》進行詳細的學習。 由於Ubuntu測

JavaScript效能優化小竅門彙總(含例項)

在眾多語言中,JavaScript已經佔有重要的一席之地,利用JavaScript我們可以做很多事情 , 應用廣泛。在web應用專案中,需要大量JavaScript的程式碼,將來也會越來越多。但是由於JavaScript是一個作為解釋執行的語言,而且它的單

前端效能優化---讀書筆記

1.減少HTTP請求 一個正常HTTP請求的流程簡述:如在瀏覽器中輸入”www.xxxxxx.com”並按下回車,瀏覽器再與這個URL指向的伺服器建立連線,然後瀏覽器才能向伺服器傳送請求資訊,伺服器在接受到請求的資訊後再返回相應的資訊,瀏覽器接收到來自伺服

javascript效能優化

迴圈 迴圈是很常用的一個控制結構,大部分東西要依靠它來完成,在JavaScript中,我們可以使用for(;;),while(),for(in) 三種迴圈,事實上,這三種迴圈中for(in)的效率極差,因為他需要查詢雜湊鍵,只要可以就應該儘量少用。for(;;)和whil

《Java程式效能優化 讓你的Java程式更快、更穩定》閱讀筆記

一.Linux中常用的監控CPU整體效能的工具有: § mpstat: mpstat 不但能檢視所有CPU的平均資訊,還能檢視指定CPU的資訊。                mpstat [-P {|ALL}] [internal [count]]  -P {|AL

js效能優化問題學習筆記

一:載入和執行 因為JavaScript是單執行緒的,具有阻塞性。當html頁面解析時,如果遇到<script>,那麼就會停止頁面的下載和解析過程,先將js指令碼執行完成,再開始下載,解析。注意:瀏覽器在遇到<body>標籤之前是不會渲染頁面的任何部分的。 1、將<scrip

JavaScript基礎概念之----效能優化

一、載入與執行 body閉合標籤之前,將所有的script標籤放到頁面的底部,能確保在指令碼執行前頁面已經完成渲染 合併指令碼,頁面中script標籤越少,載入越快,響應也更迅速 使用多種無阻塞下載Javascript方法: 使用script標籤的defer屬性

JAVA筆記 —— JVM 效能優化

JVM 引數檢視 java四類八種基本資料型別 第一類:整型 byte short int long 第二類:浮點型 float double 第三類:邏輯型 boolean(它只有兩個值可取true false) 第四類:字元型 char 在棧中可以直接分配記憶體的資料是基本資料型別。 引

Android學習筆記效能優化SparseArray

學習內容: 1.Android中SparseArray的使用..     昨天研究完橫向二級選單,發現其中使用了SparseArray去替換HashMap的使用.於是乎自己查了一些相關資料,自己同時對效能進行了一些測試。首先先說一下SparseArray的原理.

效能優化筆記

三方面:Android的渲染機制,記憶體與GC,電量優化。 渲染優化: UI達到60fps需要再16ms內完成繪製 工具:開啟手機裡的開發者選項,選擇Profile GPU Rendering,選中On screen as bars的選項。