先放面試題,答案還在整理中~
小伙伴們如果有相關分類的面試題,一起分享,做相親相愛的打工人~
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是等所有異步操作都完成之后返回結果,相當於讓這些異步同步了