2021年前端面試題-javaScript篇


先放面試題,答案還在整理中~

小伙伴們如果有相關分類的面試題,一起分享,做相親相愛的打工人~

1、es6的新特性

const let
模板字符串
箭頭函數
函數的參數默認值
對象和數組解構
for...of 和 for...in

2、promise的使用,怎么用es5實現promise

3、if有作用域嗎

只有函數有作用域,if是沒有作用域的。
但是有一種情況會讓if看上去有作用域,就是在if {}語句中,使用const、let,他們會有塊級作用域。

4、原型鏈和作用域鏈的區別

(1)原型鏈
當訪問一個對象的某個屬性時,會先在這個對象本身的屬性上找,如果沒有找到,會去這個屬性的__proto__屬性上找,即這個構造函數的prototype,如果還沒找到,就會繼續在__proto__上查找,
直到最頂層,找不到即為undefined。這樣一層一層往上找,彷佛是一條鏈子串起來,所以叫做原型鏈。
(2)作用域鏈 變量取值會到創建這個變量的函數的作用域中取值,如果找不到,就會向上級作用域去查,直到查到全局作用域,這么一個查找過程形成的鏈條就叫做作用域鏈。 (3)區別 作用域是對變量而言,原型鏈是對於對象的屬性而言 作用域鏈的頂層是window,原型鏈的頂層是Object

5、js判斷類型

1、typeof
檢測不出null 和 數組,結果都為object,所以typeof常用於檢測基本類型 2、instanceof
不能檢測出number、boolean、string、undefined、null、symbol類型,所以instancof常用於檢測復雜類型以及級成關系
3、constructor null、undefined沒有construstor方法,因此constructor不能判斷undefined和null。
但是contructor的指向是可以被改變,所以不安全
4、Object.prototype.toString.call
全類型都可以判斷

6、數據類型怎么檢測

1、typeof
例:console.log(typeof true) // boolean

2、instanceof
例:console.log([1,2] instanceof Array) // true

3、constructor
例: console.log([1, 2].constructor === Array) // ture

4、Object.prototype.toString.call
例:Object.prototype.toString.call([1, 2]) // [object Array]

7、普通函數和箭頭函數的區別

1、普通函數
可以通過bind、call、apply改變this指向
可以使用new
2、箭頭函數 本身沒有this指向, 它的this在定義的時候繼承自外層第一個普通函數的this 被繼承的普通函數的this指向改變,箭頭函數的this指向會跟着改變 箭頭函數外層沒有普通函數時,this指向window 不能通過bind、call、apply改變this指向 使用new調用箭頭函數會報錯,因為箭頭函數沒有constructor

8、如何用原生js給一個按鈕綁定兩個onclick事件?

var btn = document.getElementById('btn')
btn.addEventListener('click', fn1)
btn.addEventListener('click', fn2)

function fn1 () {
  console.log('我是方法1')  
}

function fn2 () {
  console.log('我是方法2')  
}

9、document.write和innerHTML的區別

document.write 將內容寫入頁面,清空替換掉原來的內容,會導致重繪

document.innerHTML 將內容寫入某個Dom節點,不會重繪

10、棧和堆的區別

1、堆
動態分配內存,內存大小不一,也不會自動釋放

2、棧
自動分配相對固定大小的內存空間,並由系統自動釋放

3、基本類型都是存儲在棧中,每種類型的數據占用的空間的大小是確定的,並由系統自動分配和釋放。內存可以及時回收。

4、引用類型的數據都是存儲在堆中。准確說是棧中會存儲這些數據的地址指針,並指向堆中的具體數據。

11、undefined 和 null 區別

1、null
什么都沒有,表示一個空對象引用(主動釋放一個變量引用的兌現那個,表示一個變量不再指向任何引用地址)
2、undefined
沒有設置值的變量,會自動賦值undefined
3、區別
typeof undefined             // undefined
typeof null                  // object
null === undefined           // false
null == undefined            // true

12、eval()的作用

eval(string) 函數計算 JavaScript 字符串,並把它作為腳本代碼來執行

如果參數是一個表達式,eval() 函數將執行表達式;

如果參數是Javascript語句,eval()將執行 Javascript 語句;

