国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端基本功-常見概念(二)

big_cat / 1144人閱讀

摘要:前端基本功常見概念一點(diǎn)這里前端基本功常見概念二點(diǎn)這里前端基本功常見概念三點(diǎn)這里是更完美的,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。

前端基本功-常見概念(一) 點(diǎn)這里
前端基本功-常見概念(二) 點(diǎn)這里
前端基本功-常見概念(三) 點(diǎn)這里

1.let、const/var
let 是更完美的var,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。
const 定義常量值,不能夠重新賦值,如果值是一個(gè)對象,可以改變對象里邊的屬性值

var存在的問題

var有作用域問題(會(huì)污染全局作用域)

var可已重復(fù)聲明

var會(huì)變量提升預(yù)解釋

var不能定義常量

let、const特性

let、const不可以重復(fù)聲明

let、const不會(huì)聲明到全局作用域上

let、const不會(huì)預(yù)解釋變量

const做常量聲明(一般常量名用大寫)

let聲明的變量具有塊級作用域

let聲明的變量不能通過window.變量名進(jìn)行訪問

形如for(let x..)的循環(huán)是每次迭代都為x創(chuàng)建新的綁定

下面是 var 帶來的不合理場景
var a = []
for (var i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i)
    }
}
a[5]() // 10

在上述代碼中,變量i是var聲明的,在全局范圍類都有效。所以每一次循環(huán),新的i值都會(huì)覆蓋舊值,導(dǎo)致最后輸出都是10
而如果對循環(huán)使用let語句的情況,那么每次迭代都是為x創(chuàng)建新的綁定代碼如下

var a = []
for (let i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i)
    }
}
a[5]() // 5
重溫一下閉包和立即函數(shù)兩種方法

閉包的方法

function showNum(i) {
    return function () {
        console.log(i)
    }
}
var a = []
for (var i = 0; i < 5; i++) {
    a[i] = showNum(i)
}

立即函數(shù)的方法

var a = []
for (var i = 0; i < 5; i++) {
    a[i] = (function (i) {
        return function () {
            console.log(i)
        }
    })(i)
}
a[2]()

本節(jié)參考文章:前端面試之ES6篇

2.重排/重繪

在討論重排(回流)與重繪之前,我們要知道:

瀏覽器使用流式布局模型 (Flow Based Layout)。

瀏覽器會(huì)把HTMLDOM,把CSS解析成CSSOMDOMCSSOM合并就產(chǎn)生了Render Tree

有了RenderTree,我們就知道了所有節(jié)點(diǎn)的樣式,然后計(jì)算他們在頁面上的大小和位置,最后把節(jié)點(diǎn)繪制到頁面上。

由于瀏覽器使用流式布局,對Render Tree的計(jì)算通常只需要遍歷一次就可以完成,但table及其內(nèi)部元素除外,他們可能需要多次計(jì)算,通常要花3倍于同等元素的時(shí)間,這也是為什么要避免使用table布局的原因之一。

一句話:重排必將引起重繪,重繪不一定會(huì)引起重排。
重排 (Reflow)

當(dāng)Render Tree中部分或全部元素的尺寸、結(jié)構(gòu)、或某些屬性發(fā)生改變時(shí),瀏覽器重新渲染部分或全部文檔的過程稱為重排。

會(huì)導(dǎo)致重排的操作:

頁面首次渲染

瀏覽器窗口大小發(fā)生改變

元素尺寸或位置發(fā)生改變

元素內(nèi)容變化(文字?jǐn)?shù)量或圖片大小等等)

元素字體大小變化

添加或者刪除可見的DOM元素

激活CSS偽類(例如::hover)

查詢某些屬性或調(diào)用某些方法

一些常用且會(huì)導(dǎo)致重排的屬性和方法:

clientWidth、clientHeight、clientTop、clientLeft

offsetWidth、offsetHeight、offsetTop、offsetLeft

scrollWidth、scrollHeight、scrollTop、scrollLeft

scrollIntoView()、scrollIntoViewIfNeeded()

getComputedStyle()

getBoundingClientRect()

scrollTo()

重繪 (Repaint)

當(dāng)頁面中元素樣式的改變并不影響它在文檔流中的位置時(shí)(例如:color、background-color、visibility等),瀏覽器會(huì)將新樣式賦予給元素并重新繪制它,這個(gè)過程稱為重繪。

性能影響

回流比重繪的代價(jià)要更高。

有時(shí)即使僅僅回流一個(gè)單一的元素,它的父元素以及任何跟隨它的元素也會(huì)產(chǎn)生回流。

現(xiàn)代瀏覽器會(huì)對頻繁的回流或重繪操作進(jìn)行優(yōu)化:

瀏覽器會(huì)維護(hù)一個(gè)隊(duì)列,把所有引起回流和重繪的操作放入隊(duì)列中,如果隊(duì)列中的任務(wù)數(shù)量或者時(shí)間間隔達(dá)到一個(gè)閾值的,瀏覽器就會(huì)將隊(duì)列清空,進(jìn)行一次批處理,這樣可以把多次回流和重繪變成一次。

當(dāng)你訪問以下屬性或方法時(shí),瀏覽器會(huì)立刻清空隊(duì)列:

clientWidth、clientHeight、clientTop、clientLeft

offsetWidth、offsetHeight、offsetTop、offsetLeft

scrollWidth、scrollHeight、scrollTop、scrollLeft

width、height

getComputedStyle()

