備戰金三四銀—前端必問的面試題(1)

前言

又快到了到金三四銀找工做的黃金時間,經過這些時間作面試題整理了一些經典必問的面試題,相信會對你們有幫助!javascript

如何知道(任何的)一個網站使用了多少種HTML標籤?

1,獲取全部的DOM節點html

document.querySelectorAll('*')

此時獲得的是一個NodeList集合,咱們須要將其轉化成數組,而後對其篩選前端

2,轉化爲數組vue

[...document.querySelectorAll('*')]

一個拓展運算符就搞定java

3,獲取數組每一個元素的標籤名node

[...document.querySelectorAll('*')}.map(ele => ele.tagName)

使用一個map方法,將咱們須要的結果映射到一個新數組webpack

4,去重nginx

new Set([...document.querySelectorAll('*').map(ele=>ele.tagName)).size

咱們使用ES6中的set對象,把數組做爲構造函數的參數,就實現了去重,在使用Set對象的size方法就能夠獲得有多少種HTML元素了es6

這段代碼運行結果

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function() {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
    console.log('promise1');
    resolve();
}).then(function() {
    console.log('promise2');
});
console.log('script end');
第一步,輸出script start

雖然有兩個函數聲明,有async關鍵字,可是沒有調用,就不看,直接打印同步代碼console.log(‘script start’)web

第二步,輸出async1 start

由於執行async1這個函數的時候,async表達式定義的函數也是當即執行

第三步,輸出async2

由於async2是async定義的函數,輸出async2並返回promise對象

第四步,輸出promise1

由於執行到new promise,promise是當即執行,就先打印promise1

第五步,輸出script end

由於上一步先打印了promise1,而後執行到resolve的時候,而後跳出promise繼續向下執行,輸出script end

第六步,輸出promise2

由於前面的nue promise放進resolve回調,因此resolve被放到調用棧執行

第七步,輸出async1 end

由於await定義的這個promise已經執行完,而且返回結果,因此繼續執行async1函數後的任務,就是console.log(‘async1 end’)

第八步,輸出setTimerout

setTimeout被放在最後被調用

怎麼讓裏面的div垂直水平居中

列舉6種
<div class="parent">
    <div class="child">
    </div>
</div>

<style>
    .parent{
        width: 550px;
        height: 550px;
        border: 1px  solid #FF7F24;
        /* 方法一:定位 */
        /* position: relative; */

        /* 方法二:margin: auto */
        /* position: relative; */

        /* 方法三:利用display:table-cell */
        /* display:table-cell 加上 vertical-align:middle和text-align:center 使高度不一樣的元素都水平垂直居中,其中display:inline-block使這兩個div在同一行顯示 */
        /* display: table-cell;
        vertical-align: middle;
        text-align: center; */

        /* 方法四:利用display:flex */
        /* display: flex;
        justify-content: center;
        align-items: center; */

        /* 方法五:計算父盒子與子盒子的空間距離(這跟方法一是一個道理) */

        /* 方法六:利用transfrom */
        /* position: relative */

        /* 方法七:利用calc計算 */
        /* position: relative; */

    }
    .child{
        width: 150px;
        height: 150px;
        border: 1px solid #FF3030;
        /* 方法一:定位 */
        /* position: absolute;
        top: 50%;
        left: 50%;
        margin-top: -75px;
        margin-left: -75px;    */

        /* 方法二:margin: auto */
        /* top: 0,left: 0,right: 0,bottom: 0就像四個方向有相同的力在拉這個盒子,而後margin:auto至關於平方剩餘空間居中 */
        /* position: absolute;
        margin: auto;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0; */

        /* 方法三:利用display:table-cell */
        /* display: inline-block */

        /* 方法五:計算父盒子與子盒子的空間距離(這跟方法一是一個道理) */
        /* (parent550-child150)÷2=200 */
        /* margin-top: 200px;
        margin-left: 200px; */

        /* 方法六:利用transfrom */
        /* position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%,-50%); */

        /* 方法七:利用calc計算 */
        /* top和left都是(父元素高-子元素高)÷2 */
        /* position: absolute;
        top:calc(200px);
        left: calc(200px); */
    }
</style>

如何比較React和Vue?

一、監聽數據變化的實現原理不一樣
  • Vue經過getter/setter以及一些函數,能精確知道數據變化
  • React默認是經過比較引用的方式(diff)進行的,React不精確監聽數據變化
二、數據流不一樣
  • Vue2.0能夠經過props實現雙向綁定,用vuex單向數據流的狀態管理框架
  • React不支持雙向綁定,提倡單項數據流,Redux單向數據流的狀態管理框架
三、組件通訊的區別
  • Vue三種組件通訊方法:

    父組件經過props向子組件傳遞數據或回調

    子組件經過事件event向父組件發送數據或回調

    經過provide/inject實現父組件向子組件傳入數據,可跨層級

  • React三種組件通訊方法:

    父組件經過props向子組件傳遞數據

    React不支持子組件像父組件發送數據,而使用的是回調函數

    經過 context實現父組件向子組件傳入數據, 可跨層級

四、模板渲染方式不一樣
  • 表面上來看:

    React經過JSX渲染模板

    Vue經過HTML進行渲染

  • 深層上來看:

    React是經過原生JS實現模板中常見語法,如:插件,條件,循環

    Vue是與組件JS分離的單獨模板,經過指令實現,如:v-if

五、模板中使用的數據
  • React裏模板中使用的數據能夠直接import的組件在render中調用
  • Vue裏模板中使用的數據必需要在this上進行中轉,還要import一個組件,還要在components中聲明
六、渲染過程不一樣
  • Vue不須要渲染整個組件樹
  • React狀態改變時,所有子組件從新渲染
七、框架本質不一樣
  • Vue本質是MVVM框架,由MVC發展而來
  • React是前端組件化框架,由後端組件化發展而來
八、Vuex和Redux的區別
  • Vuex可使用dispatch、commit提交更新
  • Redux只能用dispatch提交更新
九、組合不一樣功能方式不一樣
  • Vue組合不一樣功能方式是經過mixin,能夠幫我定義的模板進行編譯、聲明的props接收到數據….
  • React組合不一樣功能方式是經過HoC(高階組件),本質是高階函數

談談你對MVVM的理解

MVVM:MVVM是Model-View-ViewModel的簡寫

M指的是模型,V指的是視圖,VM指的是視圖模型

模型指的是後端傳遞的數據

視圖指的是所看到的頁面,試圖模型mvvm模式的核心,它是鏈接view和model的橋樑。
它有兩個方向:一是將模型轉化成試圖,即將後端傳遞的數據轉化成所看到的頁面。實現的方式是:數據綁定。二是將視圖轉化爲模型,即將所看到的頁面轉化成後端數據。

視圖模型指的是界面和對應的model,由於數據庫結構不能直接跟界面控件一一對應,因此,須要再定義一個數據對象專門對應view上的控件,而ViewModel的職責就是把model對象封裝成能夠顯示和接受輸入的界面數據對象

談談你對淺拷貝和深拷貝的理解

好比:

A複製了B,B被修改後

A要是隨着B的變化而變化,那就是淺拷貝

要是B改變了,A不變,那就是深拷貝

淺拷貝:

拷貝一層,對象級別的則拷貝引用

深拷貝:

拷貝多層,每一個層級的屬性都會拷貝

vue組件間的6種通訊方法

父向子傳遞數據經過props

子向父傳遞是經過$emit、event

子實例訪問父實例經過$parent

父實例訪問子實例經過$children

$attrs用父組件傳遞數據給子組件或孫組件
(包含了父做用域中不做爲 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外))

listeners用父組件傳遞數據給子組件或孫組件
包含了父做用域中的 (不含 .native 修飾器的) v-on 事件監聽器

祖先組件經過provider提供變量給子孫組件

子孫組件經過inject注入變量給祖先組件

ref用來訪問組件實例

emit用於父子、隔代、兄弟組件通訊

on用於父子、隔代、兄弟組件通訊

vuex用來做爲兄弟之間和跨級之間的通訊

call,apply和bind相同點和區別?

相同點:

都是用來改變函數的this對象的指向的

第一個參數都是this要指向的對象

均可以利用後續參數傳參

區別:

call、apply的區別:接受參數的方式不同

bind:不當即執行。而apply、call 當即執行

談談防抖和節流

