前端向面試題總結(jié)精要

個(gè)人表達(dá)

1.為何選擇前端這個(gè)方向?
第一的話對互聯(lián)網(wǎng)開發(fā)方面的東西很感興趣,之前也接觸過其他語言,但是直到接觸到前端才發(fā)現(xiàn)很有興趣做下去,興趣是一個(gè)人最好的老師。
第二的話前端的發(fā)展前景也很廣闊,像現(xiàn)在的nodejs,微信小程序這類工具和框架可以讓前端進(jìn)行后端和移動(dòng)開發(fā),所以我覺得從事前端工作未來也會有很好的發(fā)展。
2.對前端的理解?
首先前端的核心技能還是:HTML,CSS,JS。前端負(fù)責(zé)的是用戶可以看到的部分,所以也是最接近用戶的工程師。同時(shí)在產(chǎn)品研發(fā)流程中前端要同時(shí)與產(chǎn)品、設(shè)計(jì)、后端等很多人合作。

HTML/HTML5

1.知道語義化嗎?說說你理解的語義化,如果是你,平時(shí)會怎么做來保證語義化?
像html5的新的標(biāo)簽header,footer,section等就是語義化
一方面,語義化就是讓計(jì)算機(jī)能夠快速的讀懂內(nèi)容,高效的處理信息,可以對搜索引擎更友好。
另一方面,便于與他人的協(xié)作,他人通過讀代碼就可以理解你網(wǎng)頁標(biāo)簽的意義。
去掉或者丟失樣式的時(shí)候能夠讓頁面呈現(xiàn)出清晰的結(jié)構(gòu)
有利于SEO:和搜索引擎建立良好溝通,有助于爬蟲抓取更多的有效信息:爬蟲依賴于標(biāo)簽來確定上下文和各個(gè)關(guān)鍵字的權(quán)重;
方便其他設(shè)備解析(如屏幕閱讀器、盲人閱讀器、移動(dòng)設(shè)備)以意義的方式來渲染網(wǎng)頁;
便于團(tuán)隊(duì)開發(fā)和維護(hù),語義化更具可讀性,是下一步吧網(wǎng)頁的重要?jiǎng)酉?,遵循W3C標(biāo)準(zhǔn)的團(tuán)隊(duì)都遵循這個(gè)標(biāo)準(zhǔn),可以減少差異化。
2.介紹一下HTML5的新特性
新的DOCTYPE聲明 <!DOCTYPE html>
完全支持css3
video和audio
本地存儲
語義化標(biāo)簽
canvas
新事件 如ondrag onresize
3.如何解決ajax無法后退的問題?
HTML5里引入了新的API,即:history.pushState, history.replaceState
可以通過pushState和replaceState接口操作瀏覽器歷史,并且改變當(dāng)前頁面的URL。
onpopstate監(jiān)聽后退
4.websocket和ajax輪詢
Websocket是HTML5中提出的新的協(xié)議,注意,這里是協(xié)議,可以實(shí)現(xiàn)客戶端與服務(wù)器端的通信,實(shí)現(xiàn)服務(wù)器的推送功能。
其優(yōu)點(diǎn)就是,只要建立一次連接,就可以連續(xù)不斷的得到服務(wù)器推送的消息,節(jié)省帶寬和服務(wù)器端的壓力。
ajax輪詢模擬長連接就是每個(gè)一段時(shí)間(0.5s)就向服務(wù)器發(fā)起ajax請求,查詢服務(wù)器端是否有數(shù)據(jù)更新
其缺點(diǎn)顯而易見,每次都要建立HTTP連接,即使需要傳輸?shù)臄?shù)據(jù)非常少,所以這樣很浪費(fèi)帶寬

js

1.什么是閉包?