getBoundingClientRect()

因?yàn)殛?duì)列中可能會(huì)有影響到這些屬性或方法返回值的操作,即使你希望獲取的信息與隊(duì)列中操作引發(fā)的改變無關(guān),瀏覽器也會(huì)強(qiáng)行清空隊(duì)列,確保你拿到的值是最精確的。

如何避免

CSS

避免使用table布局。

盡可能在DOM樹的最末端改變class。

避免設(shè)置多層內(nèi)聯(lián)樣式。

將動(dòng)畫效果應(yīng)用到position屬性為absolute或fixed的元素上。

避免使用CSS表達(dá)式(例如:calc())。

JavaScript

避免頻繁操作樣式,最好一次性重寫style屬性,或者將樣式列表定義為class并一次性更改class屬性。

避免頻繁操作DOM,創(chuàng)建一個(gè)documentFragment,在它上面應(yīng)用所有DOM操作,最后再把它添加到文檔中。

也可以先為元素設(shè)置display: none,操作結(jié)束后再把它顯示出來。因?yàn)樵赿isplay屬性為none的元素上進(jìn)行的DOM操作不會(huì)引發(fā)回流和重繪。

避免頻繁讀取會(huì)引發(fā)回流/重繪的屬性,如果確實(shí)需要多次使用,就用一個(gè)變量緩存起來。

對具有復(fù)雜動(dòng)畫的元素使用絕對定位,使它脫離文檔流,否則會(huì)引起父元素及后續(xù)元素頻繁回流。

