js面試題(進階)梳理

墨城 發表於 2022-05-17
面試

1、undeclared 與 undefined的區別?

undefined:宣告瞭變數,但是沒有賦值
undecalared:沒有宣告變數就直接使用

var a; //undefined
b;    // b is not defined

2、let & const與 var 的區別?

var存在變數提升,可重複宣告同一變數,宣告的變數均可改
let沒有變數提升,不可重複宣告同一變數,宣告的變數均可改
const沒有變數提升,不可重複宣告同一變數,宣告的基本資料型別不可改,引用型別可改屬性,不可只宣告變數而不賦值

3、獲取DOM元素有哪些方法?

方法描述
document.getElementById(id)通過id獲取dom
document.getElementsByTagName(tagName)通過標籤名獲取dom
document.getElementsByClassName(class)通過class獲取dom
document.getElementsByName(name)通過標籤的屬性name獲取dom
document.querySelector(選擇器)通過選擇器獲取dom
document.querySelectorAll(選擇器)通過選擇器獲取dom

4、操作DOM元素有哪些方法

方法描述
createElement建立一個標籤節點
createTextNode建立一個文字節點
cloneNode(deep)複製一個節點,連同屬性與值都複製,deep為true時,連同後代節點一起復制,不傳或者傳false,則只複製當前節點
createDocumentFragment建立一個文件碎片節點
appendChild追加子元素
insertBefore將元素插入前面
removeChild刪除子元素
replaceChild替換子元素
getAttribute獲取節點的屬性
createAttribute建立屬性
setAttribute設定節點屬性
romoveAttribute刪除節點屬性
element.attributes將屬性生成類陣列物件

5、DOM的型別有哪幾種?

元素節點              Node.ELEMENT_NODE(1)
屬性節點              Node.ATTRIBUTE_NODE(2)
文字節點              Node.TEXT_NODE(3)
CDATA節點             Node.CDATA_SECTION_NODE(4)
實體引用名稱節點       Node.ENTRY_REFERENCE_NODE(5)
實體名稱節點          Node.ENTITY_NODE(6)
處理指令節點          Node.PROCESSING_INSTRUCTION_NODE(7)
註釋節點              Node.COMMENT_NODE(8)
文件節點              Node.DOCUMENT_NODE(9)
文件型別節點          Node.DOCUMENT_TYPE_NODE(10)
文件片段節點          Node.DOCUMENT_FRAGMENT_NODE(11)
DTD宣告節點            Node.NOTATION_NODE(12)

6、JS的作用域及作用域鏈
什麼是作用域呢?

在 Javascript 中,作用域分為 全域性作用域 和 函式作用域

全域性作用域:程式碼在程式任何地方都能訪問,window物件的內建屬性都屬於全域性作用域
函式作用域:在固定的程式碼片段才能被訪問

什麼是作用域鏈?

一般情況下,變數取值到 建立 這個變數 的函式的作用域中取值

但是如果在當前作用域中沒有查到值,就會向上級作用域去查,直到查到全域性作用域,這麼一個查詢過程形成的鏈條就叫做作用域鏈

var x = 10;

function fn(){
    console.log(x);
}

function show(f){
    var x = 20;
    f();    // 10 
}

show(fn);

7、陣列的splice 與 slice 的區別?

方法引數
splicesplice(start, num, item1, item2, ...)
sliceslice(start, end)

8、substr 和 substring 的區別?

方法引數
substrsubstr(start,length)
substringsubstring(start,end)

9、includes 比 indexOf好在哪?

includes可以檢測NaN,indexOf不能檢測NaN,includes內部使用了Number.isNaN對NaN進行了匹配

10、下面程式碼輸出的結果?

for(var i = 0; i < 3; i++){
  setTimeout(function(){
      console.log(i);   
  },0); 
};

答案:3,3,3

解決方法

for(let i = 0; i < 3; i++){
  setTimeout(function(){
      console.log(i);   
  },0); 
};
// 0 1 2
for (var i = 0; i < 3; i++) {
  (function(i) {
    setTimeout(function () {
      console.log(i);
    }, 0, i)
  })(i)
};
// 0 1 2

11、什麼是async/await?解決了什麼問題?

是generator + Promise的語法糖,主要的作用是用同步方式執行非同步操作,await只能在async函式中使用,async函式執行會返回一個Promise,值由函式的return值所決定

12、JS延遲載入的方法有哪些?

1、<script async src="script.js"></script>:給script標籤加async屬性,則載入和渲染後續文件元素的過程將和 script.js 的載入與執行並行進行(非同步)
2、<script defer src="script.js"></script>:給script標籤加defer屬性,載入後續文件元素的過程將和 script.js 的載入並行進行(非同步),但是 script.js 的執行要在所有元素解析完成之後,DOMContentLoaded 事件觸發之前完成
3、動態建立script標籤:等到DOMContentLoaded 事件觸發時,生成一個script標籤,渲染到頁面上上
4、setTimeout定時器延遲程式碼執行