我們知道根據(jù)作用域鏈的規(guī)則,一個(gè)函數(shù)是不能訪問到在與他同一個(gè)作用域內(nèi)的函數(shù)內(nèi)的內(nèi)部變量的,而閉包是有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。首先要明白的就是,閉包是函數(shù)。由于要求它可以訪問另一個(gè)函數(shù)的作用于中的變量,所以我們往往是在一個(gè)函數(shù)的內(nèi)部創(chuàng)建另一個(gè)函數(shù),而“另一個(gè)函數(shù)”就是閉包。

2.js這樣寫是什么意思?var a=(function(){})(a)

var a=(function(a){
    // todo
})(a);
console.log(a);
// 定義一個(gè)匿名函數(shù),把a(bǔ)傳遞進(jìn)去,a是undefined
// 因?yàn)槟涿瘮?shù)本身沒有返回值,如果是
 
var a=(function(a){
    return 1;
})(a);
 
console.log(a);// a此時(shí)就是1
 
 
// 如果要自動(dòng)運(yùn)行這個(gè)匿名函數(shù)的同時(shí)又賦值給a,那就應(yīng)該是這樣的:
var i = 0;// 計(jì)數(shù)器
var a=(function(a){
    i++;
    console.log("i am running..." + i);
    return arguments.callee;
})(a);// 這里跑一次
 
a();//被調(diào)用一次

閉包適用場景

1、模擬創(chuàng)建私有變量。

function clo() {
      var foo = 'wayne';
      this.age = 22;
      this.getFoo = function () {
        return foo;
      }
      this.setFoo = function (val) {
        foo = val;
      }
    }
    var bar = new clo();
    console.log(bar.getFoo()); // wayne
    console.log(bar.setFoo('hedy')); 
    console.log(bar.getFoo()); // hedy

如上所示,我們創(chuàng)建一個(gè)構(gòu)造函數(shù),然后想要獲取其中的變量是無法直接獲取的,而必須通過getFoo方法; 當(dāng)然,也是無法直接設(shè)置foo值的,需要通過setFoo方法。

2、 創(chuàng)建模塊化,避免全局變量污染。

比如,我們希望在一個(gè)頁面中引入多個(gè)js文件,而這些js文件可能是不同的人來寫的,那么不可避免的會出現(xiàn)重名的現(xiàn)象,但是如果我們在每個(gè)js文件外添加一層 (function(){})(),那么,這個(gè)js模塊中的所有全局變量就成了局部變量,也就沒有了全局污染的問題了。

3、 將內(nèi)部變量導(dǎo)出,給其他函數(shù)使用。

比如一個(gè)內(nèi)部變量無法直接被所在函數(shù)外的其他函數(shù)使用,這時(shí),我們就可以返回一個(gè)函數(shù),這個(gè)函數(shù)返回這個(gè)變量,這樣,就可以在函數(shù)外輕松拿到這個(gè)變量了。

網(wǎng)絡(luò)請求

1.http響應(yīng)中content-type包含哪些內(nèi)容?
Content-Type用于指定內(nèi)容類型,一般是指網(wǎng)頁中存在的Content-Type,Content-Type屬性指定請求和響應(yīng)的HTTP內(nèi)容類型。如果未指定 ContentType,默認(rèn)為text/html。
在nginx中有個(gè)配置文件mime.types,主要是標(biāo)示Content-Type的文件格式。
下面是幾個(gè)常見的Content-Type:
1.text/html
2.text/plain
3.text/css
4.text/javascript
5.application/x-www-form-urlencoded
6.multipart/form-data
7.application/json
8.application/xml
前面幾個(gè)都很好理解,都是html,css,javascript的文件類型,后面四個(gè)是POST的發(fā)包方式。

2.1.application/x-www-form-urlencoded

application/x-www-form-urlencoded是常用的表單發(fā)包方式,普通的表單提交,或者js發(fā)包,默認(rèn)都是通過這種方式,

比如一個(gè)簡單地表單:

<form enctype="application/x-www-form-urlencoded" action="http://homeway.me/post.php" method="POST">
    <input type="text" name="name" value="homeway">
    <input type="text" name="key" value="nokey">
    <input type="submit" value="submit">
</form>

那么服務(wù)器收到的raw header會類似:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4,gl;q=0.2,de;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:17
Content-Type:application/x-www-form-urlencoded

那么服務(wù)器收到的raw body會是,name=homeway&key=nokey,在php中,通過$_POST就可以獲得數(shù)組形式的數(shù)據(jù)。

2.2 multipart/form-data

multipart/form-data用在發(fā)送文件的POST包。

這里假設(shè)我用python的request發(fā)送一個(gè)文件給服務(wù)器:

data = {
    "key1": "123",
    "key2": "456",
}

files = {'file': open('index.py', 'rb')}
res = requests.post(url="http://localhost/upload", method="POST", data=data, files=files)
print res

通過工具,可以看到我發(fā)送的數(shù)據(jù)內(nèi)容如下:

POST http://www.homeway.me HTTP/1.1
Content-Type:multipart/form-data; boundary=------WebKitFormBoundaryOGkWPJsSaJCPWjZP

------WebKitFormBoundaryOGkWPJsSaJCPWjZP
Content-Disposition: form-data; name="key2"
456
------WebKitFormBoundaryOGkWPJsSaJCPWjZP
Content-Disposition: form-data; name="key1"
123
------WebKitFormBoundaryOGkWPJsSaJCPWjZP
Content-Disposition: form-data; name="file"; filename="index.py"

這里Content-Type告訴我們,發(fā)包是以multipart/form-data格式來傳輸,另外,還有boundary用于分割數(shù)據(jù)。

當(dāng)文件太長,HTTP無法在一個(gè)包之內(nèi)發(fā)送完畢,就需要分割數(shù)據(jù),分割成一個(gè)一個(gè)chunk發(fā)送給服務(wù)端,

那么--用于區(qū)分?jǐn)?shù)據(jù)快,而后面的數(shù)據(jù)就是標(biāo)示區(qū)分包作用。

2.3 text/xml

微信用的是這種數(shù)據(jù)格式發(fā)送請求的。

POST http://www.homeway.me HTTP/1.1 
Content-Type: text/xml

<?xml version="1.0"?>
<resource>
    <id>123</id>
    <params>
        <name>
            <value>homeway</value>
        </name>
        <age>
            <value>22</value>
        </age>
    </params>
</resource>

php中_POST只能讀取application/x-www-form-urlencoded數(shù)據(jù),$_FILES只能讀取multipart/form-data類型數(shù)據(jù),

那么,要讀取text/xml格式的數(shù)據(jù),可以用:

$file = fopen('php://input', 'rb');
$data = fread($file, length);
fclose($file);

或者

$data = file_get_contents('php://input');

2.4 application/json

通過json形式將數(shù)據(jù)發(fā)送給服務(wù)器,一開始,我嘗試通過curl,給服務(wù)器發(fā)送application/json格式包,

然而我收到的數(shù)據(jù)如下:

---------e1e1406176ee348a Content-Disposition: form-data; name="nid" 2---------------
---------e1e1406176ee348a Content-Disposition: form-data; name="uuid" cf9dc994-a4e7-3ad6-bc54-41965b2a0dd7-----------
----------e1e1406176ee348a Content-Disposition: form-data; name="access_token" 956731586df41229dbfec08dd5d54eedb98d73d2----------
----------e1e1406176ee348a--

HTTP通信中并不存在所謂的json,而是將string轉(zhuǎn)成json罷了,也就是,application/json可以將它理解為text/plain,普通字符串。

3.如何進(jìn)行用戶認(rèn)證?