本節(jié)參考文章:[瀏覽器的回流與重繪 (Reflow & Repaint)](https://juejin.im/post/5a9923e9518825558251c96a)

3.函數(shù)節(jié)流(throttle)與函數(shù)去抖(debounce)

Debounce:一部電梯停在某一個(gè)樓層,當(dāng)有一個(gè)人進(jìn)來后,20秒后自動(dòng)關(guān)門,這20秒的等待期間,又一個(gè)人按了電梯進(jìn)來,這20秒又重新計(jì)算,直到電梯關(guān)門那一刻才算是響應(yīng)了事件。

Throttle:好比一臺(tái)自動(dòng)的飲料機(jī),按拿鐵按鈕,在出飲料的過程中,不管按多少這個(gè)按鈕,都不會(huì)連續(xù)出飲料,中間按鈕的響應(yīng)會(huì)被忽略,必須要等這一杯的容量全部出完之后,再按拿鐵按鈕才會(huì)出下一杯。

4.強(qiáng)緩存/協(xié)商緩存

瀏覽器緩存分為強(qiáng)緩存和協(xié)商緩存,優(yōu)先讀取強(qiáng)制緩存。
當(dāng)客戶端請求某個(gè)資源時(shí),獲取緩存的流程如下:

先根據(jù)這個(gè)資源的一些 http header 判斷它是否命中強(qiáng)緩存,如果命中,則直接從本地獲取緩存資源,不會(huì)發(fā)請求到服務(wù)器;

當(dāng)強(qiáng)緩存沒有命中時(shí),客戶端會(huì)發(fā)送請求到服務(wù)器,服務(wù)器通過另一些request header驗(yàn)證這個(gè)資源是否命中協(xié)商緩存,稱為http再驗(yàn)證,如果命中,服務(wù)器將請求返回,但不返回資源,而是告訴客戶端直接從緩存中獲取,客戶端收到返回后就會(huì)從緩存中獲取資源;

強(qiáng)緩存和協(xié)商緩存共同之處在于,如果命中緩存,服務(wù)器都不會(huì)返回資源;

區(qū)別是,強(qiáng)緩存不對發(fā)送請求到服務(wù)器,但協(xié)商緩存會(huì)。

當(dāng)協(xié)商緩存也沒命中時(shí),服務(wù)器就會(huì)將資源發(fā)送回客戶端。

當(dāng) ctrl+f5 強(qiáng)制刷新網(wǎng)頁時(shí),直接從服務(wù)器加載,跳過強(qiáng)緩存和協(xié)商緩存;

當(dāng) f5 刷新網(wǎng)頁時(shí),跳過強(qiáng)緩存,但是會(huì)檢查協(xié)商緩存;

強(qiáng)緩存

Expires(該字段是 http1.0 時(shí)的規(guī)范,值為一個(gè)絕對時(shí)間的 GMT 格式的時(shí)間字符串,代表緩存資源的過期時(shí)間)

Cache-Control:max-age(該字段是 http1.1 的規(guī)范,強(qiáng)緩存利用其 max-age 值來判斷緩存資源的最大生命周期,它的值單位為秒)

協(xié)商緩存

協(xié)商緩存是利用的是【Last-Modified,If-Modified-Since】和【ETag、If-None-Match】這兩對Header來管理的

Last-Modified,If-Modified-Since

Last-Modified 表示本地文件最后修改日期,瀏覽器會(huì)在request header加上If-Modified-Since(上次返回的Last-Modified的值),詢問服務(wù)器在該日期后資源是否有更新,有更新的話就會(huì)將新的資源發(fā)送回來

但是如果在本地打開緩存文件,就會(huì)造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現(xiàn)了 ETag

ETag、If-None-Match

Etag就像一個(gè)指紋,資源變化都會(huì)導(dǎo)致ETag變化,跟最后修改時(shí)間沒有關(guān)系,ETag可以保證每一個(gè)資源是唯一的

If-None-Match的header會(huì)將上次返回的Etag發(fā)送給服務(wù)器,詢問該資源的Etag是否有更新,有變動(dòng)就會(huì)發(fā)送新的資源回來

ETag的優(yōu)先級比Last-Modified更高

一些文件也許會(huì)周期性的更改,但是他的內(nèi)容并不改變(僅僅改變的修改時(shí)間),這個(gè)時(shí)候我們并不希望客戶端認(rèn)為這個(gè)文件被修改了,而重新GET;

某些文件修改非常頻繁,比如在秒以下的時(shí)間內(nèi)進(jìn)行修改,(比方說1s內(nèi)修改了N次),If-Modified-Since能檢查到的粒度是s級的,這種修改無法判斷(或者說UNIX記錄MTIME只能精確到秒);

某些服務(wù)器不能精確的得到文件的最后修改時(shí)間。

推薦必讀:http協(xié)商緩存VS強(qiáng)緩存、瀏覽器緩存知識(shí)小結(jié)及應(yīng)用、緩存(二)——瀏覽器緩存機(jī)制:強(qiáng)緩存、協(xié)商緩存

5.原始類型 / 引用類型

JavaScript中的內(nèi)存分為棧內(nèi)存和堆內(nèi)存。棧內(nèi)存和堆內(nèi)存區(qū)別:棧內(nèi)存運(yùn)行效率比堆內(nèi)存高,空間相對堆內(nèi)存來說較小。

區(qū)別:

值類型屬于不可變類型, 由于具有固定長度大小, 其地址和具體內(nèi)容都存在與棧內(nèi)存中

而引用類型屬于可變類型, 一個(gè)對象可以賦予多個(gè)屬性及值,屬性值又可以為一個(gè)新的引用對象。其地址存在棧內(nèi)存,其具體內(nèi)容存在堆內(nèi)存中。

6.cookie/token

token和cookie一樣都是首次登陸時(shí),由服務(wù)器下發(fā),都是當(dāng)交互時(shí)進(jìn)行驗(yàn)證的功能,作用都是為無狀態(tài)的HTTP提供的持久機(jī)制。

token存在哪兒都行,localstorage或者cookie。

token和cookie舉例,token就是說你告訴我你是誰就可以。

cookie 舉例:服務(wù)員看你的身份證,給你一個(gè)編號(hào),以后,進(jìn)行任何操作,都出示編號(hào)后服務(wù)員去看查你是誰。

token 舉例:直接給服務(wù)員看自己身份證,服務(wù)器不需要去查看你是誰,不需要保存你的會(huì)話。

當(dāng)用戶logout的時(shí)候,cookie和服務(wù)器的session都會(huì)注銷;但是當(dāng)logout時(shí)候token只是注銷瀏覽器信息,不查庫。

token優(yōu)勢在于,token由于服務(wù)器端不存儲(chǔ)會(huì)話,所以可擴(kuò)展性強(qiáng),token還可用于APP中。

小結(jié):

Token 完全由應(yīng)用管理,所以它可以避開同源策略
Token 可以避免 CSRF 攻擊
Token 可以是無狀態(tài)的,可以在多個(gè)服務(wù)間共享

如果你的用戶數(shù)據(jù)可能需要和第三方共享,或者允許第三方調(diào)用 API 接口,用 Token,如果之上自己的那就無所謂了。

本節(jié)參考文章:cookie和token的五點(diǎn)區(qū)別

推薦必讀:前后端常見的幾種鑒權(quán)方式

7.cookie/sessionStorage/localStorage 1.cookie
cookie分為cookie機(jī)制和session機(jī)制(請大神判斷正確性)
Session: 是在服務(wù)端保存的一個(gè)數(shù)據(jù)結(jié)構(gòu),用來跟蹤用戶的狀態(tài),這個(gè)數(shù)據(jù)可以保存在集群、數(shù)據(jù)庫、文件中,通過在服務(wù)器端記錄信息確定用戶身份
Cookie: 是客戶端保存用戶信息的一種機(jī)制,用來記錄用戶的一些信息,也是實(shí)現(xiàn)Session的一種方式,通過在客戶端記錄信息確定用戶身份

如果說Cookie機(jī)制是通過檢查客戶身上的“通行證”來確定客戶身份的話,那么Session機(jī)制就是通過檢查服務(wù)器上的“客戶明細(xì)表”來確認(rèn)客戶身份。Session相當(dāng)于程序在服務(wù)器上建立的一份客戶檔案,客戶來訪的時(shí)候只需要查詢客戶檔案表就可以了。

cookie機(jī)制
cookie可以通過設(shè)置domain屬性值,可以不同二級域名下共享cookie,而Storage不可以,比如http://image.baidu.com的cookie http://map.baidu.com是可以訪問的,前提是Cookie的domain設(shè)置為.http://baidu.com,而Storage是不可以的

session機(jī)制

當(dāng)程序需要為某個(gè)客戶端的請求創(chuàng)建一個(gè)session時(shí),

服務(wù)器首先檢查這個(gè)客戶端的請求里是否已包含了一個(gè)session標(biāo)識(shí)---稱為session id,

如果已包含則說明以前已經(jīng)為此客戶端創(chuàng)建過session,服務(wù)器就按照session id把這個(gè)session檢索出來使用(檢索不到,會(huì)新建一個(gè)),

如果客戶端請求不包含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)中返回給客戶端保存。

比較

session 在服務(wù)器端,cookie 在客戶端(瀏覽器)

