整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          探索 JavaScript Window 對(duì)象:從

          探索 JavaScript Window 對(duì)象:從 BOM 到本地存儲(chǔ),全面掌握!

          JavaScript 的 Window 對(duì)象是瀏覽器對(duì)象模型(BOM)的核心,它為開發(fā)者提供了操作瀏覽器窗口和控制用戶體驗(yàn)的強(qiáng)大工具。本篇文章將帶你深入了解 Window 對(duì)象的各個(gè)方面:BOM、JavaScript 執(zhí)行機(jī)制、Location 對(duì)象、Navigator 對(duì)象、History 對(duì)象以及本地存儲(chǔ)。


          1. 瀏覽器對(duì)象模型(BOM)

          什么是 BOM?

          BOM 全稱為瀏覽器對(duì)象模型(Browser Object Model),它提供了與瀏覽器互動(dòng)的各種接口和方法。通過 BOM,開發(fā)者可以訪問和操作瀏覽器窗口、文檔、歷史記錄等。BOM 的核心對(duì)象是 Window 對(duì)象。

          代碼示例:

          // 設(shè)置窗口的高度和寬度
          window.innerHeight=800;
          window.innerWidth=1200;
          
          // 打開一個(gè)新窗口
          let newWindow=window.open('https://www.example.com', '_blank');

          2. JavaScript 執(zhí)行機(jī)制

          JavaScript 代碼在瀏覽器中的執(zhí)行機(jī)制主要包括兩個(gè)方面:事件循環(huán)和回調(diào)隊(duì)列。

          事件循環(huán):

          事件循環(huán)(Event Loop)是 JavaScript 的執(zhí)行模型,它確保非阻塞操作能夠正常執(zhí)行。

          代碼示例:

          console.log('任務(wù)開始');
          
          setTimeout(()=> {
            console.log('異步任務(wù)');
          }, 2000);
          
          console.log('任務(wù)結(jié)束');
          

          執(zhí)行順序?yàn)椋?/p>

          1. 任務(wù)開始
          2. 任務(wù)結(jié)束
          3. 異步任務(wù)(2秒后輸出)

          3. Location 對(duì)象

          用法:

          Location 對(duì)象包含有關(guān)當(dāng)前 URL 的信息,并提供了一些重定向和導(dǎo)航的方法。

          常用屬性和方法:

          • location.href:獲取或設(shè)置當(dāng)前 URL
          • location.reload():重新加載頁面
          • location.assign(url):加載新的 URL

          代碼示例:

          // 獲取當(dāng)前 URL
          console.log(location.href);
          
          // 重定向到新的 URL
          location.href='https://www.new-url.com';
          
          // 重新加載當(dāng)前頁面
          location.reload();
          

          4. Navigator 對(duì)象

          用法:

          Navigator 對(duì)象包含有關(guān)瀏覽器的信息,如瀏覽器名稱、版本、以及用戶代理信息。

          常用屬性和方法:

          • navigator.userAgent:返回用戶代理字符串
          • navigator.geolocation:提供用戶地理位置

          代碼示例:

          // 獲取用戶代理信息
          console.log(navigator.userAgent);
          
          // 獲取用戶地理位置
          navigator.geolocation.getCurrentPosition((position)=> {
            console.log(`Latitude: ${position.coords.latitude}, Longitude: ${position.coords.longitude}`);
          });
          

          5. History 對(duì)象

          用法:

          History 對(duì)象允許操作瀏覽器的歷史記錄(會(huì)話歷史)。

          常用屬性和方法:

          • history.back():返回到上一頁
          • history.forward():前進(jìn)到下一頁
          • history.go(n):加載歷史記錄中的某個(gè)特定頁面

          代碼示例:

          // 返回上一個(gè)頁面
          history.back();
          
          // 前進(jìn)到下一個(gè)頁面
          history.forward();
          
          // 前往歷史記錄中的第一個(gè)頁面
          history.go(-1);
          

          6. 本地存儲(chǔ)(Local Storage)

          用法:

          本地存儲(chǔ)是一種在客戶端存儲(chǔ)數(shù)據(jù)的方式,數(shù)據(jù)存儲(chǔ)在瀏覽器中,不會(huì)隨頁面刷新而丟失。

          常用方法:

          • localStorage.setItem(key, value):存儲(chǔ)數(shù)據(jù)
          • localStorage.getItem(key):獲取數(shù)據(jù)
          • localStorage.removeItem(key):刪除數(shù)據(jù)
          • localStorage.clear():清除所有數(shù)據(jù)

          代碼示例:

          // 存儲(chǔ)數(shù)據(jù)
          localStorage.setItem('username', 'john_doe');
          
          // 獲取數(shù)據(jù)
          let username=localStorage.getItem('username');
          console.log(username); // 輸出: john_doe
          
          // 刪除數(shù)據(jù)
          localStorage.removeItem('username');
          
          // 清空所有數(shù)據(jù)
          localStorage.clear();
          

          結(jié)論

          通過對(duì)這些對(duì)象和機(jī)制的深入了解,你可以更好地利用 JavaScript 提供的各種功能來優(yōu)化用戶體驗(yàn),增強(qiáng)應(yīng)用程序的互動(dòng)性。無論是控制瀏覽器窗口、獲取用戶信息,還是操作歷史記錄和本地存儲(chǔ),掌握這些知識(shí)都會(huì)讓你的開發(fā)工作事半功倍。


          更多精彩內(nèi)容,請(qǐng)持續(xù)關(guān)注!

          任何一家Saas企業(yè)都需要有自己的低代碼平臺(tái).在可視化低代碼的前端研發(fā)過程中, 發(fā)現(xiàn)了很多有意思的技術(shù)需求, 在解決這些需求的過程中, 往往也會(huì)給自己帶來很多收獲, 今天就來分享一下在研發(fā)Dooring過程中遇到的前端技術(shù)問題——javascript函數(shù)存儲(chǔ).
          ?

          背景介紹

          我們都知道要想搭建一個(gè)前端頁面基本需要如下3個(gè)要素:

          • 元素(UI)
          • 數(shù)據(jù)(Data)
          • 事件/交互(Event)

          「數(shù)據(jù)驅(qū)動(dòng)視圖」 的時(shí)代, 這三個(gè)要素的關(guān)系往往如下圖所示:

          可視化搭建平臺(tái)的設(shè)計(jì)思路往往也是基于上面的過程展開的, 我們需要提供編輯器環(huán)境給用戶來創(chuàng)建「視圖」「交互」, 最終用戶保存的產(chǎn)物可能是這樣的:

          {
              "name": "Dooring表單",
              "bgColor": "#666",
              "share_url": "http://xxx.cn",
              "mount_event": [
                  {
                      "id": "123",
                      "func": ()=> {
                          // 初始化邏輯
                          GamepadHapticActuator();
                      },
                      "sourcedata": []
                  }
              ],
              "body": [
                  {
                      "name": "header",
                      "event": [
                          {
                              "id": "123",
                              "type": "click",
                              "func": ()=> {
                                  // 組件自定義交互邏輯
                                  showModal();
                              }
                          }
                      ]
                  }
              ]
          }
          

          那么問題來了, json 字符串我們好保存(可以通過JSON.stringify序列化的方式), 但是如何將「函數(shù)」也一起保存呢? 保存好了函數(shù)如何在頁面渲染的時(shí)候能正常讓 js 運(yùn)行這個(gè)函數(shù)呢?

          實(shí)現(xiàn)方案思考

          我們都知道將 js 對(duì)象轉(zhuǎn)化為json 可以用 JSON.stringify 來實(shí)現(xiàn), 但是它也會(huì)有局限性, 比如:

          1. 轉(zhuǎn)換值如果有 toJSON() 方法,那么由 toJson() 定義什么值將被序列化
          2. 非數(shù)組對(duì)象的屬性不能保證以特定的順序出現(xiàn)在序列化后的字符串中
          3. 布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值
          4. undefined、任意的函數(shù)以及 symbol 值,在序列化過程中會(huì)被忽略(出現(xiàn)在非數(shù)組對(duì)象的屬性值中時(shí))或者被轉(zhuǎn)換成 null(出現(xiàn)在數(shù)組中時(shí))。函數(shù)、undefined 被單獨(dú)轉(zhuǎn)換時(shí),會(huì)返回 undefined,如JSON.stringify(function(){}) or JSON.stringify(undefined)
          5. 所有以 symbol 為屬性鍵的屬性都會(huì)被完全忽略掉,即便 replacer 參數(shù)中強(qiáng)制指定包含了它們
          6. Date 日期調(diào)用了 toJSON() 將其轉(zhuǎn)換為了 string 字符串(同Date.toISOString()),因此會(huì)被當(dāng)做字符串處理
          7. NaN 和 Infinity 格式的數(shù)值及 null 都會(huì)被當(dāng)做 null
          8. 其他類型的對(duì)象,包括 Map/Set/WeakMap/WeakSet,僅會(huì)序列化可枚舉的屬性

          我們可以看到第4條, 如果我們序列化的對(duì)象中有函數(shù), 它將會(huì)被忽略! 所以常理上我們使用JSON.stringify 是無法保存函數(shù)的, 那還有其他辦法嗎?

          也許大家會(huì)想到先將函數(shù)轉(zhuǎn)換成字符串, 再用 JSON.stringify 序列化后保存到后端, 最后在組件使用的時(shí)候再用 eval 或者 Function 將字符串轉(zhuǎn)換成函數(shù). 大致流程如下:

          不錯(cuò), 理想很美好, 但是現(xiàn)實(shí)很_______.

          接下來我們就一起分析一下關(guān)鍵環(huán)節(jié) func2stringstring2func 如何實(shí)現(xiàn)的.

          js存儲(chǔ)函數(shù)方案設(shè)計(jì)

          熟悉 JSON API 的朋友可能會(huì)知道 JSON.stringify 支持3個(gè)參數(shù), 第二個(gè)參數(shù) replacer 可以是一個(gè)函數(shù)或者一個(gè)數(shù)組。作為函數(shù),它有兩個(gè)參數(shù),鍵(key)和值(value),它們都會(huì)被序列化。 函數(shù)需要返回 JSON 字符串中的 value, 如下所示:

          • 如果返回一個(gè) Number, 轉(zhuǎn)換成相應(yīng)的字符串作為屬性值被添加入 JSON 字符串
          • 如果返回一個(gè) String, 該字符串作為屬性值被添加入 JSON 字符串
          • 如果返回一個(gè) Boolean, 則 "true" 或者 "false" 作為屬性值被添加入 JSON 字符串
          • 如果返回任何其他對(duì)象,該對(duì)象遞歸的序列化成 JSON 字符串,對(duì)每個(gè)屬性調(diào)用 replacer 方法。除非該對(duì)象是一個(gè)函數(shù),這種情況將不會(huì)被序列化成 JSON 字符
          • 如果返回 undefined,該屬性值不會(huì)在 JSON 字符串中輸出

          所以我們可以在第二個(gè)函數(shù)參數(shù)里對(duì) value類型為函數(shù)的數(shù)據(jù)進(jìn)行轉(zhuǎn)換。如下:

          const stringify=(obj)=> {
              return JSON.stringify(obj, (k, v)=> {
                if(typeof v==='function') {
                    return `${v}`
                }
                return v
              })
          }
          

          這樣我們看似就能把函數(shù)保存到后端了. 接下來我們看看如何反序列化帶函數(shù)字符串的 json.

          因?yàn)槲覀儗⒑瘮?shù)轉(zhuǎn)換為字符串了, 我們?cè)诜唇馕鰰r(shí)就需要知道哪些字符串是需要轉(zhuǎn)換成函數(shù)的, 如果不對(duì)函數(shù)做任何處理我們可能需要「人肉識(shí)別」.

          ? 「人肉識(shí)別」的缺點(diǎn)在于我們需要用正則把具有函數(shù)特征的字符串提取出來, 但是函數(shù)寫法有很多, 我們要考慮很多情況, 也不能保證具有函數(shù)特征的字符串一定是函數(shù).
          ?

          所以我換了一種簡(jiǎn)單的方式, 可以不用寫復(fù)雜正則就能將函數(shù)提取出來, 方法就是在函數(shù)序列化的時(shí)候注入標(biāo)識(shí)符, 這樣我們就能知道那些字符串是需要解析為函數(shù)了, 如下:

          stringify: function(obj: any, space: number | string, error: (err: Error | unknown)=> {}) {
                  try {
                      return JSON.stringify(obj, (k, v)=> {
                          if(typeof v==='function') {
                              return `${this.FUNC_PREFIX}${v}`
                          }
                          return v
                      }, space)
                  } catch(err) {
                      error && error(err)
                  }
          }
          

          this.FUNC_PREFIX 就是我們定義的標(biāo)識(shí)符, 這樣我們?cè)谟?JSON.parse 的時(shí)候就能快速解析函數(shù)了. JSON.parse 也支持第二個(gè)參數(shù), 他的用法和 JSON.stringify 的第二個(gè)參數(shù)類似, 我們可以對(duì)它進(jìn)行轉(zhuǎn)換, 如下:

          parse: function(jsonStr: string, error: (err: Error | unknown)=> {}) {
                  try {
                      return JSON.parse(jsonStr, (key, value)=> {
                          if(value && typeof value==='string') {
                              return value.indexOf(this.FUNC_PREFIX) > -1 ? new Function(`return ${value.replace(this.FUNC_PREFIX, '')}`)() : value
                          }
                          return value
                      })
                  } catch(err) {
                      error && error(err)
                  }
              }
          

          new Function 可以把字符串轉(zhuǎn)換成 js 函數(shù), 它只接受字符串參數(shù),其可選參數(shù)為方法的入?yún)ⅲ靥顓?shù)為方法體內(nèi)容, 一個(gè)形象的例子:

          我們上述的代碼中函數(shù)體的內(nèi)容:

          new Function(`return ${value.replace(this.FUNC_PREFIX, '')}`)()
          

          之所以要 return 是為了把原函數(shù)原封不動(dòng)的還原, 大家也可以用 eval , 但是出于輿論還是謹(jǐn)慎使用.

          以上方案已經(jīng)能實(shí)現(xiàn)前端存儲(chǔ)函數(shù)的功能了, 但是為了更工程化和健壯性還需要做很多額外的處理和優(yōu)化, 這樣才能讓更多人開箱即用的使用你的庫.

          最后

          為了讓更多人能直接使用這個(gè)功能, 我將完整版 json 序列化方案封裝成了類庫, 支持功能如下:

          • stringify 在原生JSON.stringify 的基礎(chǔ)上支持序列化函數(shù),錯(cuò)誤回調(diào)
          • parse 在原生JSON.parse 的基礎(chǔ)上支持反序列化函數(shù),錯(cuò)誤回調(diào)
          • funcParse 將js對(duì)象中的函數(shù)一鍵序列化, 并保持js對(duì)象類型不變

          安裝方式如下:

          # or npm install xijs
          yarn add xijs
          

          使用:

          import { parser } from 'xijs';
          
          const a={
              x: 12,
              b: function() {
                alert(1)
              }
           }
           
           const json=parser.stringify(a);
           const obj=parser.parse(json);
           // 調(diào)用方法
           obj.b();
          

          更多推薦

          . 各種存儲(chǔ)方案的簡(jiǎn)單對(duì)比

          • Cookies:瀏覽器均支持,容量為4KB
          • UserData:僅IE支持,容量為64KB
          • Flash:100KB,非HTML原生,需要插件支持
          • Google Gears SQLite :需要插件支持,容量無限制
          • LocalStorage:HTML5,容量為5M
          • SesstionStorage:HTML5,容量為5M
          • globalStorage:Firefox獨(dú)有的,F(xiàn)irefox13開始就不再支持這個(gè)方法

          UserData僅IE支持, Google Gears SQLite需要插件,F(xiàn)lash已經(jīng)伴隨著HTML5的出現(xiàn)漸漸退出了歷史舞臺(tái),因此今天我們的主角只有他們?nèi)齻€(gè):Cookie,LocalStorge,SesstionStorge;

          2. Cookie

          作為一個(gè)前端和Cookie打交道的次數(shù)肯定不會(huì)少了,Cookie算是比較古老的技術(shù)了

          1993 年,網(wǎng)景公司雇員 Lou Montulli 為了讓用戶在訪問某網(wǎng)站時(shí),進(jìn)一步提高訪問速度,同時(shí)也為了進(jìn)一步實(shí)現(xiàn)個(gè)人化網(wǎng)絡(luò),發(fā)明了今天廣泛使用的 Cookie。

          2.1 Cookie的特點(diǎn)

          我們先來看下Cookie的特點(diǎn):

          • 1)cookie的大小受限制,cookie大小被限制在4KB,不能接受像大文件或郵件那樣的大數(shù)據(jù)。
          • 2)只要有請(qǐng)求涉及cookie,cookie就要在服務(wù)器和瀏覽器之間來回傳送(這解釋為什么本地文件不能測(cè)試cookie)。而且cookie數(shù)據(jù)始終在同源的http請(qǐng)求中攜帶(即使不需要),這也是Cookie不能太大的重要原因。正統(tǒng)的cookie分發(fā)是通過擴(kuò)展HTTP協(xié)議來實(shí)現(xiàn)的,服務(wù)器通過在HTTP的響應(yīng)頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應(yīng)的cookie。
          • 3)用戶每請(qǐng)求一次服務(wù)器數(shù)據(jù),cookie則會(huì)隨著這些請(qǐng)求發(fā)送到服務(wù)器,服務(wù)器腳本語言如PHP等能夠處理cookie發(fā)送的數(shù)據(jù),可以說是非常方便的。當(dāng)然前端也是可以生成Cookie的,用js對(duì)cookie的操作相當(dāng)?shù)姆爆崳瑸g覽器只提供document.cookie這樣一個(gè)對(duì)象,對(duì)cookie的賦值,獲取都比較麻煩。而在PHP中,我們可以通過setcookie()來設(shè)置cookie,通過$_COOKIE這個(gè)超全局?jǐn)?shù)組來獲取cookie。

          cookie的內(nèi)容主要包括:名字,值,過期時(shí)間,路徑和域。路徑與域一起構(gòu)成cookie的作用范圍。若不設(shè)置過期時(shí)間,則表示這個(gè)cookie的生命期為瀏覽器會(huì)話期間,關(guān)閉瀏覽器窗口,cookie就消失。這種生命期為瀏覽器會(huì)話期的cookie被稱為會(huì)話cookie。會(huì)話cookie一般不存儲(chǔ)在硬盤上而是保存在內(nèi)存里,當(dāng)然這種行為并不是規(guī)范規(guī)定的。若設(shè)置了過期時(shí)間,瀏覽器就會(huì)把cookie保存到硬盤上,關(guān)閉后再次打開瀏覽器,這些cookie仍然有效直到超過設(shè)定的過期時(shí)間。存儲(chǔ)在硬盤上的cookie可以在不同的瀏覽器進(jìn)程間共享,比如兩個(gè)IE窗口。而對(duì)于保存在內(nèi)存里的cookie,不同的瀏覽器有不同的處理方式。

          2.2 Session

          說到Cookie就不能不說Session。

          Session機(jī)制。session機(jī)制是一種服務(wù)器端的機(jī)制,服務(wù)器使用一種類似于散列表的結(jié)構(gòu)(也可能就是使用散列表)來保存信息。當(dāng)程序需要為某個(gè)客戶端的請(qǐng)求創(chuàng)建一個(gè)session時(shí),服務(wù)器首先檢查這個(gè)客戶端的請(qǐng)求里是否已包含了一個(gè)session標(biāo)識(shí)(稱為session id),如果已包含則說明以前已經(jīng)為此客戶端創(chuàng)建過session,服務(wù)器就按照session id把這個(gè)session檢索出來使用(檢索不到,會(huì)新建一個(gè)),如果客戶端請(qǐng)求不包含session id,則為此客戶端創(chuàng)建一個(gè)session并且生成一個(gè)與此session相關(guān)聯(lián)的session id,session id的值應(yīng)該是一個(gè)既不會(huì)重復(fù),又不容易被找到規(guī)律以仿造的字符串,這個(gè)session id將被在本次響應(yīng)中返回給客戶端保存。保存這個(gè)session id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動(dòng)的按照規(guī)則把這個(gè)標(biāo)識(shí)發(fā)送給服務(wù)器。一般這個(gè)cookie的名字都是類似于SEEESIONID。但cookie可以被人為的禁止,則必須有其他機(jī)制以便在cookie被禁止時(shí)仍然能夠把session id傳遞回服務(wù)器。經(jīng)常被使用的一種技術(shù)叫做URL重寫,就是把session id直接附加在URL路徑的后面。比如:http://damonare.cn?sessionid=123456還有一種技術(shù)叫做表單隱藏字段。就是服務(wù)器會(huì)自動(dòng)修改表單,添加一個(gè)隱藏字段,以便在表單提交時(shí)能夠把session id傳遞回服務(wù)器。比如:

          <form name="testform" action="/xxx">
           <input type="hidden" name="sessionid" value="123456">
           <input type="text">
          </form>
          

          實(shí)際上這種技術(shù)可以簡(jiǎn)單的用對(duì)action應(yīng)用URL重寫來代替。

          2.3 Cookie和Session簡(jiǎn)單對(duì)比

          Cookie和Session 的區(qū)別:

          • 1)cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
          • 2)cookie不是很安全,別人可以分析存放在本地的cookie并進(jìn)行cookie欺騙,考慮到安全應(yīng)當(dāng)使用session。
          • 3)session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多,會(huì)比較占用你服務(wù)器的性能考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用cookie。
          • 4)單個(gè)cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個(gè)站點(diǎn)最多保存20個(gè)cookie。5)所以建議:將登陸信息等重要信息存放為SESSION其他信息如果需要保留,可以放在cookie中

          2.4 document.cookie的屬性

          expires屬性

          指定了coolie的生存期,默認(rèn)情況下coolie是暫時(shí)存在的,他們存儲(chǔ)的值只在瀏覽器會(huì)話期間存在,當(dāng)用戶推出瀏覽器后這些值也會(huì)丟失,如果想讓cookie存在一段時(shí)間,就要為expires屬性設(shè)置為未來的一個(gè)過期日期。現(xiàn)在已經(jīng)被max-age屬性所取代,max-age用秒來設(shè)置cookie的生存期。

          path屬性

          它指定與cookie關(guān)聯(lián)在一起的網(wǎng)頁。在默認(rèn)的情況下cookie會(huì)與創(chuàng)建它的網(wǎng)頁,該網(wǎng)頁處于同一目錄下的網(wǎng)頁以及與這個(gè)網(wǎng)頁所在目錄下的子目錄下的網(wǎng)頁關(guān)聯(lián)。

          domain屬性

          domain屬性可以使多個(gè)web服務(wù)器共享cookie。domain屬性的默認(rèn)值是創(chuàng)建cookie的網(wǎng)頁所在服務(wù)器的主機(jī)名。不能將一個(gè)cookie的域設(shè)置成服務(wù)器所在的域之外的域。例如讓位于http://order.damonare.cn的服務(wù)器能夠讀取http://catalog.damonare.cn設(shè)置的cookie值。如果http://catalog.damonare.cn的頁面創(chuàng)建的cookie把自己的path屬性設(shè)置為“/”,把domain屬性設(shè)置成“.damonare.cn”,那么所有位于http://catalog.damonare.cn的網(wǎng)頁和所有位于http://orlders.damonare.cn的網(wǎng)頁,以及位于http://damonare.cn域的其他服務(wù)器上的網(wǎng)頁都可以訪問這個(gè)cookie。

          secure屬性

          它是一個(gè)布爾值,指定在網(wǎng)絡(luò)上如何傳輸cookie,默認(rèn)是不安全的,通過一個(gè)普通的http連接傳輸

          2.5 cookie實(shí)戰(zhàn)

          這里我們使用javascript來寫一段cookie,借用w3cschool的demo:

          function getCookie(c_name){
           if (document.cookie.length>0){
           c_start=document.cookie.indexOf(c_name + "=")
           if (c_start!=-1){
           c_start=c_start + c_name.length+1
           c_end=document.cookie.indexOf(";",c_start)
           if (c_end==-1) c_end=document.cookie.length
           return unescape(document.cookie.substring(c_start,c_end))
           }
           }
           return "";
          }
          function setCookie(c_name,value,expiredays){
           var exdate=new Date()
           exdate.setDate(exdate.getDate()+expiredays)
           document.cookie=c_name+ "=" +escape(value)+
           ((expiredays==null) ? "" : "; expires="+exdate.toUTCString())
          }
          function checkCookie(){
           username=getCookie('username')
           if(username!=null && username!=""){alert('Welcome again '+username+'!')}
           else{
           username=prompt('Please enter your name:',"")
           if (username!=null && username!=""){
           setCookie('username',username,355)
           }
           }
          }
          

          注意這里對(duì)Cookie的生存期進(jìn)行了定義,也就是355天

          3. localStorage

          這是一種持久化的存儲(chǔ)方式,也就是說如果不手動(dòng)清除,數(shù)據(jù)就永遠(yuǎn)不會(huì)過期。

          它也是采用Key - Value的方式存儲(chǔ)數(shù)據(jù),底層數(shù)據(jù)接口是sqlite,按域名將數(shù)據(jù)分別保存到對(duì)應(yīng)數(shù)據(jù)庫文件里。它能保存更大的數(shù)據(jù)(IE8上是10MB,Chrome是5MB),同時(shí)保存的數(shù)據(jù)不會(huì)再發(fā)送給服務(wù)器,避免帶寬浪費(fèi)。

          3.1 localStorage的屬性方法

          下表是localStorge的一些屬性和方法

          屬性方法 說明 localStorage.length 獲得storage中的個(gè)數(shù) localStorage.key(n) 獲得storage中第n個(gè)元素對(duì)的鍵值(第一個(gè)元素是0) localStorage.getItem(key) 獲取鍵值key對(duì)應(yīng)的值 localStorage.key 獲取鍵值key對(duì)應(yīng)的值 localStorage.setItem(key, value) 添加數(shù)據(jù),鍵值為key,值為value localStorage.removeItem(key) 移除鍵值為key的數(shù)據(jù) localStorage.clear() 清除所有數(shù)據(jù)

          3.2 localStorage的缺點(diǎn)

          • ① localStorage大小限制在500萬字符左右,各個(gè)瀏覽器不一致
          • ② localStorage在隱私模式下不可讀取
          • ③ localStorage本質(zhì)是在讀寫文件,數(shù)據(jù)多的話會(huì)比較卡(firefox會(huì)一次性將數(shù)據(jù)導(dǎo)入內(nèi)存,想想就覺得嚇人啊)
          • ④ localStorage不能被爬蟲爬取,不要用它完全取代URL傳參

          4. sessionStorage

          和服務(wù)器端使用的session類似,是一種會(huì)話級(jí)別的緩存,關(guān)閉瀏覽器會(huì)數(shù)據(jù)會(huì)被清除。不過有點(diǎn)特別的是它的作用域是窗口級(jí)別的,也就是說不同窗口間的sessionStorage數(shù)據(jù)不能共享的。使用方法(和localStorage完全相同):

          屬性方法 說明 sessionStorage.length 獲得storage中的個(gè)數(shù) sessionStorage.key(n) 獲得storage中第n個(gè)元素對(duì)的鍵值(第一個(gè)元素是0) sessionStorage.getItem(key) 獲取鍵值key對(duì)應(yīng)的值 sessionStorage.key 獲取鍵值key對(duì)應(yīng)的值 sessionStorage.setItem(key, value) 添加數(shù)據(jù),鍵值為key,值為value sessionStorage.removeItem(key) 移除鍵值為key的數(shù)據(jù) sessionStorage.clear() 清除所有數(shù)據(jù)

          5. sessionStorage和localStorage的區(qū)別

          • sessionStorage用于本地存儲(chǔ)一個(gè)會(huì)話(session)中的數(shù)據(jù),這些數(shù)據(jù)只有在同一個(gè)會(huì)話中的頁面才能訪問并且當(dāng)會(huì)話結(jié)束后數(shù)據(jù)也隨之銷毀。因此sessionStorage不是一種持久化的本地存儲(chǔ),僅僅是會(huì)話級(jí)別的存儲(chǔ)。當(dāng)用戶關(guān)閉瀏覽器窗口后,數(shù)據(jù)立馬會(huì)被刪除。
          • localStorage用于持久化的本地存儲(chǔ),除非主動(dòng)刪除數(shù)據(jù),否則數(shù)據(jù)是永遠(yuǎn)不會(huì)過期的。第二天、第二周或下一年之后,數(shù)據(jù)依然可用。

          5.1 測(cè)試

          sessionStorage:

          if (sessionStorage.pagecount){
           sessionStorage.pagecount=Number(sessionStorage.pagecount) +1;
          }else{
           sessionStorage.pagecount=1;
          }
          console.log("Visits "+ sessionStorage.pagecount + " time(s).");
          

          測(cè)試過程:我們?cè)诳刂婆_(tái)輸入上述代碼查看打印結(jié)果

          控制臺(tái)首次輸入代碼:

          關(guān)閉窗口,控制臺(tái)再次輸入代碼:

          所謂的關(guān)閉窗口即銷毀,就是這樣,關(guān)閉窗口重新打開輸入代碼輸出結(jié)果還是上面圖片的樣子,也就是說關(guān)閉窗口后sessionStorage.pagecount即被銷毀,除非重心創(chuàng)建。或者從歷史記錄進(jìn)入才會(huì)相關(guān)數(shù)據(jù)才會(huì)存在。好的,我們?cè)賮砜聪耹ocalStorge表現(xiàn):

          if (localStorage.pagecount){
           localStorage.pagecount=Number(localStorage.pagecount) +1;
          }else{
           localStorage.pagecount=1;
           }
          console.log("Visits "+ localStorage.pagecount + " time(s).");
          

          控制臺(tái)首次輸入代碼:

          關(guān)閉窗口,控制臺(tái)再次輸入代碼:

          6. web Storage和cookie的區(qū)別

          Web Storage(localStorage和sessionStorage)的概念和cookie相似,區(qū)別是它是為了更大容量存儲(chǔ)設(shè)計(jì)的。Cookie的大小是受限的,并且每次你請(qǐng)求一個(gè)新的頁面的時(shí)候Cookie都會(huì)被發(fā)送過去,這樣無形中浪費(fèi)了帶寬,另外cookie還需要指定作用域,不可以跨域調(diào)用。

          除此之外,Web Storage擁有setItem,getItem,removeItem,clear等方法,不像cookie需要前端開發(fā)者自己封裝setCookie,getCookie。

          但是Cookie也是不可以或缺的:Cookie的作用是與服務(wù)器進(jìn)行交互,作為HTTP規(guī)范的一部分而存在 ,而Web Storage僅僅是為了在本地“存儲(chǔ)”數(shù)據(jù)而生


          主站蜘蛛池模板: 国产对白精品刺激一区二区| 国产一区二区三区高清在线观看 | 一区二区三区精品视频| 国产一区二区成人| 久久久无码一区二区三区| 国产成人精品无码一区二区| 好湿好大硬得深一点动态图91精品福利一区二区 | 精品国产日韩亚洲一区91| 无码一区二区三区老色鬼| 无码少妇一区二区三区| 日韩免费无码视频一区二区三区| 国产另类TS人妖一区二区| 日本不卡一区二区视频a| 亚洲AV无码一区二区乱孑伦AS| 激情内射日本一区二区三区| 成人精品一区二区三区不卡免费看| 国产伦一区二区三区高清 | 国产精品视频一区麻豆| 伊人久久精品一区二区三区| 国产乱码一区二区三区| 午夜性色一区二区三区不卡视频| 国模精品视频一区二区三区| 在线视频国产一区| 久久影院亚洲一区| 中文字幕精品一区影音先锋| AV无码精品一区二区三区| 成人毛片一区二区| 亚洲国产高清在线一区二区三区| 国产一区麻豆剧传媒果冻精品| 国精无码欧精品亚洲一区| 久久国产精品无码一区二区三区| 亚洲中文字幕一区精品自拍| 色婷婷亚洲一区二区三区| 国产vr一区二区在线观看| 国模无码人体一区二区| 国产香蕉一区二区在线网站| 国产综合无码一区二区色蜜蜜| 久久精品国产一区二区| 亚洲AV日韩AV天堂一区二区三区| 亚洲乱码av中文一区二区 | 国产激情一区二区三区|