前端登錄,后端根據(jù)用戶信息生成一個(gè)jsessionid,并保存這個(gè) jsessionid 和對應(yīng)的用戶id到Session中,接著把 jsessionid 傳給用戶,存入瀏覽器 cookie,之后瀏覽器請求帶上這個(gè)cookie,后端根據(jù)這個(gè)cookie值來查詢用戶,驗(yàn)證是否過期。

HTTP有一個(gè)特性:無狀態(tài)的,就是前后兩個(gè)HTTP事務(wù)它們并不知道對方的信息。而為了維護(hù)會話信息或用戶信息,一般可用Cookie和Session技術(shù)緩存信息。

  • Cookie是存儲在客戶端的

  • Session是存儲在服務(wù)端的

但這樣做問題就很多,如果我們的頁面出現(xiàn)了 XSS 漏洞,由于 cookie 可以被 JavaScript 讀取,XSS 漏洞會導(dǎo)致用戶 token 泄露,而作為后端識別用戶的標(biāo)識,cookie 的泄露意味著用戶信息不再安全。盡管我們通過轉(zhuǎn)義輸出內(nèi)容,使用 CDN 等可以盡量避免 XSS 注入,但誰也不能保證在大型的項(xiàng)目中不會出現(xiàn)這個(gè)問題。

在設(shè)置 cookie 的時(shí)候,其實(shí)你還可以設(shè)置 httpOnly 以及 secure 項(xiàng)。設(shè)置 httpOnly 后 cookie 將不能被 JS 讀取,瀏覽器會自動(dòng)的把它加在請求的 header 當(dāng)中,設(shè)置 secure 的話,cookie 就只允許通過 HTTPS 傳輸。secure 選項(xiàng)可以過濾掉一些使用 HTTP 協(xié)議的 XSS 注入,但并不能完全阻止。

httpOnly 選項(xiàng)使得 JS 不能讀取到 cookie,那么 XSS 注入的問題也基本不用擔(dān)心了。但設(shè)置 httpOnly 就帶來了另一個(gè)問題,就是很容易的被 XSRF,即跨站請求偽造。當(dāng)你瀏覽器開著這個(gè)頁面的時(shí)候,另一個(gè)頁面可以很容易的跨站請求這個(gè)頁面的內(nèi)容。因?yàn)?cookie 默認(rèn)被發(fā)了出去。

瀏覽器

1.瀏覽器緩存有哪些,通常緩存有哪幾種方式

瀏覽器緩存(Browser Caching)是瀏覽器端保存數(shù)據(jù)用于快速讀取或避免重復(fù)資源請求的優(yōu)化機(jī)制,有效的緩存使用可以避免重復(fù)的網(wǎng)絡(luò)請求和瀏覽器快速地讀取本地?cái)?shù)據(jù),整體上加速網(wǎng)頁展示給用戶。瀏覽器端緩存的機(jī)制種類較多,總體歸納為九種,這里詳細(xì)分析下這九種緩存機(jī)制的原理和使用場景。打開瀏覽器的調(diào)試模式->resources左側(cè)就有瀏覽器的8種緩存機(jī)制。

一、http緩存

http緩存是基于HTTP協(xié)議的瀏覽器文件級緩存機(jī)制。即針對文件的重復(fù)請求情況下,瀏覽器可以根據(jù)協(xié)議頭判斷從服務(wù)器端請求文件還是從本地讀取文件,chrome控制臺下的Frames即展示的是瀏覽器的http文件級緩存。以下是瀏覽器緩存的整個(gè)機(jī)制流程。主要是針對重復(fù)的http請求,在有緩存的情況下判斷過程主要分3步:

  • 判斷expires,如果未過期,直接讀取http緩存文件,不發(fā)http請求,否則進(jìn)入下一步
  • 判斷是否含有etag,有則帶上if-none-match發(fā)送請求,未修改返回304,修改返回200,否則進(jìn)入下一步
  • 判斷是否含有l(wèi)ast-modified,有則帶上if-modified-since發(fā)送請求,無效返回200,有效返回304,否則直接向服務(wù)器請求
    如果通過etag和last-modified判斷,即使返回304有至少有一次http請求,只不過返回的是304的返回內(nèi)容,而不是文件內(nèi)容。所以合理設(shè)計(jì)實(shí)現(xiàn)expires參數(shù)可以減少較多的瀏覽器請求。