13、new操作符為什麼能建立一個例項物件?

分析一下new的整個過程:

1、建立一個空物件
2、繼承建構函式的原型
3、this指向obj,並呼叫建構函式
4、返回物件

簡單實現一下new:
function myNew (fn, ...args) {
    // 第一步:建立一個空物件
    const obj = {}

    // 第二步:繼承建構函式的原型
    obj.__proto__ =  fn.prototype

    // 第三步:this指向obj,並呼叫建構函式
    fn.apply(obj, args)


    // 第四步:返回物件
    return obj
}

14、什麼是文件碎片?
是什麼:一個容器,用於暫時存放建立的dom元素,使用document.createDocumentFragment()建立
有什麼用:將需要新增的大量元素先新增到文件碎片中,再將文件碎片新增到需要插入的位置,大大減少dom操作,提高效能

var oFragmeng = document.createDocumentFragment(); 
for(var i=0;i<10000;i++)
{ 

    var op = document.createElement("span"); 

    var oText = document.createTextNode(i); 

    op.appendChild(oText); 

    //先附加在文件碎片中

    oFragmeng.appendChild(op);  

} 
//最後一次性新增到document中
document.body.appendChild(oFragmeng); 

15、巨集任務與微任務有哪些?

巨集任務

#瀏覽器Node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame

微任務

#瀏覽器Node
Promise.prototype.then catch finally
process.nextTick
MutationObserver

16、Object.defineProperty(target, key, options),options可傳什麼引數?

value:給target[key]設定初始值
get:呼叫target[key]時觸發
set:設定target[key]時觸發
writable:預設false,為true時此屬性才能被賦值運算子修改
enumerable:預設false,為true時此屬性才能被列舉
configurable:預設為false,為true時此屬性的描述符才能被修改,才能被刪除

17、什麼是防抖?什麼是節流?

操作描述場景
防抖頻繁去觸發一個事件,但是隻觸發最後一次。以最後一次為準1、電腦息屏時間,每動一次電腦又重新計算時間 2、input框變化頻繁觸發事件可加防抖 3、頻繁點選按鈕提交表單可加防抖
節流頻繁去觸發一個事件,但是隻能每隔一段時間觸發一次1、滾動頻繁請求列表可加節流 2、遊戲里長按滑鼠,但是動作都是每隔一段時間做一次

18、什麼是高階函式?簡單實現一個?

高階函式:JavaScript的函式其實都指向某個變數。既然變數可以指向函式,函式的引數能接收變數,那麼一個函式就可以接收另一個函式作為引數,這種函式就稱之為高階函式。

// 簡單的高階函式
function add(x, y, f) {
    return f(x) + f(y);
}

//用程式碼驗證一下:
add(-5, 6, Math.abs); // 11

像陣列的map、reduce、filter這些都是高階函式

19、什麼是函式柯里化?簡單實現一個?

柯里化,是把接受多個引數的函式變換成接受一個單一引數(最初函式的第一個引數)的函式,並且返回接受餘下的引數而且返回結果的新函式的技術。

// 普通的add函式
function add(x, y) {
    return x + y
}

// Currying後
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

好處

1、引數複用

// 正常正則驗證字串 reg.test(txt)

// 普通情況
function check(reg, txt) {
    return reg.test(txt)
}

check(/\d+/g, 'test')       //false
check(/[a-z]+/g, 'test')    //true

// Currying後
function curryingCheck(reg) {
    return function(txt) {
        return reg.test(txt)
    }
}

var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)

hasNumber('test1')      // true
hasNumber('testtest')   // false
hasLetter('21212')      // false

2、延遲執行 其實Function.prototype.bind就是科裡化的實現例子

function sayKey(key) {
  console.log(this[key])
}
const person = {
  name: 'Sunshine_Lin',
  age: 23
}
// call不是科裡化
sayKey.call(person, 'name') // 立即輸出 Sunshine_Lin
sayKey.call(person, 'age') // 立即輸出 23

// bind是科裡化
const say = sayKey.bind(person) // 不執行
// 想執行再執行
say('name') // Sunshine_Lin
say('age') // 23

20、箭頭函式與普通函式的區別?

1、箭頭函式不能作為建構函式,不能new
2、箭頭函式沒有自己的this
3、箭頭函式沒有arguments物件
4、箭頭函式沒有原型物件

21、Symbol的應用場景?

使用Symbol充當屬性名
使用Symbol充當變數
使用Symbol實現私有屬性

22、AMD 和 CMD 的區別?

模組化代表應用特點
AMDrequire.js1、AMD的api預設一個當多個用 2、依賴前置,非同步執行
CMDsea.js1、CMD的api嚴格區分,推崇職責單一 2、依賴就近,按需載入,同步執行

23、Commonjs 和 ES6 Module的區別?

1、前者是拷貝輸出,後者是引用輸出
2、前者可修改引入值,後者只讀
3、前者是執行時,後者是編譯時

