當前位置:編程學習大全網 - 編程語言 - 前端經典面試題(60道前端面試題包含JS、CSS、React、瀏覽器等)

前端經典面試題(60道前端面試題包含JS、CSS、React、瀏覽器等)

防抖

節流

誤區:我們經常說get請求參數的大小存在限制,而post請求的參數大小是無限制的。

實際上HTTP 協議從未規定 GET/POST 的請求長度限制是多少。對get請求參數的限制是來源與瀏覽器或web服務器,瀏覽器或web服務器限制了url的長度。為了明確這個概念,我們必須再次強調下面幾點:

補充補充壹個get和post在緩存方面的區別:

可從IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、

vue和react都是采用diff算法來對比新舊虛擬節點,從而更新節點。在vue的diff函數中(建議先了解壹下diff算法過程)。在交叉對比中,當新節點跟舊節點 頭尾交叉對比 沒有結果時,會根據新節點的key去對比舊節點數組中的key,從而找到相應舊節點(這裏對應的是壹個key => index 的map映射)。如果沒找到就認為是壹個新增節點。而如果沒有key,那麽就會采用遍歷查找的方式去找到對應的舊節點。壹種壹個map映射,另壹種是遍歷查找。相比而言。map映射的速度更快。vue部分源碼如下:

創建map函數

遍歷尋找

在React中, 如果是由React引發的事件處理(比如通過onClick引發的事件處理),調用setState不會同步更新this.state,除此之外的setState調用會同步執行this.state 。所謂“除此之外”,指的是繞過React通過addEventListener直接添加的事件處理函數,還有通過setTimeout/setInterval產生的異步調用。

**原因:**在React的setState函數實現中,會根據壹個變量isBatchingUpdates判斷是直接更新this.state還是放到隊列中回頭再說,而isBatchingUpdates默認是false,也就表示setState會同步更新this.state,但是, 有壹個函數batchedUpdates,這個函數會把isBatchingUpdates修改為true,而當React在調用事件處理函數之前就會調用這個batchedUpdates,造成的後果,就是由React控制的事件處理過程setState不會同步更新this.state

虛擬dom相當於在js和真實dom中間加了壹個緩存,利用dom diff算法避免了沒有必要的dom操作,從而提高性能。

具體實現步驟如下:

用 JavaScript 對象結構表示 DOM 樹的結構;然後用這個樹構建壹個真正的 DOM 樹,插到文檔當中

當狀態變更的時候,重新構造壹棵新的對象樹。然後用新的樹和舊的樹進行比較,記錄兩棵樹差異

把2所記錄的差異應用到步驟1所構建的真正的DOM樹上,視圖就更新了。

結構:display:none: 會讓元素完全從渲染樹中消失,渲染的時候不占據任何空間, 不能點擊, visibility: hidden:不會讓元素從渲染樹消失,渲染元素繼續占據空間,只是內容不可見,不能點擊 opacity: 0: 不會讓元素從渲染樹消失,渲染元素繼續占據空間,只是內容不可見,可以點擊

繼承:display: none:是非繼承屬性,子孫節點消失由於元素從渲染樹消失造成,通過修改子孫節點屬性無法顯示。visibility: hidden:是繼承屬性,子孫節點消失由於繼承了hidden,通過設置visibility: visible;可以讓子孫節點顯式。

性能:displaynone : 修改元素會造成文檔回流,讀屏器不會讀取display: none元素內容,性能消耗較大 visibility:hidden: 修改元素只會造成本元素的重繪,性能消耗較少讀屏器讀取visibility: hidden元素內容 opacity: 0 :修改元素會造成重繪,性能消耗較少

聯系:它們都能讓元素不可見

常用的壹般為三種 .clearfix , clear:both , overflow:hidden ;

比較好是 .clearfix ,偽元素萬金油版本,後兩者有局限性.

clear:both :若是用在同壹個容器內相鄰元素上,那是賊好的,有時候在容器外就有些問題了, 比如相鄰容器的包裹層元素塌陷

overflow:hidden :這種若是用在同個容器內,可以形成 BFC 避免浮動造成的元素塌陷

