成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

javascript性能優(yōu)化

WilsonLiu95 / 1305人閱讀

摘要:當(dāng)函數(shù)執(zhí)行完畢后,這個(gè)執(zhí)行上下文就會(huì)被銷(xiāo)毀。訪問(wèn)字面量和局部變量的速度最快,而訪問(wèn)數(shù)組元素和對(duì)象成員相對(duì)較慢。因此,由父節(jié)點(diǎn)來(lái)負(fù)責(zé)監(jiān)聽(tīng)和處理該事件。

本文主要是在我讀《高性能Javascript》之后,想要記錄下一些有用的優(yōu)化方案,并且就我本身的一些經(jīng)驗(yàn),來(lái)大家一起分享下,

Javascript的加載與執(zhí)行

大家都知道,瀏覽器在解析DOM樹(shù)的時(shí)候,當(dāng)解析到script標(biāo)簽的時(shí)候,會(huì)阻塞其他的所有任務(wù),直到該js文件下載、解析執(zhí)行完成后,才會(huì)繼續(xù)往下執(zhí)行。因此,這個(gè)時(shí)候?yàn)g覽器就會(huì)被阻塞在這里,如果將script標(biāo)簽放在head里的話,那么在該js文件加載執(zhí)行前,用戶(hù)只能看到空白的頁(yè)面,這樣的用戶(hù)體驗(yàn)肯定是特別爛。對(duì)此,常用的方法有以下:

將所有的script標(biāo)簽都放到body最底部,這樣可以保證js文件是最后加載并執(zhí)行的,可以先將頁(yè)面展現(xiàn)給用戶(hù)。但是,你首先得清楚,頁(yè)面的首屏渲染是否依賴(lài)于你的部分js文件,如果是的話,則需要將這一部分js文件放到head上。

使用defer,比如下面這種寫(xiě)法。使用defer這種寫(xiě)法時(shí),雖然瀏覽器解析到該標(biāo)簽的時(shí)候,也會(huì)下載對(duì)應(yīng)的js文件,不過(guò)它并不會(huì)馬上執(zhí)行,而是會(huì)等到DOM解析完后(DomContentLoader之前)才會(huì)執(zhí)行這些js文件。因此,就不會(huì)阻塞到瀏覽器。


動(dòng)態(tài)加載js文件,通過(guò)這種方式,可以在頁(yè)面加載完成后,再去加載所需要的代碼,也可以通過(guò)這種方式實(shí)現(xiàn)js文件懶加載/按需加載,比如現(xiàn)在比較常見(jiàn)的,就是webpack結(jié)合vue-router/react-router實(shí)現(xiàn)按需加載,只有訪問(wèn)到具體路由的時(shí)候,才加載相應(yīng)的代碼。具體的方法如下:

1.動(dòng)態(tài)的插入script標(biāo)簽來(lái)加載腳本,比如通過(guò)以下代碼

  function loadScript(url, callback) {
    const script = document.createElement("script");
    script.type = "text/javascript";
    // 處理IE
    if (script.readyState) {
      script.onreadystatechange = function () {
        if (script.readyState === "loaded" || script.readyState === "complete") {
          script.onreadystatechange = null;
          callback();
        }
      }
    } else {
      // 處理其他瀏覽器的情況
      script.onload = function () {
        callback();
      }
    }
    script.src = url;
    document.body.append(script);
  }

  // 動(dòng)態(tài)加載js
  loadScript("file.js", function () {
    console.log("加載完成");
  })

2.通過(guò)xhr方式加載js文件,不過(guò)通過(guò)這種方式的話,就可能會(huì)面臨著跨域的問(wèn)題。例子如下:

  const xhr = new XMLHttpRequest();
  xhr.open("get", "file.js");
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
        const script = document.createElement("script");
        script.type = "text/javascript";
        script.text = xhr.responseText;
        document.body.append(script);
      }
    }
  }

3.將多個(gè)js文件合并為同一個(gè),并且進(jìn)行壓縮。 原因:目前瀏覽器大多已經(jīng)支持并行下載js文件了,但是并發(fā)下載還是有一定的數(shù)量限制了(基于瀏覽器,一部分瀏覽器只能下載4個(gè)),并且,每一個(gè)js文件都需要建立一次額外的http連接,加載4個(gè)25KB的文件比起加載一個(gè)100KB的文件消耗的時(shí)間要大。因此,我們最好就是將多個(gè)js文件合并為同一個(gè),并且進(jìn)行代碼壓縮。

javascript作用域