若是事件處理函數調用的頻率無限制,會加劇瀏覽器的負擔,致使用戶體驗很是糟糕。此時咱們能夠採用debounce(防抖)和throttle(節流)的方式來減小調用頻率,同時又不影響實際效果

防抖:當持續觸發事件時,必定時間段內沒有再觸發事件,事件處理函數纔會執行一次,若是設定的時間到來以前,又一次觸發了事件,就從新開始延時

節流:當持續觸發事件時,保證必定時間段內只調用一次事件處理函數,原理是經過判斷是否到達必定時間來觸發函數。

節流無論事件觸發有多頻繁,都會保證在規定時間內必定會執行一次真正的事件處理函數,而函數防抖只是在最後一次事件後才觸發一次函數。 好比在頁面的無限加載場景下,咱們須要用戶在滾動頁面時,每隔一段時間發一次 Ajax 請求,而不是在用戶停下滾動頁面操做時纔去請求數據。這樣的場景,就適合用節流技術來實現
## 給數字增長「逗號」分隔?
<font color=#CD2626>例如輸入: '"123456789.888"' 輸出:123,456,789.888</font>

var rmb = 123456789.888; 
var retRmb = rmb.toFixed(3).replace(/\d{1,3}(?=(\d{3})+(\.\d*)?$)/g, '$&,'); 
console.log(retRmb);

描述一下vue響應原理?

Vue響應式底層實現方法是Object.defineProperty()方法,該方法中存在一個getter和setter的可選項,能夠對屬性值的獲取和設置形成影響

Vue中編寫了一個wather來處理數據

在使用getter方法時,總會通知wather實例對view層渲染頁面

一樣的,在使用setter方法時,總會在變動值的同時,通知wather實例對view層進行更新

js中有幾種判斷數據類型的方法?

js的基本數據類型:

number、string、boolean、null、undefined、symbol(es6新增)

js的引用數據類型:

object、function

一、經過typeof判斷

經過typeof沒法判斷出數組、對象、null的具體類型

console.log(typeof 10); //number
  console.log(typeof NaN); //number

  console.log(typeof "10"); //string
  console.log(typeof false); //boolean
  console.log(typeof Symbol()); //symbol
  console.log(typeof function () {}); //function

  console.log(typeof []); //object
  console.log(typeof {}); //object
  console.log(typeof null); //object
  console.log(typeof undefined); //undefined

二、經過constructor判斷

經過constructor判斷數組和對象,但沒法判斷null,由於null不是對象 沒有construtor

console.log("".constructor == String); //true
  console.log(false.constructor == Boolean); //true
  console.log(new Number(10).constructor == Number); //true 這裏要使用對象的方式
  console.log([].constructor == Array); //true
  console.log({}.constructor == Object); //true

三、經過instanceof判斷

instanceof是用於判斷A是否爲B的實例,由於instanceof是基於原型鏈進行檢測的,因此能夠經過instanceof檢測數組,可是要檢測對象就不是那麼準確了,由於數組對象也是Object

console.log([] instanceof Array); //true
  console.log([] instanceof Object); //true
  console.log({} instanceof Array); //false
  console.log({} instanceof Object); //true

四、經過Object.prototype.toString.call判斷

都能判斷出來,包括unll undefined

let getType = Object.prototype.toString;
  console.log(getType.call(undefined)); //[object Undefined]
  console.log(getType.call(null)); //[object Null]
  console.log(getType.call([])); //[object Array]
  console.log(getType.call({})); //[object Object]

## js中事件傳遞有哪幾個階段?
捕獲階段:先由文檔的根節點document往事件觸發對象,從外向內捕獲事件對象

目標階段:到達目標事件位置(事發地),觸發事件

冒泡階段:再從目標事件位置往文檔的根節點方向回溯,從內向外冒泡事件對象

談談對this的理解?

this表示當前對象,this的指向是根據調用的上下文來決定的,默認指向window對象,指向window對象時能夠省略不寫

調用的上下文環境包括全局和局部

全局環境:
全局環境就是在<script></script>裏面,這裏的this始終指向的是window對象

局部環境:
在全局做用域下直接調用函數,this指向window
對象函數調用,哪一個對象調用就指向哪一個對象
使用new實例化對象,在構造函數中的this指向實例化對象
使用call或apply改變this的指向