如果執行結果是一個值就返回,不是就返回undefined,如果參數不是一個字符串,則直接返回該參數。

特殊:eval("{b:2}") // 聲明一個對象

 eval("({b:2})") // 返回對象{b:2}

13、JS哪些操作會造成內存泄露

這個文章講的通俗易懂,可以參考具體案例 https://www.jianshu.com/p/763ba9562864

內存泄漏是指一塊被分配的內存既不能使用,也不能回收,直到瀏覽器進程結束。
1、意外的全局變量
2、閉包
3、沒有清理的dom元素
dom元素賦值給變量,又通過removeChild移除dom元素。但是dom元素的引用還在內存中
4、被遺忘的定時器或者回調

14、談談垃圾回收機制方式及內存管理

JavaScript 在定義變量時就完成了內存分配。當不在使用變量了就會被回收,因為其開銷比較大,垃圾收集器會定期(周期性)找出那些不在繼續使用的變量,然后釋放其內存。
(1)垃圾回收
標記清除法
當變量進入環境時,將這個變量標記為'進入環境'。當標記離開環境時,標記為‘離開環境’。離開環境的變量會被回收
引用技計數法
跟蹤記錄每個值被引用的次數,如果沒有被引用,就會回收
(2)內存管理
內存分配=》內存使用=》內存回收

15、什么是閉包,如何使用它,為什么要使用它?

(1)閉包就是能夠讀取其它函數內部變量的函數
(2)使用方法:在一個函數內部創建另一個函數
(3)最大用處有兩個:讀取其他函數的變量值,讓這些變量始終保存在內存中
(4)缺點:會引起內存泄漏(引用無法被銷毀,一直存在)

16、請解釋JSONP的工作原理,以及它為什么不是真正的AJAX

JSONP 是一種非正式傳輸協議,允許用戶傳遞一個callback給服務端,然后服務端返回數據時會將這個callback 參數作為函數名來包裹住 JSON 數據,這樣客戶端就可以隨意定制自己的函數來自動處理返回數據了。
當GET請求從后台頁面返回時,可以返回一段JavaScript代碼,這段代碼會自動執行,可以用來負責調用后台頁面中的一個callback函數。 它們的實質不同 ajax的核心是通過xmlHttpRequest獲取非本頁內容 jsonp的核心是動態添加script標簽調用服務器提供的js腳本 jsonp只支持get請求,ajax支持get和post請求

17、請解釋一下JavaScript的同源策略

同源指協議,域名,端口相同,
同源策略是一種安全協議,指一段腳本只能讀取來自同一來源的窗口和文檔的屬性。

18、關於JS事件冒泡與JS事件代理(事件委托)

(1)事件冒泡
當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window,過程就像冒泡泡 。如果在某一層想要中止冒泡,使用 event.stopPropagation() 。
但是當大量標簽大量事件的時候先然不可能為每個元素都加上事件,(事件綁定占用事件,瀏覽器要跟蹤每個事件,占用更多內存。而且並不是所有事件都會被用戶使用到)。所以需要事件委托來解決這個問題。 (2)事件委托 將事件給最外層的元素,自己不實現邏輯,由最外層元素來代理。(判斷事件源,做不同處理)

19、new操作符到底到了什么

(1)var obj = new Fun() 做了三件事

var obj  = {}  // 創建一個空對象
obj.__proto__ = Fun.prototype //空對象的__proto__指向構造函數的原型對象
Fun.call(obj) // 構造函數this指向替換成obj

(2)實現一個new
function _new(fn, ...arg) {
    const obj = Object.create(fn.prototype);
    const ret = fn.apply(obj, arg);
    // 根據規范,返回 null 和 undefined 不處理,依然返回obj,不能使用
    // typeof result === 'object' ? result : obj
    return ret instanceof Object ? ret : obj;
}

20、js延遲加載的方式有哪些?

(1)defer屬性
<script src="test.js" defer="defer"></script>
立即下載,但是會等到整個頁面都解析完成之后再執行
(2)async屬性
<script src="test.js" async></script>
不讓頁面等待腳本下載和執行(異步下載),但是無法控制加載的順序
(3)動態創建script標簽
(4)使用定時器延遲
(5)讓js最后加載

21、promise、async有什么區別

1、什么是Async/Await
async/await是寫異步代碼的新方式,使用的方式看起來像同步
async/await是基於Promise實現的,它不能用於普通的回調函數。

2、什么是promise
為了解決異步嵌套而產生,讓代碼更易於理解

區別,async/await讓代碼更像同步,進一步優化了代碼

22、== 和 ===的區別,什么情況下用相等==

”==” 是判斷轉換后的值是否相等, 

”===” 是判斷值及類型是否完全相等

不需要判斷類型時可以使用==

23、bind、call、apply的區別

var a = {
    user:"良人",
    fn: function(arg1, arg2) {
        console.log(this.user)  // 良人
        console.log(arg1+ arg2) // 2
    }
}
var b = a.fn

1、bind
var c = b.bind(a) // 返回一個已經切換this指向的新函數
c(1,1)

2、apply
b.apply(a, [1, 1])  // 將b添加到a環境中
第一個參數是this指向的新環境
第二個參數是要傳遞給新環境的參數
注意: 第一個參數為null時表示指向window

3、call
b.call(a, 1, 1) // 將b添加到a環境中
第一個參數是this指向的新環境
第二、三...個參數是傳遞給新環境的參數
注意: 第一個參數為null時表示指向window

小結: bind方法可以讓函數想什么時候調用就什么時候調用。apply、call方法只是臨時改變了this指向。

24、如何判斷鏈表是否有環
25、介紹暫時性死區

在代碼塊內,使用let、const命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”。

26、兩個對象如何比較

有思路即可,步驟:
(1)判斷兩個類型是否對象
(2)判斷兩個對象key的長度是否一致
(3)判斷屬性value值的數據類型,根據不同數據類型做比較
    a、是對象,重復這個步驟
    b、是數組,轉字符串比較
    c、是基本類型,直接判斷

27、介紹各種異步方案

(1)回調函數
(2)promise
(3)async/await

28、Promise和Async處理失敗的時候有什么區別

(1)Promise錯誤可以在構造體里面被捕獲,而async/await返回的是promise,可以通過catch直接捕獲錯誤。
(2)await 后接的Promise.reject都必須被捕獲,否則會中斷執行

29、JS為什么要區分微任務和宏任務

(1)js是單線程的,但是分同步異步
(2)微任務和宏任務皆為異步任務,它們都屬於一個隊列
(3)宏任務一般是:script,setTimeout,setInterval、setImmediate
(4)微任務:原生Promise
(5)遇到微任務,先執行微任務,執行完后如果沒有微任務,就執行下一個宏任務,如果有微任務,就按順序一個一個執行微任務

30、Promise和setTimeout執行先后的區別

Promise是微任務,setTimeout是宏任務,先執行微任務,如有還有微任務執行完微任務再執行下一個宏任務

31、單例、工廠、觀察者項目中實際場景
32、添加原生事件不移除為什么會內存泄露

 

 原文:https://juejin.cn/post/6844903892547797006

33、setTimeout(0)和setTimeout(2)之間的區別

定時器表面意思是過指定時間后執行,但是真正的含義是每過指定時間后,會有fn進入事件隊列
(1)setTimeout(fn,0)的含義是,指定某個任務在主線程最早可得的空閑時間執行,意思就是不用再等多少秒了,只要主線程執行棧內的同步任務全部執行完成,棧為空就馬上執行 (2)setTimeout(fn,1) 1毫秒后執行,但是因為要先執行前面的宏任務,所以不一定就是在一毫秒后執行,取決於隊列里任務執行的速度

34、for..in 和 object.keys的區別

Object.keys不會遍歷繼承的原型屬性
for...in 會遍歷繼承的原型屬性

35、XML和JSON的區別?

1,xml是重量級的,json是輕量級的。
2,xml在傳輸過程中比較占帶寬,json占帶寬少,易於壓縮。
3,xml和json都用在項目交互下,xml多用於做配置文件,json用於數據交互。

36、說說你對AMD和Commonjs的理解