二、websql

websql這種方式只有較新的chrome瀏覽器支持,并以一個(gè)獨(dú)立規(guī)范形式出現(xiàn),主要有以下特點(diǎn)

  • Web Sql 數(shù)據(jù)庫API 實(shí)際上不是HTML5規(guī)范的組成部分;
  • 在HTML5之前就已經(jīng)存在了,是單獨(dú)的規(guī)范;
  • 它是將數(shù)據(jù)以數(shù)據(jù)庫的形式存儲在客戶端,根據(jù)需求去讀??;
  • 跟Storage的區(qū)別是: Storage和Cookie都是以鍵值對的形式存在的;
  • Web Sql 更方便于檢索,允許sql語句查詢;
  • 讓瀏覽器實(shí)現(xiàn)小型數(shù)據(jù)庫存儲功能;
  • 這個(gè)數(shù)據(jù)庫是集成在瀏覽器里面的,目前主流瀏覽器基本都已支持;

websql API主要包含三個(gè)核心方法:

  • openDatabase : 這個(gè)方法使用現(xiàn)有數(shù)據(jù)庫或創(chuàng)建新數(shù)據(jù)庫創(chuàng)建數(shù)據(jù)庫對象。
  • transaction : 這個(gè)方法允許我們根據(jù)情況控制事務(wù)提交或回滾。
  • executeSql : 這個(gè)方法用于執(zhí)行真實(shí)的SQL查詢。

openDatabase方法可以打開已經(jīng)存在的數(shù)據(jù)庫,不存在則創(chuàng)建

    var db = openDatabase('mydatabase', '2.0', my db', 2 * 1024);

openDatabasek中五個(gè)參數(shù)分別為:數(shù)據(jù)庫名、版本號、描述、數(shù)據(jù)庫大小、創(chuàng)建回調(diào)。創(chuàng)建回調(diào)沒有也可以創(chuàng)建數(shù)據(jù)庫。

database.transaction() 函數(shù)用來查詢,executeSql()用于執(zhí)行sql語句

例如在mydatabase數(shù)據(jù)庫中創(chuàng)建表t1:

  var db = openDatabase(' mydatabase ', '1.0', 'Test DB', 2 * 1024 * 1024);  
   db.transaction(function (tx) {    
      tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');  
   });

插入操作

var db = openDatabase('mydatabase', '2.0', my db', 2 * 1024);
   db.transaction(function (tx) { 
      tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');  
      tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');  
      tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');  
   });

在插入新記錄時(shí),我們還可以傳遞動(dòng)態(tài)值,如:

  var db = openDatabase(' mydatabase ', '2.0', 'my db', 2 * 1024);  
   db.transaction(function (tx) {    
     tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');  
     tx.executeSql('INSERT INTO t1 (id,log) VALUES (?, ?'), [e_id, e_log];  //e_id和e_log是外部變量
   });

讀操作,如果要讀取已經(jīng)存在的記錄,我們使用一個(gè)回調(diào)捕獲結(jié)果:

   var db = openDatabase(mydatabase, '2.0', 'my db', 2*1024);     
      db.transaction(function (tx) { 
      tx.executeSql('CREATE TABLE IF NOT EXISTS t1 (id unique, log)');  
      tx.executeSql('INSERT INTO t1 (id, log) VALUES (1, "foobar")');  
      tx.executeSql('INSERT INTO t1 (id, log) VALUES (2, "logmsg")');  
   });  
   db.transaction(function (tx) { 
      tx.executeSql('SELECT * FROM t1, [], function (tx, results) { 
      var len = results.rows.length, i;  
      msg = "<p>Found rows: " + len + "</p>";  
      document.querySelector('#status').innerHTML +=  msg;  
      for (i = 0; i < len; i++){ 
         alert(results.rows.item(i).log );  
      } 
    }, null);  
   });

三、indexDB

IndexedDB 是一個(gè)為了能夠在客戶端存儲可觀數(shù)量的結(jié)構(gòu)化數(shù)據(jù),并且在這些數(shù)據(jù)上使用索引進(jìn)行高性能檢索的 API。雖然 DOM 存儲 對于存儲少量數(shù)據(jù)是非常有用的,但是它對大量結(jié)構(gòu)化數(shù)據(jù)的存儲就顯得力不從心了。IndexedDB 則提供了這樣的一個(gè)解決方案。??IndexedDB 分別為同步和異步訪問提供了單獨(dú)的 API 。同步 API 本來是要用于僅供 Web Workers 內(nèi)部使用,但是還沒有被任何瀏覽器所實(shí)現(xiàn)。異步 API 在 Web Workers 內(nèi)部和外部都可以使用,另外瀏覽器可能對indexDB有50M大小的限制,一般用戶保存大量用戶數(shù)據(jù)并要求數(shù)據(jù)之間有搜索需要的場景。

  • 異步API
    ??異步 API 方法調(diào)用完后會立即返回,而不會阻塞調(diào)用線程。要異步訪問數(shù)據(jù)庫,要調(diào)用 window 對象 indexedDB 屬性的 open() 方法。該方法返回一個(gè) IDBRequest 對象 (IDBOpenDBRequest);異步操作通過在 IDBRequest 對象上觸發(fā)事件來和調(diào)用程序進(jìn)行通信。
  • IDBFactory 提供了對數(shù)據(jù)庫的訪問。這是由全局對象 indexedDB 實(shí)現(xiàn)的接口,因而也是該 API 的入口。- IDBCursor 遍歷對象存儲空間和索引。- IDBCursorWithValue 遍歷對象存儲空間和索引并返回游標(biāo)的當(dāng)前值。- IDBDatabase 表示到數(shù)據(jù)庫的連接。只能通過這個(gè)連接來拿到一個(gè)數(shù)據(jù)庫事務(wù)。- IDBEnvironment 提供了到客戶端數(shù)據(jù)庫的訪問。它由 window 對象實(shí)現(xiàn)。- IDBIndex 提供了到索引元數(shù)據(jù)的訪問。- IDBKeyRange 定義鍵的范圍。- IDBObjectStore 表示一個(gè)對象存儲空間。- IDBOpenDBRequest 表示一個(gè)打開數(shù)據(jù)庫的請求。-IDBRequest 提供了到數(shù)據(jù)庫異步請求結(jié)果和數(shù)據(jù)庫的訪問。這也是在你調(diào)用一個(gè)異步方法時(shí)所得到的。- IDBTransaction 表示一個(gè)事務(wù)。你在數(shù)據(jù)庫上創(chuàng)建一個(gè)事務(wù),指定它的范圍(例如你希望訪問哪一個(gè)對象存儲空間),并確定你希望的訪問類型(只讀或?qū)懭耄? IDBVersionChangeEvent 表明數(shù)據(jù)庫的版本號已經(jīng)改變。
  • 同步API
    ??規(guī)范里面還定義了 API 的同步版本。同步 API 還沒有在任何瀏覽器中得以實(shí)現(xiàn)。它原本是要和 webWork 一起使用的。

四、cookie

Cookie(或者Cookies),指一般網(wǎng)站為了辨別用戶身份、進(jìn)行session跟蹤而儲存在用戶本地終端上的數(shù)據(jù)(通常經(jīng)過加密)。cookie一般通過http請求中在頭部一起發(fā)送到服務(wù)器端。一條cookie記錄主要由鍵、值、域、過期時(shí)間、大小組成,一般用戶保存用戶的認(rèn)證信息。cookie最大長度和域名個(gè)數(shù)由不同瀏覽器決定,具體如下:

瀏覽器 支持域名個(gè)數(shù) 最大長度
IE7以上 50個(gè) 4095B
Firefox 50個(gè) 4097B
Opera 30個(gè) 4096B
Safari/WebKit 無限制 4097B

不同域名之間的cookie信息是獨(dú)立的,如果需要設(shè)置共享可以在服務(wù)器端設(shè)置cookie的path和domain來實(shí)現(xiàn)共享。瀏覽器端也可以通過document.cookie來獲取cookie,并通過js瀏覽器端也可以方便地讀取/設(shè)置cookie的值。

五、localstorage

localStorage是html5的一種新的本地緩存方案,目前用的比較多,一般用來存儲ajax返回的數(shù)據(jù),加快下次頁面打開時(shí)的渲染速度。

瀏覽器 最大長度
IE8以上 5M
Firefox 8以上 5.24M
Opera 2M
Safari/WebKit 2.6M
//localStorage核心API:localStorage.setItem(key, value)    
//設(shè)置記錄localStorage.getItem(key)            
//獲取記錄localStorage.removeItem(key)       
//刪除該域名下單條記錄localStorage.clear()                
//刪除該域名下所有記錄

值得注意的是,localstorage大小有限制,不適合存放過多的數(shù)據(jù),如果數(shù)據(jù)存放超過最大限制會報(bào)錯(cuò),并移除最先保存的數(shù)據(jù)。

六、sessionstorage

sessionStorage和localstorage類似,但是瀏覽器關(guān)閉則會全部刪除,api和localstorage相同,實(shí)際項(xiàng)目中使用較少。

七、application cache

application cahce是將大部分圖片資源、js、css等靜態(tài)資源放在manifest文件配置中。當(dāng)頁面打開時(shí)通過manifest文件來讀取本地文件或是請求服務(wù)器文件。??離線訪問對基于網(wǎng)絡(luò)的應(yīng)用而言越來越重要。雖然所有瀏覽器都有緩存機(jī)制,但它們并不可靠,也不一定總能起到預(yù)期的作用。HTML5 使用ApplicationCache 接口可以解決由離線帶來的部分難題。前提是你需要訪問的web頁面至少被在線訪問過一次。??使用緩存接口可為您的應(yīng)用帶來以下三個(gè)優(yōu)勢:

  • 離線瀏覽 – 用戶可在離線時(shí)瀏覽您的完整網(wǎng)站
  • 速度 – 緩存資源為本地資源,因此加載速度較快。
  • 服務(wù)器負(fù)載更少 – 瀏覽器只會從發(fā)生了更改的服務(wù)器下載資源。

一個(gè)簡單的離線頁面主要包含以下幾個(gè)部分:

index.html

<html manifest="clock.manifest">
  <head>
    <title>AppCache Test</title>
    <link rel="stylesheet" href="clock.css">
    <script src="clock.js"></script>
  </head>
  <body>
    <p><output id="clock"></output></p>
    <div id="log"></div>
  </body>
</html>

clock.manifest

CACHE MANIFEST
#VERSION 1.0
CACHE:
clock.css
clock.js

clock.js和clock.css為獨(dú)立的另外文件。??另外需要注意的是更新緩存。在程序中,你可以通過window.applicationCache 對象來訪問瀏覽器的app cache。你可以查看 status 屬性來獲取cache的當(dāng)前狀態(tài):

var appCache = window.applicationCache;
switch (appCache.status) {
  case appCache.UNCACHED: // UNCACHED == 0
    return 'UNCACHED';
    break;
  case appCache.IDLE: // IDLE == 1
    return 'IDLE';
    break;
  case appCache.CHECKING: // CHECKING == 2
    return 'CHECKING';
    break;
  case appCache.DOWNLOADING: // DOWNLOADING == 3
    return 'DOWNLOADING';
    break;
  case appCache.UPDATEREADY:  // UPDATEREADY == 4
    return 'UPDATEREADY';
    break;
  case appCache.OBSOLETE: // OBSOLETE == 5
    return 'OBSOLETE';
    break;
  default:
    return 'UKNOWN CACHE STATUS';
    break;
};

為了通過編程更新cache,首先調(diào)用 applicationCache.update()。這將會試圖更新用戶的 cache(要求manifest文件已經(jīng)改變)。最后,當(dāng) applicationCache.status 處于 UPDATEREADY 狀態(tài)時(shí), 調(diào)用applicationCache.swapCache(),舊的cache就會被置換成新的。

var appCache = window.applicationCache;
appCache.update(); // Attempt to update the user’s cache.
…
if (appCache.status == window.applicationCache.UPDATEREADY) {
  appCache.swapCache();  // The fetch was successful, swap in the new cache.
}

這里是通過更新menifest文件來控制其它文件更新的。

八、cacheStorage

CacheStorage是在ServiceWorker的規(guī)范中定義的。CacheStorage 可以保存每個(gè)serverWorker申明的cache對象,cacheStorage有open、match、has、delete、keys五個(gè)核心方法,可以對cache對象的不同匹配進(jìn)行不同的響應(yīng)。

cacheStorage.has()如果包含cache對象,則返回一個(gè)promise對象。cacheStorage.open()打開一個(gè)cache對象,則返回一個(gè)promise對象。cacheStorage.delete()刪除cache對象,成功則返回一個(gè)promise對象,否則返回false。cacheStorage.keys()含有keys中字符串的任意一個(gè),則返回一個(gè)promise對象。cacheStorage.delete()匹配key中含有該字符串的cache對象,返回一個(gè)promise對象。

caches.has('v1').then(function() {
  caches.open('v1').then(function(cache) {
      return cache.addAll(myAssets);
  });
}).catch(function() {
  someCacheSetupfunction();
});;
var response;
var cachedResponse = caches.match(event.request).catch(function() {
  return fetch(event.request);
}).then(function(r) {
  response = r;
  caches.open('v1').then(function(cache) {
    cache.put(event.request, response);
  });  
  return response.clone();
}).catch(function() {
  return caches.match('/sw-test/gallery/myLittleVader.jpg');
});
then.addEventListener('activate', function(event) {
  var cacheWhitelist = ['v2'];
 
  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheWhitelist.indexOf(key) === -1) {
          return caches.delete(keyList[i]);
        }
      });
    })
  );
});

九、flash緩存

這種方式基本不用,這一方法主要基于flash有讀寫瀏覽器端本地目錄的功能,同時(shí)也可以向js提供調(diào)用的api,則頁面可以通過js調(diào)用flash去讀寫特定的磁盤目錄,達(dá)到本地?cái)?shù)據(jù)緩存的目的。

注釋PS

  • Web Storage / Web SQL Database / Indexed Database 的數(shù)據(jù)都存儲在瀏覽器對應(yīng)的用戶配置文件目錄(user profile directory)下,以 Windows 7 為例,Chrome 的數(shù)據(jù)存儲在”C:\Users\your-account-name\AppData\Local\Google\Chrome\User Data\Default\”下,而 Firefox 的數(shù)據(jù)存儲在”C:\Users\your-account-name\AppData\Local\Mozilla\Firefox\Profiles\”目錄下。
  • cookie文件存儲于documents and settings\userName\cookie\文件夾下。通常的命名格式為:userName@domain.txt。
  • 較多的緩存機(jī)制目前主流瀏覽器并不兼容,不過可以使用polyfill的方法來處理

瀏覽器涉及的緩存方式主要包含這些,具體結(jié)合自己的業(yè)務(wù)場景進(jìn)行選擇使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容