24、為什麼Commonjs不適用於瀏覽器

var math = require('math');

math.add(2, 3);

第二行math.add(2, 3),在第一行require('math')之後執行,因此必須等math.js載入完成。也就是說,如果載入時間很長,整個應用就會停在那裡等。

這對伺服器端不是一個問題,因為所有的模組都存放在本地硬碟,可以同步載入完成,等待時間就是硬碟的讀取時間。但是,對於瀏覽器,這卻是一個大問題,因為模組都放在伺服器端,等待時間取決於網速的快慢,可能要等很長時間,瀏覽器處於"假死"狀態。

因此,瀏覽器端的模組,不能採用"同步載入"(synchronous),只能採用"非同步載入"(asynchronous)。這就是AMD規範誕生的背景。

25、函式的length是多少?

length 是函式物件的一個屬性值,指該函式有多少個必須要傳入的引數,即形參的個數。形參的數量不包括剩餘引數個數,僅包括第一個具有預設值之前的引數個數

26、深度遍歷廣度遍歷的區別?

對於演算法來說 無非就是時間換空間 空間換時間

1、深度優先不需要記住所有的節點, 所以佔用空間小, 而廣度優先需要先記錄所有的節點佔用空間大
2、深度優先有回溯的操作(沒有路走了需要回頭)所以相對而言時間會長一點
3、深度優先採用的是堆疊的形式, 即先進後出
4、廣度優先則採用的是佇列的形式, 即先進先出

27、JS中的設計模式有哪些?

建立模式:該模式抽象了物件例項化過程。
結構型模式:這些模式處理不同的類和物件以提供新功能。
行為模式:也稱釋出-訂閱模式,定義了一個被觀察者和多個觀察者的、一對多的物件關係。
並行設計模式:這些模式處理多執行緒程式設計範例。
架構設計模式:這些模式用於處理架構設計

28、JS中如何將頁面重定向到另一個頁面?

1、使用 location.href:window.location.href =“https://www.baidu.com/”)
2、使用 location.replace:window.location.replace(" https://www.baidu.com/;")

29、JS中滑鼠事件的各個座標?

屬性說明相容性
offsetX以當前的目標元素左上角為原點,定位x軸座標除Mozilla外都相容
offsetY以當前的目標元素左上角為原點,定位y軸座標除Mozilla外都相容
clientX以瀏覽器可視視窗左上角為原點,定位x軸座標都相容
clientY以瀏覽器可視視窗左上角為原點,定位y軸座標都相容
pageX以doument物件左上角為原點,定位x軸座標除IE外都相容
pageY以doument物件左上角為原點,定位y軸座標除IE外都相容
screenX以計算機螢幕左上頂角為原點,定位x軸座標(多螢幕會影響)全相容
screenY以計算機螢幕左上頂角為原點,定位y軸座標全相容
layerX最近的絕對定位的父元素(如果沒有,則為 document 物件)左上頂角為元素,定位 x 軸座標Mozilla 和 Safari
layerY最近的絕對定位的父元素(如果沒有,則為 document 物件)左上頂角為元素,定位 y 軸座標Mozilla 和 Safari

30、JS中元素檢視的各個尺寸?

屬性說明
offsetLeft獲取當前元素到定位父節點的left方向的距離
offsetTop獲取當前元素到定位父節點的top方向的距離
offsetWidth獲取當前元素 width + 左右padding + 左右border-width
offsetHeight獲取當前元素 height + 上下padding + 上下border-width
clientWidth獲取當前元素 width + 左右padding
clientHeight獲取當前元素 height + 上下padding
scrollWidth當前元素內容真實的寬度,內容不超出盒子寬度時為盒子的clientWidth
scrollHeight當前元素內容真實的高度,內容不超出盒子高度時為盒子的clientHeight

31、Window檢視的各個尺寸?

屬性說明
innerWidthinnerWidth 瀏覽器視窗可視區寬度(不包括瀏覽器控制檯、選單欄、工具欄)
innerHeightinnerHeight 瀏覽器視窗可視區高度(不包括瀏覽器控制檯、選單欄、工具欄)

32、Document文件檢視的各個尺寸?

屬性說明
document.documentElement.clientWidth瀏覽器視窗可視區寬度(不包括瀏覽器控制檯、選單欄、工具欄、滾動條)
document.documentElement.clientHeight瀏覽器視窗可視區高度(不包括瀏覽器控制檯、選單欄、工具欄、滾動條)
document.documentElement.offsetHeight獲取整個文件的高度(包含body的margin)
document.body.offsetHeight獲取整個文件的高度(不包含body的margin)
document.documentElement.scrollTop返回文件的滾動top方向的距離(當視窗發生滾動時值改變)
document.documentElement.scrollLeft返回文件的滾動left方向的距離(當視窗發生滾動時值改變)

33、監聽ajax上傳進度

//【上傳進度呼叫方法實現】
xhr.upload.onprogress = progressFunction