其它:
用於區分全局變量和局部變量,須要使用this
返回函數當前的對象

瀏覽器地址輸入URL到看到界面經歷了哪些?

  • 輸入網址
  • 緩存解析
  • 域名解析
  • tcp鏈接,三層握手
  • 頁面渲染

詳細介紹一下前端緩存

前端緩存主要分爲HTTP緩存和瀏覽器緩存,

其中HTTP緩存是在HTTP請求傳輸時用到的緩存,

主要在服務器代碼上設置,而瀏覽器緩存則主要由前端js上進行設置

你知道閉包嗎?平時工做中又有用到過嗎?適用於什麼場景?

閉包就是可以讀取其餘函數內部變量的函數,也就是個函數,只不過是處於其餘函數內部而已
因爲在javascript中,只有函數內部的子函數才能讀取局部變量,因此說,閉包能夠簡單理解成「定義在一個函數內部的函數「

因此,在本質上,閉包是將函數內部和函數外部鏈接起來的橋樑

閉包能夠讀取函數內部的變量,和讓這些變量的值始終保持在內存中

適用場景:

採用函數引用方式的setTimeout調用

將函數關聯到對象的實例方法

封裝相關的功能集

說說JS中原型鏈與繼承

每一個構造函數都有一個原型對象,

原型對象都包含一個指向構造函數想指針(constructor),而實例對象都包含一個指向原型對象的內部指針(__proto__)。

若是讓原型對象等於另外一個類型的實例,此時的原型對象將包含一個指向另外一個原型的指針(__proto__),另外一個原型也包含着一個指向另外一個構造函數的指針(constructor)。

假如另外一個原型又是另外一個類型的實例……這就構成了實例與原型的鏈條

原型鏈是實現繼承的主要方法

你瞭解前端跨域嗎?有哪些方法能夠處理跨域?

跨域是指一個域下的文檔或腳本試圖去請求另外一個域下的資源

跨域的解決方案:

  • 經過jsonp跨域
  • document.domain + iframe跨域
  • location.hash + iframe
  • window.name + iframe跨域
  • postMessage跨域
  • 跨域資源共享(CORS)
  • nginx代理跨域
  • nodejs中間件代理跨域
  • WebSocket協議跨域

Proxy與Object.defineProperty的優缺點?

Proxy的優勢:

能夠直接監聽對象而非屬性,並返回一個新對象

能夠直接監聽數值的變化

攔截方法較多

能夠劫持整個對象,並返回一個新對象

Proxy做爲新標準將受到瀏覽器廠商重點持續的性能優化

Proxy的缺點:

Proxy是es6提供的新特性,兼容性很差

Object.defineProperty的優勢:

兼容性好,支持IE9

IE9如下的版本不兼容

Object.defineProperty的缺點:

沒法監控到數組下標的變化,致使直接經過數組的下標給數組設置值,不能實時響應

只能劫持對象的屬性,咱們須要對每一個對象的每一個屬性進行遍歷

在vue2.0中,是經過遞歸+遍歷data對象來實現對數據的監控的,

若是屬性值也是對象,那麼須要深度遍歷,顯然若是能劫持一個完整的對象纔是最好的選擇,

因此在vue2.0中選Object.defineProperty,

當時雖然es6的新屬性出現了Proxy,可是兼容性很差,最主要的是這個屬性沒法用polyfill來兼容,

可是在vue3.0的版本中會有效的提供兼容解決方案

在vue3.0中,Proxy不用像Object.defineProperty給屬性都設置set,get的方法,因此Proxy不會觸發循環調用

Vue中的key的做用?

key的做用是爲了在diff算法執行時更快的找到對應的節點,提升diff速度

vue組件高度複用增長key能夠標識組件的惟一性,爲了更高效更新虛擬DOM

談談 Vue 響應式原理?

Vue響應式底層實現方法是Object.defineProperty()方法,該方法中存在一個getter和setter的可選項,能夠對屬性值的獲取和設置形成影響

Vue中編寫了一個wather來處理數據

在使用getter方法時,總會通知wather實例對view層渲染頁面