當(dāng)一個(gè)函數(shù)執(zhí)行的時(shí)候,會(huì)生成一個(gè)執(zhí)行上下文,這個(gè)執(zhí)行上下文定義了函數(shù)執(zhí)行時(shí)的環(huán)境。當(dāng)函數(shù)執(zhí)行完畢后,這個(gè)執(zhí)行上下文就會(huì)被銷(xiāo)毀。因此,多次調(diào)用同一個(gè)函數(shù)會(huì)導(dǎo)致創(chuàng)建多個(gè)執(zhí)行上下文。每隔執(zhí)行上下文都有自己的作用域鏈。相信大家應(yīng)該早就知道了作用域這個(gè)東西,對(duì)于一個(gè)函數(shù)而言,其第一個(gè)作用域就是它函數(shù)內(nèi)部的變量。在函數(shù)執(zhí)行過(guò)程中,每遇到一個(gè)變量,都會(huì)搜索函數(shù)的作用域鏈找到第一個(gè)匹配的變量,首先查找函數(shù)內(nèi)部的變量,之后再沿著作用域鏈逐層尋找。因此,若我們要訪問(wèn)最外層的變量(全局變量),則相比直接訪問(wèn)內(nèi)部的變量而言,會(huì)帶來(lái)比較大的性能損耗。因此,我們可以將經(jīng)常使用的全局變量引用儲(chǔ)存在一個(gè)局部變量里。

const a = 5;
function outter () {
  const a = 2;
  function inner () {
    const b = 2;
    console.log(b); // 2
    console.log(a); // 2
  }
  inner();
}
對(duì)象的讀取

javascript中,主要分為字面量、局部變量、數(shù)組元素和對(duì)象這四種。訪問(wèn)字面量和局部變量的速度最快,而訪問(wèn)數(shù)組元素和對(duì)象成員相對(duì)較慢。而訪問(wèn)對(duì)象成員的時(shí)候,就和作用域鏈一樣,是在原型鏈(prototype)上進(jìn)行查找。因此,若查找的成員在原型鏈位置太深,則訪問(wèn)速度越慢。因此,我們應(yīng)該盡可能的減少對(duì)象成員的查找次數(shù)和嵌套深度。比如以下代碼

  // 進(jìn)行兩次對(duì)象成員查找
  function hasEitherClass(element, className1, className2) {
    return element.className === className1 || element.className === className2;
  }
  // 優(yōu)化,如果該變量不會(huì)改變,則可以使用局部變量保存查找的內(nèi)容
  function hasEitherClass(element, className1, className2) {
    const currentClassName = element.className;
    return currentClassName === className1 || currentClassName === className2;
  }
DOM操作優(yōu)化

最小化DOM的操作次數(shù),盡可能的用javascript來(lái)處理,并且盡可能的使用局部變量?jī)?chǔ)存DOM節(jié)點(diǎn)。比如以下的代碼:

  // 優(yōu)化前,在每次循環(huán)的時(shí)候,都要獲取id為t的節(jié)點(diǎn),并且設(shè)置它的innerHTML
  function innerHTMLLoop () {
    for (let count = 0; count < 15000; count++) {
      document.getElementById("t").innerHTML += "a";
    }
  }
  // 優(yōu)化后,
  function innerHTMLLoop () {
    const tNode = document.getElemenById("t");
    const insertHtml = "";
    for (let count = 0; count < 15000; count++) {
      insertHtml += "a";
    }
    tNode.innerHtml += insertHtml;
  }

盡可能的減少重排和重繪,重排和重匯可能會(huì)代價(jià)非常昂貴,因此,為了減少重排重匯的發(fā)生次數(shù),我們可以做以下的優(yōu)化

1.當(dāng)我們要對(duì)Dom的樣式進(jìn)行修改的時(shí)候,我們應(yīng)該盡可能的合并所有的修改并且一次處理,減少重排和重匯的次數(shù)。

  // 優(yōu)化前
  const el = document.getElementById("test");
  el.style.borderLeft = "1px";
  el.style.borderRight = "2px";
  el.style.padding = "5px";

  // 優(yōu)化后,一次性修改樣式,這樣可以將三次重排減少到一次重排
  const el = document.getElementById("test");
  el.style.cssText += "; border-left: 1px ;border-right: 2px; padding: 5px;"

2.當(dāng)我們要批量修改DOM節(jié)點(diǎn)的時(shí)候,我們可以將DOM節(jié)點(diǎn)隱藏掉,然后進(jìn)行一系列的修改操作,之后再將其設(shè)置為可見(jiàn),這樣就可以最多只進(jìn)行兩次重排。具體的方法如下:

  // 未優(yōu)化前
  const ele = document.getElementById("test");
  // 一系列dom修改操作

  // 優(yōu)化方案一,將要修改的節(jié)點(diǎn)設(shè)置為不顯示,之后對(duì)它進(jìn)行修改,修改完成后再顯示該節(jié)點(diǎn),從而只需要兩次重排
  const ele = document.getElementById("test");
  ele.style.display = "none";
  // 一系列dom修改操作
  ele.style.display = "block";

  // 優(yōu)化方案二,首先創(chuàng)建一個(gè)文檔片段(documentFragment),然后對(duì)該片段進(jìn)行修改,之后將文檔片段插入到文檔中,只有最后將文檔片段插入文檔的時(shí)候會(huì)引起重排,因此只會(huì)觸發(fā)一次重排。。
  const fragment = document.createDocumentFragment();
  const ele = document.getElementById("test");
  // 一系列dom修改操作
  ele.appendChild(fragment);

