摘要:一垃圾回收與內(nèi)存泄漏參考內(nèi)存控制垃圾回收的垃圾回收策略主要基于分代式垃圾回收機(jī)制。內(nèi)存泄漏內(nèi)存泄漏的實質(zhì)就是應(yīng)當(dāng)回收的對象因為意外沒有被回收,變成了常駐在老生代中的對象。造成內(nèi)存泄漏的主要原因有緩存隊列消費不及時作用域未釋放。
內(nèi)容
1.內(nèi)存泄漏與垃圾回收一、垃圾回收與內(nèi)存泄漏
2.cookie和session
3.單線程原理
4.上下左右居中的幾種實現(xiàn)。
5.BFC和IFC模型。
參考:內(nèi)存控制
1.垃圾回收v8的垃圾回收策略主要基于分代式垃圾回收機(jī)制。按照對象的存活時間將內(nèi)存的垃圾回收進(jìn)行不同的分代,然后,分別對不同的分代的內(nèi)存再進(jìn)行高效的垃圾回收算法。在V8中,主要將內(nèi)存分為新生代和老生代兩代。新內(nèi)存中的對象存活時間短,老內(nèi)存中的對象存活時間長或常駐內(nèi)存對象。
1)新生代垃圾回收算法scavenge算法
新生代中的對象主要通過scavenge算法進(jìn)行垃圾回收,其主要是采用cheney算法進(jìn)行具體處理。
cheney算法采用一種復(fù)制方式的垃圾回收算法,將堆內(nèi)存一分為二,只有一部分空間被使用稱為From空間,另一個處于閑置稱為To空間。當(dāng)進(jìn)行分配對象的時候先在from空間分配,當(dāng)進(jìn)行垃圾回收時,會檢查from空間中的存活對象,將這些存活對象復(fù)制到to空間中,復(fù)制完成后From和to空間角色互換,清空to空間,在垃圾回收過程中就是通過將存活對象在兩個空間中進(jìn)行復(fù)制。
缺點: 只能使用一半的內(nèi)存
優(yōu)點: 只復(fù)制存活的對象,對于生命周期短的場景存活對象只占小部分,所以時間效率高
當(dāng)一個對象經(jīng)過多次復(fù)制依然存活時,就會被認(rèn)為是生命周期較長的對象,會被移入老生代內(nèi)存中。
對于移入老生代內(nèi)存有兩個條件:
對象已經(jīng)經(jīng)過新生代內(nèi)存回收機(jī)制的回收依然存活
復(fù)制到To空間的對象超過25%(為什么是25%?這個To空間接下來會成為From空間并接受內(nèi)存分配,如果占比過高影響后續(xù)分配)
2)老內(nèi)存垃圾回收算法Mark-Sweep & Mark-Compact
老內(nèi)存中,大多是不死的老對象,用scavenge算法又費力,又占用空間,因此,采用了新的內(nèi)存垃圾回收算法:Mark-Sweep & Mark-Compact。
Mark-Sweep 標(biāo)記清掃
mark-sweep分為標(biāo)記和清除兩個階段,mark階段會遍歷堆,然后標(biāo)記處活著的對象,sweep階段會清除沒有被標(biāo)記的對象。mark-sweep只清理沒有標(biāo)記的對象,在老內(nèi)存中,死了的對象占比較少,這也是這個算法高效的原因。
mark-sweep的問題在于,每次sweep后,會存在內(nèi)存碎片,這些不連續(xù)的內(nèi)存碎片會占有大量空間,因此,下一次復(fù)制大對象時,將會發(fā)現(xiàn)空間不夠,因而再次觸發(fā)垃圾回收,這個回收是不必要的,也浪費了cpu。為了解決這個問題,增加了mark-compact算法。
mark-compact 標(biāo)記整理和壓縮
mark-compact在整理過程中,將活著的對象往一端移動,移動完成后,直接將另外一端的內(nèi)存清理掉。
因為mark-compact需要移動內(nèi)存,因此,垃圾回收主要使用mark-sweep,在內(nèi)存不夠時,才會觸發(fā)一次mark-compact。
這三種算法的比較:
Incremental Marking
為了避免出現(xiàn)javaScript應(yīng)用邏輯與垃圾回收器看到不一致的情況,垃圾回收都要將應(yīng)用邏輯停下來,這種行為會造成停頓,在新生代垃圾回收過程中因為存活對象比較少,即使停頓基本影響不大。在老生代垃圾回收中,通常存活對象較多,全堆垃圾回收的標(biāo)記、清除、整理影響較大。
解決辦法:分批次進(jìn)行,拆分成許多小步,每進(jìn)行一小步就讓邏輯運行一會。
v8后續(xù)還引入了lazy sweeping與incremental compaction,同時還引入了,并行標(biāo)記和并行清理,進(jìn)一步的利用多核性能降低每次停頓的時間。
2.內(nèi)存泄漏內(nèi)存泄漏的實質(zhì)就是應(yīng)當(dāng)回收的對象因為意外沒有被回收,變成了常駐在老生代中的對象。
造成內(nèi)存泄漏的主要原因有:緩存、隊列消費不及時、作用域未釋放。
1)緩存
慎將內(nèi)存當(dāng)做緩存,一旦一個對象被當(dāng)做緩存來使用,那它將會常駐在老生代中,這將導(dǎo)致垃圾回收在進(jìn)行掃描和整理時,對這些對象做無用功。
v8內(nèi)存是通過垃圾回收進(jìn)行處理的,沒有過期策略,而真正的緩存是存在過期策略的。
緩存限制策略:將結(jié)果記錄在數(shù)組中,一旦超過數(shù)量,就以先進(jìn)先出的方式進(jìn)行淘汰。
2)閉包
閉包是通過中間函數(shù)進(jìn)行間接訪問內(nèi)部變量實現(xiàn)的一個功能,一旦變量引用這個中間函數(shù),這個中間函數(shù)將不會釋放,同時也會使原始的作用域不會得到釋放,作用域中產(chǎn)生的內(nèi)存占用也不會得到釋放。除非不再有引用,才會逐步釋放。
參考:構(gòu)建Web應(yīng)用
1.cookiehttp是一個無狀態(tài)的協(xié)議,現(xiàn)實中的業(yè)務(wù)卻是需要有狀態(tài)的,否則無法區(qū)分用戶之間的身份。利用cookie記錄瀏覽器與客戶端之間的狀態(tài)。
cookie的處理分為如下幾步:
服務(wù)器向客戶服務(wù)發(fā)送cookie
瀏覽器將cookie保存
之后每次瀏覽器都會將cookie發(fā)送給服務(wù)器,服務(wù)器端再進(jìn)行校驗
告知客戶端是通過響應(yīng)報文實現(xiàn)的,響應(yīng)的cookie值在set-cookie字段中,它的格式與請求中的格式不太相同,規(guī)范中對它的定義如下:
Set-Cookie: name=value; Path=/; Expires=Sun, 23-Apr-23 09:01:35 GMT; Domain=.domain.com;
name = value是必選字段,其他為可選字段。
可選字段 | 說明 |
---|---|
path | 表示這個cookie影響的路徑,當(dāng)前訪問的路徑不滿足該匹配時,瀏覽器則不發(fā)送這個cookie |
Expires、Max-Age | 用來告知瀏覽器這個cookie何時過期的,如果不設(shè)置該選項,在關(guān)閉瀏覽器時,會丟失掉這個cookie,如果設(shè)置過期時間,瀏覽器將會把cookie內(nèi)容寫入到磁盤中,并保存,下次打開瀏覽器,該cookie依舊有效。expires是一個utc格式的時間字符串,告知瀏覽器此cookie何時將過期,max-age則告知瀏覽器,此cookie多久后將過期。expires會在瀏覽器時間設(shè)置和服務(wù)器時間設(shè)置不一致時,存在過期偏差。因此,一般用max-age會相對準(zhǔn)確。 |
HttpOnly | 告知瀏覽器不允許通過腳本document.cookie去更改這個cookie值,也就是document.cookie不可見,但是,在http請求的過程中,依然會發(fā)送這個cookie到服務(wù)器端。 |
secure | 當(dāng)secure = true時,創(chuàng)建的cookie只在https連接中,被瀏覽器傳遞到服務(wù)器端進(jìn)行會話驗證,如果http連接,則不會傳遞。因此,增加了被竊聽的難度。 |
cookie的性能影響
當(dāng)cookie過多時,會導(dǎo)致報文頭較大,由于大多數(shù)cookie不需要每次都用上,因此,除非cookie過期,否則會造成帶寬的浪費。
cookie優(yōu)化的建議:
減小cookie的大小,切記不要在路由根節(jié)點設(shè)置cookie,因為這將造成該路徑下的全部請求都會帶上這些cookie,同時,靜態(tài)文件的業(yè)務(wù)不關(guān)心狀態(tài),因此,cookie在靜態(tài)文件服務(wù)下,是沒有用處,請不要為靜態(tài)服務(wù)設(shè)置cookie。
為靜態(tài)組件使用不同的域名,cookie作用于相同的路由,因此,設(shè)定不同的域名,可以防止cookie被上傳。
減少dns查詢,這個可以基于瀏覽器的dns緩存來削弱這個副作用的影響(換用額外域名需要DNS查詢)。
cookie的不安全性
cookie可以在瀏覽器端,通過調(diào)用document.cookie來請求cookie并修改,修改之后,后續(xù)的網(wǎng)絡(luò)請求中就會攜帶上修改過后的值。
例如:第三方廣告或者統(tǒng)計腳本,將cookie和當(dāng)前頁面綁定,這樣可以標(biāo)識用戶,得到用戶瀏覽行為。
cookie存在各種問題,例如體積大、不安全,為了解決cookie的這些問題,session應(yīng)運而生,session只保存在服務(wù)器端,客戶端無法修改,因此,安全性和數(shù)據(jù)傳遞都被保護(hù)。
如何將每個客戶和服務(wù)器中的數(shù)據(jù)一一對應(yīng):
基于cookie來實現(xiàn)用戶和數(shù)據(jù)的映射
通過查詢字符串來實現(xiàn)瀏覽器端和服務(wù)器端數(shù)據(jù)的對應(yīng)。它的原理是檢查請求的查詢字符串,如果沒值,會先生成新的帶值的URL。
安全性
session的口令保存在瀏覽器(基于cookie或者查詢字符串的形式都是將口令保存于瀏覽器),因此,會存在session口令被盜用的情況。當(dāng)web應(yīng)用的用戶十分多,自行設(shè)計的隨機(jī)算法的口令值就有理論機(jī)會命中有效的口令值。一旦口令被偽造,服務(wù)器端的數(shù)據(jù)也可能間接被利用,這里提到的session的安全,就主要指如何讓這一口令更加安全。
有一種方法是將這個口令通過私鑰加密進(jìn)行簽名,使得偽造的成本較高??蛻舳吮M管可以偽造口令值,但是由于不知道私鑰值,簽名信息很難偽造。如此,我們只要在響應(yīng)時將口令和簽名進(jìn)行對比,如果簽名非法,我們將服務(wù)器端的數(shù)據(jù)立即過期即可,
將口令進(jìn)行簽名是一個很好的解決方案,但是如果攻擊者通過某種方式獲取了一個真實的口令和簽名,他就能實現(xiàn)身份的偽造了,一種方案是將客戶端的某些獨有信息與口令作為原值,然后簽名,這樣攻擊者一旦不在原始的客戶端上進(jìn)行訪問,就會導(dǎo)致簽名失敗。這些獨有信息包括用戶IP和用戶代理。
三、單線程原理 1.單線程JavaScript的單線程,與它的用途有關(guān)。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復(fù)雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器應(yīng)該以哪個線程為準(zhǔn)?
所以,為了避免復(fù)雜性,從一誕生,JavaScript就是單線程,這已經(jīng)成了這門語言的核心特征,將來也不會改變。
為了利用多核CPU的計算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標(biāo)準(zhǔn)并沒有改變JavaScript單線程的本質(zhì)。
2.任務(wù)隊列所有任務(wù)可以分成兩種,一種是同步任務(wù)(synchronous),另一種是異步任務(wù)(asynchronous)。同步任務(wù)指的是,在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢,才能執(zhí)行后一個任務(wù);異步任務(wù)指的是,不進(jìn)入主線程、而進(jìn)入"任務(wù)隊列"(task queue)的任務(wù),只有"任務(wù)隊列"通知主線程,某個異步任務(wù)可以執(zhí)行了,該任務(wù)才會進(jìn)入主線程執(zhí)行。
異步執(zhí)行的運行機(jī)制如下。(同步執(zhí)行也是如此,因為它可以被視為沒有異步任務(wù)的異步執(zhí)行。)
所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧(execution context stack)。
主線程之外,還存在一個"任務(wù)隊列"(task queue)。只要異步任務(wù)有了運行結(jié)果,就在"任務(wù)隊列"之中放置一個事件。
一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊列",看看里面有哪些事件。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。
主線程不斷重復(fù)上面的第三步
js引擎執(zhí)行異步代碼而不用等待,是因有為有 消息隊列和事件循環(huán)。
消息隊列:消息隊列是一個先進(jìn)先出的隊列,它里面存放著各種消息。
事件循環(huán):事件循環(huán)是指主線程重復(fù)從消息隊列中取消息、執(zhí)行的過程。
JS中分為兩種任務(wù)類型:macrotask和microtask,在ECMAScript中,microtask稱為jobs,macrotask可稱為task。
宏任務(wù)(macrotask):setTimeout, setInterval, setImmediate, requestAnimationFrame,I/O, UI rendering。
微任務(wù)(microtask):process.nextTick, Promise.then catch finally, MutationObserver,Object.observe 。
在掛起任務(wù)時,JS 引擎會將所有任務(wù)按照類別分到這兩個隊列中,首先在 macrotask 的隊列(這個隊列也被叫做 task queue)中取出第一個任務(wù),執(zhí)行完畢后取出 microtask 隊列中的所有任務(wù)順序執(zhí)行;之后再取 macrotask 任務(wù),周而復(fù)始,直至兩個隊列的任務(wù)都取完。
宏任務(wù)和微任務(wù)之間的關(guān)系:
事件循環(huán)機(jī)制進(jìn)一步補(bǔ)充
主線程運行時會產(chǎn)生執(zhí)行棧,棧中的代碼調(diào)用某些api時,它們會在事件隊列中添加各種事件(當(dāng)滿足觸發(fā)條件后,如ajax請求完畢)
而棧中的代碼執(zhí)行完畢,就會讀取事件隊列中的事件,去執(zhí)行那些回調(diào)
如此循環(huán)
注意,總是要等待棧中的代碼執(zhí)行完畢后才會去讀取事件隊列中的事件
參考1.http://www.ruanyifeng.com/blo...
2.https://www.jianshu.com/p/f47...
3.實例
https://blog.csdn.net/mars200...
五、BFC和IFC模型 1.BFCBFC(Block Formatting Context)叫做“塊級格式化上下文”。
當(dāng)一個元素設(shè)置了新的BFC后,就和這個元素外部的BFC沒有關(guān)系了,這個元素只會去約束自己內(nèi)部的子元素。
1)BFC的布局規(guī)則如下:
內(nèi)部的Box會在垂直方向,一個接一個地放置。
Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發(fā)生重疊
每個盒子的左邊界都要緊靠包含容器的左邊界。即使存在浮動也是如此。除非這個元素自己形成了一個新的BFC。
BFC的區(qū)域不會與float box重疊。
BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
計算BFC的高度時,浮動元素也參與計算
2)如何產(chǎn)生新的BFC
根元素;
float不為none;
position為absolute,fixed;
display為inline-block,table-cell,table-caption,flex;
overflow不為visible;
3)實際應(yīng)用
清除浮動 例子
margin折疊問題
兩側(cè)布局:左邊固定,右邊自適應(yīng)
雙飛翼布局 例子
張鑫旭:CSS深入理解流體特性和BFC特性下多欄自適應(yīng)布局
2.IFCIFC(Inline Formatting Content)叫做 行內(nèi)格式化上下文。
1)規(guī)則
盒子是水平一個接一個的排列,水平的margin,內(nèi)邊距,邊框是可以有的。
垂直方向的對齊,可能是底部對齊,頂部對齊,也可能是基線對齊(這個是默認(rèn)的);ps.這里的盒子應(yīng)該是指的內(nèi)聯(lián)元素的盒子(span,strong等)和匿名內(nèi)聯(lián)盒子(只有文本,沒有內(nèi)聯(lián)元素包含,自動創(chuàng)建的),他們合稱內(nèi)聯(lián)盒子,一個或者多個內(nèi)聯(lián)盒子組成一個行框,行框的寬度由包含塊和出現(xiàn)的浮動決定的。
行框中的內(nèi)聯(lián)盒子的高度小于行框的高度時,內(nèi)聯(lián)盒子的垂直方向的對齊方式取決于vertical-align屬性
當(dāng)一個行框水平不能容納內(nèi)聯(lián)盒子時,他們將會在垂直方向上產(chǎn)生多個行框,他們上下一個挨著一個,但是不會重疊
一般來說,行框的左邊界緊挨著包含容器的左邊界,行框的右邊界緊挨著包含容器的右邊界,(是兩個邊都緊挨著)。然而,浮動盒子可能存在于包含邊框邊界和行框邊界之間;
多個內(nèi)聯(lián)盒子的寬度小于包含他們的行框時,他們在水平方向的分布取決于text-align屬性(默認(rèn)是left)
2)主要影響IFC內(nèi)布局的css: 參考
font-size
line-height
height
vertical-aligin
容器的高度 height = line-height + vertical-align
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/110198.html
摘要:對應(yīng)的代碼接下來的句是關(guān)鍵部分,兩句分分別把剛剛創(chuàng)建的兩個對象的引用壓到棧頂。所以雖然指令的調(diào)用是相同的,但行調(diào)用方法時,此時棧頂存放的對象引用是,行則是。這,就是語言中方法重寫的本質(zhì)。 類初始化 在講類的初始化之前,我們先來大概了解一下類的聲明周期。如下圖 類的聲明周期可以分為7個階段,但今天我們只講初始化階段。我們我覺得出來使用和卸載階段外,初始化階段是最貼近我們平時學(xué)的,也是筆試...
摘要:以前前端時代做按鈕,圖標(biāo)背景圖用,后來主流現(xiàn)在各種流體結(jié)構(gòu),高分屏的需求,大行其道,無論是體積還是靈活性還是品質(zhì)都遠(yuǎn)勝。 以前前端IE6時代做按鈕, 圖標(biāo)背景圖用gif, png, 后來主流png, 現(xiàn)在各種流體結(jié)構(gòu),高分屏的需求, svg大行其道, 無論是體積還是靈活性還是品質(zhì)都遠(yuǎn)勝png。 之前自己也總結(jié)了一下使用svg的各種方法吧: 1.直接使用 alt=> IE/Edge的...
摘要:前端最基礎(chǔ)的就是。前面我們已經(jīng)基本掌握常規(guī)的語法語義,以及基本的使用方法。等價于當(dāng)載入就緒執(zhí)行一個函數(shù)回調(diào)。返回一組匹配的元素。據(jù)提供的原始標(biāo)記字符串,動態(tài)創(chuàng)建由對象包裝的元素。同時設(shè)置一系列的屬性事件等。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提...
摘要:前端最基礎(chǔ)的就是。前面我們已經(jīng)基本掌握常規(guī)的語法語義,以及基本的使用方法。等價于當(dāng)載入就緒執(zhí)行一個函數(shù)回調(diào)。返回一組匹配的元素。據(jù)提供的原始標(biāo)記字符串,動態(tài)創(chuàng)建由對象包裝的元素。同時設(shè)置一系列的屬性事件等。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS),本著提...
閱讀 3551·2021-11-08 13:15
閱讀 2107·2019-08-30 14:20
閱讀 1386·2019-08-28 18:08
閱讀 977·2019-08-28 17:51
閱讀 1484·2019-08-26 18:26
閱讀 2988·2019-08-26 13:56
閱讀 1483·2019-08-26 11:46
閱讀 2586·2019-08-23 14:22