session保存在服務(wù)器,客戶端不知道其中的信息;反之,cookie保存在客戶端,服務(wù)器能夠知道其中的信息

session會(huì)在一定時(shí)間內(nèi)保存在服務(wù)器上,當(dāng)訪問增多,會(huì)比較占用你服務(wù)器的性能,考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用cookie

session中保存的是對象,cookie中保存的是字符串

cookie不是很安全,別人可以分析存放在本地的cookie并進(jìn)行cookie欺騙,考慮到安全應(yīng)當(dāng)使用session。用戶驗(yàn)證這種場合一般會(huì)用 session

用戶驗(yàn)證這種場合一般會(huì)用 session,因此,維持一個(gè)會(huì)話的核心就是客戶端的唯一標(biāo)識(shí),即 session id

session 的運(yùn)行依賴 session id,而 session id 是存在 cookie 中的,也就是說,如果瀏覽器禁用了 cookie ,同時(shí) session 也會(huì)失效(但是可以通過其它方式實(shí)現(xiàn),比如在 url 中傳遞?session_id)

session不能區(qū)分路徑,同一個(gè)用戶在訪問一個(gè)網(wǎng)站期間,所有的session在任何一個(gè)地方都可以訪問到,而cookie中如果設(shè)置了路徑參數(shù),那么同一個(gè)網(wǎng)站中不同路徑下的cookie互相是訪問不到的

JavaScript原生的用法。

Cookie 以名/值對形式存儲(chǔ)
例如username=John Doe,這里的數(shù)據(jù)是string類型,如要是其他格式注意進(jìn)行格式轉(zhuǎn)換。

JavaScript 可以使用 document.cookie 屬性來創(chuàng)建 、讀取、及刪除 cookie。JavaScript 中,創(chuàng)建 cookie 如下所示:

document.cookie="username=John Doe";

您還可以為 cookie 添加一個(gè)過期時(shí)間(以 UTC 或 GMT 時(shí)間)。默認(rèn)情況下,cookie 在瀏覽器關(guān)閉時(shí)刪除:

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT";

您可以使用 path 參數(shù)告訴瀏覽器 cookie 的路徑。默認(rèn)情況下,cookie 屬于當(dāng)前頁面。

document.cookie="username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 GMT; path=/";

設(shè)置cookie

function setCookie(cname,cvalue,exdays){
  var SetTime = new Date();                                         //設(shè)置過期時(shí)間
  SetTime.setTime(SetTime.getTime()+(exdays*24*60*60*1000));        //設(shè)置過期時(shí)間
  var expires = "expires="+SetTime.toGMTString();                   //設(shè)置過期時(shí)間
  document.cookie = cname + "=" + cvalue + "; " + expires;          //創(chuàng)建一個(gè)cookie
}

讀取cookie

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 ""
}

刪除cookie

將cookie的有效時(shí)間改成昨天。

使用jquery.cookies.2.2.0.min.js插件

添加/修改cookie并設(shè)定過期時(shí)間:

$.cookies.set("cookie_id", "cookie_value", { hoursToLive: 10 });

這里設(shè)置的是過期時(shí)間是10小時(shí), 還可以這樣設(shè)置過期時(shí)間:

expireDate = new Date();
expireDate.setTime( expireDate.getTime() + ( 10 * 60 * 60 * 1000 ) );
$.cookies.set("cookie_id", "cookie_value", {expiresAt:expireDate});

獲取cookie

$.cookies.get("cookie_id");

刪除cookie

$.cookies.del("cookie_id");
2.Storage:localStorage、sessionStorage

大小:官方建議是5M存儲(chǔ)空間
類型:只能操作字符串,在存儲(chǔ)之前應(yīng)該使用JSON.stringfy()方法先進(jìn)行一步安全轉(zhuǎn)換字符串,取值時(shí)再用JSON.parse()方法再轉(zhuǎn)換一次
存儲(chǔ)的內(nèi)容: 數(shù)組,圖片,json,樣式,腳本。。。(只要是能序列化成字符串的內(nèi)容都可以存儲(chǔ))
區(qū)別:sessionStorage將數(shù)據(jù)臨時(shí)存儲(chǔ)在session中,瀏覽器關(guān)閉,數(shù)據(jù)隨之消失,localStorage將數(shù)據(jù)存儲(chǔ)在本地,理論上來說數(shù)據(jù)永遠(yuǎn)不會(huì)消失,除非人為刪除
注意:數(shù)據(jù)是明文存儲(chǔ),毫無隱私性可言,絕對不能用于存儲(chǔ)

基礎(chǔ)操作API

保存數(shù)據(jù)

localStorage.setItem( key, value );
sessionStorage.setItem(keyName,value);   // 將value存儲(chǔ)到key字段中
//或者
sessionStorage.keyName="value";

讀取數(shù)據(jù)

localStorage.getItem( key );
sessionStorage.getItem(keyName);          //獲取指定key的本地存儲(chǔ)的值
//或者
var keyName=sessionStorage.key;

刪除單個(gè)數(shù)據(jù)

localStorage.removeItem( key );
sessionStorage.removeItem( key );

刪除全部數(shù)據(jù)

localStorage.clear( );
sessionStorage.clear( );

獲取索引的key

localStorage.key( index );
sessionStorage.key( index );
監(jiān)聽storage事件

可以通過監(jiān)聽 window 對象的 storage 事件并指定其事件處理函數(shù),當(dāng)頁面中對 localStorage 或 sessionStorage 進(jìn)行修改時(shí),則會(huì)觸發(fā)對應(yīng)的處理函數(shù)