3.使用事件委托:事件委托就是將目標(biāo)節(jié)點(diǎn)的事件移到父節(jié)點(diǎn)來(lái)處理,由于瀏覽器冒泡的特點(diǎn),當(dāng)目標(biāo)節(jié)點(diǎn)觸發(fā)了該事件的時(shí)候,父節(jié)點(diǎn)也會(huì)觸發(fā)該事件。因此,由父節(jié)點(diǎn)來(lái)負(fù)責(zé)監(jiān)聽(tīng)和處理該事件。

那么,它的優(yōu)點(diǎn)在哪里呢?假設(shè)你有一個(gè)列表,里面每一個(gè)列表項(xiàng)都需要綁定相同的事件,而這個(gè)列表可能會(huì)頻繁的插入和刪除。如果按照平常的方法,你只能給每一個(gè)列表項(xiàng)都綁定一個(gè)事件處理器,并且,每當(dāng)插入新的列表項(xiàng)的時(shí)候,你也需要為新的列表項(xiàng)注冊(cè)新的事件處理器。這樣的話,如果列表項(xiàng)很大的話,就會(huì)導(dǎo)致有特別多的事件處理器,造成極大的性能問(wèn)題。而通過(guò)事件委托,我們只需要在列表項(xiàng)的父節(jié)點(diǎn)監(jiān)聽(tīng)這個(gè)事件,由它來(lái)統(tǒng)一處理就可以了。這樣,對(duì)于新增的列表項(xiàng)也不需要做額外的處理。而且事件委托的用法其實(shí)也很簡(jiǎn)單:

function handleClick(target) {
  // 點(diǎn)擊列表項(xiàng)的處理事件
}
function delegate (e) {
  // 判斷目標(biāo)對(duì)象是否為列表項(xiàng)
  if (e.target.nodeName === "LI") {
    handleClick(e.target);
  }
}
const parent = document.getElementById("parent");
parent.addEventListener("click", delegate);

本文地址在->本人博客地址, 歡迎給個(gè) start 或 follow

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/53291.html

相關(guān)文章

  • 圖說(shuō) WebAssembly(五):高性能原因

    摘要:本文是圖說(shuō)系列文章的第五篇。這樣的話,使用的開(kāi)發(fā)者也不需要做任何適配,但是它們卻能獲得更高性能。該圖并不是用來(lái)準(zhǔn)確的衡量其性能的。運(yùn)行編寫(xiě)出高性能的代碼是可能的。這種清理工作由引擎自動(dòng)進(jìn)行,稱(chēng)為垃圾回收。 本文是圖說(shuō) WebAssembly 系列文章的第五篇。如果您還未閱讀之前的文章,建議您從第一篇入手。 在上一篇文章中,我們說(shuō)到了使用 WebAssembly 和 JavaScript...

    seal_de 評(píng)論0 收藏0
  • 前端性能優(yōu)化之--頁(yè)面渲染優(yōu)化全面解析

    摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...

    MadPecker 評(píng)論0 收藏0
  • 前端性能優(yōu)化之--頁(yè)面渲染優(yōu)化全面解析

    摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...

    gghyoo 評(píng)論0 收藏0
  • 前端性能優(yōu)化之--頁(yè)面渲染優(yōu)化全面解析

    摘要:下面我們撇開(kāi)網(wǎng)絡(luò)方面的優(yōu)化,只分析靜態(tài)資源方面的優(yōu)化。不過(guò),也會(huì)阻止的構(gòu)建和延緩網(wǎng)頁(yè)渲染。未優(yōu)化正常加載優(yōu)化后異步加載根據(jù)上面的分析,我們可以清楚的認(rèn)識(shí)到,非必要優(yōu)先加載的,選擇異步加載是最優(yōu)選擇。 為什么做優(yōu)化 經(jīng)典問(wèn)題:白屏?xí)r間過(guò)長(zhǎng),用戶(hù)體驗(yàn)差產(chǎn)生的原因:網(wǎng)絡(luò)問(wèn)題、關(guān)鍵渲染路徑(CRP)問(wèn)題 怎么做優(yōu)化 如何做好優(yōu)化呢,網(wǎng)上隨便一搜,就有很多優(yōu)化總結(jié),無(wú)非就是網(wǎng)絡(luò)優(yōu)化、靜態(tài)資源(h...

    gaomysion 評(píng)論0 收藏0
  • 個(gè)人常用JavaScript及React常用優(yōu)化總結(jié)

    摘要:插件性能優(yōu)化及個(gè)人常用優(yōu)化方法經(jīng)常會(huì)觸發(fā)視覺(jué)變化。作用域鏈指的是當(dāng)前作用于下可用變量的集合,它在各種主流瀏覽器中至少包含兩個(gè)部分局部變量的集合和全局變量的集合。在考慮優(yōu)化時(shí),數(shù)值和變量的性能差不多,并且速度顯著優(yōu)于對(duì)象屬性和數(shù)組元素。 JavaScript 插件性能優(yōu)化及個(gè)人react常用優(yōu)化方法 JavaScript 經(jīng)常會(huì)觸發(fā)視覺(jué)變化。有時(shí)是直接通過(guò)樣式操作,有時(shí)是會(huì)產(chǎn)生視覺(jué)變化...

    yuanxin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<