前端--關於客戶端javascript

来源:http://www.cnblogs.com/jinjilin/archive/2016/02/16/5191611.html
-Advertisement-
Play Games

瀏覽器中的Javascript 客戶端javascript就是運行在瀏覽器中的javascript,現代的瀏覽器已經有了很好的發展,雖然它是一個應用程式,但完全可以把它看作是一個簡易的操作系統,因為像windows、linux等操作系統提供的文檔存儲、網路調用、繪製圖像等功能在瀏覽器中也同樣都可以得


  • 瀏覽器中的Javascript

  客戶端javascript就是運行在瀏覽器中的javascript,現代的瀏覽器已經有了很好的發展,雖然它是一個應用程式,但完全可以把它看作是一個簡易的操作系統,因為像windows、linux等操作系統提供的文檔存儲、網路調用、繪製圖像等功能在瀏覽器中也同樣都可以得到支持,所以就像操作系統中的應用程式叫做桌面應用一樣,瀏覽器中可互動的web文檔也叫做web應用。

  在web應用中,瀏覽器是javascript的運行環境,這個運行環境不僅包含了javascript解釋器以使js程式可以正確的運行,還為解釋器提供了其他服務的介面來擴展了javascript的功能,比如發起網路調用、DOM編程等。當一個頁面開始載入的時候js解釋器就會啟動,啟動後做的第一件事就是初始化一個全局對象,這個全局對象在不同運行環境中會有不同的標識符表示和內容,在nodeJS中這個全局對象叫global,而在瀏覽器中這個全局對象叫window。一個window對象就代表一個窗體,裡面除了包含javascript語法內置的函數和對象外,還包括瀏覽器為其擴展的功能對象,這些功能對象就是前面說的服務介面,是瀏覽器提供的服務的對象化表示。

  • Javascript的執行

  解釋器啟動之後就可以執行javascript代碼了,在瀏覽器中觸發javascript代碼運行的情況只有兩種:

  • 文檔載入的時候:瀏覽器在載入解析頁面文檔的過程中如果遇到了<script>標簽引用或者包含的js代碼,解釋器就會執行一遍。
  • 事件觸發的時候:這種情況是非同步且由事件驅動的,解釋器執行的代碼是前一種情況下為事件註冊的處理函數。

  其中第一種情況要尤其註意,當瀏覽器在下載執行js文件的時候,頁面的解析和渲染是被阻塞的,也就是說頁面的其他有關資源會停止下載(比如css文件、圖片等),同時DOM樹的構建也會暫停,因為js程式的執行是有可能影響到DOM樹的結構的(比如說使用到了document.write方法),DOM樹的解析一暫停,頁面的UI渲染也會被迫暫停。這樣就會產生性能問題,如果js文件過大或者js代碼執行時間過長,瀏覽器等待響應的時間就越久。所以考慮到性能問題,瀏覽器中js腳本應該儘可能的是無阻塞的腳本。

  • 無阻塞腳本

  由阻塞腳本的阻塞過程可以知道,無阻塞的腳本可以從兩個方面來考慮:不阻塞頁面相關資源的下載和不阻塞頁面UI的渲染。

    要是單單實現不阻塞其他資源的下載只有一種方法,就是在<script>標簽中添加defer或者async,這種方法的效果是實現並行下載,也就是說當js文件在下載的時候不會阻塞其他資源的下載,它倆的區別是下載完後js代碼執行的時機,defer會一直推遲到頁面解析完,而async會在js文件下載完後立即執行,但js文件在執行過程中還是會阻塞頁面解析和渲染的。由於瀏覽器對這種方法的支持不是很充分,所以這並不是一個相容性很強的方法。

  其他的幾種方法就是既不阻塞下載也不阻塞渲染了,首先是一種討巧的方法,就是把<script>標簽放到<body>底部,因為瀏覽器是一邊解析渲染一邊顯示出來的,等解析到body標簽最底部的時候頁面也就完全在瀏覽器中顯示出來了,這時候再下載和執行js文件基本上不存在阻塞這回事情了,但是要註意的是放到最後面的js文件儘量不要再對DOM進行操作,因為更改了DOM可能會產生迴流或者重繪,迴流和重繪也是非常耗性能的兩個操作,影響用戶的使用體驗。還有一點是asp.net程式要註意的是在webform編程中,如果後臺代碼要用到前臺的js函數,那麼放在body標簽底部的函數是註冊不過去的,後臺只能註冊放在head標簽中的函數。

  還有一種方法是創建動態腳本元素,這種方法可以說是做到了非同步無阻塞,在js文件下載和執行的時候都不會阻塞頁面的解析和渲染。該方法需要動態的創建script標簽,並把標簽添加到head元素中,比如

