原文鏈接:https://github.com/helloyoucan/knowledge
JavaScript相關(guān)
1、聲明相關(guān)
-
var
變量提升晦鞋,function
函數(shù)提升,function
>var
(優(yōu)先級(jí)) - 塊級(jí)作用域:
with
矾克、try/catch
忌怎、let
、const
-
let
蒙畴,不可重復(fù)聲明贰镣,暫時(shí)性死區(qū) -
const
,不可重復(fù)聲明膳凝、修改碑隆,暫時(shí)性死區(qū)
2、JS引擎
任務(wù)隊(duì)列
- JS分為同步任務(wù)蹬音、異步任務(wù)上煤。
- 同步任務(wù)在主線程上執(zhí)行,形成一個(gè)Call Stack(執(zhí)行棧)著淆。
- 主線程之外劫狠,事件觸發(fā)線程管理著一個(gè)Task Queue(任務(wù)隊(duì)列),當(dāng)異步任務(wù)完成時(shí)牧抽,會(huì)指定對(duì)應(yīng)的事件(回調(diào))進(jìn)入Task Queue嘉熊。
- 一旦Call Stack(執(zhí)行棧)中所有同步任務(wù)執(zhí)行完畢(此時(shí)JS引擎空閑),系統(tǒng)就會(huì)讀取Task Queue扬舒,將Task Queue中可運(yùn)行的事件添加到Call Stack(執(zhí)行棧)中阐肤,開(kāi)始執(zhí)行。
- 事件循環(huán)是通過(guò)任務(wù)隊(duì)列機(jī)制來(lái)進(jìn)行協(xié)調(diào)的讲坎。
- 一個(gè)Event Loop中孕惜,可以有一個(gè)或者多個(gè)任務(wù)隊(duì)列(task queue),一個(gè)任務(wù)隊(duì)列就是一系列有序任務(wù)(task)的集合
- 每個(gè)任務(wù)都要一 個(gè)任務(wù)源(task source)晨炕,源自同一個(gè)任務(wù)源的task必須放到同一個(gè)任務(wù)隊(duì)列衫画,從不同源來(lái)的則被添加到不同隊(duì)列。
- setTimeout/Promise等API便是任務(wù)源瓮栗,而進(jìn)入任務(wù)隊(duì)列的是他們指定的具體執(zhí)行任務(wù)削罩。
<img src="./images/task.png" style="width:500px"/>
宏任務(wù)
- (macro)task(宏任務(wù))瞄勾,可以理解為每次執(zhí)行棧執(zhí)行的代碼就行一個(gè)宏任務(wù)(包括每次從Task Queue中獲取一個(gè)事件(回調(diào))并放到執(zhí)行棧中執(zhí)行)。
- macrotask中的事件(回調(diào))都是放在一個(gè)事件隊(duì)列中(Task Queue)的弥激,而這個(gè)隊(duì)列由事件觸發(fā)線程維護(hù)进陡。
- 瀏覽器為了能夠使得JS內(nèi)部(macro)task與DOM任務(wù)能夠有序地執(zhí)行,會(huì)在一個(gè)task執(zhí)行結(jié)束后微服,在下一個(gè)task執(zhí)行開(kāi)始前趾疚,對(duì)頁(yè)面進(jìn)行渲染(task->渲染->task->......)。
- macrotask主要包含:script(整體代碼)以蕴、setTimeout/setInterval糙麦、I/O、UI交互事件丛肮、postMessage赡磅、MessageChannel(創(chuàng)建消息通道傳遞消息的api,可用在iframe上)腾供、setImmediate(Node.js環(huán)境)
微任務(wù)
- microtask(又稱為微任務(wù))仆邓,可以理解是當(dāng)前task執(zhí)行結(jié)束后立刻執(zhí)行的任務(wù)(在當(dāng)前macrotask后,渲染前伴鳖,下一個(gè)macrotask前)节值。
- 產(chǎn)生的microtask會(huì)添加到微任務(wù)隊(duì)列(Microtask Queues)中搞疗,該隊(duì)列由JS引擎線程維護(hù)须肆。
- 響應(yīng)速度比macrotask(例如setTimeout)會(huì)更快,因?yàn)闊o(wú)需等渲染豌汇。(某個(gè)macrotask執(zhí)行后,就會(huì)將在它執(zhí)行期間產(chǎn)生的所有microtask都執(zhí)行完畢(在渲染前))宛徊。
- microtask主要包含:Promise.then(原生的逻澳,部分實(shí)行可能是task)、MutationObserver(監(jiān)聽(tīng)DOM變化的api)斜做、process.nextTick(Node.js環(huán)境)。
微任務(wù)和宏任務(wù)皆為異步任務(wù)瓤逼,主要區(qū)別在于他們的執(zhí)行順序笼吟,Event Loop的走向和取值库物。
運(yùn)行機(jī)制
在事件循環(huán)(Event Loop)中,每進(jìn)行一次循環(huán)操作成為tick赞厕,每一次tick的任務(wù)處理模型是比較復(fù)制的艳狐,但關(guān)鍵步驟如下:
- 執(zhí)行Call Stack(執(zhí)行棧)一個(gè)宏任務(wù)(棧中沒(méi)有就從事件隊(duì)列(Task Queue)中獲取)
- 執(zhí)行過(guò)程中如果遇到微任務(wù)皿桑,就將它添加到微任務(wù)的任務(wù)隊(duì)列中
- 宏任務(wù)執(zhí)行完畢后,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
- 當(dāng)前宏任務(wù)執(zhí)行完畢蔬啡,開(kāi)始檢查渲染诲侮,然后GUI線程接管渲染
- 渲染完畢后,JS線程繼續(xù)接管箱蟆,開(kāi)始下一個(gè)宏任務(wù)(從事件隊(duì)列中獲裙敌鳌)
<img src="/images/執(zhí)行機(jī)制.jpg" style="width:300px;"/>
3、 閉包
有權(quán)訪問(wèn)另外一個(gè)函數(shù)作用域中的變量的函數(shù)
用途
- 設(shè)計(jì)私有方法和變量
- 單例模式
- 模塊化——使用閉包模塊化代碼空猜,減少全局變量的使用
缺陷
- 閉包會(huì)常駐在內(nèi)存中绽慈,不會(huì)被垃圾回收機(jī)制主動(dòng)回收,增大內(nèi)存使用量辈毯,使用不當(dāng)容易泄露
- 閉包對(duì)腳本性能有負(fù)面效果坝疼,比如處理速度和內(nèi)存消耗
4、異步執(zhí)行
- 動(dòng)態(tài)插入腳本
-
defer="defer"
——IE支持谆沃,頁(yè)面解釋完成時(shí)執(zhí)行钝凶,按照加載順序執(zhí)行 -
async="async"
——加載完成則執(zhí)行
5、數(shù)據(jù)類型
-
基本類型
Number唁影、String、Boolean哟沫、Undefined嗜诀、Null裹虫、Symbol
-
引用類型
Objcet筑公、Array匣屡、Function
主要要點(diǎn):
- typeof {} 或 null 或 [ ] === "object"
6誉结、原型鏈
<img src="/images/原型鏈.png" style="width:500px;"/>
實(shí)例惩坑、構(gòu)造函數(shù)以舒、原型對(duì)象
- 實(shí)例 = new 構(gòu)造函數(shù)
- 實(shí)例.__proto__ === 原型對(duì)象
- 構(gòu)造函數(shù).prototype === 原型對(duì)象
- 原型對(duì)象.constructor === 構(gòu)造函數(shù)
- 原型對(duì)象.__proto__ === 原型鏈上一級(jí)的原型對(duì)象
instanceof
- 判斷 實(shí)例.__proto__ === 原型鏈上任意的構(gòu)造函數(shù)(原型對(duì)象).prototype
- 實(shí)例.__proto__.constructor === 實(shí)例的構(gòu)造函數(shù)
New運(yùn)算符
new做了什么?
- 創(chuàng)建了一個(gè)全新的對(duì)象滥沫。
- 這個(gè)對(duì)象會(huì)被執(zhí)行
[[Prototype]]
(也就是__proto__
)鏈接兰绣。 - 生成的新對(duì)象會(huì)綁定到函數(shù)調(diào)用的
this
狭魂。 - 通過(guò)
new
創(chuàng)建的每個(gè)對(duì)象將最終被[[Prototype]]
鏈接到這個(gè)函數(shù)的prototype
對(duì)象上雌澄。 - 如果函數(shù)沒(méi)有返回對(duì)象類型
Object
(包含Functoin
,Array
,Date
,RegExg
,Error
),那么new
表達(dá)式中的函數(shù)調(diào)用會(huì)自動(dòng)返回這個(gè)新的對(duì)象魁莉。
function Func(name){this.name = name};
var o1 = new Func('name1')
//模擬new
function new2(func,...param){
/*
//Object.create的作用
function F(){}
F.prototype = func.prototype
var o =new F()
*/
var o = Object.create(func.prototype)
var ret = func.apply(o,param)
return ret instanceof Object ? ret : o; //構(gòu)造函數(shù)return了內(nèi)容可以這樣
}
var o2 = new2(Func,'name2')
7畦浓、this
- this是一個(gè)關(guān)鍵字
- 代表函數(shù)運(yùn)行時(shí)讶请,自動(dòng)生成的一個(gè)內(nèi)部對(duì)象夺溢,只能在函數(shù)內(nèi)部使用
- this是在執(zhí)行時(shí)確定是什么值嘉汰,定以時(shí)無(wú)法確定
- this指向的是鞋怀,調(diào)用函數(shù)的那個(gè)對(duì)象
- bind(this)接箫、call(this,p1,p2,...)、apply(this,[p1,p2,....])
8剪返、繼承
-
借助原型鏈實(shí)現(xiàn)繼承
/* 缺點(diǎn): 1.父類中的屬性(也就是父類this上的屬性)是子類共用 2.子類實(shí)例時(shí)無(wú)法向父類傳參(因?yàn)楦割愒缫褜?shí)例化) */ function P(){} function C(){} C.prototype = new P()
-
構(gòu)造函數(shù)實(shí)現(xiàn)繼承
/* 缺點(diǎn): 1.子類無(wú)法繼承父類的prototype 2.若父類方法綁定在this上則每個(gè)子類都會(huì)copy一份,違背代碼復(fù)用 */ function P(){} P.prototype.say = function(){}//子類無(wú)法繼承 function C(){ P.call(this,arguments) } //繼承父類屬性
-
組合式繼承
/* 缺點(diǎn) 1.父類構(gòu)造函數(shù)調(diào)用兩次 */ function P(){} function C(){ P.call(this,arguments) } //P執(zhí)行了1次 C.prototype = new P() // P執(zhí)行了2次
-
寄生組合繼承
function P(){} function C(){ P.call(this,arguments) } //實(shí)現(xiàn)方式 C.prototype = Object.create(P.prototype) //通過(guò)淺拷貝繼承父類方法钱反,不需要調(diào)用一次父類構(gòu)造函數(shù) C.prototype.constructor = C // 上一行代碼對(duì)子類原型進(jìn)行了拷貝面哥,因此子類的constructor屬性被重寫,所以需要這樣修復(fù)
-
extends繼承
class P(){} class C extends P(){ constructor(){ super() //獲得this對(duì)象 } }
ES5的繼承 vs ES6的繼承
ES5
- ES5的繼承是通過(guò)prototype或構(gòu)造函數(shù)機(jī)制來(lái)實(shí)現(xiàn)
- ES5繼承的實(shí)質(zhì)是先創(chuàng)建子類實(shí)例吱涉,再將父類方法添加到this上怎爵。
ES6
- ES6是先創(chuàng)建父類實(shí)例對(duì)象this(先調(diào)用super()方法)鳖链,再用子類構(gòu)造函數(shù)修改this撒轮。
- ES6通過(guò)class關(guān)鍵字定以類题山,里面有構(gòu)造方法玖姑,類之間通過(guò)extend關(guān)鍵字實(shí)現(xiàn)繼承焰络。子類必須在constructor方法中調(diào)用super方法闪彼,否則新建實(shí)例失敗畏腕。因?yàn)樽宇悰](méi)有自己的this對(duì)象,而是繼承父類的this對(duì)象而线,然后對(duì)齊加工嘹狞。如果不調(diào)用super方法刁绒,子類得不到this對(duì)象知市。
9嫂丙、Promise
Promise是一種用于解決異步問(wèn)題的思路跟啤、方案或者對(duì)象方式竿奏。
狀態(tài):
pending
泛啸、fulfilled
、rejected
-
寫法:
new Promise((resolve,rejected)=>{ //success setTimeout(()=>{ resolve('success') },2000) //fail rejected() }) .then(()=>{}) .catch(()=>{}) .finally(()=>{})
-
主要要點(diǎn):
- 一旦執(zhí)行resolve或rejected岗仑,后面的再執(zhí)行rejected或resolve則無(wú)效
- 執(zhí)行了resolve或rejected荠雕,Promise后面的代碼還會(huì)執(zhí)行下去
-
靜態(tài)方法
Promise.all([]) // 數(shù)組內(nèi) 所有 狀態(tài)都為fulfilled舞虱,則狀態(tài)變?yōu)閒ulfilled损趋,數(shù)組內(nèi)其中一個(gè)狀態(tài)變?yōu)閞ejected蒋失,則狀態(tài)為rejected Promise.race([]) // 數(shù)組內(nèi) 其中一個(gè) 狀態(tài)都為fulfilled篙挽,則狀態(tài)變?yōu)閒ulfilled Promise.resolve() // 轉(zhuǎn)化為Promise對(duì)象铣卡,等價(jià)于new Promise(resolve => resolve()) Promise.reject() // 轉(zhuǎn)化為Promise對(duì)象
10煮落、Ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status===200||
xhr.status===304||
xhr.status===206){//媒體資源體積大蝉仇,分步傳輸沉迹,狀態(tài)碼為206
res = xhr.responseText
if(typeof res==='string'){
res = JSON.parse(res)
console.log(res)
}else{
console.log(res)
}
}else{
console.log(new Error(res))
}
}
}
xhr.open('GET','url',true)
xhr.send()
/*
xhr.open('POST','url',true)
xhr.setRequestHeader('content-type','application/json;charset=UTF-8')
xhr.send(JSON.stringify({}))
*/
- 狀態(tài)碼
readState
0-(未初始化)還沒(méi)有調(diào)用send方法
1-(載入)已調(diào)用send()方法,正在發(fā)生請(qǐng)求
2-(載入完成)send方法執(zhí)行完成鞭呕,已經(jīng)接收到前部響應(yīng)內(nèi)容
3-(交互)正在解析響應(yīng)內(nèi)容
4-(完成)響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了
status
2xx - 表示成功處理請(qǐng)求摘刑,如200
3xx - 需要重定向枷恕,瀏覽器直接跳轉(zhuǎn)
4xx - 客戶端請(qǐng)求錯(cuò)誤未玻,如404
5xx - 服務(wù)器端錯(cuò)誤
11扳剿、跨域
同源策略:非同源(域名庇绽、協(xié)議瞧掺、端口)的腳本不能訪問(wèn)或者操作其它域的頁(yè)面對(duì)象辟狈。
由于同源策略,非同源之間需要通訊槽华,所以就需要跨域訪問(wèn)。
跨域庶溶,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本偏螺。它是由瀏覽器的同源策略造成的套像,是瀏覽器對(duì)JavaScript實(shí)施的安全限制贞让。
同源策略限制了一下行為:
- Cookie喳张、LocalStorage 和 IndexDB 無(wú)法讀取
- DOM 和 JS 對(duì)象無(wú)法獲取
- Ajax請(qǐng)求發(fā)送后response會(huì)被瀏覽器攔截
跨域通訊
- JSONP(動(dòng)態(tài)插入
js
文件销部,文件中調(diào)用預(yù)先定義好的函數(shù)并傳入?yún)?shù)) - Hash+ iframe
- document.domain + iframe跨域 (適用于不同子域通訊)
-
postMessage
(HTML5新增) - window.name + iframe(窗口載入所有頁(yè)面共享)
-
webScoket
(協(xié)議不受同源策略限制) - 跨域資源共享CROS(服務(wù)端支持+絕對(duì)路徑訪問(wèn)接口)
- 代理服務(wù)器(nginx、node等)
12擂涛、優(yōu)化
頁(yè)面加載資源優(yōu)化
- 靜態(tài)資源壓縮合并(減少http請(qǐng)求次數(shù)歼指、減少文件體積)
- 緩存資源
- CDN
- 按需加載資源(動(dòng)態(tài)加載腳本胀茵,圖片懶加載,數(shù)據(jù)下拉加載等)
- 預(yù)加載(preload:強(qiáng)制瀏覽器不阻塞document.onload情況下請(qǐng)求資源;prefetch:告知瀏覽器將來(lái)可能需要瞒瘸,什么時(shí)候加載由瀏覽器決定)
- 減少DOM的數(shù)量
- 延遲加載腳本
- 合理放置腳本位置(CSS放在前面加載熄浓,js文件放到頁(yè)面底部加載)
JavaScript執(zhí)行優(yōu)化
- 緩存DOM查詢(減少DOM查詢俯在,可對(duì)DOM查詢做緩存)
- 合并DOM操作(減少DOM操作跷乐,可將多個(gè)操作合并為一個(gè))
- 事件委托(使用事件委托的方式綁定事件)
- 事件節(jié)流(一定時(shí)間內(nèi)任務(wù)執(zhí)行的次數(shù)馒稍。每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法)
- 事件防抖(在任務(wù)高頻率觸發(fā)的時(shí)候纽谒,只有觸發(fā)間隔超過(guò)制定間隔的任務(wù)才會(huì)執(zhí)行。每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù))
- 慎用閉包(減少不必要的閉包的使用挨决,及時(shí)釋放無(wú)用的內(nèi)存占用)
- web worker執(zhí)行耗時(shí)代碼(耗時(shí)的代碼塊可移動(dòng)到web worker執(zhí)行)
雅虎軍規(guī)
網(wǎng)頁(yè)內(nèi)容
- 減少http請(qǐng)求
- 減少DNS查詢
- 避免重定向
- 緩存Ajax請(qǐng)求
- 延遲加載
- 預(yù)加載
- 減少DOM元素?cái)?shù)量
- 劃分內(nèi)容到不同域名(接口和靜態(tài)資源)
- 減少iframe的使用
- 避免404錯(cuò)誤
服務(wù)器
- CDN
- 靜態(tài)內(nèi)容添加Expires肆捕;動(dòng)態(tài)內(nèi)容設(shè)置Cache-Control報(bào)響應(yīng)頭
- 啟用Gzip
- 配置Etag
- 盡早輸出(flush)緩沖
- Ajax使用Get請(qǐng)求
- 避免空的圖片src
cookie
- 減少Cookie大小
- 頁(yè)面靜態(tài)資源使用無(wú)Cookie域名
CSS
- 樣式表放在<head>中
- 避免css表達(dá)式
- 使用<link>代替@import
- 避免使用filters
JavaScript
- 腳本置底
- 外部js和css文件
- 精簡(jiǎn)JavaScript和css
- 去除重復(fù)腳本
- 減少DOM訪問(wèn)
- 使用高效事件處理
圖片
- 壓縮圖片
- 優(yōu)化CSS Sprite
- 不在HTML中縮放圖片
- 使用小且可緩存的ico
ETags:是服務(wù)器和瀏覽器用來(lái)決定瀏覽器緩存中組件與源服務(wù)器中的組件是否匹配的一種機(jī)制(“實(shí)體”也就是組件:圖片,腳本席纽,樣式表等等)。添加ETags可以提供一種實(shí)體驗(yàn)證機(jī)制纺铭,比最后修改日期更加靈活舶赔。一個(gè)ETag是一個(gè)字符串竟纳,作為一個(gè)組件某一具體版本的唯一標(biāo)識(shí)符征懈。唯一的格式約束是字符串必須用引號(hào)括起來(lái)卖哎,源服務(wù)器用相應(yīng)頭中的ETag來(lái)指定組件的ETag。
然后维贺,如果瀏覽器必須驗(yàn)證一個(gè)組件溯泣,它用If-None-Match請(qǐng)求頭來(lái)把ETag傳回源服務(wù)器。如果ETags匹配成功肢簿,會(huì)返回一個(gè)304狀態(tài)碼池充,這樣就減少了12195個(gè)字節(jié)的響應(yīng)體收夸。Etag 通過(guò)文件版本標(biāo)識(shí),方便服務(wù)器判斷請(qǐng)求的內(nèi)容是否有更新手幢,如果沒(méi)有就響應(yīng) 304跺涤,避免重新下載桶错。
13航唆、事件綁定
種類
- DOM0級(jí)(onclick=function(){})
- DOM2級(jí)(addEventListener)
- DOM3級(jí)(新增事件類型)
事件模型
- 捕獲
- 冒泡
事件流
- 捕獲階段(從window對(duì)象自上而選向目標(biāo)節(jié)點(diǎn)傳播)
- 目標(biāo)階段(目標(biāo)節(jié)點(diǎn)處理事件)
- 冒泡階段(事件從目標(biāo)節(jié)點(diǎn)自下而上向window對(duì)象傳播)
事件綁定
addEventListener
(event,function,useCapture)
event
:事件類型
function
:執(zhí)行函數(shù)
useCapture
:可選;true:捕獲階段執(zhí)行院刁;false(默認(rèn)):冒泡階段執(zhí)行
常用對(duì)象
event.preventDefault() //阻止默認(rèn)事件
event.stopPropagation() //阻止冒泡
event.stoplmmediatePropagation() //阻止其它事件的響應(yīng)(當(dāng)注冊(cè)了多個(gè)事件時(shí))
event.currentTarget //其監(jiān)聽(tīng)器觸發(fā)事件的節(jié)點(diǎn)(綁定事件的元素)糯钙,即當(dāng)前處理該事件的元素、文檔或窗口退腥。
event.target //當(dāng)前被點(diǎn)擊的元素(舊版本的ie是sourceElement)
自定義事件
-
Event
(IE不支持)var event = new Event(custome' //事件名稱 {//可選 bubbles:false,//是否冒泡 cancelable:false,//能否被取消 composed:false//是否會(huì)在影子DOM根節(jié)點(diǎn)之外觸發(fā)偵聽(tīng)器 }) dom.addEventListener('custome',function(){}) dom.dispatchEvent(event)
-
CustomEvent
(IE不完全支持)var event = new CustomEvent('custome', {//可選 bubbles:false,//是否冒泡 cancelable:false,//能否被取消 detail:{a:1,b:2} //當(dāng)事件初始化時(shí)傳遞的數(shù)據(jù) }) dom.addEventListener('custome',function(e){ console.log(e.detail.a,e.detail.b) }) dom.dispatchEvent(event)
-
document.createEvent
(僅IE支持)var event = document.createEvent('HTMLEvents'); event.hello='hello,I am event'; event.initEvent('customEvent', true, true);//事件名稱任岸;事件是否冒泡;事件是否可以被取消 dom.addEventListener('customEvent', function(e){ console.log(e.hello) }, false); dom.dispatchEvent(event)
14、本地存儲(chǔ)
-
cookie
4kb(不同瀏覽器存放大小不一樣,一般為4kb)
不同瀏覽器存放位置(磁盤)不一樣
http請(qǐng)求會(huì)帶上
字符串形式存在
僅以域名區(qū)分(不同協(xié)議、端口、子域可共享)
可設(shè)過(guò)期時(shí)間,默認(rèn)是會(huì)話結(jié)束則銷毀
document.cookie = "username=cfangxu; domain=qq.com; path=/" // 添加cookie畦贸,設(shè)置生效子域及路徑
-
sessionStorage
- 同源策略限制
- 本質(zhì)是讀取字符串胶坠,存儲(chǔ)過(guò)多會(huì)消耗內(nèi)存,頁(yè)面變卡
- 一般為5M
- 非IE可本地打開(kāi)玖翅,IE需要在服務(wù)器中打開(kāi)
- 通過(guò)跳轉(zhuǎn)打開(kāi)新頁(yè)面會(huì)復(fù)制源頁(yè)面當(dāng)前會(huì)話的
sessionStorage
- 會(huì)話結(jié)束時(shí)刪除
-
localStorage
- 同源策略限制
- 本質(zhì)是讀取字符串审姓,存儲(chǔ)過(guò)多會(huì)消耗內(nèi)存嗜桌,頁(yè)面變卡
- 一般為5M
- 非IE可本地打開(kāi)层亿,IE需要在服務(wù)器中打開(kāi)
- 修改時(shí)會(huì)觸發(fā)其它頁(yè)面storage事件
- 同一域中共享
- 持久化本地存儲(chǔ)碌更,需要主動(dòng)刪除旭绒,不會(huì)過(guò)期
15、安全
Cross-site requset forgery(CSRF,跨站請(qǐng)求偽造)
-
原理:
用戶已登錄A網(wǎng)站萎羔,同時(shí)用戶在瀏覽B網(wǎng)站髓废,在B網(wǎng)站中誘導(dǎo)用戶點(diǎn)擊操作A網(wǎng)站的連接(例如一個(gè)關(guān)注某用戶的GET請(qǐng)求的連接)
-
防御
Token認(rèn)證
Referer驗(yàn)證(頁(yè)面來(lái)源認(rèn)證)
隱藏令牌(例如把令牌存放在頁(yè)面的<head>)
驗(yàn)證碼
Cross Site Script(XSS,跨站腳本工具)
-
原理:
攻擊者在網(wǎng)站惡意注入的客戶端代碼维咸,通過(guò)惡意腳本對(duì)網(wǎng)頁(yè)進(jìn)行篡改,在用戶瀏覽網(wǎng)頁(yè)時(shí),對(duì)用戶瀏覽器進(jìn)行控制或者獲取用戶隱私數(shù)據(jù)。
-
防御
- HttpOnly 防止劫取 Cookie(設(shè)置cookie是否能通過(guò) js 去訪問(wèn))
- 對(duì)用戶的任何輸入進(jìn)行檢查剥汤、過(guò)濾和轉(zhuǎn)義(XSS Filter)
- 對(duì)服務(wù)端的輸出進(jìn)行檢查蠢沿、過(guò)濾和轉(zhuǎn)義
16、函數(shù)式編程
- 不可變性 (不能更改數(shù)據(jù)河胎,如需更改則復(fù)制數(shù)據(jù)副本來(lái)更改访锻,并返回新數(shù)據(jù))
- 純函數(shù) (沒(méi)有副作用,例如不要設(shè)置全局狀態(tài)垂券,不更改應(yīng)用程序狀態(tài),函數(shù)參數(shù)不可變)
- 數(shù)據(jù)轉(zhuǎn)換 (不改變現(xiàn)有數(shù)據(jù)是尖,返回新的數(shù)組或?qū)ο螅鏏rray.prototype.join)
- 高階函數(shù) (將函數(shù)作為參數(shù)或者返回函數(shù)编检,或兩者都有琅捏;可操縱其它函數(shù))
- 遞歸 (滿足一定條件之前調(diào)用自身的技術(shù))
- 組合 (將較小的函數(shù)組合成更大的函數(shù),最終得到一個(gè)應(yīng)用程序)
17勇吊、Set族沃、WeakSet铣缠、Map、WeakMap
- Set
- 成員唯一、無(wú)序且不重復(fù)
- [value, value]农曲,鍵值與鍵名是一致的(或者說(shuō)只有鍵值淌实,沒(méi)有鍵名)
- 可以遍歷谈息,方法有:add犁享、delete、has
- WeakSet
- 成員都是對(duì)象
- 成員都是弱引用,可以被垃圾回收機(jī)制回收较雕,可以用來(lái)保存DOM節(jié)點(diǎn)蚤吹,不容易造成內(nèi)存泄漏
- 不能遍歷例诀,方法有add、delete裁着、has
- Map
- 本質(zhì)上是鍵值對(duì)的集合繁涂,類似集合
- 可以遍歷,方法很多可以跟各種數(shù)據(jù)格式轉(zhuǎn)換
- 鍵與內(nèi)存地址綁定二驰,簡(jiǎn)單類型(number扔罪、string、boolean)的值嚴(yán)格相等則同一鍵桶雀,undefined與null不同鍵矿酵,NaN不嚴(yán)格等于自身但Map視為同一鍵
- WeakMap
- 只接受對(duì)象作為鍵名(null除外),不接受其他類型的值作為鍵名
- 鍵名是弱引用矗积,鍵值可以是任意的全肮,鍵名所指向的對(duì)象可以被垃圾回收,此時(shí)鍵名是無(wú)效的
- 不能遍歷漠魏,方法有g(shù)et倔矾、set妄均、has柱锹、delete
18、布爾類型轉(zhuǎn)換
數(shù)據(jù)類型 | 轉(zhuǎn)換成true的取值 | 轉(zhuǎn)換成false的取值 |
---|---|---|
Undefined | 無(wú) | undefined |
Boolean | true | false |
Object | 非null時(shí)都為true | null |
Number | 任何非零數(shù)字值(包括無(wú)窮大) | 0和NaN |
String | 非空字符串 | ""(空字符串) |
19丰包、位運(yùn)算符
&與禁熏,|或,~取反邑彪,^異或瞧毙,>>左移,<<右移寄症。
20宙彪、ES5的類 vs ES6 class
- 提升
- class聲明會(huì)提升,但不會(huì)初始化賦值有巧。Foo進(jìn)入暫時(shí)性死區(qū)释漆,類似let、const聲明變量
- es5的函數(shù)會(huì)進(jìn)行函數(shù)提升
- class聲明內(nèi)部會(huì)啟動(dòng)嚴(yán)格模式
- class的所有方法(包括靜態(tài)方法和實(shí)例方法)都是不可枚舉
-
class
的所有方法(包括靜態(tài)方法和實(shí)例方法)都沒(méi)有原型對(duì)象 prototype篮迎,所以也沒(méi)有[[construct]]
男图,不能使用new
來(lái)調(diào)用 - 必須使用
new
調(diào)用class
-
class
內(nèi)部無(wú)法重寫類名示姿。 - 繼承
- ES5是通過(guò)call或者apply回調(diào)方法調(diào)用父類
- ES6的繼承實(shí)現(xiàn)在于使用super關(guān)鍵字調(diào)用父類
21、async/await
- await是一個(gè)讓出線程標(biāo)志逊笆。
- await后面的表達(dá)式會(huì)先執(zhí)行一遍栈戳。
- 然后將await后面的代碼加入到microtask中
- 然后跳出整個(gè)async函數(shù)。
async本身是promise+generator的語(yǔ)法糖难裆。所以await后面的代碼是miscrotask子檀。
22、異步編程
- 回調(diào)函數(shù)
- 事件監(jiān)聽(tīng)
- Promise對(duì)象
- Generator
- async/await
23差牛、call & apply
作用一樣命锄,區(qū)別在于傳參的不同
- 第一個(gè)參數(shù)都是指定函數(shù)體內(nèi)this的指向
- 第二個(gè)參數(shù)開(kāi)始不同
- apply是傳入帶下標(biāo)的集合、數(shù)組或類數(shù)組偏化,apply把它傳給函數(shù)作為參數(shù)
- call從第二個(gè)開(kāi)次傳入的參數(shù)是不固定的脐恩,都會(huì)傳給函數(shù)作為參數(shù)
- call比apply的性能都要好,call傳參數(shù)正式內(nèi)部所需要的格式(在ES6中可用解構(gòu)語(yǔ)法替代apply的傳參方式)
實(shí)現(xiàn)bind侦讨、call驶冒、apply
Function.prototype.myBind = function(ctx,...arg1){
var fn = this
return function(...arg2){
return fn.call(ctx,...arg1,...arg2);
}
}
Function.prototype.myCall = function(ctx,...args){
const fn = Symbol('fn');
ctx[fn] = this
const result = ctx[fn](...args)
Reflect.deleteProperty(ctx,fn);
return result
}
Function.prototype.myApply = function(ctx,args){
const fn = Symbol('fn');
ctx[fn] = this
const result = ctx[fn](...args)
Reflect.deleteProperty(ctx,fn);
return result
}
24、箭頭函數(shù)
- 沒(méi)有this韵卤,從作用域鏈的上一層繼承this(無(wú)法使用call/apply/bind)
- 不綁定arguments
- 不可使用yield(不能作為Generator)
- 不可使用new命令(無(wú)this骗污,無(wú)prototype:new命令執(zhí)行時(shí)需要將構(gòu)造函數(shù)的prototype復(fù)制給新的對(duì)象__proto__)
25、判斷瀏覽器
function myBrowser() {
var userAgent = navigator.userAgent; //取得瀏覽器的userAgent字符串
var isOpera = userAgent.indexOf("Opera") > -1;
if (isOpera) {
return "Opera"
}; //判斷是否Opera瀏覽器
if (userAgent.indexOf("Firefox") > -1) {
return "Firefox";
} //判斷是否Firefox瀏覽器
if (userAgent.indexOf("Chrome") > -1) {
return "Chrome";
} //判斷是否Google瀏覽器
if (userAgent.indexOf("Safari") > -1) {
return "Safari";
} //判斷是否Safari瀏覽器
if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera) {
return "IE";
}; //判斷是否IE瀏覽器
}
26沈条、垃圾回收機(jī)制
沒(méi)有被引用的對(duì)象就是垃圾需忿,要被清除。幾個(gè)對(duì)象引用形成一個(gè)環(huán)蜡歹,相互引用屋厘,但是訪問(wèn)不到的,也是垃圾月而。
- 標(biāo)記清除
- 標(biāo)記階段:把所有活動(dòng)對(duì)象做上標(biāo)記
- 清除階段:把沒(méi)有標(biāo)記(非活動(dòng)對(duì)象)銷毀
- 引用計(jì)數(shù)
- 跟蹤記錄每個(gè)值被引用的次數(shù)
- 當(dāng)引用次數(shù)0時(shí)汗洒,垃圾回收器下次運(yùn)行時(shí),就會(huì)是否次數(shù)為0的值所占用的內(nèi)存
27父款、塊級(jí)作用域與函數(shù)聲明
// 瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重復(fù)聲明一次函數(shù)f
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
為了兼容舊代碼溢谤,瀏覽器的實(shí)習(xí)可以不遵守規(guī)定(塊級(jí)作用域之中,函數(shù)聲明語(yǔ)句的行為類似于let
憨攒,在塊級(jí)作用域之外不可引用):
- 允許在塊級(jí)作用域內(nèi)聲明函數(shù)世杀。
- 函數(shù)聲明類似于
var
,即會(huì)提升到全局作用域或函數(shù)作用域的頭部肝集。 - 同時(shí)瞻坝,函數(shù)聲明還會(huì)提升到所在的塊級(jí)作用域的頭部。
相當(dāng)于如下:
瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
28包晰、表示一個(gè)字符的方式(6種)
'\z' === 'z' // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true