兩者都是為了實現模塊化編程而出現的
(1)commonjs
通常被應用於服務器,在服務器端,模塊的加載和執行都在本地完成,因此,CommonJS並不要求模塊加載的異步化。
核心思想:
一個單獨文件就是一個模塊,通過require方法來同步加載要依賴的模塊,然后通過extports或則module.exports來導出需要暴露的接口。
(2)AMD
可以實現異步加載依賴模塊,預加載,在並行加載js文件同時,還會解析執行該模塊。雖然可以並行加載,異步處理,但是加載順序不一定
(3)CMD
懶加載,雖然會一開始就並行加載js文件,但是不會執行,而是在需要的時候才執行。

37、js的涉及模式

單例模式、策略模式、代理模式、迭代器模式...等等

這篇文章覺得很好,簡介明了能讓人大致懂得這些模式,具體還是要自己去學習 https://www.cnblogs.com/imwtr/p/9451129.html
38、["1", "2", "3"].map(parseInt) 答案是多少?

這題看到的時候都懵逼了,還是太菜了 = =...
(1)map用法:
arr.map(function(el, index, arr) {
    return el
})
map方法接收一個函數參數,並且這個函數可以接收三個參數
el:遍歷過程中的當前項,
index:遍歷過程中的當前下標
arr: 原數組

(2)parseInt用法:
parseInt(str, num) 
根據num解析str,並返回一個整數。
str: 要解析的字符串,如果字符第一個數不能被轉換,返回NaN。
num: 基數,介於 2 ~ 36 之間,如果傳0,則默認用10計算。num不在區間內,返回NaN

(3)所以這道題,關鍵點就在num
el和index 相當於 str 和 num 帶入一下
parseInt('1', 0) // '1' 用基數10算 為1
parseInt('2', 1) // NaN
parseInt('3', 2) // NaN

39、常見兼容性問題?

(1)事件對象兼容
e  = e || window.event;
(2)阻止事件冒泡兼容
event.stopPropagation? event.stopPropagation():event.cancelBubble=true;
(3)阻止默認行為兼容
evt.preventDefault?evt.preventDefault():evt.returnValue=false;
(4)事件監聽兼容
addEventListener  ? addEventListener  : attachEvent()
removeEventListener() ? removeEventListener() : detachEvent()
(5)事件目標對象兼容
var src = event.target || event.srcElement;

40、說說你對promise的了解

(1)promise是為解決異步處理回調金字塔問題而產生的
(2)有三種狀態,pengding、resolve、reject,狀態一旦決定就不會改變
(3)then接收resolve(),catch接收reject()

41、模塊化開發怎么做?
42、介紹js有哪些內置對象?

String對象、Array對象、Object對象、Number對象
Math對象、Date對象、Boolean對象

43、說幾條寫JavaScript的基本規范?

1、不要在同一行聲明多個變量
2、使用 === 和 !== 來比較
3、不要使用全局函數
4、變量在使用之前的位置聲明(減少變量提升干擾)
5、if用花括號包起來即使只有一行
6、寫注釋

44、JavaScript有幾種類型的值?,你能畫一下他們的內存圖嗎?

棧:原始數據類型(Undefined  Null  Boolean  Number  String)
堆:引用數據類型(對象、數組、函數)

 

45、href="#"與href="javascript:void(0)的區別"?

1、# 包含了一個位置信息,默認的錨是#top 也就是網頁的上端。在頁面很長的時候會使用 # 來定位頁面的具體位置,格式為:# + id。

2、javascript:void(0), 僅僅表示一個死鏈接。

如果你要定義一個死鏈接請使用 javascript:void(0) 

46、對this的理解

1、單獨使用,this表示全局對象
2、在函數中,this表示全局對象
3、在對象的一個函數方法中,this表示這個對象
4、可以通過apply、bind來更改this的指向

ps: this永遠指向的是最后調用它的對象,僅當它在對象的一個函數方法中時會有差異

47、promise.all 返回什么

如果沒有報錯,返回執行結果[res1, res2,...]
如果報錯,則返回第一個報錯的promise的結果

48、多個await的執行順序,如果要同步執行如何實現?

使用Promise.all
promise.all是等所有異步操作都完成之后返回結果,相當於讓這些異步同步了

 


免責聲明!

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



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