window.addEventListener("storage",function(e){
   console.log("key="+e.key+",oldValue="+e.oldValue+",newValue="+e.newValue);
})

localstorage是瀏覽器多個(gè)標(biāo)簽共用的存儲(chǔ)空間,可以用來實(shí)現(xiàn)多標(biāo)簽之間的通信(ps:session是會(huì)話級的存儲(chǔ)空間,每個(gè)標(biāo)簽頁都是多帶帶的

觸發(fā)事件的時(shí)間對象(e 參數(shù)值)有幾個(gè)屬性:
key : 鍵值。
oldValue : 被修改前的值。
newValue : 被修改后的值。
url : 頁面url。
storageArea : 被修改的 storage 對象。
3.對比

共同點(diǎn):都是保存在瀏覽器端、且同源的,都受同源策略的制約。

區(qū)別:

cookie數(shù)據(jù)始終在同源的http請求中攜帶(即使不需要),即cookie在瀏覽器和服務(wù)器間來回傳遞,而sessionStorage和localStorage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)送給服務(wù)器,僅在本地保存。cookie數(shù)據(jù)還有路徑(path)的概念,可以限制cookie只屬于某個(gè)路徑下

存儲(chǔ)大小限制也不同,cookie數(shù)據(jù)不能超過4K,同時(shí)因?yàn)槊看蝖ttp請求都會(huì)攜帶cookie、所以cookie只適合保存很小的數(shù)據(jù),如會(huì)話標(biāo)識(shí)。sessionStorage和localStorage雖然也有存儲(chǔ)大小的限制,但比cookie大得多,可以達(dá)到5M或更大

數(shù)據(jù)有效期不同,sessionStorage:僅在當(dāng)前瀏覽器窗口關(guān)閉之前有效;localStorage:始終有效,窗口或?yàn)g覽器關(guān)閉也一直保存,因此用作持久數(shù)據(jù);cookie:只在設(shè)置的cookie過期時(shí)間之前有效,即使窗口關(guān)閉或?yàn)g覽器關(guān)閉

作用域不同,sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個(gè)頁面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的

本節(jié)參考文章:緩存(三)——數(shù)據(jù)存儲(chǔ)...

其他閱讀:關(guān)于Cookie、session和Web Storage

8.js事件 1.事件
事件指可以被 JavaScript 偵測到的行為。即鼠標(biāo)點(diǎn)擊、頁面或圖像載入、鼠標(biāo)懸浮于頁面的某個(gè)熱點(diǎn)之上、在表單中選取輸入框、確認(rèn)表單、鍵盤按鍵等操作。
事件通常與函數(shù)配合使用,當(dāng)事件發(fā)生時(shí)函數(shù)才會(huì)執(zhí)行。

事件名稱:click/mouseover/blur("不帶on")
事件處理程序(事件偵聽器):響應(yīng)某個(gè)事件的函數(shù),名稱為:onclick/onmouseove/onblur,例如

2.DOM事件模型:冒泡和捕獲

冒泡:往上
捕獲:向下

3.事件流
事件流指從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序。

DOM2級事件規(guī)定的事件流包括三個(gè)階段:
(1)事件捕獲階段(2)處于目標(biāo)階段(3)事件冒泡階段。

當(dāng)事件發(fā)生時(shí),最先得到通知的是window,然后是document,由上至下逐級依次而入,直到真正觸發(fā)事件的那個(gè)元素(目標(biāo)元素)為止,這個(gè)過程就是捕獲。
接下來,事件會(huì)從目標(biāo)元素開始起泡,由下至上逐級依次傳播,直到window對象為止,這個(gè)過程就是冒泡。
所以捕獲比冒泡先執(zhí)行。

希望注冊在DOM元素上的事件處理程序在捕獲階段還是在冒泡階段觸發(fā),取決于 addEventListener() 方法的第三個(gè)參數(shù)為 true 還是 false 。

其中DOM3級事件在DOM2的基礎(chǔ)之上添加了更多的事件類型。

描述DOM事件捕獲的具體流程

window-->document-->html(document.documentElement)-->body(document.body)...
4.DOM級別/DOM事件
DOM級別一共可以分為4個(gè)級別:DOM0級,DOM1級,DOM2級和DOM3級,
而DOM事件分為3個(gè)級別:DOM0級事件處理,DOM2級事件處理和DOM3級事件處理。

其中1級DOM標(biāo)準(zhǔn)中并沒有定義事件相關(guān)的內(nèi)容,所以沒有所謂的1級DOM事件模型。

DOM0:element.onclick = function(){}
DOM2:element.addEventlistenter("click",function(){},flase)
DOM3:element.addEventlistenter("keyup",function(){},flase)

HTML事件處理程序



DOM0級事件處理程序

 btn.onclick=function(){
    alert("hello");
  }
btn.onclick = null;//來刪除指定的事件處理程序。

如果我們嘗試給事件添加兩個(gè)事件,如:


 

輸出,hello again,很明顯,第一個(gè)事件函數(shù)被第二個(gè)事件函數(shù)給覆蓋掉了, 所以,DOM0級事件處理程序不能添加多個(gè),也不能控制事件流到底是捕獲還是冒泡。

DOM2級事件處理程序

addEventListener() ---添加事件偵聽器