概念:將多個小圖片拼接到壹個圖片中。通過 background-position 和元素尺寸調節需要顯示的背景圖案。

優點:

缺點:

block 元素特點:

1.處於常規流中時,如果 width 沒有設置,會自動填充滿父容器 2.可以應用 margin/padding 3.在沒有設置高度的情況下會擴展高度以包含常規流中的子元素 4.處於常規流中時布局時在前後元素位置之間(獨占壹個水平空間) 5.忽略 vertical-align

inline 元素特點

1.水平方向上根據 direction 依次布局

2.不會在元素前後進行換行

3.受 white-space 控制

4. margin/padding 在豎直方向上無效,水平方向上有效

5. width/height 屬性對非替換行內元素無效,寬度由元素內容決定

6.非替換行內元素的行框高由 line-height 確定,替換行內元素的行框高由 height , margin , padding , border 決定 7.浮動或絕對定位時會轉換為 block 8. vertical-align 屬性生效

GIF :

JPEG

PNG

七種數據類型

(ES6之前)其中5種為基本類型: string , number , boolean , null , undefined ,

ES6出來的 Symbol 也是原始數據類型 ,表示獨壹無二的值

Object 為引用類型(範圍挺大),也包括數組、函數,

輸出結果是:

工廠模式

簡單的工廠模式可以理解為解決多個相似的問題;

單例模式

只能被實例化(構造函數給實例添加屬性與方法)壹次

沙箱模式

將壹些函數放到自執行函數裏面,但要用閉包暴露接口,用變量接收暴露的接口,再調用裏面的值,否則無法使用裏面的值

1.字面量

2.Object構造函數創建

3.使用工廠模式創建對象

4.使用構造函數創建對象

HTML中與javascript交互是通過事件驅動來實現的,例如鼠標點擊事件onclick、頁面的滾動事件onscroll等等,可以向文檔或者文檔中的元素添加事件偵聽器來預訂事件。想要知道這些事件是在什麽時候進行調用的,就需要了解壹下“事件流”的概念。

什麽是事件流:事件流描述的是從頁面中接收事件的順序,DOM2級事件流包括下面幾個階段。

addEventListener addEventListener 是DOM2 級事件新增的指定事件處理程序的操作,這個方法接收3個參數:要處理的事件名、作為事件處理程序的函數和壹個布爾值。最後這個布爾值參數如果是true,表示在捕獲階段調用事件處理程序;如果是false,表示在冒泡階段調用事件處理程序。

IE只支持事件冒泡

獲取壹個對象的原型,在chrome中可以通過__proto__的形式,或者在ES6中可以通過Object.getPrototypeOf的形式。

那麽Function.proto是什麽麽?也就是說Function由什麽對象繼承而來,我們來做如下判別。

我們發現Function的原型也是Function。

我們用圖可以來明確這個關系:

這裏來舉個栗子,以 Object 為例,我們常用的 Object 便是壹個構造函數,因此我們可以通過它構建實例。

則此時, 實例為instance , 構造函數為Object ,我們知道,構造函數擁有壹個 prototype 的屬性指向原型,因此原型為:

這裏我們可以來看出三者的關系:

在 JS 中,繼承通常指的便是 原型鏈繼承 ,也就是通過指定原型,並可以通過原型鏈繼承原型上的屬性或者方法。

在函數式編程中,函數是壹等公民。那麽函數柯裏化是怎樣的呢?

函數柯裏化指的是將能夠接收多個參數的函數轉化為接收單壹參數的函數,並且返回接收余下參數且返回結果的新函數的技術。

函數柯裏化的主要作用和特點就是參數復用、提前返回和延遲執行。

在壹個函數中,首先填充幾個參數,然後再返回壹個新的函數的技術,稱為函數的柯裏化。通常可用於在不侵入函數的前提下,為函數 預置通用參數 ,供多次重復調用。

call 和 apply 都是為了解決改變 this 的指向。作用都是相同的,只是傳參的方式不同。

除了第壹個參數外, call 可以接收壹個參數列表, apply 只接受壹個參數數組。

bind 和其他兩個方法作用也是壹致的,只是該方法會返回壹個函數。並且我們可以通過 bind 實現柯裏化。