var script = document.createElement('script');
script.type='text/javascript';
script.src='xxxxx.js';
document.getElementsByTagName('head')[0].appendChild(script);

 當代碼執行到最後一句的時候js文件開始下載,下載完後立即執行,這整個過程不會阻塞頁面解析和渲染。這是動態創建帶有src屬性的script標簽的時候,還有另外一種動態創建內聯腳本的方式,該方法通過Ajax請求獲取到js腳本內容,再動態創建script標簽把腳本內容註入到script標簽當中。這種方法不是很常用因為有一個缺點就是獲取的js內容只能是同域中的。

  一個性能良好的頁面不只是要做到無阻塞腳本,還有很多其他方面要註意的。 其中一條就是不要讓一段js代碼執行太長時間,因為javascript語言中不存在任何線程機制,並且js引擎也是單線程模型的,所以js代碼的執行都是同步的,長時間的占用執行線程會使其他的js代碼無法得到執行。如果必須要計算一個密集的任務,那麼可以把這個任務通過setTimeout或setInterval分離成多個非同步子任務。這裡的同步和非同步看起來似乎有些矛盾,javascript怎麼可能既是單線程同步的又是多線程非同步的呢? 原因在於瀏覽器的機制。

  • Javascript單線程與事件的非同步        

   雖然javascript引擎是單線程的,但是瀏覽器是多線程的,在一個瀏覽器進程中一般有四個線程:javascript引擎線程、渲染引擎線程、瀏覽器事件線程(我也不知道叫什麼)、http請求線程。在javascript引擎線程中有一個執行隊列,裡面的任務是同步的依次執行,而在瀏覽器事件線程中有一個任務隊列,當某個事件觸發時,該事件對應的回掉函數會放到這個任務隊列中,這個任務隊列是一個先進先出結構,當javascript引擎線程中的任務都執行完畢後,會從瀏覽器事件線程中的任務隊列里讀取任務放到javascript引擎線程中的執行隊列里去執行,這個過程是不斷迴圈的,這有個專業術語叫Event Loop。所以就算setTimeout(fun,0)這種看起來是立即執行的函數也並不一定會立即執行的,這個fun函數會先放到任務隊列裡面等待執行隊列中的任務執行完畢才會被執行,所以fun函數的執行會延遲一段時間,這麼樣子的寫法只是改變了fun函數的執行順序。

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • php處理大量數據,每處理一個數據返回客戶端顯示當前狀態的方法。 類似於dedecms生成靜態頁 想法: 客戶端發送請求 伺服器端接受請求,開始統計所需處理的數據量 將所需處理數據按一定規則排列,發送到伺服器處理端 伺服器處理端處理了第一個數據,將處理結果經過一定處理後發送給客戶端 客戶端接收到結果
  • 1、Java與C++之間有一堵由記憶體動態分配和垃圾收集技術所圍成的“高牆”,牆外面的人想進去,牆裡面的人卻想出來。 2、運行時數據區域劃分 java虛擬機在執行java程式的過程中會把它所管理的記憶體劃分為若幹個區域,這些區域都有各自的用途,創建和銷毀時間,有的區域隨著虛擬機進程的啟動而存在,有的區域
  • 這篇文章主要介紹了spl_autoload_register()和__autoload()區別,需要的朋友可以參考下 關於spl_autoload_register()和__autoload(),相信大多數都會選擇前者了? 看兩者的用法: 複製代碼代碼如下: //__autoload用法functi
  • 1.直接插入排序(straight insertion sort)思想:第一趟比較前兩個數,然後把第二個數按大小插入到有序表中;第二趟對前兩個數從後向前掃描,把第三個數按大小插入到有序表中;依次進行下去,進行(n-1)趟掃描以後就完成了整個排序過程屬於穩定的排序,最壞時間複雜度O(n^2),空間複雜
  • 從婚禮通知說起 此處應有一張圖片,新娘和新郎拿著手機湊在一起商量,該邀請哪些人來參加婚禮呢? 重點放在婚禮通知這個動作上,那麼如何用代碼來簡單描述這個『通知』呢? 回味下婚禮通知中的兩個重點過程: 1. 親朋好友要求這對新婚夫婦將自己添加進通知名單裡面,這樣新婚夫婦結婚的時候就可以通知他們來參加婚禮
  • 重要程度:★★★★☆ 一、什麼是代理模式 通過代理對象間接控制並訪問目標對象的方法; 二、補充說明 想到代理模式,容易讓人想到AOP思想,Spring中的AOP可以通過動態代理實現; 代理模式有靜態代理和動態代理兩種; 解耦調用者和被調用者; 三、角色 抽象主題,定義一些需要代理的方法 具體主題,實
  • 原始單例模式 1 package com.shejimoshi.create.Singleton; 2 3 4 /** 5 * 功能:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點 6 * 適用:1、當類只能有一個實例而且客戶可以從一個眾所周知的訪問點訪問他的時候 7 * :2、當這個唯一實例
  • 前言 春節期間,無意中看到一篇文章,文章中講到12306的業務複雜度遠遠比淘寶天貓這種電商網站要複雜。後來自己想想,也確實如此。所以,很想挑戰一下12306這個系統的核心領域模型的設計。一般的電商網站,購買都是基於商品的概念,每個商品有一定量的庫存,用戶的購買行為是針對商品的。當用戶發起購買行為時,
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...