Js面試題以及答案(建議收藏,面試必過!)
- 從輸入 URL 到頁面展示,這中間發生了什么?
- JavaScript的資料型別及其檢測?
- typeof 和 instanceof 的區別?
- 對堆疊和堆記憶體有了解嗎,二者的區別?
- 深拷貝和淺拷貝的區別?
- 專案中實作深淺拷貝常用的方法有哪些?
- 賦值、淺拷貝和深拷貝的區別?
- new創建一個物件的時候做了些什么?
- Javascript中的原型和原型鏈有了解嗎?
- 說說Javascript中的繼承,如何實作繼承?
- Javascript中的執行背景關系和執行堆疊是什么?
- 說說你對Javascript作用域的理解?
- 說說你對閉包的理解以及使用場景?
- 說說你對Javascript中this物件的理解?
- Javascript陣列常見的方法有哪些?
- 手寫一個陣列排序方法?
- Javascript字串常見的方法有哪些?
- 談談Javascript中型別轉變機制?
- == 和 === 的區別和使用場景?
- Javascript中的事件模型如何理解?
- 談談你對行程和執行緒的理解?
- 說一說Javascript中事件回圈的理解?
- 介紹一下宏任務和微任務
- 解釋下什么是事件代理和應用場景?
- 什么是函式柯里化?
- Ajax的原理是什么,如何實作?
- bind、call和apply的區別?
- 說說你對DOM的理解,常見的操作有哪些?
- 說說你對BOM的理解,常見的BOM物件你了解哪些?
- 說說 JavaScript 中記憶體泄漏的幾種情況?
- JavaScript中本地存盤的方式有哪些?區別及應用場景?
- JavaScript中如何實作函式快取?有哪些應用場景?
- 說說函式節流和防抖?有什么區別?如何實作?
- es6有哪些新特性?
- 說一說var、let和const的區別?
- 你是怎么理解ES6中promise的,和使用場景?
從輸入 URL 到頁面展示,這中間發生了什么?
- 用戶輸入url并回車
- 瀏覽器行程檢查url,組裝協議,構成完整的url
- 瀏覽器行程通過行程間通信(IPC)把url請求發送給網路行程
- 網路行程接收到url請求后檢查本地快取是否快取了該請求資源,如果有則將該資源回傳給瀏覽器行程
- 如果沒有,網路行程向web服務器發起http請求(網路請求)
- 網路行程決議回應流程,如果是200,檢查回應型別Content-Type,如果是位元組流型別,則將該請求提交給下載管理器,該導航流程結束,不再進行;如果是html則通知瀏覽器行程準備渲染行程準備進行渲染
- 準備渲染行程;瀏覽器行程檢查當前url是否和之前打開的渲染行程根域名是否相同,如果相同,則復用原來的行程,如果不同,則開啟新的渲染行程;
- 傳輸資料、更新狀態
(點擊 瀏覽器作業原理面試題一:從輸入 URL 到頁面展示,這中間發生了什么?可查看詳解)
JavaScript的資料型別及其檢測?
Js資料型別分為兩種:
- 基本資料型別;包括Undefined、Null、Boolean、Number、String、Symbol (ES6 新增,表示獨一無二的值)
- 參考資料型別;可統稱為 Object 物件,包括Object、Array和Function等
檢測方法:
- typeof; typeof 回傳一個表示資料型別的字串,回傳結果包括:number、boolean、string、symbol、object、undefined、function 等 7 種資料型別,但不能判斷 null、array 等;(一般判斷基本資料型別)
- instanceof; instanceof 是用來判斷 A 是否為 B 的實體;(一般判斷參考資料型別)
- Object.prototype.toString.call()(可判斷所有的資料型別,最準確最常用的方式)
typeof 和 instanceof 的區別?
typeof:
- 用來判斷基本資料型別,但是typeof null回傳的是Object,這只是JavaScript 存在的一個悠久 Bug,不代表null就是參考資料型別,并且null本身也不是物件
- 參考型別資料,用typeof來判斷的話,除了function會被識別出來之外,其余的都輸出object
instanceof:
- instanceof 運算子用于檢測建構式的 prototype 屬性是否出現在某個實體物件的原型鏈上
- 主要檢測參考資料型別,檢測基本型別都回傳false;
區別:
- typeof會回傳一個變數的基本型別,instanceof回傳的是一個布林值
- instanceof 可以準確地判斷復雜參考資料型別,但是不能正確判斷基礎資料型別
- 而typeof 也存在弊端,它雖然可以判斷基礎資料型別(null 除外),但是參考資料型別中,除了function 型別以外,其他的也無法判斷
- 如果需要通用檢測資料型別,可以采用Object.prototype.toString,呼叫該方法,統一回傳格式“[object Xxx]”的字串
對堆疊和堆記憶體有了解嗎,二者的區別?
堆疊記憶體:
- 堆疊就是我們之前反復提及的呼叫堆疊,是用來存盤執行背景關系的,
- 堆疊空間都不會設定太大,堆疊主要用于來保存基本值和參考型別值的地址
- 自動分配的相對固定大小的記憶體空間,其資料讀取快,寫入速度快,但存盤內容少,變數一旦不使用就由系統自動清理釋放;
堆記憶體:
- 用來保存一組無序且唯一的參考型別值,可以使用堆疊中的鍵名來取得
- 堆的讀取和寫入速度慢,但存盤的內容多,一般物件會存盤在堆中,存盤的資料對于大小在這方面都是未知的
- 堆是動態分配的記憶體,大小不定也不會自動釋放,
二者區別:
- 空間分配區別:堆疊由作業系統(編譯器)自動分配釋放 ,存放函式的引數值,區域變數的值等,其操作方式類似于資料結構中的堆疊,堆(作業系統) 一般由程式員分配釋放, 若程式員不釋放,程式結束時可能由OS回收,分配方式倒是類似于鏈表,
- 快取方式區別:堆疊使用的是一級快取, 它們通常都是被呼叫時處于存盤空間中,呼叫完畢立即釋放,堆則是存放在二級快取中,生命周期由虛擬機的垃圾回收演算法來決定(并不是一旦成為孤兒物件就能被回收),所以呼叫這些物件的速度要相對來得低一些,
- 資料結構區別:堆可以被看成是一棵樹,如:堆排序,堆疊是一種先進后出的資料結構,
- 存盤型別區別:堆疊一般來保存基本值和參考型別值的地址;堆用來保存一組無序且唯一的參考型別物件
點擊瀏覽器作業原理和實踐——堆疊空間和堆空間查看詳解
深拷貝和淺拷貝的區別?
淺拷貝:
創建一個新的物件,不會指向同一個地址,這個物件有著原始物件屬性值的精確拷貝,就是物件的淺拷貝只會對“主”物件進行拷貝,拷貝的是物件屬性的基本型別的值,如果屬性是參考型別,拷貝的就是記憶體地址,拷貝的不深,所以稱為淺拷貝;
- 修改淺拷貝物件第一層的非物件參考類屬性,都不會影響原物件
- 由于淺拷貝不會拷貝物件里面的物件,“里面的物件”會和原物件共享記憶體,所以修改淺拷貝物件的子屬性物件里面的屬性,原物件也會受到影響
深拷貝:
深拷貝不僅將元物件的各個屬性逐個復制,還將原物件各個屬性所包含的物件屬性也一次采用深復制的方法遞回復制到新物件上,所以修改拷貝后的物件不會影響原物件;
- 深拷貝是逐層對物件的各個屬性進行拷貝,修改拷貝物件任意屬性,都不會影響原物件
區別:
| 和原資料是否指向同一個物件 | 第一層資料為基本資料型別 | 原資料中包含的子物件 | |
|---|---|---|---|
| 淺拷貝 | 否 | 不會使原資料一起改變 | 會使原資料一起改變 |
| 深拷貝 | 否 | 不會使原資料一起改變 | 不會使原資料一起改變 |
點擊對Javscript中淺拷貝和深拷貝的探索和詳解查看詳解
專案中實作深淺拷貝常用的方法有哪些?
實作淺拷貝的方法:
- 簡單賦值
- 利用 for…in回圈實作淺拷貝
- 利用Object.assign()方法
實作深拷貝的方法:
- 使用遞回的方式實作深拷貝
- 通過 JSON 物件實作深拷貝
- slice()、concat()對陣列進行深拷貝
點擊對Javscript中淺拷貝和深拷貝的探索和詳解查看詳解
賦值、淺拷貝和深拷貝的區別?
| 和原資料是否指向同一個物件 | 第一層資料為基本資料型別 | 原資料中包含的子物件 | |
|---|---|---|---|
| 賦值 | 是 | 會使原資料一起改變 | 會使原資料一起改變 |
| 淺拷貝 | 否 | 不會使原資料一起改變 | 會使原資料一起改變 |
| 深拷貝 | 否 | 不會使原資料一起改變 | 不會使原資料一起改變 |
三者的記憶體圖:
賦值