如何實現壹個 bind 函數

對於實現以下幾個函數,可以從幾個方面思考

如何實現壹個call函數

如何實現壹個apply函數

箭頭函數其實是沒有 this 的,這個函數中的 this 只取決於他外面的第壹個不是箭頭函數的函數的 this 。在這個例子中,因為調用 a 符合前面代碼中的第壹個情況,所以 this 是 window 。並且 this 壹旦綁定了上下文,就不會被任何代碼改變。

關於 let 的是否存在變量提升,我們何以用下面的例子來驗證:

let 變量如果不存在變量提升, console.log(name) 就會輸出 ConardLi ,結果卻拋出了 ReferenceError ,那麽這很好的說明了, let 也存在變量提升,但是它存在壹個“暫時死區”,在變量未初始化或賦值前不允許訪問。

變量的賦值可以分為三個階段:

關於 let 、 var 和 function :

依次輸出:undefined -> 10 -> 20

答案: D

colorChange 方法是靜態的。靜態方法僅在創建它們的構造函數中存在,並且不能傳遞給任何子級。由於 freddie 是壹個子級對象,函數不會傳遞,所以在 freddie 實例上不存在 freddie 方法:拋出 TypeError 。

1.使用第壹次push,obj對象的push方法設置 obj[2]=1;obj.length+=1 2.使用第二次push,obj對象的push方法設置 obj[3]=2;obj.length+=1 3.使用console.log輸出的時候,因為obj具有 length 屬性和 splice 方法,故將其作為數組進行打印 4.打印時因為數組未設置下標為 0 1 處的值,故打印為empty,主動 obj[0] 獲取為 undefined

undefined {n:2}

首先,a和b同時引用了{n:2}對象,接著執行到a.x = a = {n:2}語句,盡管賦值是從右到左的沒錯,但是.的優先級比=要高,所以這裏首先執行a.x,相當於為a(或者b)所指向的{n:1}對象新增了壹個屬性x,即此時對象將變為{n:1;x:undefined}。之後按正常情況,從右到左進行賦值,此時執行a ={n:2}的時候,a的引用改變,指向了新對象{n:2},而b依然指向的是舊對象。之後執行a.x = {n:2}的時候,並不會重新解析壹遍a,而是沿用最初解析a.x時候的a,也即舊對象,故此時舊對象的x的值為{n:2},舊對象為 {n:1;x:{n:2}},它被b引用著。後面輸出a.x的時候,又要解析a了,此時的a是指向新對象的a,而這個新對象是沒有x屬性的,故訪問時輸出undefined;而訪問b.x的時候,將輸出舊對象的x的值,即{n:2}。

在比較相等性,原始類型通過它們的值進行比較,而對象通過它們的引用進行比較。 JavaScript 檢查對象是否具有對內存中相同位置的引用。

我們作為參數傳遞的對象和我們用於檢查相等性的對象在內存中位於不同位置,所以它們的引用是不同的。

這就是為什麽 { age: 18 } === { age: 18 } 和 { age: 18 } == { age: 18 } 返回 false 的原因。

所有對象鍵(不包括 Symbols )都會被存儲為字符串,即使妳沒有給定字符串類型的鍵。這就是為什麽 obj.hasOwnProperty('1') 也返回 true 。

上面的說法不適用於 Set 。在我們的 Set 中沒有 “1” : set.has('1') 返回 false 。它有數字類型 1 , set.has(1) 返回 true 。

這題考察的是對象的鍵名的轉換。

catch 塊接收參數 x 。當我們傳遞參數時,這與變量的 x 不同。這個變量 x 是屬於 catch 作用域的。

之後,我們將這個塊級作用域的變量設置為 1 ,並設置變量 y 的值。現在,我們打印塊級作用域的變量 x ,它等於 1 。

在 catch 塊之外, x 仍然是 undefined ,而 y 是 2 。當我們想在 catch 塊之外的 console.log(x) 時,它返回 undefined ,而 y 返回 2 。

  • 上一篇:VC中如何配置可調試項目
  • 下一篇:工業機器人實訓設備參數是什麽?
  • copyright 2024編程學習大全網