函數(shù)均有3個(gè)參數(shù),
第一個(gè)參數(shù)是要處理的事件名(不帶on前綴的才是事件名)
第二個(gè)參數(shù)是作為事件處理程序的函數(shù)
第三個(gè)參數(shù)是一個(gè)boolean值,默認(rèn)false表示使用冒泡機(jī)制,true表示捕獲機(jī)制。


 
 removeEventListener() //刪除事件偵聽器

可以綁定多個(gè)事件處理程序,但是注意,如果定義了一摸一樣時(shí)監(jiān)聽方法,是會(huì)發(fā)生覆蓋的,即同樣的事件和事件流機(jī)制下相同方法只會(huì)觸發(fā)一次,事件觸發(fā)的順序是添加的順序

```
// 為了兼容IE瀏覽器和標(biāo)準(zhǔn)的瀏覽器,我們需要編寫通用的方法來處理:
var EventUtil = {
    addHandler: function (element, type, handler) {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) {
            element.attachEvent("on" + type, handler);
        } else {
            element["on" + type] = handler;
        }
    },
    removeHandler: function (element, type, handler) {
        if (element.removeEventListener()) {
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent) {
            element.detachEvent("on" + type, handler);
        } else {
            element["on" + type] = null;
        }
    }
};
```


5.事件對象
事件對象是用來記錄一些事件發(fā)生時(shí)的相關(guān)信息的對象,但事件對象只有事件發(fā)生時(shí)才會(huì)產(chǎn)生,并且只能是事件處理函數(shù)內(nèi)部訪問,在所有事件處理函數(shù)運(yùn)行結(jié)束后,事件對象就被銷毀!

//currentTarget、eventPhase 一個(gè)例子:


 

當(dāng)然,事件對象也存在一定的兼容性問題,在IE8及以前本版之中,通過設(shè)置屬性注冊事件處理程序時(shí),調(diào)用的時(shí)候并未傳遞事件對象,需要通過全局對象window.event來獲取。解決方法如下:

function getEvent(event) {
 event = event || window.event;
}

在IE瀏覽器上面是event事件是沒有preventDefault()這個(gè)屬性的,所以在IE上,我們需要設(shè)置的屬性是returnValue

window.event.returnValue=false

stopPropagation()也是,所以需要設(shè)置cancelBubble,cancelBubble是IE事件對象的一個(gè)屬性,設(shè)置這個(gè)屬性為true能阻止事件進(jìn)一步傳播。

event.cancelBubble=true
常見屬性 解析
event.preventDefault() 阻止默認(rèn)行為
event.stopPropagation() 阻止冒泡。使用了stopPropagation()之后,事件就不能進(jìn)一步傳播了,同時(shí)如果是同一個(gè)div上有捕獲和冒泡兩種事件監(jiān)聽,在捕獲階段傳播阻止后冒泡階段事件監(jiān)聽也不會(huì)觸發(fā)。
event.stopImmediatePropagation() 使用了stopImmediatePropagation()之后,綁定的后續(xù)事件監(jiān)聽都會(huì)忽略。
event.currentTarget 當(dāng)前綁定的事件
event.target 事件代理時(shí) 點(diǎn)擊的元素

關(guān)于捕獲和冒泡:理解 addEventListener、捕獲和冒泡

6.自定義事件

jq

 // 添加一個(gè)適當(dāng)?shù)氖录O(jiān)聽器
