摘要:但是如果一個值不再用到了,引用次數(shù)卻不為,垃圾回收機制卻無法釋放這塊內(nèi)存,從而導致內(nèi)存泄漏。內(nèi)存泄漏垃圾回收語言的內(nèi)存泄漏主因是不需要的引用。常見內(nèi)存泄漏意外的全局變量處理未定義變量的方式比較寬松未定義的變量會在全局對象創(chuàng)建一個新變量。
簡答題: settimeout 與 setInterval的區(qū)別, 及對他們的內(nèi)存的分析 區(qū)別
setTimeout是在一段時間后調(diào)用指定函數(shù)(僅一次)
setInterval是每隔一段時間調(diào)用指定函數(shù)(N次)
function run(){ // 其他代碼 setTimeout(function(){ run(); }, 10000); } run();
以上面的代碼來說, 雖然設置的是10s執(zhí)行一次, 但是實際時間卻是需要// 其他代碼的執(zhí)行時間來確定
即setTimeout的間隔時間是, // setTimeout 的間隔時間 === 最小時間是(10s+)
setInterval(function(){ run(); }, 10000);
而setInterval, 不會有上面的問題, 但是如果run()的執(zhí)行時間, 操作大于10s, 那么甚至可能跳過任務;
setInterval 和 setTimeout 會產(chǎn)生內(nèi)存溢出
JavaScript setInterval()方法是否導致內(nèi)存泄漏?
程序的運行需要內(nèi)存。只要程序提出要求,操作系統(tǒng)或者運行時(runtime)就必須供給內(nèi)存。
對于持續(xù)運行的服務進程(daemon),必須及時釋放不再用到的內(nèi)存。否則,內(nèi)存占用越來越高,輕則影響系統(tǒng)性能,重則導致進程崩潰。
不再用到的內(nèi)存,沒有及時釋放,就叫做內(nèi)存泄漏(memory leak)。
(比如 C 語言)必須手動釋放內(nèi)存,程序員負責內(nèi)存管理。
char * buffer; buffer = (char*) malloc(42); //... free(buffer) //手動釋放內(nèi)存
垃圾回收機制上面是 C 語言代碼,malloc方法用來申請內(nèi)存,使用完畢之后,必須自己用free方法釋放內(nèi)存。
這很麻煩,所以大多數(shù)語言提供自動內(nèi)存管理,減輕程序員的負擔,這被稱為"垃圾回收機制"(garbage collector)。
怎么知道哪些內(nèi)存不再需要呢?常用的方法是 "引用計數(shù)", 語言的引擎有一張 "引用表", 保存了內(nèi)存里面所有的資源(通常是各種值)的引用次數(shù),當一個值的引用次數(shù)為 0 時,表示這個值用不到了,因此可將其釋放。
但是如果一個值不再用到了,引用次數(shù)卻不為 0 ,垃圾回收機制卻無法釋放這塊內(nèi)存,從而導致內(nèi)存泄漏。
const arr = [1, 2, 3, 4]; console.log(arr);
打印完 arr 之后, arr 便用不到了,引用次數(shù)為 1, 但是它還會繼續(xù)占用內(nèi)存。
const arr = [1, 2, 3, 4]; console.log(arr); arr = null;
arr 重置為 null,就解除了對 [1, 2, 3, 4] 的引用,引用次數(shù)變成了 0 ,內(nèi)存就可以釋放了。
JavaScript 內(nèi)存管理JavaScript 是一種垃圾回收語言。垃圾回收語言通過周期性地檢查先前分配的內(nèi)存是否可達,幫助開發(fā)者管理內(nèi)存。換言之,垃圾回收語言減輕了“內(nèi)存仍可用”及“內(nèi)存仍可達”的問題。兩者的區(qū)別是微妙而重要的:僅有開發(fā)者了解哪些內(nèi)存在將來仍會使用,而不可達內(nèi)存通過算法確定和標記,適時被操作系統(tǒng)回收。
JavaScript 內(nèi)存泄漏垃圾回收語言的內(nèi)存泄漏主因是不需要的引用。理解它之前,還需了解垃圾回收語言如何辨別內(nèi)存的可達與不可達。
Mark-and-sweep
大部分垃圾回收語言用的算法稱之為 Mark-and-sweep 。算法由以下幾步組成:
垃圾回收器創(chuàng)建了一個“roots”列表。Roots 通常是代碼中全局變量的引用。JavaScript 中,“window” 對象是一個全局變量,被當作 root 。window 對象總是存在,因此垃圾回收器可以檢查它和它的所有子對象是否存在(即不是垃圾);
所有的 roots 被檢查和標記為激活(即不是垃圾)。所有的子對象也被遞歸地檢查。從 root 開始的所有對象如果是可達的,它就不被當作垃圾。
所有未被標記的內(nèi)存會被當做垃圾,收集器現(xiàn)在可以釋放內(nèi)存,歸還給操作系統(tǒng)了。
現(xiàn)代的垃圾回收器改良了算法,但是本質(zhì)是相同的:可達內(nèi)存被標記,其余的被當作垃圾回收。
不需要的引用是指開發(fā)者明知內(nèi)存引用不再需要,卻由于某些原因,它仍被留在激活的 root 樹中。在 JavaScript 中,不需要的引用是保留在代碼中的變量,它不再需要,卻指向一塊本該被釋放的內(nèi)存。有些人認為這是開發(fā)者的錯誤。
為了理解 JavaScript 中最常見的內(nèi)存泄漏,我們需要了解哪種方式的引用容易被遺忘。
常見 JavaScript 內(nèi)存泄漏JavaScript 處理未定義變量的方式比較寬松:未定義的變量會在全局對象創(chuàng)建一個新變量。在瀏覽器中,全局對象是 window 。
function foo(arg) { bar = "this is a hidden global variable"; }
真相是:
function foo(arg) { window.bar = "this is an explicit global variable"; }
函數(shù) foo 內(nèi)部忘記使用 var ,意外創(chuàng)建了一個全局變量。此例泄漏了一個簡單的字符串,無傷大雅,但是有更糟的情況。
另一種意外的全局變量可能由 this 創(chuàng)建:
function foo() { this.variable = "potential accidental global"; } // Foo 調(diào)用自己,this 指向了全局對象(window) // 而不是 undefined foo();
在 JavaScript 文件頭部加上 "use strict",可以避免此類錯誤發(fā)生。啟用嚴格模式解析 JavaScript ,避免意外的全局變量。
全局變量注意事項:
盡管我們討論了一些意外的全局變量,但是仍有一些明確的全局變量產(chǎn)生的垃圾。它們被定義為不可回收(除非定義為空或重新分配)。尤其當全局變量用于臨時存儲和處理大量信息時,需要多加小心。如果必須使用全局變量存儲大量數(shù)據(jù)時,確保用完以后把它設置為 null 或者重新定義。與全局變量相關的增加內(nèi)存消耗的一個主因是緩存。緩存數(shù)據(jù)是為了重用,緩存必須有一個大小上限才有用。高內(nèi)存消耗導致緩存突破上限,因為緩存內(nèi)容無法被回收。
在 JavaScript 中使用 setInterval 非常平常。一段常見的代碼:
var someResource = getData(); setInterval(function() { var node = document.getElementById("Node"); if(node) { // 處理 node 和 someResource node.innerHTML = JSON.stringify(someResource)); } }, 1000);
此例說明了什么:與節(jié)點或數(shù)據(jù)關聯(lián)的計時器不再需要,node 對象可以刪除,整個回調(diào)函數(shù)也不需要了。可是,計時器回調(diào)函數(shù)仍然沒被回收(計時器停止才會被回收)。同時,someResource 如果存儲了大量的數(shù)據(jù),也是無法被回收的。
對于觀察者的例子,一旦它們不再需要(或者關聯(lián)的對象變成不可達),明確地移除它們非常重要。老的 IE 6 是無法處理循環(huán)引用的。如今,即使沒有明確移除它們,一旦觀察者對象變成不可達,大部分瀏覽器是可以回收觀察者處理函數(shù)的。
觀察者代碼示例:
var element = document.getElementById("button"); function onClick(event) { element.innerHTML = "text"; } element.addEventListener("click", onClick); // => 循環(huán)調(diào)用
對象觀察者和循環(huán)引用注意事項
老版本的 IE 是無法檢測 DOM 節(jié)點與 JavaScript 代碼之間的循環(huán)引用,會導致內(nèi)存泄漏。如今,現(xiàn)代的瀏覽器(包括 IE 和 Microsoft Edge)使用了更先進的垃圾回收算法,已經(jīng)可以正確檢測和處理循環(huán)引用了。換言之,回收節(jié)點內(nèi)存時,不必非要調(diào)用 removeEventListener 了。
有時,保存 DOM 節(jié)點內(nèi)部數(shù)據(jù)結構很有用。假如你想快速更新表格的幾行內(nèi)容,把每一行 DOM 存成字典(JSON 鍵值對)或者數(shù)組很有意義。此時,同樣的 DOM 元素存在兩個引用:一個在 DOM 樹中,另一個在字典中。將來你決定刪除這些行時,需要把兩個引用都清除.
var elements = { button: document.getElementById("button"), image: document.getElementById("image"), text: document.getElementById("text") }; function doStuff() { image.src = "http://some.url/image"; button.click(); console.log(text.innerHTML); // 更多邏輯 } function removeButton() { // 按鈕是 body 的后代元素 document.body.removeChild(document.getElementById("button")); // 此時,仍舊存在一個全局的 #button 的引用 // elements 字典。button 元素仍舊在內(nèi)存中,不能被 GC 回收。 }
此外還要考慮 DOM 樹內(nèi)部或子節(jié)點的引用問題。假如你的 JavaScript 代碼中保存了表格某一個
如果閉包的作用域中保存著一個 HTML 元素,則該元素無法被銷毀。(下面代碼來自高程)
閉包是 JavaScript 開發(fā)的一個關鍵方面:匿名函數(shù)可以訪問父級作用域的變量。
function assgin() { var ele = document.getElementById("someEle"); ele.onclick = function(){ alert(ele.id); } }
以上代碼創(chuàng)建了一個作為 ele 元素事件處理程序的閉包,而這個閉包有創(chuàng)建了一個循環(huán)的引用,由于匿名函數(shù)保存了一個 assgin() 的活動對象的引用 ,因此無法減少對 ele 的引用次數(shù) , 只要匿名函數(shù)存在,ele的引用次數(shù)至少是 1。我們可以稍微改寫一下:
function assgin() { var ele = document.getElementById("someEle"); var id = ele.id ele.onclick = function(){ alert(id); } ele = null; }
上面代碼中,通過把 ele.id 的一個副本保存在一個變量中,并且在比保重引用該變量消除了循環(huán)引用,但是這樣還不能解決內(nèi)存泄露,閉包會引用包含函數(shù)的整個活動對象,而其中包含著 ele ,即使閉包不直接引用 ele ,包含函數(shù)的活動對象中也會保存 一個引用,因此需要把 ele 變量設置為 null ,這樣就解除了對 DOM 對象的引用,減少其引用數(shù),確保能正常回收。
關于內(nèi)存的發(fā)現(xiàn) chrome 的使用~暫時沒有使用過,看不太明白,就不 copy 了。
js閉包測試 => 看不懂~
上述內(nèi)容 copy 自下面二者:JavaScript 內(nèi)存泄漏教程-阮一峰
4類 JavaScript 內(nèi)存泄漏及如何避免
var xhr = createXHR() xhr.onreadystatechange = function() { if(xhr.readyState == 4) { if(xhr.status == 200) { console.log(xhr.responeText) //do sth... } else { console.log("request fail" + xhr.status) } } }; xhr.open("get", "hello.com", true) xhr.send(null);閉包的理解
閉包是指有權訪問另一個函數(shù)作用域中的變量的函數(shù)。
這個口述我還是不知道怎么說,或許是應用不夠~看了無數(shù)文章到頭來敵不過忘記~也可能我理解的還是不到位吧~個人不解釋了,放參考鏈接吧
How do JavaScript closures work?--StackOverflow
學習Javascript閉包(Closure)--阮一峰的網(wǎng)絡日志
JS 中的閉包是什么--方應杭
JavaScript 中 閉包 的詳解
閉包--MDN
閉包的應用
方法一:循環(huán)hdslakddnska8das
const textToMark = document.querySelector(".textToMark");
const text = textToMark.innerHTML;
const arr = ["d", "a", "*", "8"];
const newText = text.split("");
function toMark (textArr, arr) {
for(let i = 0; i < newText.length; i++) {
for(let j = 0; j < arr.length; j++) {
if(newText[i] == arr[j]) {
newText[i] = `${newText[i]}`;
}
}
}
return newText;
}
toMark(newText, arr);
textToMark.innerHTML = newText.join("");
方法二: 字符串的 replace
const textToMark = document.querySelector(".textToMark");
const text = textToMark.innerHTML;
const reg = /[da*8]+/g;
var newtext = text.replace(reg, (match) => {
return match = `${match}`;
});
textToMark.innerHTML = newtext;
原生JS創(chuàng)建這樣的 dom 結構 < div id="hello"> < p class="textToMark">hdslakddnska8das< p>< /div>代碼為個人寫出,如果有更好的辦法歡迎指教
function createElement() { var body = document.body; var fragment = document.createDocumentFragment() var div = document.createElement("div") div.setAttribute("id", "hello") fragment.appendChild(div) var p = document.createElement("p") p.className = "textToMark" p.innerHTML = "hdslakddnska8das" div.appendChild(p); body.appendChild(fragment) } createElement();
感謝評論指出,已改正,關于節(jié)點創(chuàng)建 createElement 的效率問題,如果當插入的節(jié)點很多的時候,createElement 的效率會不如 createDocumentFragment .
createElement 每次 append 一個節(jié)點的時候,都會導致頁面的重排,例如:
數(shù)據(jù)為這樣:
var data = [ { name: "36O秋招", url: "http://campus.360.cn/2015/grad.html"}, { name: "TX校招", url: "http://join.qq.com/index.php"} ]function appendChildToElement(appendToElement, data) { var a, li; for (var i = 0, len = data.length; i < len; i++) { a = document.createElement("a"); a.href = data[i].url; a.appChild(document.createTextNode(data[i].name)) li = document.createElement("li"); li.appendChild(a); appendChildToElement(li); } }
這種情況下,data 內(nèi)的每一個對象插入到 DOM 結構的時候都會觸發(fā)一次重排,因此效率會較低。
但是我們可以改變他的 display 屬性,臨時從文檔移除 ul ,即可有效減少重排次數(shù)。
var ul = document.getElementById("myList"); ur.style.display = "none"; appendChildToElement(ul, data); ul.style.display = "block";
當然,更好的辦法就是利用 createDocumentFragment 來創(chuàng)建一個文檔片段.
var fragment = document.createElementFragment(); appendChildToElement(fragment, data); document.getElementById("myList").appendChild(fragment);
只訪問了一次 DOM 節(jié)點,只觸發(fā)了一次重排;再次感謝 @xaclincoln 的指出。
查了一些關于 createDocumentFragment 和 createElement 比較的文章。
createDocumentFragment or createElement--StackOverflow
createElement vs createDocumentFragment
createElement 與 createDocumentFragment 的點點區(qū)別
CreateDocumentFragment 的用處
創(chuàng)建一個函數(shù)對 JS 基礎類型 ( function, boolean, array, number, string, object) 進行值復制function valueToCopy (valueBeCopy) { var copyValue; if (typeof (+valueBeCopy) === "number" && typeof valueBeCopy !== "object") { copyValue = +valueBeCopy; } else if (typeof valueBeCopy === "string") { copyValue = parseInt(copyValue); } else if (typeof valueBeCopy === "object"){ if(Array.isArray(valueBeCopy)) { copyValue = valueBeCopy.slice(); } copyValue = JSON.parse(JSON.stringify(valueBeCopy)) } copyValue = valueBeCopy; // console.log(copyValue) return copyValue; }url 輸入到頁面完成經(jīng)歷了什么
感覺這篇文章非常非常詳細了~太長了,過段時間再整理(抄襲~)
老生常談-從輸入url到頁面展示到底發(fā)生了什么
var input = document.getElementById("cls") input.onmouseup = function() { console.log("onmouseup") } input.onmousedown = function() { console.log("onmousedown") } input.onclick = function() { console.log("onclick") } input.onfocus = function() { console.log("onfocus") }
a 鏈接默認事件的阻止onmousedown => onfocus => onmouseup => onclick
A. a.onmouseup = function(e) {
e.preventDefault() }B. a.onmousedown = function(e) {
e.preventDefault() }C. a.onclick = function(e) {
e.preventDefault() }D. A B C 都可以~
=> 經(jīng)測試只有 onclick 可以
IE瀏覽器中 attachEvent 方式的事件綁定attachEvent的this總是Window。
el.attachEvent("onclick", function(){ alert(this); });HTTP狀態(tài)碼
400 Bad Request
由于明顯的客戶端錯誤(例如,格式錯誤的請求語法,太大的大小,無效的請求消息或欺騙性路由請求),服務器不能或不會處理該請求。[31]
401 Unauthorized(RFC 7235)
參見:HTTP基本認證、HTTP摘要認證
類似于403 Forbidden,401語義即“未認證”,即用戶沒有必要的憑據(jù)。[32]該狀態(tài)碼表示當前請求需要用戶驗證。
注意:當網(wǎng)站(通常是網(wǎng)站域名)禁止IP地址時,有些網(wǎng)站狀態(tài)碼顯示的401,表示該特定地址被拒絕訪問網(wǎng)站。
402 Payment Required
該狀態(tài)碼是為了將來可能的需求而預留的。該狀態(tài)碼最初的意圖可能被用作某種形式的數(shù)字現(xiàn)金或在線支付方案的一部分,但幾乎沒有哪家服務商使用,而且這個狀態(tài)碼通常不被使用。如果特定開發(fā)人員已超過請求的每日限制,Google Developers API會使用此狀態(tài)碼。[34]
403 Forbidden
服務器已經(jīng)理解請求,但是拒絕執(zhí)行它。與401響應不同的是,身份驗證并不能提供任何幫助,而且這個請求也不應該被重復提交。如果這不是一個HEAD請求,而且服務器希望能夠講清楚為何請求不能被執(zhí)行,那么就應該在實體內(nèi)描述拒絕的原因。當然服務器也可以返回一個404響應,假如它不希望讓客戶端獲得任何信息。
var str = "asd; var str2 = new String(str) var str1 = new String(str) console.log(str1 == str2 , str1 === str2)
A. true true
B. true false
C. false true
D. false false
// => 輸出 => false false
下面的輸出結果 (this 指向問題)因為 new 出來的倆個字符串引用地址不同
function one () { this.name = 1; return function two () { name = 2; return function three() { var name = 3; console.log(this.name); } } } one()()() // => 2;
還有一部分題忘掉嘍 ~ 還有一些題具體的記不太清了,稍作修改,考點計本差不多,上面答案有的是我自己寫的,有的是我 google 整理出來的,筆試期間攝像頭壞了,而且不小心彈出去了三四次~就當練習了吧,反正簡歷也沒準備好呢,哦,對了,考點大多都在高程中有詳細講解,需要好好看一下高程,面試應該會問一些 Node 和 ES6吧,如果有錯誤或者更好的方法請告訴我
更多筆試整理更新在個人博客和Github,歡迎小伙伴來一起準備秋招(求大腿抱)。
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/84605.html
摘要:但是如果一個值不再用到了,引用次數(shù)卻不為,垃圾回收機制卻無法釋放這塊內(nèi)存,從而導致內(nèi)存泄漏。內(nèi)存泄漏垃圾回收語言的內(nèi)存泄漏主因是不需要的引用。常見內(nèi)存泄漏意外的全局變量處理未定義變量的方式比較寬松未定義的變量會在全局對象創(chuàng)建一個新變量。 簡答題: settimeout 與 setInterval的區(qū)別, 及對他們的內(nèi)存的分析 區(qū)別 setTimeout是在一段時間后調(diào)用指定函數(shù)(僅一...
摘要:但是如果一個值不再用到了,引用次數(shù)卻不為,垃圾回收機制卻無法釋放這塊內(nèi)存,從而導致內(nèi)存泄漏。內(nèi)存泄漏垃圾回收語言的內(nèi)存泄漏主因是不需要的引用。常見內(nèi)存泄漏意外的全局變量處理未定義變量的方式比較寬松未定義的變量會在全局對象創(chuàng)建一個新變量。 簡答題: settimeout 與 setInterval的區(qū)別, 及對他們的內(nèi)存的分析 區(qū)別 setTimeout是在一段時間后調(diào)用指定函數(shù)(僅一...
摘要:前端日報精選專題之通用遍歷方法的實現(xiàn)深入了解的子組件上最流行的項目再聊移動端頁面的適配譯盒子模型實踐教程中文全棧第天數(shù)據(jù)驅(qū)動龍云全棧譯年開發(fā)趨勢瘋狂的技術宅在翻譯譯閉包并不神秘前端心得拼多多前端筆試個人文章容器技術方 2017-08-03 前端日報 精選 JavaScript專題之jQuery通用遍歷方法each的實現(xiàn)深入了解React的子組件GitHub上最流行的Top 10 Jav...
摘要:詳見我的另一篇文章前端面試問題之面向?qū)ο箢悓崿F(xiàn)代碼父類我的名字是我今年歲原型繼承原型鏈相關問題請看我的另一篇文章前端面試之原型鏈問題實現(xiàn)效果構造函數(shù)繼承實現(xiàn)效果組合繼承實現(xiàn)效果組合繼承優(yōu)化實現(xiàn)效果未完待續(xù) Github - program-learning-lists 知乎 個人博客 Github 開源(open source)這個詞,指的是事物規(guī)劃為可以公開訪問的,因此人們可以修改...
摘要:先介紹一下本人應屆前端開發(fā)一枚,非科班出身,專業(yè)是化學,大學期間開始自學前端開發(fā),在今年春招實習和秋招的時候投了一些公司,拿到一些京東拼多多虎牙等,總體來說還算滿意,特地寫一篇文章來總結一下面試的那些套路。 showImg(https://segmentfault.com/img/remote/1460000011897700); 先介紹一下本人應屆前端開發(fā)一枚,非科班出身,專業(yè)是化學...
閱讀 2335·2023-04-25 14:29
閱讀 1457·2021-11-22 09:34
閱讀 2702·2021-11-22 09:34
閱讀 3392·2021-11-11 10:59
閱讀 1851·2021-09-26 09:46
閱讀 2222·2021-09-22 16:03
閱讀 1921·2019-08-30 12:56
閱讀 479·2019-08-30 11:12