淺拷貝

深拷貝

點擊對Javscript中淺拷貝和深拷貝的探索和詳解查看詳解
new創建一個物件的時候做了些什么?
- 首先創建了一個空物件 obj
- 將物件與構建函式通過原型鏈連接起來
- 將構建函式中的this系結到新建的物件obj上
- 根據構建函式回傳型別作判斷,如果是原始值則被忽略,如果是回傳物件,需要正常處理
Javascript中的原型和原型鏈有了解嗎?
原型:
- 在 JavaScript 中,每當定義一個物件時候,物件中都會包含一些預定義的屬性,其中每個函式物件都有一個prototype 屬性,這個屬性指向函式的原型物件,
- 原型物件都會自動獲得一個constructor屬性,這個屬性是一個指向prototype屬性所在函式的指標;
- 當呼叫建構式創建一個新實體后,高實體物件內部將包含一個指標(內部屬性_proto_),指向建構式的原型物件;
- 原型物件的用途是包含可以由特定型別的所有實體共享的屬性和方法,
原型鏈:
- 原型鏈是就是實體物件在查找屬性時,如果查找不到,就會沿著__proto__去與物件關聯的原型上查找,有則回傳,如果找不到,就去找原型的原型,直至查到最頂層Object函式的原型,其原型物件的_proto__已經沒有可以指向的上層原型,因此其值為null,回傳undefind;
- 原型鏈是實作繼承的主要方法,其基本思想就是利用原型讓一個參考型別繼承另一個參考型別的屬性和方法;
點擊對Javascript中原型和原型鏈的探索和詳解查看詳解
說說Javascript中的繼承,如何實作繼承?
繼承是什么:
繼承(inheritance)是面向物件軟體技術當中的一個概念;如果一個類別B“繼承自”另一個類別A,就把這個B稱為“A的子類”,而把A稱為“B的父類別”也可以稱“A是B的超類”;
- 繼承可以使得子類具有父類別的各種屬性和方法,而不需要再次撰寫相同的代碼
- 在子類別繼承父類別的同時,可以重新定義某些屬性,并重寫某些方法,即覆寫父類別的原有屬性和方法,使其獲得與父類別不同的功能
實作繼承的方法:
- 原型鏈繼承
- 建構式繼承(借助 call)
- 組合繼承
- 原型式繼承
- 寄生式繼承
- 寄生組合式繼承
點擊Javascript中的繼承和實作方法查看詳解
Javascript中的執行背景關系和執行堆疊是什么?
執行背景關系:
執行背景關系是對Javascript代碼執行環境的一種抽象概念,只要有Javascript代碼運行,那么它就一定是運行在執行背景關系中;
執行背景關系的型別分為三種:
- 全域執行背景關系:只有一個,瀏覽器中的全域物件就是 window物件,this 指向這個全域物件
- 函式執行背景關系:存在無數個,只有在函式被呼叫的時候才會被創建,每次呼叫函式都會創建一個新的執行背景關系
- Eval 函式執行背景關系:指的是運行在 eval 函式中的代碼,很少用而且不建議使用
執行堆疊:
執行堆疊,也叫呼叫堆疊,具有 LIFO(后進先出)結構,用于存盤在代碼執行期間創建的所有執行背景關系;
當Javascript引擎開始執行你第一行腳本代碼的時候,它就會創建一個全域執行背景關系然后將它壓到執行堆疊中
每當引擎碰到一個函式的時候,它就會創建一個函式執行背景關系,然后將這個執行背景關系壓到執行堆疊中
引擎會執行位于執行堆疊堆疊頂的執行背景關系(一般是函式執行背景關系),當該函式執行結束后,對應的執行背景關系就會被彈出,然后控制流程到達執行堆疊的下一個執行背景關系
點擊JavaScript的執行機制——呼叫堆疊查看詳解
說說你對Javascript作用域的理解?
作用域是指在程式中定義變數的區域,該位置決定了變數的生命周期,通俗地理解,作用域就是變數與函式的可訪問范圍,即作用域控制著變數和函式的可見性和生命周期,
在 ES6 之前,ES 的作用域只有兩種:全域作用域和函式作用域,
- 全域作用域中的物件在代碼中的任何地方都能訪問,其生命周期伴隨著頁面的生命周期,
- 函式作用域就是在函式內部定義的變數或者函式,并且定義的變數或者函式只能在函式內部被訪問,函式執行結束之后,函式內部定義的變數會被銷毀,
ES6 出現了塊級作用域,塊級作用域就是使用一對大括號包裹的一段代碼,比如函式、判斷陳述句、回圈陳述句,甚至單獨的一個{}都可以被看作是一個塊級作用域,
說說你對閉包的理解以及使用場景?
在 JavaScript 中,根據詞法作用域的規則,內部函式總是可以訪問其外部函式中宣告的變數,當通過呼叫一個外部函式回傳一個內部函式后,即使該外部函式已經執行結束了,但是內部函式參考外部函式的變數依然保存在記憶體中,我們就把這些變數的集合稱為閉包,
如果閉包使用不正確,會很容易造成記憶體泄漏,所以在使用閉包的時候,你要盡量注意一個原則:如果該閉包會一直使用,那么它可以作為全域變數而存在;但如果使用頻率不高,而且占用記憶體又比較大的話,那就盡量讓它成為一個區域變數,
任何閉包的使用場景都離不開這兩點:
- 創建私有變數
- 延長變數的生命周期
場景:
- 柯里化函式
點擊JavaScript的執行機制——作用域鏈和閉包查看詳解
說說你對Javascript中this物件的理解?
- 函式執行時首先看函式名前面是否有".",有的話,"."前面是誰,this就是誰;沒有的話this就是window
- 自執行函式中的this永遠是window
- 在建構式模式中,類中(函式體中)出現的this.xxx=xxx中的this是當前類的一個實體
- call、apply和bind,可以改變this的指向,為函式的第一個引數
- 箭頭函式的this看外層的是否有函式,如果有,外層函式的this就是內部箭頭函式的this,如果沒有,則this是window,
Javascript陣列常見的方法有哪些?
操作方法:
- 增:push()、unshift()、splice()、concat()
- 刪:pop()、shift()、splice()、slice()
- 改:splice()
- 查:indexOf()、includes()、find()
排序方法:
- 陣列本身有兩個方法:reverse()、sort()
- 定義排序函式:冒泡排序、插入排序、遞并排序、計數排序
轉換方法:
- join()
迭代方法:
- some()
- every()
- forEach()
- filter()
- map()
點擊Javscript陣列中最常用的方法(建議收藏)查看詳解
手寫一個陣列排序方法?
冒泡排序:
var arr = [3,4,1,2,21,5,15,6,63];
function BubbleSort(ary){
for(var i = 0; i < ary.length - 1; i++){
for(var j = i + 1; j < ary.length; j++){
var current = ary[i];
if(current > ary[j]){
var tmp = ary[j];
ary[j] = current;
ary[i] = tmp;
}
}
}
return ary;
}
1
BubbleSort(arr); // [1, 2, 3, 4, 5, 6, 15, 21, 63]
點擊Javscript陣列中最常用的方法(建議收藏)查看詳解
Javascript字串常見的方法有哪些?
操作方法:
- 增:concat()、
- 刪:slice()、substr()、substring()
- 改:trim()、trimLeft()、trimRight()、repeat()、toLowerCase()、 toUpperCase()
- 查:chatAt()、indexOf()、startWith()、includes()
轉換方法:
- split
模板匹配方法:
- match()
- search()
- replace()
點擊Javascript字串常見的方法查看詳解
談談Javascript中型別轉變機制?
常見的型別轉換有:
- 強制轉換(顯示轉換)
- 自動轉換(隱式轉換)
點擊js的六種資料型別、強制型別轉換和隱式型別轉換查看詳解
== 和 === 的區別和使用場景?
等于運算子:
等于運算子用兩個等于號( == )表示,如果運算元相等,則會回傳 true;
等于運算子(==)在比較中會先進行型別轉換,再確定運算元是否相等;
- 兩個都為簡單型別,字串和布林值都會轉換成數值,再比較
- 簡單型別與參考型別比較,物件轉化成其原始型別的值,再比較
- 兩個都為參考型別,則比較它們是否指向同一個物件
- null 和 undefined 相等
- 存在 NaN 則回傳 false
全等操作符:
全等運算子由 3 個等于號( === )表示,只有兩個運算元在不轉換的前提下相等才回傳 true,即型別相同,值也需相同
區別:
- 相等運算子(==)會做型別轉換,再進行值的比較,全等運算子不會做型別轉換
- null 和 undefined 比較,相等運算子(==)為true,全等為false
除了在比較物件屬性為null或者undefined的情況下,我們可以使用相等運算子==,其他情況建議一律使用全等運算子===;
Javascript中的事件模型如何理解?
事件模型可以分為三種:
- 原始事件模型(DOM0級)
- 標準事件模型(DOM2級)
- IE事件模型(基本不用)
點擊Javascript中的事件模型查看詳情
談談你對行程和執行緒的理解?
多執行緒可以并行處理任務,但是執行緒是不能單獨存在的,它是由行程來啟動和管理的,
一個行程就是一個程式的運行實體,詳細解釋就是,啟動一個程式的時候,作業系統會為該程式創建一塊記憶體,用來存放代碼、運行中的資料和一個執行任務的主執行緒,我們把這樣的一個運行環境叫行程,
關系:
- 行程中的任意一執行緒執行出錯,都會導致整個行程的崩潰,
- 執行緒之間共享行程中的資料,
- 當一個行程關閉之后,作業系統會回收行程所占用的記憶體,
- 行程之間的內容相互隔離,
點擊瀏覽器作業原理和實踐——行程和執行緒查看詳解
說一說Javascript中事件回圈的理解?
JavaScript 在設計之初便是單執行緒,即指程式運行時,只有一個執行緒存在,同一時間只能做一件事;為了解決單執行緒運行阻塞問題,JavaScript用到了計算機系統的一種運行機制,這種機制就叫做事件回圈(Event Loop)
在JavaScript中,所有的任務都可以分為:
- 同步任務:立即執行的任務,同步任務一般會直接進入到主執行緒中執行
- 異步任務:異步執行的任務,比如ajax網路請求,setTimeout定時函式等
同步任務與異步任務的運行流程圖如下:

從上面我們可以看到,同步任務進入主執行緒,即主執行堆疊,異步任務進入任務佇列,主執行緒內的任務執行完畢為空,會去任務佇列讀取對應的任務,推入主執行緒執行,上述程序的不斷重復就是事件回圈;
點擊瀏覽器中的訊息佇列和事件回圈查看詳解
介紹一下宏任務和微任務
頁面中的大部分任務都是在主執行緒上執行的,這些任務包括了:
- 渲染事件(如決議 DOM、計算布局、繪制);
- 用戶互動事件(如滑鼠點擊、滾動頁面、放大縮小等);
- JavaScript 腳本執行事件;
- 網路請求完成、檔案讀寫完成事件,
為了協調這些任務有條不紊地在主執行緒上執行,頁面行程引入了訊息佇列和事件回圈機制,渲染行程內部會維護多個訊息佇列,比如延遲執行佇列和普通的訊息佇列,然后主執行緒采用一個 for 回圈,不斷地從這些任務佇列中取出任務并執行任務,我們把這些訊息佇列中的任務稱為宏任務,
微任務就是一個需要異步執行的函式,執行時機是在主函式執行結束之后、當前宏任務結束之前,
通過 DOM 節點變化產生的微任務或者使用 Promise 產生的微任務都會被 JavaScript 引擎按照順序保存到微任務佇列中,
解釋下什么是事件代理和應用場景?
是什么:
事件代理,俗地來講,就是把一個元素回應事件(click、keydown…)的函式委托到另一個元素;
事件流的都會經過三個階段:捕獲階段 -> 目標階段 -> 冒泡階段,而事件委托就是在冒泡階段完成;
事件委托,會把一個或者一組元素的事件委托到它的父層或者更外層元素上,真正系結事件的是外層元素,而不是目標元素
當事件回應到目標元素上時,會通過事件冒泡機制從而觸發它的外層元素的系結事件上,然后在外層元素上去執行函式
應用場景:
如果我們有一個串列,串列之中有大量的串列項,我們需要在點擊串列項的時候回應一個事件,如果給每個串列項一一都系結一個函式,那對于記憶體消耗是非常大的,這時候就可以事件委托,把點擊事件系結在父級元素ul上面,然后執行事件的時候再去匹配目標元素
點擊事件代理和應用場景查看詳情
什么是函式柯里化?
是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,并且回傳接受余下的引數而且回傳結果的新函式的技術,
把接受多個引數的函式轉換成接受一個單一引數的函式
// 普通函式
var add = function(x, y) {
return x + y;
}
add(3, 4) //7var foo = 'bar';
// 柯里化
var foo = function(x) {
return function(y) {
return x + y
}
}
foo(3)(4) // 7
Ajax的原理是什么,如何實作?
是什么:
AJAX全稱(Async Javascript and XML)
即異步的JavaScript 和XML,是一種創建互動式網頁應用的網頁開發技術,可以在不重新加載整個網頁的情況下,與服務器交換資料,并且更新部分網頁
Ajax的原理簡單來說通過XmlHttpRequest物件來向服務器發異步請求,從服務器獲得資料,然后用JavaScript來操作DOM而更新頁面
流程圖如下:

實作程序:
- 創建 Ajax的核心物件 XMLHttpRequest物件
- 通過 XMLHttpRequest 物件的 open() 方法與服務端建立連接
- 構建請求所需的資料內容,并通過XMLHttpRequest 物件的 send() 方法發送給服務器端
- 通過 XMLHttpRequest 物件提供的 onreadystatechange 事件監聽服務器端你的通信狀態
- 接受并處理服務端向客戶端回應的資料結果
- 將處理結果更新到 HTML頁面中
點擊Ajax的原理、實作步驟和封裝查看詳解
bind、call和apply的區別?
作用:
call、apply、bind作用是改變函式執行時的背景關系,簡而言之就是改變函式運行時的this指向;
區別:
- apply、call、bind 三者都是可以改變函式的this指向的
- apply 和 call 都是改變函式this指向,并傳入引數后立即呼叫執行該函式
- bind 是在改變函式this指向,并傳入引數后回傳一個新的函式,不會立即呼叫執行
- apply 傳入的引數是陣列形式的;call 傳入的引數是按順序的逐個傳入并以逗號隔開; bind 傳入的引數既可以是陣列形式,也可以是按順序逐個傳入,
點擊bind、call和apply的區別查看詳情
說說你對DOM的理解,常見的操作有哪些?
DOM全稱為The Document Object Model,即檔案物件模型,應該理解為是一個規范,是一種跨平臺的、獨立于編程語言的API,它把HTML、XHTML或XML檔案當作一個樹結構,而每個節點視為一個物件,這些物件可以被編程語言操作,進而改變檔案的結構,映射到檔案的顯示,
簡單來說,DOM就是我們為了方便編程語言對HTML等檔案進行操作,所以啊,把HTML檔案中的節點全部視為一個個的物件,然后這些物件依照層級關系形成一棵樹,這棵樹就命名為DOM樹,有了物件,編程就方便多了,只要一層層拿到物件就可以優雅地改變物件的屬性進而動態地改變HTML等檔案的展示,
下面就來分析DOM常見的操作,主要分為:
- 創建節點
- 查詢節點
- 更新節點
- 添加節點
- 洗掉節點
點擊DOM的理解和常見的操作查看詳解
說說你對BOM的理解,常見的BOM物件你了解哪些?
是什么:
BOM (Browser Object Model),瀏覽器物件模型,提供了獨立于內容與瀏覽器視窗進行互動的物件
其作用就是跟瀏覽器做一些互動效果,比如如何進行頁面的后退,前進,重繪,瀏覽器的視窗發生變化,滾動條的滾動,以及獲取客戶的一些資訊如:瀏覽器品牌版本,螢屏解析度;
BOM物件:
- window
- location
- navigator
- screen
- history
點擊對BOM的理解和常見的BOM物件查看詳解
說說 JavaScript 中記憶體泄漏的幾種情況?
是什么:
記憶體泄漏(Memory leak)是在計算機科學中,由于疏忽或錯誤造成程式未能釋放已經不再使用的記憶體;
對于持續運行的服務行程,必須及時釋放不再用到的記憶體,否則,記憶體占用越來越高,輕則影響系統性能,重則導致行程崩潰;
所以大多數語言提供自動記憶體管理,減輕程式員的負擔,這被稱為"垃圾回識訓制"
常見記憶體泄露情況:
- 意外的全域變數
- 定時器也常會造成記憶體泄露
- 還有閉包,延長了函式內部變數的生命周期,呼叫不當和不及時釋放也會造成記憶體泄漏
JavaScript中本地存盤的方式有哪些?區別及應用場景?
本地存盤的方式:
- cookie
- sessionStorage
- sessionStorage
區別:
- 存盤大小:cookie資料大小不能超過4k,sessionStorage和localStorage雖然也有存盤大小的限制,但比cookie大得多,可以達到5M或更大
- 有效時間:localStorage存盤持久資料,瀏覽器關閉后資料不丟失除非主動洗掉資料;sessionStorage資料在當前瀏覽器視窗關閉后自動洗掉;cookie設定的cookie過期時間之前一直有效,即使視窗或瀏覽器關閉
- 資料與服務器之間的互動方式,cookie的資料會自動的傳遞到服務器,服務器端也可以寫cookie到客戶端;sessionStorage和localStorage不會自動把資料發給服務
應用場景:
- 標記用戶與跟蹤用戶行為的情況,推薦使用cookie
- 適合長期保存在本地的資料(令牌),推薦使用localStorage
- 敏感賬號一次性登錄,推薦使用sessionStorage
點擊本地存盤的方式介紹查看詳解
JavaScript中如何實作函式快取?有哪些應用場景?
是什么:
函式快取,就是將函式運算過的結果進行快取
本質上就是用空間(快取存盤)換時間(計算程序)
快取只是一個臨時的資料存盤,它保存資料,以便將來對該資料的請求能夠更快地得到處理
實作方法:
- 閉包
- 柯里化
- 高階函式
以下幾種情況下,適合使用快取:
- 對于昂貴的函式呼叫,執行復雜計算的函式;
- 對于具有有限且高度重復輸入范圍的函式
- 對于具有重復輸入值的遞回函式
- 對于純函式,即每次使用特定輸入呼叫時回傳相同輸出的函式
點擊如何實作函式快取查看詳解
說說函式節流和防抖?有什么區別?如何實作?
節流(throttle):
- n 秒內只運行一次,若在 n 秒內重復觸發,只有一次執行
防抖(debounce):
- n 秒后在執行該事件,若在 n 秒內被重復觸發,則重新計時
白話文理解:
把電梯完成一次運送,類比為一次函式的執行和回應
假設電梯有兩種運行策略 debounce(防抖) 和 throttle(節流),超時設定為15秒,不考慮容量限制
電梯第一個人進來后,15秒后準時運送一次,這是節流;
電梯第一個人進來后,等待15秒,如果程序中又有人進來,15秒等待重新計時,直到15秒后開始運送,這是防抖
區別:
相同點:
- 都可以通過使用 setTimeout 實作
- 目的都是,降低回呼執行頻率,節省計算資源
不同點:
- 函式防抖,在一段連續操作結束后,處理回呼,利用clearTimeout和 setTimeout實作,函式節流,在一段連續操作中,每一段時間只執行一次,頻率較高的事件中使用來提高性能
- 函式防抖關注一定時間連續觸發的事件,只在最后執行一次,而函式節流一段時間內只執行一次
點擊函式節流和防抖查看詳解
es6有哪些新特性?
- Let和const關鍵字
- 變數的解構賦值
- 陣列,物件的擴展
- 箭頭函式
- 展開運算子
- 類的支持
- 函式的引數默認值
- 物件的簡化賦值
說一說var、let和const的區別?
- var宣告的變數存在變數提升,即變數可以在宣告之前呼叫,值為undefined;let和const不存在變數提升,即它們所宣告的變數一定要在宣告后使用,否則報錯
- var不存在暫時性死區;let和const存在暫時性死區,只有等到宣告變數的那一行代碼出現,才可以獲取和使用該變數
- var不存在塊級作用域;let和const存在塊級作用域
- var允許重復宣告變數;let和const在同一作用域不允許重復宣告變數
- var和let可以修改;const宣告一個只讀的常量,一旦宣告,常量的值就不能改變
你是怎么理解ES6中promise的,和使用場景?
點擊理解ES6中promise查看詳解
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/347146.html
標籤:其他
上一篇:怎么查看每個網頁的記憶體問題