$("#foo").on("custom", function(event, param1, param2) {
  alert(param1 + "
" + param2);
});
$("#foo").trigger("custom", ["Custom", "Event"]);

原生Event:

var eve = new Event("custome")
element.addEventListenter("custome",function(){
    console.log("custome")
})
element.dispatchEvent(eve)

原生CustomEvent

// 添加一個(gè)適當(dāng)?shù)氖录O(jiān)聽器
obj.addEventListener("custom", function(e) { 
   console.log(JSON.stringify(e.detail));
 })
// 創(chuàng)建并分發(fā)事件
var event = new CustomEvent("custom", {"detail":{"Custom":true}});
obj.dispatchEvent(event)

本節(jié)參考文章:一個(gè)能拖動(dòng),能調(diào)整大小,能更新bind值的vue指令-vuedragx

7.事件委托(代理)
事件委托就是利用事件冒泡,只指定一個(gè)事件處理程序,就可以管理某一類型的所有事件。

案例一:

    
    
  • 1
  • 2
  • 3
//例子說明,我們?yōu)閡l添加新的li, //其中對li標(biāo)簽元素綁定了click事件, //但是發(fā)現(xiàn),后增加的元素沒有辦法觸發(fā)我們的click事件。

解決方法:事件委托

 
    
  • 1
  • 2
  • 3

案例二:

點(diǎn)擊“添加”按鈕添加一個(gè)按鈕,點(diǎn)擊添加的按鈕移除這個(gè)按鈕

添加
繪畫
散步
靜坐
document.getElementById("wrap").addEventListener("click", function(e){
    var target = e.target;
    while(target !== this){
        var type = target.dataset.type;
        if(type == "btn"){
            var feat = target.dataset.feat;
            switch(feat){
                case "add":
                    this.innerHTML += "
靜坐
" return; case "delete": target.parentNode.removeChild(target); return; } } target = target.parentNode; } }, false);
適合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

推薦閱讀:JavaScript 事件委托詳解

本節(jié)參考文章:前端小知識(shí)--JavaScript事件流

9.link / @import

兩者都是外部引用 CSS 的方式,但是存在一定的區(qū)別:

link是XHTML標(biāo)簽,除了能夠加載CSS,還可以定義RSS等其他事務(wù);而@import屬于CSS范疇,只可以加載CSS。

link引用CSS時(shí),在頁面載入時(shí)同時(shí)加載;@import需要頁面完全載入以后再加載。

link是XHTML標(biāo)簽,無兼容問題;@import則是在CSS2.1提出的,低版本的瀏覽器不支持。

link方式的樣式的權(quán)重 高于@import的權(quán)重.

link支持使用Javascript控制DOM改變樣式;而@import不支持。

本節(jié)參考文章:前端面試題-url、href、src

10.異步編程的實(shí)現(xiàn)方式

1.回調(diào)函數(shù)
優(yōu)點(diǎn):簡單、容易理解
缺點(diǎn):不利于維護(hù),代碼耦合高

2.事件監(jiān)聽(采用時(shí)間驅(qū)動(dòng)模式,取決于某個(gè)事件是否發(fā)生):
優(yōu)點(diǎn):容易理解,可以綁定多個(gè)事件,每個(gè)事件可以指定多個(gè)回調(diào)函數(shù)
缺點(diǎn):事件驅(qū)動(dòng)型,流程不夠清晰

3.發(fā)布/訂閱(觀察者模式)
類似于事件監(jiān)聽,但是可以通過‘消息中心’,了解現(xiàn)在有多少發(fā)布者,多少訂閱者

4.Promise對象
優(yōu)點(diǎn):可以利用then方法,進(jìn)行鏈?zhǔn)綄懛ǎ豢梢詴鴮戝e(cuò)誤時(shí)的回調(diào)函數(shù);
缺點(diǎn):編寫和理解,相對比較難

5.Generator函數(shù)
優(yōu)點(diǎn):函數(shù)體內(nèi)外的數(shù)據(jù)交換、錯(cuò)誤處理機(jī)制
缺點(diǎn):流程管理不方便

6.async函數(shù)
優(yōu)點(diǎn):內(nèi)置執(zhí)行器、更好的語義、更廣的適用性、返回的是Promise、結(jié)構(gòu)清晰。
缺點(diǎn):錯(cuò)誤處理機(jī)制

11.documen.write/ innerHTML的區(qū)別

document.write只能重繪整個(gè)頁面
innerHTML可以重繪頁面的一部分

12.isPrototypeOf()/instanceof

isPrototypeOf() 與 instanceof 運(yùn)算符不同。

在表達(dá)式 "object instanceof AFunction"中,object 的原型鏈?zhǔn)轻槍?AFunction.prototype 進(jìn)行檢查的,而不是針對 AFunction 本身。

isPrototypeOf() 方法允許你檢查一個(gè)對象是否存在于另一個(gè)對象的原型鏈上。

function Foo() {}
function Bar() {}
function Baz() {}

Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);

var baz = new Baz();

//isPrototypeOf
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true

if (Foo.prototype.isPrototypeOf(baz)) {
  // do something safe
}

//instanceof
console.log(baz instanceof Baz); // true
console.log(baz instanceof Bar); // true
console.log(baz instanceof Foo); // true
console.log(baz instanceof Object); // true
var obj1 = {
    name: "esw"
}
var obj2 = Object.create(obj1)

// isPrototypeOf()方法
Object.prototype.isPrototypeOf(obj1)  // true
obj1.isPrototypeOf(obj2)  // true
Object.prototype.isPrototypeOf(obj2)  // true
13.constructor、__proto__與prototype

在javascript中我們每創(chuàng)建一個(gè)對象,該對象都會(huì)獲得一個(gè)__proto__屬性(該屬性是個(gè)對象),該屬性指向創(chuàng)建該對象的構(gòu)造函數(shù)的原型prototype,同時(shí)__proto__對象有一個(gè)constructor屬性指向該構(gòu)造函數(shù)。這里我們需要注意的是只有函數(shù)才有prototype,每個(gè)對象(函數(shù)也是對象)都有__proto__Object本身是個(gè)構(gòu)造函數(shù)。舉例來說:

var obj = new Object()
// 也可以使用對象字面量創(chuàng)建,但使用Object.create()情況會(huì)不一樣
// Object本身是個(gè)構(gòu)造函數(shù)
Object instanceof Function  // true
obj.__proto__ === Object.prototype  // true
obj.__proto__.constructor === Object  // true
// 我們一般習(xí)慣這樣寫
obj.constructor === Object  // true

當(dāng)我們訪問obj.constructor的時(shí)候,obj本身是沒有constructor屬性的,但屬性訪問會(huì)沿著__proto__向上查找,即在obj.__proto__里面尋找constructor屬性,如果找到了就返回值,如果未找到則繼續(xù)向上查找直到obj.__proto__.__proto__...(__proto__) === null為止,沒有找到則返回undefined。這樣由__proto__構(gòu)成的一條查找屬性的線稱為‘原型鏈’。

本節(jié)參考文章:重新認(rèn)識(shí)javascript對象(三)——原型及原型鏈、一篇文章帶你進(jìn)一步了解object屬性

14.淺拷貝/深拷貝

1.淺拷貝只能復(fù)制值類型的屬性。對于引用類型的屬性,復(fù)制前后的兩個(gè)對象指向同一內(nèi)存地址,操作其中一個(gè)對象的引用類型屬性,另一個(gè)對象也會(huì)相應(yīng)發(fā)生改變;也就是說只有改變值類型的屬性兩個(gè)對象才不會(huì)相互影響。
2.深拷貝不僅可以復(fù)制值類型的屬性,還可以復(fù)制引用類型的屬性,無論兩個(gè)對象怎么改變都不會(huì)相互影響。

淺復(fù)制

var obj = {
    a : 1,
    b: {
        c: 2
    }
}
// 淺復(fù)制
function lowerClone(obj){
    var newObj=obj.constructor === Array ? [] : {};
    for(var i in obj){
      newObj[i]=obj[i]
    }
    return newObj;
}
var objClone = lowerClone(obj)
objClone.a   // 1
obj.a  // 1
objClone.a = 100
// 改變復(fù)制對象的值類型屬性,值類型屬性的值不變
obj.a // 1
objClone.b.c = 200
// 改變復(fù)制對象的引用類型的屬性,引用類型的屬性值改變
obj.b.c //200

深復(fù)制

var obj = {
    a : 1,
    b: {
        c: 2
    }
}
function deepClone(obj){
    if( typeof obj != "object"){
      return obj;
    }
    var newObj=obj.constructor === Array ? [] : {};
    for(var i in obj){
      newObj[i]=deepClone(obj[i]);
    }
    return newObj;
}
var objClone = deepClone(obj)
objClone.a   // 1
obj.a  // 1
objClone.a = 100
// 改變復(fù)制對象的值類型屬性,值類型屬性的值不變
obj.a // 1
objClone.b.c = 200
// 改變復(fù)制對象的引用類型的屬性,引用類型的屬性值不變
obj.b.c // 2

本節(jié)參考文章:javascript淺復(fù)制與深復(fù)制

15.apply/call/bind
apply 、 call 、bind 三者都是用來改變函數(shù)的this對象的指向的; 
apply 、 call 、bind 三者第一個(gè)參數(shù)都是this要指向的對象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后續(xù)參數(shù)傳參;
bind是返回對應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。
call apply 的區(qū)別是他們指定參數(shù)的方式不同。

案例

function fn(a,b){
    console.log(this);
    console.log(a);
    console.log(b);
}
// bind(this,args...)
bf = fn.bind("Bind this",10); // 沒有任何輸出,也就是說沒有執(zhí)行這個(gè)函數(shù)
bf(); // "Bind this",10,undefined
bf(20);// “Bind this”,10,20
// 原函數(shù)不受影響
fn(1,2); //window, 1,2
bf2 = fn.bind("Bind this",1,2);
bf2(); // "Bind this",1,2

// call(this,args...)
fn.call("Call this",1) // "Call this",1,undefined
fn.call("Call this",1,2) // "Call this",1,2

// apply(this,[args])
fn.apply("Apply this",[1]) // "Apply this",1,undefined
fn.apply("Apply this",[1,2]) // "Apply this",1,2

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/53555.html

相關(guān)文章

  • 前端本功-常見概念(一)

    摘要:前端基本功常見概念一點(diǎn)這里前端基本功常見概念二點(diǎn)這里前端基本功常見概念三點(diǎn)這里什么是原型鏈當(dāng)一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法時(shí)候就會(huì)產(chǎn)生一個(gè)原型鏈。函數(shù)式編程是聲明式而不是命令式,并且應(yīng)用程序狀態(tài)通過純函數(shù)流轉(zhuǎn)。 前端基本功-常見概念(一) 點(diǎn)這里前端基本功-常見概念(二) 點(diǎn)這里前端基本功-常見概念(三) 點(diǎn)這里 1.什么是原型鏈 當(dāng)一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方...

    bladefury 評論0 收藏0
  • 前端本功-常見概念()

    摘要:前端基本功常見概念一點(diǎn)這里前端基本功常見概念二點(diǎn)這里前端基本功常見概念三點(diǎn)這里是更完美的,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。 前端基本功-常見概念(一) 點(diǎn)這里前端基本功-常見概念(二) 點(diǎn)這里前端基本功-常見概念(三) 點(diǎn)這里 1.let、const/var let 是更完美的var,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。cons...

    netScorpion 評論0 收藏0
  • 前端本功-常見概念()

    摘要:前端基本功常見概念一點(diǎn)這里前端基本功常見概念二點(diǎn)這里前端基本功常見概念三點(diǎn)這里是更完美的,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。 前端基本功-常見概念(一) 點(diǎn)這里前端基本功-常見概念(二) 點(diǎn)這里前端基本功-常見概念(三) 點(diǎn)這里 1.let、const/var let 是更完美的var,不是全局變量,具有塊級函數(shù)作用域,大多數(shù)情況不會(huì)發(fā)生變量提升。cons...

    ckllj 評論0 收藏0
  • [譯] 前端攻略-從路人甲到英雄無敵:JavaScript 與不斷演化的框架

    摘要:一般來說,聲明式編程關(guān)注于發(fā)生了啥,而命令式則同時(shí)關(guān)注與咋發(fā)生的。聲明式編程可以較好地解決這個(gè)問題,剛才提到的比較麻煩的元素選擇這個(gè)動(dòng)作可以交托給框架或者庫區(qū)處理,這樣就能讓開發(fā)者專注于發(fā)生了啥,這里推薦一波與。 本文翻譯自FreeCodeCamp的from-zero-to-front-end-hero-part。 繼續(xù)譯者的廢話,這篇文章是前端攻略-從路人甲到英雄無敵的下半部分,在...

    roadtogeek 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<