一樣的,在使用setter方法時,總會在變動值得同時,通知wather實例對view層進行更新

Vue 組件 data 選項爲何必定要是函數?

若是data是一個函數的話,這樣沒複用一次組件,就會返回一份新的data,相似於給每一個組件實例建立一個私有的數據空間,讓各個組件實例維護各自的數據。而單純的寫成對象形式,就使得全部組件實例共用一份data,就會形成一個變了全都會變得結果

因此說vue組件的data必須是函數。這都是由於js的特性帶來的,跟vue自己設計無關。

js自己的面向對象編程也是基於原型鏈和構造函數,應該會注意原型鏈上添加通常都是一個函數方法而不會去添加一個對象了

談談 Vue 的渲染過程?

一、把模板編譯爲render函數

二、實例進行掛載, 根據根節點render函數的調用,遞歸的生成虛擬dom

三、對比虛擬dom,渲染到真實dom

四、組件內部data發生變化,組件和子組件引用data做爲props從新調用render函數,生成虛擬dom, 返回到步驟3

你對Webpack4瞭解嗎?能夠說說它的打包原理嗎?

webpack是一個打包模塊化JavaScript的工具,在webpack裏一切文件皆模塊,經過Loader轉換文件,經過Plugin注入鉤子,最後輸出由多個模塊組合成得文件,webpack專一於構建模塊化項目

一、利用babel完成代碼轉換及解析,並生成單個文件的依賴模塊Map

二、從入口開始遞歸分析,並生成整個項目的依賴圖譜

三、將各個引用模塊打包爲一個當即執行函數

四、將最終的bundle文件寫入bundle.js中

用CSS畫一個三角形的原理?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
<style>
    #app{
        width: 0;
        height: 0;
        border: 93px solid;
        border-color: red green yellow transparent;
    }
</style>

cmd-markdown-logo
這裏主要用到了CSS3的一個transparent屬性

transparent是透明的意思,在CSS3之後,支持全部的coloe屬性

畫的三角形其實border的寬度加上顏色來控制的,其實三角形的造成不過是,其它的邊框顏色設置成了透明瞭而已

CSS3有哪些新特性?

  • CSS3的選擇器:

    E:last-child匹配父元素的最後一個子元素E

    E:nth-child(n)匹配父元素的第n個子元素E

    E:nth-last-child(n)匹配父元素的倒數第n個子元素E

  • @Font-face特性
  • 圓角(border-radius)
  • 多列布局
  • 陰影(Shadow)
  • CSS3的漸變效果
  • CSS彈性盒子模型
  • transition對象變換時的過渡效果
  • transforms 2D轉換效果
  • Animation動畫效果

position有哪些值?分別表明什麼做用?

static:默認值 沒有定位,元素出如今正常的流中

absolute:絕對定位 相對於static定位之外的第一個父元素進行定位

relative:相對定位 生成相對定位的元素,相對於其正常位置進行定位

fixed:固定定位 生成絕對定位的元素,相對於瀏覽器窗口進行定位

你對緩存有了解嗎?

緩存是創建一個函數的過程,這個函數可以記住以前計算的結果或值。使用緩存函數是爲了不在最後一次使用相同參數的計算中已經執行的函數的計算。這節省了時間,但也有不利的一面,即咱們將消耗更多的內存來保存之前的結果

js有哪些繼承方式?

原型鏈繼承:父類的實例做爲子類的原型

借用構造函數繼承:複製父類的實例屬性給子類

組合繼承:調用父類構造函數,繼承父類的屬性,經過將父類實例做爲子類原型,實現函數複用

原型式繼承:不自定義類型的狀況下,臨時建立一個構造函數,藉助已有的對象做爲臨時構造函數的原型,而後在此基礎實例化對象,並返回

寄生式繼承:其實就是在原型式繼承獲得對象的基礎上,在內部再以某種方式來加強對象,而後返回

寄生組合繼承:經過寄生的方式來修復組合式繼承的不足,完美的實現繼承

最後

但願看到文章的同窗都有收穫!

文章要是有不對的地方還望指正!

最後祝你們都愈來愈優秀!

歡迎你們加入,一塊兒學習前端,共同進步!
cmd-markdown-logo
cmd-markdown-logo

相關文章
相關標籤/搜索