js高頻面試題,整理好咯


中級前端面試題,不低於12k,整理的是js較高頻知識點,可能不夠完善,大家有興趣可以留言補充,我會逐步完善,若發現哪里有錯,還請多多斧正,哈哈

http和瀏覽器相關知識點,已分離出,會在下篇整理

 

數據類型

基本類型:number,string,boolean,null,undefined
引用類型:object,array,function (統稱為object)


基本類型和引用類型的區別

引用類型值保存在堆里,基本類型是存放在棧里
引用類型值可添加屬性和方法,而基本類型值則不可以

 

判斷類型方式

  1. typeof:常用,但是無法區分objec t和 null
  2. instanceof:通過原型鏈來判斷
  3. Object.prototype.toString.call() :最完美的判斷方法

 

棧和堆的區別

棧由編譯器自動分配釋放空間,堆一般由程序員分配釋放
棧存放在一級緩存中,調用完畢立即釋放;堆則是在二級緩存中,生命周期由虛擬機的垃圾回收算法來決定

 

數組常用方法

改變原數組

shift:刪除第一個元素
unshift:向數組開頭添加元素
pop:刪除最后一個元素
push:向數組末尾添加元素
reverse:數組倒序排序
sort:數組正序排序
splice: splice(start,length,item)刪,增,替換數組元素

不改變原數組

concat:連接多個數組
join:將數組所有元素以字符分隔
slice:slice(start,end),切割數組
map,filter,some,every等不改變原數組

 

數組排序

  1. reverse()倒序
  2. sort()正序
  3. 冒泡排序
var arr = [1, 9, 4, 50, 49, 6, 3, 2];
function test(){
  for (var i = 0; i < arr.length - 1; i++){
    for (var j = i + 1; j < arr.length; j++){
      var tempi = arr[i]; // 獲取第一個值,並與后一個值比較
      var tempj = arr[j];
      if (tempi > tempj) {
        arr[i] = tempj;
        arr[j] = tempi; // 如果前一個值比后一個值大,那么相互交換
      }
    }
  }
  console.log(arr); // return arr
}
test(arr); // [1, 2, 3, 4, 6, 9, 49, 50]

 

 

數組去重

  1. indexOf() 用for循環遍歷數組,把等於下標值為-1的值push進新建的空數組里
  2. es6的set()方法
var arr = [1,1,12,12,13,13,8,8,9,7,5];
var arr2 = [...new Set(arr)]; // [1, 12, 13, 8, 9, 7, 5]


淺拷貝與深拷貝

  1. 深拷貝和淺拷貝只針引用類型(Object、Array)的數據
  2. 淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象共享同一內存,修改新對象會改變原對象
  3. 深拷貝則另外創造個一模一樣的對象,新舊對象不共享內存,修改新對象不會改到原對象

淺拷貝實現方法

  1. Object.assign() // 注意,當object只有一層結構,是深拷貝
  2. Array.prototype.concat()
  3. Array.prototype.slice()

深拷貝實現方法

  1. JSON.parse(JSON.stringify())
  2. 遞歸法,for循環遍歷對象、數組直到里邊都是基本數據類型,然后再賦值

 

JSON.stringify()實現深拷貝的缺點

如obj里有時間對象,則JSON.stringify(序列化)再JSON.parse(反序列化)后,時間對象將變成字符串形式,而不是對象形式
如obj里有正則(RegExp)、Error對象,則序列化后只得到空對象
如obj里有函數,undefined,則序列化后會丟失
如obj里有NaN、正無窮(Infinity)和負無窮(-Infinity),則序列化后會變成null

 

null,undefined的區別

null用來表示尚未存在的對象

undefined表示"缺少值",就是此處應該有一個值,但是還沒有定義

 

函數聲明與函數表達式

在js中,解析器會率先讀取函數聲明,並使其在執行任何代碼前可用(可訪問)
而函數表達式,則必須等到解析器執行到它所在的代碼行,才會真正被解析執行

 

原型鏈

函數對象

在JS中,函數即對象

原型對象

定義函數對象時,會包含一個預定義屬性prototype,稱為原型對象

__proto__

創建對象時,會有個[[proto]]內置屬性,用於指向創建它的函數對象的prototype,prototype也有[[proto]]屬性,在不斷指向中,形成了原型鏈

 

原型鏈的終點

原型鏈終點是null


原型鏈終點為什么是null

  1. 原型鏈上所有節點都是對象,不能是字符串、數字、布爾值等原始類型
  2. 另外,規范要求原型鏈必須是有限長度

 


new操作符具體做了什么

  1. 創建空對象,this引用該對象,同時繼承該對象的原型
  2. 屬性和方法被加入到this引用的對象中

 

this指向問題

  1. 當沒有被對象調用時,指向window
  2. 當被對象調用時,指向調用他的對象
  3. 當實例化對象就在對象中時,指向該實例化對象


判斷空對象方法

1. JSON.stringify(obj)
// 判斷JSON.stringify(data) == "{}"

2. Object.keys(obj)
// 返回自身的可枚舉屬性
// 判斷Object.keys(data).length === 0

 

閉包

閉包就是能夠讀取其他函數內部變量的函數

 

閉包優點

  1. 將變量長期保存,不被垃圾回收機制回收
  2. 避免全局變量的污染
  3. 安全性提高

 

閉包缺點

  1. 容易造成內存泄漏


閉包應用場景

  1. 封裝私有變量
  2. 通過閉包實現setTimeout傳參
  3. 作為回調函數綁定到事件

 

常見內存泄漏

  1. 閉包
  2. 全局變量,相當於掛載到 window 對象上
  3. 被遺忘的定時器和回調函數

 

垃圾回收機制

  1. 標記清除
  2. 引用計數

 

事件冒泡

當元素接收事件時,會把接收的事件傳遞給自己的父級,層層傳遞直到window


阻止事件冒泡

IE瀏覽器: e.cancelBubble = true
其他: e.stopPropagation()

 

事件捕獲

用addEventListener監聽目標元素事件

 

阻止默認事件

return false
ev.preventDefault()

 

事件委托原理,及優缺點

原理為事件冒泡機制

優點

  1. 可大量節省內存占用,減少事件注冊
  2. 可實現當新增子對象時,無需再對其事件綁定,對於動態內容部分尤為合適

缺點

  1. 可能會出現事件誤判,把本不應用觸發事件的被綁上了事件


事件循環

Javascriprt為單線程。單線程的缺點是所有任務需排隊,后一個任務要等前一個任務執行完畢,這樣耗時太久,於是js所有任務分為兩種:同步任務,異步任務

JS引擎將所有任務按類添加到宏任務、微任務兩個隊列,首先在宏任務隊列中取出第一個任務,執行完畢后,再把微任務隊列中所有任務按序執行完,之后再取宏任務,周而復始,直至兩個隊列的任務都取完,過程就叫事件循環

 

宏任務和微任務

宏任務:setTimeout,setInterval

微任務:Promise,process.nextTick

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM