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