原始數據類型主要分爲:
number,string,Boolean,null,undefind
null是對象css
基礎類型按值儲存在棧內存中
對象類型(引用類型)儲存在堆內存中。以指針方式去使用
函數參數和複製操做:
基礎數據類型在從新建立一份新值。改變其中任何一個,另外一個不受影響
引用數據類型。變量對象也會爲其開闢空間,但複製的是指針,都指向內存的值,一個改變,另外一個也回受影響html
typeof 與 instanceof都是判斷數據類型的。區別以下:
typeof判斷基礎數據類型。當判斷null的時候將返回objcet
instanceof判斷引用數據類型,原理根據原型鏈追蹤去實現前端
null=》0
undefined=》NaN
Boolean
true =》1
false=》0
Sting
數字=》數字
字母=》NaN
空字符串=》0
數組
空數組=》0
一個元素且爲數字=》數字
其餘=》NaN
引用類型
NaNnode
underfind=》‘underfind’
null=》‘null’
Number
'數字'
Boolean
‘true’
‘false’
數組
‘【12.43,323】’=>12.43,323
對象
[object Object]
function
function(){console.log(212)}es6
null
false
underfind
false
Number
0,-0,NaN=>false
其餘=>true
String
''=>false
其餘=>true
引用類型
trueweb
轉字符串類型直接調用toString()
轉其餘類型先轉valueOf()面試
運算中其中一方是字符串,另外一個方也將轉換成字符串
若是一方不是字符串數字。那麼會將它轉成數字或者字符串
除了加減運算以外。一方爲數字,另外一方轉爲數字算法
若是是對象,就經過 toPrimitive 轉換對象
若是是字符串,就經過 unicode 字符索引來比較chrome
window數據庫
對象調用,則指向這個對象
獨立調用,指向window
apply.call,bind動態this
指向當前實例化後的對象。
調用箭頭函數外層第一個普通函數的this
先判斷數據類型是否相同,一致判斷值大小
類型不一樣,進行類型轉換
先判斷是不是null和underfind的比較,是返回true
判斷是不是string和number的比較,是先將字符串轉成對應的數字進行比較
判斷一方是否爲布爾值,是則把布爾值換成number進行比較
判斷一方是否爲object,且另一方爲string,number,是則把object轉成基礎類型進行判斷
不會盡享類型轉換,直接對比值的大小
在函數執行上下A
在執行上下文A中的函數B
調用了A中的變量。閉包產生
在js中,函數上下文執行完以後,生命週期結束後。垃圾回收機制就會回收內部不被使用的變量,也就是內存中失去引用的變量,對其進行回收。閉包會阻止此過程
js中具備自動垃圾回收機制,對於函數內部的變量失去引用以後,很快會被回收,可是處於全局的變量,js不會回收,除非引用完及時釋放,儘可能少使用全局變量
基礎類型值的拷貝
引用類型拷貝的引用地址(指針)
一個改變另外一個必受影響
Object.assign()和...都是淺拷貝
深拷貝
從新開闢內存空間,互相不影響
function deepClone(obj) { function isObject(o) { return (typeof o == 'object' || typeof o == 'function') && o !== null } if (!isObject(obj)) { throw new Error('this is not objcet') } let isArray = Array.isArray(obj) let newObj = isArray ? [...obj] : { ...obj } Reflect.ownKeys(newObj).forEach(key => { newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] }) return newObj }
對象的 __proto__ 屬性指向原型, __proto__ 將對象和原型鏈接起來組成了原型鏈
當控制器執行到可執行的代碼的時候,js就會建立執行上下文
執行上下文的建立階段會建立變量對象。此時
此時會先建立arguments對象
檢查函數,以函數聲明並建立屬性
檢查var聲明的變量,複製underfind
其實這個就是所謂的變量提高階段
區別:
var存在變量提高
能夠重複聲明
能夠用window去調用
const、let
不存在變量提高
不可重複聲明
擁有塊級做用域
不可經過window去調用
const賦值不可更改
當變量未聲明以前。去調用此變量,被叫作暫時性死區
原型繼承
構造函數繼承經過
call改變this指向去繼承上面的方法和屬性
原型上的繼承
將子類的原型指向父級的實例話對象
構造函數繼承一樣使用call改變指向進行繼承
原型繼承則經過Object.create()進行繼承
class 實現繼承的核心在於使用 extends 代表繼承自哪一個父類
而且在子類構造函數中必須調用 super,由於這段代碼能夠當作 Parent.call(this, value)
class 的本質就是函數。
解決命名衝突
實現複用
提升代碼的可維護程度
避免變量全局污染
不支持動態引入
對象的代理
代理,但是實現數據的雙向綁定
let handler = { get(target, property, receiver) { getLogger(target, property) return Reflect.get(target, property, receiver) }, set(target, property, value, receiver) { setBind(value, property) return Reflect.set(target, property, value) } } return new Proxy(obj, handler) } let p = onWatch( obj, (v, property) => { console.log(`監聽到屬性${property}改變爲${v}`) }, (target, property) => { console.log(`'${property}' = ${target[property]}`) } ) p.a = 2 // 監聽到屬性a改變 console.log(p.a)
返回一個新數組。能夠在這個函數中加邏輯處理返回
接受三個參數
當前的元素
index
願數組
返回一個新數組。對符合條件元素進行返回
接受三個參數
當前的元素
index
願數組
數組的計算
接受兩個參數,分別是回調函數和初始值
隱藏了這個複雜的過程,只須要一句代碼調用就能實現功能。
隱藏了這個複雜的過程,只須要一句代碼調用就能實現功能。
適配器用來解決兩個接口不兼容的狀況,不須要改變已有的接口,經過包裝一層的方式實現兩個接口的正常協做。
class Man { getName() { return '港版插頭' } } class Son { constructor() { this.proxy = new Man() } getName() { return this.proxy.getName() + 'hahahahh' } static create(name) { console.log(name) } } let s = new Son() console.log(s.getName())
代理是爲了控制對對象的訪問,不讓外部直接訪問到對象。在現實生活中,也有不少代理的場景。好比事件代理
發佈-訂閱模式也叫作觀察者模式。經過一對一或者一對多的依賴關係,當對象發生改變時,訂閱方都會收到通知。
併發是一段時間相繼完成,好比A和B,一段時間內切換完成相似早上起牀前。洗漱,吃飯,出門。一段時間完成的一些事
並行是同時進行,好比邊看手機邊吃飯
當咱們異步請求成功時會在回調函數中寫咱們的邏輯。固然這裏的邏輯還涉及到進一步的請求,不斷嵌套就會出現回調地獄
回調函數缺點:
嵌套過深,耦合度高,不易維護
難以捕捉錯誤
不能使用try。。catch
使用Generator和promise以及async均可以
自然的迭代器,能夠是遍歷停下來
可控制迭代器的函數,能夠暫停,也能夠選擇任什麼時候候恢復
使用場景:
抽獎
小遊戲
斐波那契數列
特色:
Promise三個狀態,padding,resolve和reject。狀態不可逆,一旦確認,沒法改變
Promise鏈:
經過then方法去傳遞執行,執行then方法以後會返回一個promise對象,來完成鏈式操做
構造函數和then函數執行有哪些區別?
構造函數內的內容當即執行。
then的函數當狀態改變在進行執行
優化了promise鏈式調用,以同步的寫法去操做異步代碼
原理實際上是promise的語法糖,await 內部經過promise靜態方法Promise.resove()返回一個新的promise
Function.prototype.myApply = function (context, arr) { if (typeof this !== 'function') { throw new Error('error') } context = context || window context.fn = this let reslut; if (arr) { reslut = context.fn(...arr) } else { reslut = context.fn() } delete context.fn return reslut }
Function.prototype.myCall = function (context) { if (typeof this !== 'function') { throw new Error('error') } context = context || window context.fn = this let args = [...arguments].slice(1) let reslut = context.fn(...args) delete context.fn return reslut }
Function.prototype.myApply = function (context, arr) { if (typeof this !== 'function') { throw new Error('error') } context = context || window context.fn = this let reslut; reslut = arr ? context.fn(...arr) : context.fn() delete context.fn return reslut }
function news() { let obj = new Object() let Constructor = [...arguments].shift() obj.__proto__ = Constructor.prototype let res = constructor.apply(obj, arguments) return typeof res === 'object' ? ret : obj }
function instanceofs(left, right) { let prototype = right.prototype left = left.__proto__ while (1) { if (left == null || left == undefined) { return false } if (left == prototype) { return true } left = left.__proto__ } }
v8實現了精確式GC,GC算法採用分代垃圾回收機制,所以。v8將內存(堆)分爲新生代和老生代兩部分
新生代算法
對象存活時間較短,使用 Scavenge GC 算法
在新生代內存空間分爲2部分,分別是from空間和to空間,在這2個空間其中必然有一個是空閒的。新分配的對象會放到from空間,當from空間被佔滿的時候,新生代GC就會啓動,算法會檢查from空間的存活對象,將他們複製到to空間,其中失去存活的對象就會被銷燬,將複製完,from和to空間互換,
老生代算法
某一個空間沒有分塊時
空間中被對象超過一段限制時
空間不能保證新生代對象轉到老生代中
這個時候遍歷堆中全部活的對象,在標記完成後,銷燬那些沒有標記的對象。
清除對象後會形成堆內存出現碎片的狀況
當碎片超過必定限制的時,會啓動壓縮算法。在壓縮過程當中,將活的對象像一端移動,直到全部對象都移動完成而後清理掉不須要的內存。
新生代中的對象是否已經經歷過Scavenge算法。若是經歷過,會將新生代空間轉到老生代空間中
當to空間的對象佔空間大小的25%,這樣狀況下。爲了避免影響內存分配。會將對象重新生代的空間轉老生代空間中
瀏覽器出與安全考慮。有同源策略。也就是當協議。域名。端口號任何一個不一樣就是跨域。Ajax就會請求失敗
其實主要是用來防止 CSRF 攻擊的。簡單點說,CSRF 攻擊是利用用戶的登陸態發起惡意請求。
jsonp
cors
document.domain
postMessage
對於複雜請求來講,首先會發起一個預檢請求,該請求是 option 方法的,經過該請求來知道服務端是否容許跨域請求。
事件處理程序
增長和和刪除事件:
element.attachEvent('on'+事件類型,處理函數)
element.detachEvent(‘on’+事件類型,處理函數)
element.addEventListener('click',處理函數,是否冒泡)
false(默認冒泡)
true(捕獲)
element.removeEventListener('click',處理程序,是否冒泡)
同添加事件一致
事件對象
cancelBubble =》默認值爲false,但設置true就能夠取消事件冒泡
returnValue =》默認true,設置爲false,,就能夠取消事件的默認行爲
srcElement =>事件目標
type=>事件類型
stopPropagation =》取消事件冒泡
preventDefault =》取消事件的默認行爲
target =>事件目標
type=>事件類型
若是一個節點中子節點是動態生成的,那麼子節點須要註冊事件的化應該註冊在父節點上
好處:
節省內存空間
不須要給子節點註銷事件
事件的觸發過程是怎麼樣的?知道什麼是事件代理嘛?
事件觸發有三個階段:
window往事件觸發傳播。遇到註冊的捕獲事件會觸發
傳播到事件觸發時觸發註冊事件
從事件觸發之處向window傳播。遇到註冊的冒泡會觸發
從捕獲到目標階段再到冒泡的過程
從上向下執行的一個過程
Document=》html=》body=》div
從當前事件觸發向上查找過程
div=>body=>html=>document
cookie已經不建議存儲了,若是沒有大量數據存儲須要,使用localStorage和sessionStorage
對於不怎麼改變的數據存使用localStorage。不然使用sessionStorage
cookie
做用:主要用於儲存用戶的登錄信息,
生命週期:通常有服務器生成,能夠設置過時時間
數據儲存大小:4k
與服務端通訊:每次都會攜帶在headr中,對於請求性能影響
屬性 | 做用 |
---|---|
value | 若是用於保存登錄狀態,應加密,不能使用明文的用戶標示 |
http-only | 不能經過js訪問cookie,減小xss的攻擊 |
secure | 只能在協議爲https的請求中攜帶 |
same-site | 規定瀏覽器不能在跨域請求中攜帶cookie,減小CSRE攻擊 |
生命週期:除非被清理,不然一直存在
數據存儲大小:5M
與服務端通訊:不參與
數據生命週期:頁面關閉就清理
數據存儲大小:5M
與服務端通訊:不參與
數據生命週期:除非被清理,不然一直存在
數據存儲大小:無限
是否與服務端通訊:不參與
service worker是一段腳本,與web worker同樣,也在後臺運行,做爲一個獨立的線程。運行環境和普通腳本不一樣,因此不能直接參與web交互行爲。native app能夠作到離線使用,消息推送。後臺自啓動,service worker的出現爲了是web app 也有相似的能力
使用場景
離線緩存
性能優化領域
緩存能夠說是性能優化中最簡單高效的一種方式了。他以最高減小網絡傳輸所帶來的損耗
數據請求:
網絡請求
後端處理
瀏覽器響應
直接使用緩存,而不發請求
或發起請求後端存儲的數據和前端一致,那麼就不必將數據回傳過來,這樣能夠減小響應數據
優勢:
它的緩存和其餘內建的緩存機制不一樣。它能夠由咱們自定緩存那些文件,如何匹配緩存,如何讀取緩存,而且緩存是持久性的
Memory Cache
優勢:
內存中的緩存。讀取內存中的數據比磁盤要快不少
訪問過頁面以後,再次刷新頁面,能夠發現以前不少數據都來自內存緩存
缺點:
持續性短,隨着進程的釋放而釋放
大文件通常都是不會儲存內存中,反之優先
優勢:
儲存在硬盤中。覆蓋率基本是最大的,什麼均可以存入
跟內存相比。容量和儲存時效性超級好
儲存在會話中,一旦會話結束就會被釋放
強緩存
是HTTP/1的產物,表示資源的過時時間,並受限與本地時間。若是修改了時間,緩存失效
出現於HTTP/1.1的產物,優先級比Expires要高
該屬性能夠調整設置時間
Cache-control能夠在請求頭或者響應中設置,而且能夠組合多種指令
private=>響應能夠被客戶端緩存
pablic=》能夠同被客戶端和代理服務器緩存
no-cache=》資源會被緩存,但當即失效。下次發起請求會驗證是否過時
協議緩存
若是緩存過時了。就須要發起請求驗證資源是否更新,協議緩存能夠經過2個http-header實現:Last-Modified+ETag
當瀏覽器發起請求驗證資源時,若是資源沒有作出改變,那麼服務器會返回304狀態嗎。而且更新緩存有效期
若是資源有所改變,更新資源
表示本地文件最後更改的日期。If-Modified-Since會將last-Modified的值發送給服務器,詢問服務器在該日期更新後資源是否有變更,有更新,返回更新後的信息,反之,返回狀態碼
弊端:
若是是本地打開緩存文件,即便沒有對文件進行修改,但仍是會形成last-Modified的修改。服務端不能命中緩存致使發送相同的資源
由於last-Modified只能以秒計時。若是在不可感知的時間你內完成了這個文件,那麼會形成服務端認爲資源被秒中,不會返回正確值
相似指紋,If-None-Match會將ETag發送給你服務器,詢問服務器資源ETag是否改變,若有改變,將更新的資源返回來,ETag比Last-Modified的優先級高
首先瀏覽器打開一個網頁的時候,首先會解析他對應的html,在網絡傳輸中咱們平時所寫的js+css+html都都是以子節數據(0-1)進行傳輸
轉子節轉爲字符串。
字符串經過詞法解析爲標記(token),這一過程也被稱爲標記法。
將結束標記以後,將會把標記轉爲node
根據node以前的聯繫轉成dom
首先這一過程是很是耗性能的,由於瀏覽器會肯定每個節點樣式分別是什麼,須要遞歸匹配到數據的變化
子節數據
字符串
標記(token)
node
cssom
當咱們生成dom樹和cssom樹的時候,就須要將這2個樹和成渲染樹
在這一過程當中,將包括須要的節點和這些節點的樣式去渲染出來
當瀏覽器生成渲染樹以後,瀏覽器根據渲染樹佈局,而後GPU繪製。合成圖層
由於dom屬於渲染引擎,js屬於js引擎,面對兩個線程以前的通訊,操做dom次數一多,也就等同於進行線程以前的切換,而且操做dom可能帶來回流。
渲染的前提是生成渲染樹,全部html和css確定會堵塞渲染
下降一開始須要渲染的文件大小
而且扁平化。優化選擇器
當瀏覽器在執行到script標籤時,就會暫時dom,完成後從暫停處繼續執行,
首評加載的越快,就不應在首評加載js。建議將script放到body下面的緣由
async(適合沒有依賴的文件)
js文件下載和解析不會阻塞渲染
defer
並行下載,會等到html執行完畢以後在進行執行
迴流必定會引發重繪
但重繪不必定會引發迴流
當改變節點的樣的時候。不會改變佈局的時候,好比修改color樣式。
通常佈局修改,dom操縱通常會觸發迴流
使用 transform 替代 top
使用 visibility 替換 display: none ,由於前者只會引發重繪,後者會引起迴流(改變了佈局)
不要把節點的屬性值放在一個循環裏當成循環裏的變量
不要使用 table 佈局,可能很小的一個小改動會形成整個 table 的從新佈局
動畫實現的速度的選擇,動畫速度越快,迴流次數越多,也能夠選擇使用 requestAnimationFrame
CSS 選擇符從右往左匹配查找,避免節點層級過多
從文件大小
從script標籤上使用來考慮
從html和css代碼書寫上來考慮
從須要下載的內容是否須要在首屏使用上來考慮
想盡一切辦法將可執行的代碼注入網頁中
攻擊的代碼被服務器寫日數據庫,這種危害會很大,若是網站訪問量大的話,會致使正常訪問頁面的用戶都收到攻擊
通常會以評論方式去注入
通常以修改URL參數的方式進行攻擊
誘導用戶訪問連接從而實現攻擊
對於用戶輸入的東西永遠不要相信,最普通的作法是對用戶輸入的內容進行轉譯。
引號。尖括號。斜槓等進行轉譯‘
或者使用白名單也能夠,js-xss來實現
跨站僞造請求,攻擊者構造出一個向後端請求的地址,誘導用戶點擊或者經過某種途徑自動發起請求,若是用戶是在登錄的狀況下,後端覺得是用戶操做,從而進行誘導。
經常使用方式:
加入網站中有個get請求提交表單的接口。那麼攻擊者會在釣魚網站加入一個圖片,圖片的地址就是這個評論的接口
防護:
get請求不對數據進行修改
不讓第三方訪問到用戶的cookie(some-site)
阻止第三方網站請求接口(驗證refrer)
請求是附帶驗證信息,好比token或者驗證碼,進行判斷
攻擊者經過將要攻擊的網站經過iframe的方式放入本身的網站中,並將iframe設爲透明,誘導用戶點擊
防護:
js判斷,刪除頁面中的iframe
是指攻擊方同時將服務端和客戶端同時進行鏈接。並讓對方認爲都是安全的,但實際上整個過程當中,都是被控制了,攻擊者能夠同時修改用戶的信息和數據庫中的內容
防護:
儘可能避免在公衆場合使用Wi-Fi。避免被攻擊
XMind: ZEN - Trial Version