【前端面試匯總】

1. HTML

1. 必考:你是如何理解 HTML 語義化的?

荒野階段:最開始是 PHP 后端寫 HTML故黑,不會 CSS傀广,于是就用 table 來布局。table 使用展示表格的翘单。嚴重違反了 HTML 語義化吨枉,索然很快就會寫出頁面,但是后期維護很麻煩哄芜。
美工階段:后來有了專門的寫 CSS 貌亭、html 的前端,他們只會使用 DIV + CSS 布局认臊,主要是用 float 和絕對定位布局圃庭。稍微符合一點,但還是不夠語義化,因為不知道每個div什么意思剧腻,其實是對于第一種方法的換湯不換藥的做法拘央。
前端階段:再后來,前端越來越專業(yè)化书在,知道 HTML 的各個標簽的用法灰伟,于是會使用恰當?shù)臉撕瀬碚故緝?nèi)容,而不是傻傻的全用 div儒旬,會盡量使用標題用 h1~h6栏账、列表用ul/ol>li、段落用 p栈源、導航欄用header, 側(cè)邊欄用aside,底部用footer挡爵,鏈接用a標簽,圖片用img等等標簽分別表示不同的意思凉翻。目前我們寫頁面的就是html語義化標簽了讨。

語義化的好處是易讀、有利于SEO等制轰。

2.meta viewport 是做什么用的前计,怎么寫?

這個標簽是控制頁面在移動端不要縮小顯示垃杖。具體寫法是<meta name=viewport content="width=divice-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
一開始男杈,所有頁面都是給PC準備的,喬布斯推出 iPhone 3GS调俘,頁面是不適應(yīng)手機屏幕的伶棒,所以喬布斯的工程師想了一個辦法,默認把手機模擬成 980px彩库,頁面縮小肤无。
后來,智能手機普及骇钦,這個功能在部分網(wǎng)站不需要了宛渐,所以我們就用 meta:vp 讓手機不要縮小我的網(wǎng)頁。

3.你用過哪些 HTML 5 標簽眯搭?

最常見的有:

  • 內(nèi)容相關(guān)的:header/main/footer/article等

  • 功能相關(guān)的:canvas/video.audio等

     *   canvas繪制(的用法等):mdn,首先獲取canvas,然后獲取它的二維上下文窥翩,在設(shè)置筆的顏色最后設(shè)置筆刷的范圍,就能繪圖了鳞仙。
     *   mdn,添加視頻  video標簽  用到的屬性有:<video src="xx.ogg" autoplay poster="posterimg.jpg" >//想用自己喜歡的播放器看可以加a <a href="xxx.ogg">下載</a> //還可以加字幕:<track></vodeo>
    *    mdn, 添加音頻  audio   屬性和video的差不多  
    

4.H5 是什么寇蚊?

移動端頁面就叫做H5,注意注意棍好!html5是一項標準仗岸,而H5是是一門技術(shù)允耿,他倆不是一個概念。


2. CSS

1. 必考:兩種盒模型分別說一下

  • border-box怪異(IE)和模型: width = padding + content + border
  • content-box標準盒模型:width = content
    高度和寬度類似扒怖。
    兩種盒模型比較:正常情況下都用border-box,原因:border-box寫起來更方便右犹。

2. 必考:如何居中?

  1. 水平居中:
    • 塊級元素:
    • 內(nèi)聯(lián)元素:
  2. 垂直居中:

3. 考:flex 怎么用,常用屬性有哪些积糯?

Flex是Flexible Box的縮寫掂墓,意為”彈性布局”,用來為盒狀模型提供最大的靈活性看成。Flex布局有兩層,采用flex布局的元素稱為flex容器,其子元素則自動成flex item,即項目.

  • flex容器屬性:

          flex-direction:決定項目的排列方向君编。
    
          flex-wrap:即一條軸線排不下時如何換行。
    
          flex-flow:是flex-direction屬性和flex-wrap屬性的簡寫形式川慌,默認值為row nowrap吃嘿。
    
          justify-content:定義了項目在主軸上的對齊方式。(justify)
    
          align-items:定義項目在交叉軸上如何對齊梦重。
    
          align-content:定義了多根軸線的對齊方式兑燥。如果項目只有一根軸線,該屬性不起作用琴拧。(換行會產(chǎn)生多軸)
    

flex-item屬性:

          order:定義項目的排列順序降瞳。數(shù)值越小,排列越靠前蚓胸,默認為0挣饥。
          flex-grow:定義項目的放大比例,如果所有項目的flex-grow屬性都為1,則它們將等分剩余空間(如果有的話)沛膳。如果一個項目的flex-grow屬性為2扔枫,其他項目都為1,則前者占據(jù)的剩余空間將比其他項多一倍锹安。

          flex-shrink:定義了項目的縮小比例短荐,默認為1,如果所有項目的flex-shrink屬性都為1八毯,當空間不足時搓侄,都將等比例縮小瞄桨。如果一個項目的flex-shrink屬性為0话速,其他項目都為1,則空間不足時芯侥,前者不縮小泊交。

          flex-basis:定義了在分配多余空間之前乳讥,項目占據(jù)的主軸空間(main size)。

           flex:是flex-grow, flex-shrink 和 flex-basis的簡寫廓俭,默認值為0 1 auto云石。后兩個屬性可選。

          align-self:允許單個項目有與其他項目不一樣的對齊方式研乒,可覆蓋align-items屬性汹忠。默認值為auto,表示繼承父元素的align-items屬性雹熬,如果沒有父元素宽菜,則等同于stretch。

舉例子問題:在行欄中竿报,最左邊是一個按鈕铅乡,右邊有兩個按鈕
實現(xiàn)方法:

<box>
  <item>logo<item>
  <item>登錄<item>
  <item>注冊<item>
</box>
<style>
  box{
      display:flex;        
      justify-content:space-between;
}
item:nth-child(2){
    margin-left:auto;
}
</style>

4.必考:BFC 是什么?

中文翻譯:塊級格式化上下文烈菌,舉個例子:我如果給一個div添加overflow:hidden;那么它里面的浮動元素就會被包裹起來阵幸。

  • 舉例(抽象問題具體化:不能直接回答B(yǎng)FC是什么,而是舉含有BFC的例子):
    • overflow:hidden;是清楚浮動芽世,但是不建議使用這個清楚浮動挚赊,而是用 .clearfix{}來清楚浮動
    • overflow:hidden;消除父子margin 合并。

5. CSS 選擇器優(yōu)先級

選擇器優(yōu)先級的說法 class第一位济瓢,id第二位咬腕,……是錯的,在css2時帶還能用葬荷,但是目前css3時帶是不能用涨共。【注意】如果hr引導你往這個錯誤的方向宠漩,那就說這個举反。

  1. 越具體優(yōu)先級越高
  2. 寫在后面的覆蓋寫在前面的
  3. !important的優(yōu)先級最高,但是建議少用  

6. 清除浮動說一下(背代碼)

  • .clearfix{
    content:'';
    display:block/table;
    clear:both;
    }
    把這個clearfix加到容器上扒吁,里面的子元素的浮動就被清楚了

3.原生 js

1. 必考:ES 6 語法知道哪些火鼻,分別怎么用?

1. 作用域:

  • var 聲明的變量沒有塊級作用域m在語句塊里聲明的變量作用域是其所在的函數(shù)或者 script 標簽內(nèi)雕崩,你可以在語句塊外面訪問到它魁索。
  • let : 聲明塊級變量,是有塊級作用域的粗蔚,而且不能重復聲明鹏控。在處理構(gòu)造函數(shù)的時候,可以通過let聲明而不是閉包來創(chuàng)建一個或多個私有成員抖僵。
  • const:聲明塊級變量耍群,是有塊級作用域的找筝,常量的值不能通過重新賦值來改變呻征,并且不能重新聲明。

2. 箭頭函數(shù):

  • 箭頭函數(shù)的語法比函數(shù)表達式更簡潔沐祷,沒有自己的this\arguments等攒岛,箭頭函數(shù)更適用于那些需要匿名函數(shù)的地方赖临,并且不能用作構(gòu)造函數(shù)。箭頭函數(shù)只有IE瀏覽器不能兼容灾锯。
    1. sum = (a, b) => a + b
    2. nums.forEach( v => { console.log(v) })

3. 模板字符串:
1. 實現(xiàn)多行字符串:

```
    console.log(`string text line 1
    string text line 2`)
```
  1. 插入表達式:
       var a = 10;
       var b = 5;
       console.log(`Fifteen is ${a + b } and
       not ${a * b} `)
    

4. 解構(gòu)賦值:可以將屬性/值從對象/數(shù)組中取出,賦值給其他變量兢榨,對象或數(shù)組諸葛對應(yīng)值或表達式。

  • 結(jié)構(gòu)數(shù)組:
[a,b] = [10,20]
console.log(a); //10
console.log(b); //20
[a,b,...rest] = [10,20,30,40,50]
console.log(rest); //[30,40,50]
  • 交換變量:
var a = 10;
var b = 20;
[a,b] = [b,a];
  • 用正則表達式匹配提取值:用正則表達式的 exec()方法匹配字符串會返回一個數(shù)組顺饮,該數(shù)組第一個值是完全匹配正則表達式的字符串吵聪,然后的值是匹配正則表達式括號內(nèi)內(nèi)容部分。解構(gòu)賦值允許你輕易地提取出需要的部分兼雄,忽略完全匹配的字符串——如果不需要的話吟逝。
function parseProtocol(url) { 
  var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
  if (!parsedURL) {
    return false;
  }
  console.log(parsedURL); // ["https://developer.mozilla.org/en-US/Web/JavaScript", "https", "developer.mozilla.org", "en-US/Web/JavaScript"]

  var [, protocol, fullhost, fullpath] = parsedURL;
  return protocol;
}

console.log(parseProtocol('https://developer.mozilla.org/en-US/Web/JavaScript')); // "https"
  • 結(jié)構(gòu)對象:
//基本賦值
var obj = {p:42,q:true}
var {p.q} = obj
console.log(p) //42
console.log(q) //true
//無聲明賦值
var a,b;
({a,b} = {a:1,b:2})
  • 對象解構(gòu)中的 Rest
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40}
a; // 10 
b; // 20 
rest; // { c: 30, d: 40 }

5. 模塊
1.導入:import:

  • 靜態(tài)的inport語句帶入由另一個模板導出的綁定
//語法(必須在嚴格模式下,type='module'的script標簽中使用)
import defaultExport from "Moudule-name" 
  • 類似于函數(shù)的動態(tài) import(),它不需要依賴 type="module" 的script標簽赦肋。
    script 標簽中使用 nomodule 屬性块攒,可以確保向后兼容
let module = await import('/modules/my-module.js')
  1. 導出:export:在創(chuàng)建 javascript 模塊時,export語句從模塊中導出函數(shù)佃乘、對象或原始值囱井,以便其他程序通過import 導入并使用他們。
//導出單個單個特性
export let name1,name2,...,nameN;(var const 一樣)
export function FunName(){}
export class ClassName{}
//導出列表
export {name1,name2,...,nameN}
//重命名導出
export {Variable1 as name1,variable2 as name2,...,namwN}
  1. 默認導出:export default
export default expression
export default function(){}
export default function name1(…) { … } // also class, function*
export { name1 as default, … };

4.模塊重定向

export {defaullt} from './other-module';
exprt * from './other-module';

6.class 類 :類其實是一個特殊的函數(shù)庞呕,類語法糖有兩個部分組成:類表達式和類聲明

  • 類聲明:不像函數(shù)聲明,類聲明不會聲明提升澎羞,所以需要先聲明,否則返回一個ReferenceError
class Rectangle{
    constructor(width,height){
      this.width = width;
      this.height = height;
    }
}
  • 類表達式:
//匿名類:
let Rectangle = class {
    constructor(width,height){
      this.width = width;
      this.height = height;
    }
}
//具名類
let Rectangle = class  Rectangle{
    constructor(width,height){
      this.width = width;
      this.height = height;
    }
}
  • 使用extends創(chuàng)建子類(注意:如果在子類中使用構(gòu)造函數(shù)則在使用之前調(diào)用super())
class Animal{
    constructor(){
      this.name = name
    }
    speak(){
        console.log(this.name + 'makes a noise')
    }
}
class Dog extends Animal{
     speak(){
        console.log(this.name + 'barks')
      }
}
var dog  = new Dog('mike');
dog.speak();//mike barks
  • 也可以繼承傳統(tǒng)的基于函數(shù)的類
function Animal(name){
    this.name = name
}
Animal.prototype.speak = function (){
    console.log(this.name + 'make a noise')
}
class Dog extends Animal{
    speak(){
        console.log(this.name + 'barks')
    }
}
var dog = new Dog('mike')
dog.speak();  //mike barks
  • 調(diào)用超類
class Cat{
    constructor(name){
        this.name = name
    }

    speak(){
        console.log(this.name + 'makes a noise')
    }
}
 class Lion extends Cat{
    speak(){
        super.speak();
        console.log(this.name + 'roars')
    }
}

7.迭代器
for of VS for in :
這兩個語句都是迭代一些東西;
for in 以任意順序迭代對象的(synbol以外的)可枚舉屬性;
for of 遍歷可迭代對象要迭代的數(shù)據(jù)技羔。

  • 一句話總結(jié):for of 遍歷的結(jié)果是值,for in 遍歷的結(jié)果是索引。
  • 舉例一:
let arr = ["Apple","Samsung","Nokia","Xiaomi"];

for (let value of arr){
   console.log(value)
}
//  Apple Samsung Nokia Xiaomi


for (let x in arr){
cosnole.log(x)
}
// 0 1 2 3
  • 舉例二:
let obj = { Apple:"iPhone X", Samsung:"Galaxy 6", Nokia:"Lumia",Xiaomi:"Note 3" }

for(let x of obj){
  console.log(x)
}

// !! 這樣就報錯了(obj is not iterable)原因是這個對象的值的索引必須是可迭代的

for(let x in obj){
  console.log(x)
}

// Apple Samsung Nokia Xiaomi

  • 舉例三:
// for-of 遍歷可以迭代的任意對象标沪。而 for-in 遍歷的是必需有明確索引的對象
function* company(){
  yield 'Apple';
  yield 'Samsung';
  yield 'Nokia';
  yield 'Xiaomi';
}


for(let x of company()){
  console.log(x)
}

// Apple Samsung Nokia Xiaomi

for(let x in company()){
  console.log(x)
}

// !! 這將什么都不會輸出
  • 總結(jié):for of 遍歷的結(jié)果是值,并且被遍歷的對象必須是可以迭代的,for in 遍歷的結(jié)果是索引坞靶,并且這個索引必須是明確的。

8.Symbol :
ES5的屬性名都是字符串尿这,容易造成屬性名沖突碟摆,ES6引進了一種新的原始數(shù)據(jù)類型:Symbol,表示獨一無二值(每個從Symbol()返回的symbol值都是唯一的)。
Symbol函數(shù)可以接受一個字符串作為參數(shù),表示對Symbol實例的描述轩缤,主要是為了在控制臺顯示,或者轉(zhuǎn)為字符串時,比較容易區(qū)分假瞬。
它每次都會創(chuàng)建一個新的 symbol類型:

//沒有參數(shù)的情況
var s1 = Symbol();
var s2 = Symbol();
s1 === s2  //false
//有參數(shù)的情況下:
var s1 = Symbol('foo');
var s2 = Symbol('foo');
s1 === s2 //false

2. 必考 Promise、Promise.all琴许、Promise.race 分別怎么用?

promise對象用于返回一個異步操作的最終完成結(jié)果。

  1. promise對象使用方法:

    • .then方法:
      $.ajax(……).then(成功函數(shù)辩块,失敗函數(shù))
    • 鏈式 .then方法:
      $.ajax(……).then(成功函數(shù),失敗函數(shù)).then(成功函數(shù)2液兽,失敗函數(shù)2)
  2. 如何自己生成promise對象:

function fn(){
     return new Promise((resolve, reject)=>{
         成功時調(diào)用 resolve(數(shù)據(jù))
         失敗時調(diào)用 reject(錯誤)
     })
 }
 fn().then(success, fail).then(success2, fail2)
  1. Promise.all()的用法:
    promise.all(iterable)方法返回一個promise實例桃漾,其參數(shù)iterable是可迭代對象适滓,接受一個或多個值的數(shù)組(比如,立即值、promise鱼鸠、thenable)。它返回一個promise麻蹋,此方法在集合多個 promise 的返回結(jié)果時很有用专肪。
    舉例:promise1和promise2都成功才會調(diào)用success1
          Promise.all([promise1, promise2]).then(success1, fail1)
  1. promise.race()的用法:顧名思義深夯,Promise.race就是賽跑的意思,意思就是說滓玖,promise1和promise2只要有一個成功就會調(diào)用success1,不管結(jié)果本身是成功還是失敗狀態(tài)。所接受的參數(shù)是一樣的禁悠,接收多個值的數(shù)組隶糕。
 Promise.race([promise1, promise2]).then(success1, fail1)

3. 手寫函數(shù)防抖和函數(shù)節(jié)流

  • 函數(shù)節(jié)流:可以理解為CD冷卻時間(就是在指定時間段內(nèi)不能執(zhí)行函數(shù)):
function fn(){}
CD = false
button.oncLick = function(){
    if(CD){
    }else{
      fn()
      CD = true
     var timerId = setTimeout(()=>{
        CD = false
      } ,3000)
    }
}
  • 防抖函數(shù):簡單理解為把任務(wù)帶著一起做濒旦,比如說我是一個送外賣的,然后規(guī)定如果定了一個外賣就再等5分鐘,如果來了繼續(xù)再等5分鐘慷荔,如果5分鐘之內(nèi)沒來過就開始把積累的外賣都送。
    function fn(){}
    var timerId = null
    button.onclick = function(){
          if(timerId){
              window.clearTimeout(timerId)
          }
          fn()
         timerId = null
        timerId = setTimeout(()=>{
                  timerId = null
            },5000)
          }
    }

4. 必考:手寫AJAX(背誦代碼)

function get/post(url,data,callback){
      var xhr = new XMLHttpRequest()
      xhr.open('POST',"/xxx")
      xhr.setRequestHeader("Content-type":"application/x-www-form-url-encoded")
      xhr.onreadystatechange = function(){
            if(xhr.readyState === 4 && xhr.response.Status === 200 || xhr.status === 304){
                  callback(response)
            }
     }
      xhr.send("a = 1 & b = 2")
}

5. 考:這段代碼里的 this 是什么?

函數(shù)里的this就看函數(shù)是怎么調(diào)用的:

  • fn() 在正常情況下:window;在'use strict'下:undefined
  • obj.fn() this =>obj
  • fn.call(xx) this=>xx
  • fn.appy(xx) this => xx
  • fn.bind(xx) this=> xx
  • new Fn() this=>新的對象(生成的實例)
  • fn = () => {} this=>外面的的this

6螟蒸, 必考:閉包/立即執(zhí)行函數(shù)是什么?

  1. 閉包是什么诵原?
    由于在JS中,變量的作用域?qū)儆诤瘮?shù)作用域吗蚌,在函數(shù)執(zhí)行后作用域就會被清理潦刃、內(nèi)存也隨之回收,但是由于閉包是建立在一個函數(shù)內(nèi)部的子函數(shù)胧洒,由于其可訪問上級作用域的原因,即使上級函數(shù)執(zhí)行完列赎,作用域也不會隨之銷毀,這時的子函數(shù)——也就是閉包,便擁有了訪問上級作用域中的變量的權(quán)限嚷狞,即使上級函數(shù)執(zhí)行完后作用域內(nèi)的值也不會被銷毀。
//這里就有閉包逃片,local 變量和 bar 函數(shù)就組成了一個閉包(Closure)。
function foo(){
  var local = 1
  function bar(){
    local++
    return local
  }
  return bar //只是為了 bar 能被使用损离,也跟閉包無關(guān),把 return bar 改成 window.bar = bar 也是一樣的,只要讓外面可以訪問到這個 bar 函數(shù)就行了
}

var func = foo()
func()
  1. 閉包的作用:

在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁秉氧,由于閉包可以緩存上級作用域,那么就使得函數(shù)外部打破了“函數(shù)作用域”的束縛攘滩,可以訪問函數(shù)內(nèi)部的變量。以平時使用的Ajax成功回調(diào)為例级解,這里其實就是個閉包,由于上述的特性芒划,回調(diào)就擁有了整個上級作用域的訪問和操作能力泵殴,提高了極大的便利。開發(fā)者不用去寫鉤子函數(shù)來操作上級函數(shù)作用域內(nèi)部的變量了吆你。閉包隨處可見,一個Ajax請求的成功回調(diào)者祖,一個事件綁定的回調(diào)方法杖虾,一個setTimeout的延時回調(diào),或者一個函數(shù)內(nèi)部返回另一個匿名函數(shù)嚷往,這些都是閉包。簡而言之贷祈,無論使用何種方式對函數(shù)類型的值進行傳遞谣蠢,當函數(shù)在別處被調(diào)用時都有閉包的身影。

7. 必考:什么是 JSONP,什么是 CORS戈泼,什么是跨域?

1. JSONP:
JSONP是JSON with Padding的略稱邀跃。它是一個非官方的協(xié)議,它允許在服務(wù)器集成JavaScript返回至 客戶端巨坊,通過javascript callback形式實現(xiàn)跨域訪問共啃。

  • JSONP的完整過程:

    1. 請求方:一個網(wǎng)站的前端(瀏覽器):創(chuàng)建一個script,src指向響應(yīng)方究珊,同時傳一個查詢參數(shù)callback=xxx;不用callbackName,而是用callback。
    2. 響應(yīng)方:另一個網(wǎng)站的后端(服務(wù)器),根據(jù)查詢參數(shù)callbackName,構(gòu)造形如xxx.call(undefined,'你要的參數(shù)')響應(yīng)瑟蜈。
    3. 瀏覽器接收到響應(yīng)就會執(zhí)行回調(diào)函數(shù)xxx.call(undefined,'你要的參數(shù)')宪躯。
    4. 請求方就會知道了他想要的數(shù)據(jù)(執(zhí)行函數(shù)體里面的執(zhí)行語句)掂林。
      這就是JSONP
  • 行業(yè)約定:

    1. 查詢參數(shù)要用callback來指定精置,在jQuery中用jQuery_callback。
    2. 回調(diào)函數(shù)名不固定,就用用隨機函數(shù)名火欧,簡單又避免函數(shù)名重復的問題,例如不叫xxx ,而是jQuery12343這種隨機數(shù)衅檀;只要符合變量名規(guī)則就行打却。
    3. 調(diào)用函數(shù)后馬上刪除捌肴,避免污染全局變量。
  • 為什么SJONP只能發(fā)起不能發(fā)post請求坦喘?
    因為JSONP是通過動態(tài)創(chuàng)建scriipt實現(xiàn)的,動態(tài)創(chuàng)建的script的時候只能發(fā)送get請求西设,不能發(fā)送post請求.

  • jQuery實現(xiàn)Ajax:

$.ajax({
    url : "http://jack.com:8080/pay",
    dataType : "jsonp",
     success : function(response){
        if(response === "success"){
             ...  //執(zhí)行語句
        }
    }
})

2. CORS:跨源資源分享
Cross-Origin Resource Sharing瓣铣,是W3C標準,它是解決Ajax跨源請求的根本方法贷揽,CORS 允許發(fā)送任何類型的請求
用法:

  response.setHeader('Access-Control-Allow-Origin':'http://haha.com:8080')
//設(shè)置CORS,http://haha.com:8001這個網(wǎng)站可以訪問本服務(wù)器響應(yīng)內(nèi)容

后臺用 JSONP 還是 CORS? 首先JSONP 不能發(fā)起POST請求但可以實現(xiàn)跨源請求棠笑。CORS可以發(fā)起多種類型的請求(后臺必須要用POST請求的話只能用CORS),但是需要訪問的話在后臺設(shè)置CORS才能實現(xiàn)跨源請求丐一。
3. 跨域:
跨域是指從一個域名的網(wǎng)頁去請求另一個域名的資源。比如從http://www.baidu.com/ 頁面去請求 http://www.google.com 的資源√局蓿跨域的嚴格一點的定義是:只要 協(xié)議,域名坏快,端口有任何一個的不同级及,就被當作是跨域硼啤。

8. 尘觯考:async/await 怎么用葫辐,如何捕獲異常歌馍?

捕獲異常就是拋出promise.reject異常值

aysnc function fn(){
    try{
        var z = await.promise.reject(3)
    }catch(e){
        console.log(e)  //3
    }
}
fn();

9.常考:如何實現(xiàn)深拷貝灿里?(背代碼)

  1. JSON來實現(xiàn)深拷貝:
      var a = {...}
      var b = JSON.parse( JSON.stringify(a) )
    

缺點:JSON 不支持函數(shù)撵儿、引用掸哑、undefined江锨、RegExp、Date……

  1. 遞歸:
       function clone(object){
          var object2
          if(! (object instanceof Object) ){
              return object
          }else if(object instanceof Array){
                object2 = []
          }else if(object instanceof Function){
                object2 = eval(object.toString())
          }else if(object instanceof Object){
                object2 = {}
          }
        //你也可以把 Array Function Object 都當做 Object 來看待烟号,參考 https://juejin.im/post/587dab348d6d810058d87a0a
          for(let key in object){
                object2[key] = clone(object[key])
          }
          return object2
      }
  1. 判斷類型:

  2. 檢查循環(huán)引用(環(huán)):

10. 骋乩辏考:如何用正則實現(xiàn) trim()雹食?
      function trim(string){
            return string.replace(/^\s | \s+$/g,' ')
      }

11. 考:不用 class 如何實現(xiàn)繼承?用 class 又如何實現(xiàn)门扇?

  • 不用class實現(xiàn)繼承:原型鏈
    function Animal(){
      this.body = '肉體'
    }
    Animal.prototype.move = function(){
    
    }
    
    function Human(name){
      Animal.apply(this, arguments)
      this.name = name
    }
    // Human.prototype.__proto__ = Animal.prototype // 非法
    
    var f = function(){}
    f.prototype = Animal.prototype
    Human.prototype = new f()
    
    Human.prototype.useTools = function(){}
    
    var qinglin = new Human()
    
    
  • 使用class 實現(xiàn)繼承:
     class Animal{
        constructor(){
          this.body = '肉體'
        },
        move(){}
    }
    class Dog extends Animal{
      constructor(name){
          super(name)
          this.name = name
      },
      useTools(){}
    }
    var qinglin = new Human()

12. 辰抵考:如何實現(xiàn)數(shù)組去重带到?

  • 第一種方案:
    //計數(shù)排序的邏輯(只能正整數(shù))
 var a = [4,2,5,6,3,4,5]
 var hashTab = {}
 for(let i=0; i<a.length;i++){
     if(a[i] in hashTab){
         // 什么也不做
     }else{
         hashTab[ a[i] ] = true
     }
 }
 //hashTab: {4: true, 2: true, 5: true, 6:true, 3: true}
 console.log(Object.keys(hashTab)) // ['4','2','5','6','3']

  • 第二種方案:
      function unique(array){
          return [...new set(array)]
      }

13. 棄:== 相關(guān)題目(反著答)

14. 送命題:手寫一個 Promise

function Promise(executor) {
    let self = this;
    self.status = 'pending'; //等待態(tài)
    self.value = undefined;  //成功的返回值
    self.reason = undefined; //失敗的原因

    function resolve(value){
        if(self.status === 'pending'){
            self.status = 'resolved';
            self.value = value;
        }
    }
    function reject(reason) {
        if(self.status === 'pending') {
            self.status = 'rejected';
            self.reason = reason;
        }
    }
    try{
        executor(resolve, reject);
    }catch(e){
        reject(e);// 捕獲時發(fā)生異常鸳碧,就直接失敗
    }
}
//onFufiled 成功的回調(diào)
//onRejected 失敗的回調(diào)
Promise.prototype.then = function (onFufiled, onRejected) {
    let self = this;
    if(self.status === 'resolved'){
        onFufiled(self.value);
    }
    if(self.status === 'rejected'){
        onRejected(self.reason);
    }
}
module.exports = Promise;


4. Dom

1. 考:事件委托

//錯誤版(但是可能能過)bug 在于,如果用戶點擊的是 li 里面的 span,就沒法觸發(fā) fn愤兵,這顯然不對。
ul.addEventListener('click',function(e){
    if(e.target.tagName.tiLowerCase === 'li'){
        console.log('li被點擊了')
        fn() //執(zhí)行謀個函數(shù)
    }
})

最標準版:

function delegate(element, eventType, selector, fn) {
     element.addEventListener(eventType, e => {
       let el = e.target
       while (!el.matches(selector)) {
         if (element === el) {
           el = null
           break
         }
         el = el.parentNode
       }
       el && fn.call(el, e, el)
     })
     return element
   }

2. 曾考:用 mouse 事件寫一個可拖曳的 div

//html
<div id="xxx"></div>
//js
var dragging = false
var position = null

xxx.addEventListener('mousedown',function(e){
  dragging = true
  position = [e.clientX, e.clientY]
})


document.addEventListener('mousemove', function(e){
  if(dragging === false){return}
  console.log('hi')
  const x = e.clientX
  const y = e.clientY
  const deltaX = x - position[0]
  const deltaY = y - position[1]
  const left = parseInt(xxx.style.left || 0)
  const top = parseInt(xxx.style.top || 0)
  xxx.style.left = left + deltaX + 'px'
  xxx.style.top = top + deltaY + 'px'
  position = [x, y]
})
document.addEventListener('mouseup', function(e){
  dragging = false
})

5. HTTP

1. 考:HTTP 狀態(tài)碼知道哪些扣泊?分別什么意思近范?

狀態(tài)碼 202 表示:服務(wù)器已接受請求,但尚未處理延蟹。
狀態(tài)碼 204 表示:請求處理成功评矩,但沒有資源可返回。
狀態(tài)碼 206 表示:服務(wù)器已經(jīng)成功處理了部分 GET 請求阱飘。

狀態(tài)碼 301 表示:請求的資源已被永久的分配了新的 URI斥杜。
狀態(tài)碼 302 表示:請求的資源臨時的分配了新的 URI。

狀態(tài)碼 400 表示:請求報文中存在語法錯誤沥匈。
狀態(tài)碼 401 表示:發(fā)送的請求需要有通過 HTTP 認證的認證信息蔗喂。
狀態(tài)碼 403 表示:對請求資源的訪問被服務(wù)器拒絕了。
狀態(tài)碼 404 表示:服務(wù)器上無法找到請求的資源高帖。

狀態(tài)碼 500 表示:服務(wù)器端在執(zhí)行請求時發(fā)生了錯誤缰儿。
狀態(tài)碼 503 表示:服務(wù)器暫時處于超負債或正在進行停機維護,現(xiàn)在無法處理請求散址。

2. 大公司必考:HTTP 緩存有哪幾種乖阵?

  • 幾種緩存:
    Etag —— 是根據(jù)瀏覽器和服務(wù)器資源的唯一特征標識符(比如MD5)宣赔,果服務(wù)器發(fā)現(xiàn)ETag匹配不上,那么直接以常規(guī)GET 200回包形式將新的資源(當然也包括了新的ETag)發(fā)給客戶端瞪浸;如果ETag是一致的儒将,則直接返回304知會客戶端直接使用本地緩存即可。
    Expires —— 自然也需要有個東西來啟用緩存和定義緩存時間默终,對http1.0而言椅棺,Expires就是做這件事的首部字段。 Expires的值對應(yīng)一個GMT(格林尼治時間)齐蔽,指定的是過期時間點(相對于服務(wù)器時間而言)两疚,來決定是否重新發(fā)起請求。這個方法會有bug含滴,但是如果用戶的本地時間錯亂了诱渤,可能會有問題
    Cache-Control —— 設(shè)置一個時間段,它意味著該資源是從原服務(wù)器上取得的谈况,且其緩存(新鮮度)的有效時間為一段時間勺美,在后續(xù)這段時間內(nèi),用戶重新訪問該資源則無須發(fā)送請求碑韵。 當然這種組合的方式也會有些限制赡茸,比如 no-cache 就不能和 max-age、min-fresh祝闻、max-stale 一起搭配使用占卧。
  • 之間區(qū)別:
    1. Expire和Cache-Control之間區(qū)別:前者是指定過期時間點,而后者是指定有效緩存的時間段联喘。
    2. Etag 和 Cache-Control之間的區(qū)別:Cache-Control的讀取時從瀏覽器本地文件中讀取的(無請求)华蜒,而Etag是有請求的。
  • 近幾年有些大公司使用 PWA來緩存:那么瀏覽器的http緩存順序是什么豁遭?

3. 考:GET 和 POST 的區(qū)別

  • 錯誤答案:

    1. POST安全叭喜,GET不安全,
    2. Get 有長度限制(URL 長度有1024字節(jié))蓖谢,而Post沒有長度限制(一般URL的長度限制在4M)捂蕴,
    3. Get的參數(shù)是放在URL上,Post的參數(shù)放在消息體里面蜈抓,
    4. Get只需要一個報文启绰,Post需要兩個以上。
    5. Get是冪等的沟使,Post不冪等委可。
  • 正確答案: Get是獲取數(shù)據(jù),Post是提交數(shù)據(jù)。其他的沒有本質(zhì)的區(qū)別着倾。

4. ookie V.S. LocalStorage V.S. SessionStorage V.S. Session

  1. Cookie —— http協(xié)議的一部分
  2. session —— 存在服務(wù)器中的一小段哈希表(每個用戶都有自己的sessionId請求時存放在session中拾酝,),是服務(wù)器與瀏覽器之間的一段時間內(nèi)的會話卡者。
  3. LocalStorage —— html5提供的API ,常用屬性有 setItem()/getItem()/LocalStorage.clear()/removeItem().實現(xiàn)了不同頁面中保存變量且其值不變蒿囤。讓后端有了記憶力。
  • Cookie 與 session之間的關(guān)系:
    a. Cookie 存在瀏覽器的文件里崇决,Session 存在服務(wù)器的文件里
    b.Session 是基于 Cookie 實現(xiàn)的材诽,具體做法就是把 SessionID 存在 Cookie 里
  • Cookie 與 LocalStorage之間的關(guān)系:
    a. Cookie大小約4kb,LocalStorage一般有5M,
    b. Cookie 會被發(fā)送到服務(wù)器,LocalStorage不會
    c.Cookie 會存儲用戶信息恒傻,LocalStorage存儲沒用的東西脸侥。
  • SessionStorage 與 LocalStorage之間的關(guān)系:
    a.LocalStorage 一般不會自動過期(除非用戶手動清除),而 SessionStorage 在session(會話)結(jié)束時過期(如關(guān)閉瀏覽器).

5. HTTP1和 HTTP2的區(qū)別:

HTTP2的新特性:
a. 多路復用 (MultiPlexing) —— 解決了線頭阻塞的問題盈厘,減少了 TCP 連接數(shù)量和 TCP 連接慢啟動造成的問題
b. 服務(wù)端推送 (Server Push) —— 瀏覽器發(fā)送一個請求睁枕,服務(wù)器主動向瀏覽器推送與這個請求相關(guān)的資源,這樣瀏覽器就不用發(fā)起后續(xù)請求沸手。
c. Header 壓縮 (HPACK) —— 使用 HPACK 算法來壓縮首部內(nèi)容
d. 二進制分幀層 (Binary Framing Layer)—— 幀是數(shù)據(jù)傳輸?shù)淖钚挝煌庥觯远M制傳輸代替原本的明文傳輸,原本的報文消息被劃分為更小的數(shù)據(jù)幀契吉。


6. 框架

6.1 Vue

1. 必考:watch 和 computed 和 methods 區(qū)別是什么跳仿?

watch是監(jiān)聽數(shù)據(jù),computed是計算屬性捐晶;
watch和computed的最大區(qū)別是:computed是有緩存的塔嬉,如果computed依賴的屬性沒有變化,computed屬性就不會重新激計算租悄。而watch則是看到一次計算一次。

2. 必考:Vue 有哪些生命周期鉤子函數(shù)恩袱?分別有什么用泣棋?

Vue的生命周期:

  • beforeCreate : 實例初始化之后,數(shù)據(jù)觀測(data observoe)和事件配置(event/watcher)調(diào)用之前調(diào)用畔塔。
  • created : 實例初始化之后潭辈,數(shù)據(jù)觀測和事件配置調(diào)用之前調(diào)用。
  • beforeMount : 掛載組件開始之前被調(diào)用澈吨,相關(guān)的render函數(shù)首次被調(diào)用
  • Mounted : el 被創(chuàng)建的vm.$el 替換把敢,被掛載到實例上之后調(diào)用該鉤子,
  • beforeUpdate : 數(shù)據(jù)更新時谅辣,發(fā)生在虛擬DOM 打補丁之前修赞。
  • update : 由于數(shù)據(jù)更新導致的虛擬DOM重新渲染和打補丁之后會調(diào)用。
  • beforeDestroy :實例被銷毀之前,這個時候?qū)嵗匀煌耆捎谩?/li>
  • destroyed : 實例銷毀之后調(diào)用柏副,調(diào)用后Vue 實例指示的所有東西都會被解除綁定勾邦,所有事件監(jiān)聽都會被移除,所有 的子實例也會被銷毀割择。

Vue 的 Mounted生命周期進行數(shù)據(jù)請求眷篇。

3. 考:Vue 如何實現(xiàn)組件間通信?
  1. 父子組件: $emit('xxx',data) on('xxx',function(){})
  2. 爺孫組件之間: 兩次 v-on 通過爺爺 => 爸爸 => 孫子
  3. 任意組件之間通信:eventBus = new Vue() 來通信荔泳;主要API: eventBus.on和eventBus.emit ; 任意組件之間也可以使用 Vuex來通信蕉饼。
  • Vuex是專門為Vue應(yīng)用程序開發(fā)的狀態(tài)管理工具。Vuex的核心概念有以下幾種:
    state => 基本數(shù)據(jù)
    getters => 從基本數(shù)據(jù)派生的數(shù)據(jù)
    mutations => 提交更改數(shù)據(jù)的方法玛歌,同步昧港!
    actions => 像一個裝飾器,包裹mutations沾鳄,使之可以異步慨飘。
    modules => 模塊化Vuex
4. 必考:Vue 數(shù)據(jù)響應(yīng)式怎么做到的?(以前的概念:雙向綁定)

v-model實現(xiàn)響應(yīng)式:一句話總結(jié)就是:在數(shù)據(jù)渲染時使用prop渲染數(shù)據(jù)译荞,將prop綁定到子組件自身的數(shù)據(jù)上瓤的,修改數(shù)據(jù)時更新自身數(shù)據(jù)來替代prop,watch子組件自身數(shù)據(jù)的改變吞歼,觸發(fā)事件通知父組件更改綁定到prop的數(shù)據(jù)圈膏。

 a. Object.defineProperty 通過 getter 和 setter 劫持了對象賦值的過程,在這個過程中可以進行更新 dom 操作等等篙骡。
 b. Vue 不能檢測到對象屬性的添加或刪除稽坤,解決方法是手動調(diào)用 Vue.set 或者 this.$set.
const component = {
    model : {
        prop : 'value',
        event : 'change'
    },
    props : ['value'],
    template:`
       <div> 
          <component v-model="value"></component>
      </div>
    `,
    methods : {
        handleInput(e){
          this.$emit('change',e.target.value)
        }
    }
}

5. 必考:Vue.set 是做什么用的?

Vue不能識別添加或刪除屬性的變化糯俗,vue不能在已經(jīng)創(chuàng)建的實力上動態(tài)的添加新的根級響應(yīng)式屬性尿褪,而是必須用 Vue.set方法將響應(yīng)式屬性添加到嵌套對象上。

6. Vuex 你怎么用的得湘?

Vuex是Vue.js應(yīng)用的程序的狀態(tài)管理工具杖玲。
其核心概念有以下:
state : 基本數(shù)據(jù)
getters : 基本數(shù)據(jù)派生的數(shù)據(jù)
mutations : 提交更改數(shù)據(jù)的方法,同步
actions : 相當于裝飾器淘正,封裝mutations,使之可以異步實現(xiàn)
mudules : 模塊化Vuex;

7. VueRouter 你怎么用的摆马?

VueRouter是Vue.js官方的路由器管理。澈柽海考點:重定向模式囤采,history模式,導航守衛(wèi)惩淳,路由懶加載(import('./Foo.vue')//組件路徑,返回promise對象)蕉毯。
1. 重定向模式:“重定向”的意思是,當用戶訪問 /a時,URL 將會被替換成 /b恕刘,然后匹配路由為 /b缤谎。
2. 導航守衛(wèi):導航守衛(wèi)是路由跳轉(zhuǎn)過程中的一些鉤子函數(shù),路由跳轉(zhuǎn)是一個大的過程褐着,這個大的過程分為跳轉(zhuǎn)前中后等多個細節(jié)過程坷澡,在每一個過程中都有一個函數(shù),這些個函數(shù)能讓你操作一些其他的操作的機會含蓉,這就是導航守衛(wèi)频敛。
導航守衛(wèi)有三種模式:
* 全局的:指路由在實例上直接操作的函數(shù):鉤子函數(shù)按執(zhí)行順序包括beforeEach、beforeResolve馅扣、afterEach三個斟赚。
* 單個路由獨享的:指單個路由配置的時候可以設(shè)置的函數(shù),只有一個函數(shù):beforeEnter差油,其參數(shù)有to,from,next.
* 組件內(nèi)的:組件內(nèi)執(zhí)行的鉤子函數(shù)拗军,類似于組件內(nèi)的生命周期,鉤子函數(shù)按執(zhí)行順序包括beforeRouteEnter蓄喇、beforeRouteUpdate发侵、beforeRouteLeave三個。
3. history模式:history模式采用html5的新特性妆偏,提供了兩個新方法刃鳄,pushState ,replaceState,可以對瀏覽器歷史記錄棧進行修改,以及popState事件的監(jiān)聽到狀態(tài)變更钱骂。
4. 路由懶加載:當打包構(gòu)建應(yīng)用時叔锐,JavaScript 包會變得非常大,影響頁面加載见秽。如果我們能把不同路由對應(yīng)的組件分割成不同的代碼塊愉烙,然后當路由被訪問的時候才加載對應(yīng)組件,這樣就更加高效了解取。
結(jié)合 Vue 的異步組件和 Webpack 的[代碼分割功能]齿梁,輕松實現(xiàn)路由組件的懶加載。
使用方法:

import('./Foo.vue') // 返回 Promise肮蛹。
const router = new VueRouter({
  routes: [
    {
      path: '/Foo',
      name: 'Home',
      component:() = import('../views/home')
        }
  ]
})
8. 路由守衛(wèi)是什么创南?(導航守衛(wèi)的鉤子函數(shù)來完成)
    • 業(yè)務(wù):
      • 監(jiān)聽整個項目的路由變化情況 全局的前置守衛(wèi)
      • 監(jiān)聽某個路由的變化情況 路由的獨享守衛(wèi)
      • 監(jiān)聽的路由組件的路由變化情況 組件內(nèi)的導航守衛(wèi)

6.2 React

1. 必考:受控組件 V.S. 非受控組件

舉個例子:
<FInput value={x} onChange={fn} /> //受控組件
<FInput defaultValue={x} />//非受控組件

2. 必考:React 有哪些生命周期函數(shù)伦忠?分別有什么用?(Ajax 請求放在哪個階段稿辙?)
  • 生命周期函數(shù):
    一昆码、初始化階段:
    getDefaultProps:獲取實例的默認屬性
    getInitialState:獲取每個實例的初始化狀態(tài)
    constructor :聲明State變量
    componentWillMount:組件即將被裝載、渲染到頁面上
    render:組件在這里生成虛擬的DOM節(jié)點
    componentDidMount:組件真正在被裝載之后
    二、運行中狀態(tài):
    componentWillReceiveProps:組件將要接收到屬性的時候調(diào)用
    shouldComponentUpdate:組件接受到新屬性或者新狀態(tài)的時候(可以返回false赋咽,接收數(shù)據(jù)后不更新旧噪,阻止
    render調(diào)用,后面的函數(shù)不會被繼續(xù)執(zhí)行了)
    componentWillUpdate:組件即將更新不能修改屬性和狀態(tài)render:組件重新描繪
    componentDidUpdate:組件已經(jīng)更新三
    銷毀階段:
    componentWillUnmount:組件即將銷毀
  • 異步請求:ajax異步請求數(shù)據(jù)應(yīng)該放在 componentDidMount函數(shù)中脓匿。
3. 必考:React 如何實現(xiàn)組件間通信淘钟?
  • 父組件向子組件通訊: 父組件可以向子組件通過傳 props 的方式,向子組件進行通訊
  • 子組件向父組件通訊: props+回調(diào)的方式,父組件向子組件傳遞props進行通訊陪毡,此props為作用域為父組件自身的函數(shù)米母,子組件調(diào)用該函數(shù),將子組件想要傳遞的信息毡琉,作為參數(shù)铁瞒,傳遞到父組件的作用域中
  • 兄弟組件通信: 找到這兩個兄弟節(jié)點共同的父節(jié)點,結(jié)合上面兩種方式由父節(jié)點轉(zhuǎn)發(fā)信息進行通信
  • 跨層級通信: Context設(shè)計目的是為了共享那些對于一個組件樹而言是“全局”的數(shù)據(jù),例如當前認證的用戶桅滋、主題或首選語言,對于跨越多層的全局數(shù)據(jù)通過Context通信再適合不過
  • 發(fā)布訂閱模式: 發(fā)布者發(fā)布事件慧耍,訂閱者監(jiān)聽事件并做出反應(yīng),我們可以通過引入event模塊進行通信
  • 全局狀態(tài)管理工具: 借助Redux或者Mobx等全局狀態(tài)管理工具進行通信,這種工具會維護一個全局狀態(tài)中心Store,并根據(jù)不同的事件產(chǎn)生新的狀態(tài)
4. 必考:shouldComponentUpdate 有什么用?

shouldComponentUpdate 這個方法用來判斷是否需要調(diào)用 render 方法重新描繪 dom丐谋。因為 dom 的描繪非常消耗性能芍碧,如果我們能在 shouldComponentUpdate 方法中能夠?qū)懗龈鼉?yōu)化的 dom diff 算法,可以極大的提高性能笋鄙。

5. 考:虛擬 DOM 是什么师枣?

react操作中render的結(jié)果并不能得到一個真正的DOM節(jié)點,而是一個輕量級的javascript對象,我們稱之為虛擬DOM萧落。
就是用來模擬DOM的一個對象践美,有一些常用屬性,并且更新 UI 主要就是通過對比(DIFF)舊的虛擬 DOM 樹 和新的虛擬 DOM 樹的區(qū)別完成的找岖,對真實的DOM進行最小化的修改陨倡。

  • 優(yōu)點:虛擬DOM具有批處理和高效的Diff算法,最終表現(xiàn)在DOM上的修改只是變更的部分,可以保證非常高效的渲染,優(yōu)化性能.
  • 缺點:首次渲染大量DOM時许布,由于多了一層虛擬DOM的計算兴革,會比innerHTML插入慢
6. 必考:什么是高階組件?

高階組件是一個以組件為參數(shù)并返回一個新組件的函數(shù)蜜唾。HOC 運行你重用代碼杂曲、邏輯和引導抽象。最常見的高階組件是 Redux 的 connect 函數(shù)袁余。比如 connect(mapState)(MyComponent) 接受組件 MyComponent擎勘,返回一個具有狀態(tài)的新 MyComponent 組件。除了簡單分享工具庫和簡單的組合颖榜,HOC 最好的方式是共享 React 組件之間的行為棚饵。如果你發(fā)現(xiàn)你在不同的地方寫了大量代碼來做同一件事時煤裙,就應(yīng)該考慮將代碼重構(gòu)為可重用的 HOC。

  • 高階組件是一個以組件為參數(shù)并返回一個新組件的函數(shù)噪漾。
  • 如果你發(fā)現(xiàn)你在不同的地方寫了大量代碼來做同一件事時硼砰,就應(yīng)該考慮將代碼重構(gòu)為可重用的 HOC。
7. React diff 的原理是什么欣硼?

對比兩顆DOM樹的區(qū)別题翰,找出其中不同的部分。React diff 作為Virtual DOM的加速器分别,其算法上的改進優(yōu)化是 React 整個界面渲染的基礎(chǔ)遍愿,以及性能提高的保障,同時也是 React 源碼中最神秘耘斩、最不可思議的部分沼填,本文將剖析 React diff 的不可思議之處。

8. 考 Redux 是什么括授?

Redux是一個庫坞笙,它是javascript狀態(tài)容器(事件分發(fā)中心),提供可以預(yù)策劃的狀態(tài)管理荚虚。核心概念的名詞:action reducer store 單向數(shù)據(jù)流薛夜。
常用的API 有:store.dispatch(action) store.getState() 等。

9. connect 的原理是什么版述?

是react-redux庫提供的API梯澜,是基于react和redux封裝的函數(shù),負責連接React和Redux渴析,把組件和store連接起來組成一個新的組件晚伙。
* 獲取state: connect通過context獲取Provider中的store,通過store.getState()獲取整個store tree 上所有state

  • 包裝原組件: 將state和action通過props的方式傳入到原組件內(nèi)部wrapWithConnect返回一個ReactComponent對象Connect俭茧,Connect重新render外部傳入的原組件WrappedComponent咆疗,并把connect中傳入的mapStateToProps, mapDispatchToProps與組件上原有的props合并后,通過屬性的方式傳給WrappedComponent
  • 監(jiān)聽store tree變化: connect緩存了store tree中state的狀態(tài),通過當前state狀態(tài)和變更前state狀態(tài)進行比較,從而確定是否調(diào)用this.setState()方法觸發(fā)Connect及其子組件的重新渲染
10. (組件的)狀態(tài)(state)和屬性(props)之間有何不同母债?
  • State 是一種數(shù)據(jù)結(jié)構(gòu)午磁,用于組件掛載時所需數(shù)據(jù)的默認值。State 可能會隨著時間的推移而發(fā)生突變毡们,但多數(shù)時候是作為用戶事件行為的結(jié)果迅皇。
  • Props(properties 的簡寫)則是組件的配置。props 由父組件傳遞給子組件衙熔,并且就子組件而言喧半,props 是不可變的(immutable)。組件不能改變自身的 props青责,但是可以把其子組件的 props 放在一起(統(tǒng)一管理)挺据。Props 也不僅僅是數(shù)據(jù)--回調(diào)函數(shù)也可以通過 props 傳遞。

7. TypeScript

1. never 類型是什么脖隶?

never是不應(yīng)該出現(xiàn)的類型扁耐,never類型可以理解為沒有返回指的函數(shù)或者總是會拋出錯誤的函數(shù)。

//舉例:
function(){while return{}}//如果函數(shù)內(nèi)含有 while(true) {}
function foo(){
      throw new Error('not implemented')
  }
//foo的返回類型是never

【注意】never僅能被賦值給另一個never
viod表示沒有任何類型产阱。never表示永遠不存在的類型婉称。

2. TypeScript 比起 JavaScript 有什么優(yōu)點?

目前主流框架都已經(jīng)使用了typescript,Vue3.0\React都已經(jīng)使用了构蹬,typescript是javascript的超集王暗,也就是說js能做到的東西typescript都能做到,javascript程序員會的東西typescript程序員都會庄敛,js程序員不會的他們也都會俗壹,所以typescript一定是以后的主流。其優(yōu)點:typescript提供了類型約束藻烤,因此可控绷雏,更容易重構(gòu),做更大的項目怖亭,更容易維護涎显。

  • bug 顯著減少,之前會遇到的 xxx 為空的問題幾乎不會出現(xiàn)了兴猩,類型相關(guān) bug 直線減少期吓。
  • 應(yīng)用更可控,當你需要約束某些代碼的時候倾芝,用類型就能很簡單地做到讨勤,比如 React 里強制寫 displayName 方便調(diào)試。
  • 查文檔更方便蛀醉,以前要打開瀏覽器看文檔悬襟,現(xiàn)在直接查看定義就基本明白了。

項目目前只支持 JS拯刁,也沒有關(guān)系脊岳,只需要加一個 ts-loader 或者 awesome-typescript-loader 就能提供 TypeScript 支持,TS 可以和 JS 共存垛玻。學完 JS 后割捅,只需要學習一下類型聲明就可以掌握 TS 了。TS 就是在 JS 上加上類型聲明帚桩,這樣我們就能知道代碼是否「大概」正確亿驾。
另外,這種方式速度非痴撕浚快莫瞬,快到你只要修改代碼儡蔓,TS 就能告訴你代碼是否「大概」正確。
從而避免很多 bug疼邀。


8. Webpack

參考鏈接【https://zhuanlan.zhihu.com/p/44438844

1. 必考:有哪些常見 loader 和 plugin喂江,你用過哪些?

三者都是前端構(gòu)建工具旁振,grunt和gulp在早期比較流行获询,現(xiàn)在webpack相對來說比較主流,webpack會自動地遞歸解析入口所需要加載的所有資源文件拐袜,然后用不同的Loader來處理不同的文件吉嚣,用Plugin來擴展webpack功能。
常見的loader—— 加載器

    * html —— pug-loader    markdown-loader
    * css —— style-loader   less-loader   scss-loader  postloader
    * js ——  babel-loader   
    * 圖片 —— url-loader  eslint-loader
  • file-loader:把文件輸出到一個文件夾中蹬铺,在代碼中通過相對 URL 去引用輸出的文件
  • url-loader:和 file-loader 類似尝哆,但是能在文件很小的情況下以 base64 的方式把文件內(nèi)容注入到代碼中去
  • source-map-loader:加載額外的 Source Map 文件,以方便斷點調(diào)試
  • image-loader:加載并且壓縮圖片文件
  • babel-loader:把 ES6 轉(zhuǎn)換成 ES5
  • css-loader:加載 CSS丛塌,支持模塊化较解、壓縮、文件導入等特性
  • style-loader:把 CSS 代碼注入到 JavaScript 中赴邻,通過 DOM 操作去加載 CSS印衔。
  • eslint-loader:通過 ESLint 檢查 JavaScript 代碼

常見的plugin—— 用Plugin來擴展webpack功能

  • html —— html-webpack-plugin
  • css —— ex tract-text-plugin
  • js ——
    • define-plugin:定義環(huán)境變量
    • commons-chunk-plugin:提取公共代碼
    • uglifyjs-webpack-plugin:通過UglifyES壓縮ES6代碼

2. loader 和 plugin的區(qū)別是什么?

  1. 不同的作用:
    a. Loader直譯為"加載器"姥敛。Webpack將一切文件視為模塊奸焙,但是webpack原生是只能解析js文件,如果想將其他文件也打包的話彤敛,就會用到loader与帆。 所以Loader的作用是讓webpack擁有了加載和解析非JavaScript文件的能力。
    b . Plugin直譯為"插件"墨榄。Plugin可以擴展webpack的功能玄糟,讓webpack具有更多的靈活性。 在 Webpack 運行的生命周期中會廣播出許多事件袄秩,Plugin 可以監(jiān)聽這些事件阵翎,在合適的時機通過 Webpack 提供的 API 改變輸出結(jié)果。
  2. 不同的用法:
    a. Loader在module.rules中配置之剧,也就是說他作為模塊的解析規(guī)則而存在郭卫。 類型為數(shù)組,每一項都是一個Object背稼,里面描述了對于什么類型的文件(test)贰军,使用什么加載(loader)和使用的參數(shù)(options)
    b. Plugin在plugins中單獨配置。 類型為數(shù)組蟹肘,每一項是一個plugin的實例词疼,參數(shù)都通過構(gòu)造函數(shù)傳入俯树。

3. 必考:如何按需加載代碼?

Vue UI組件庫的按需加載 為了快速開發(fā)前端項目贰盗,經(jīng)常會引入現(xiàn)成的UI組件庫如ElementUI聘萨、iView等,但是他們的體積和他們所提供的功能一樣童太,是很龐大的。 而通常情況下胸完,我們僅僅需要少量的幾個組件就足夠了书释,但是我們卻將龐大的組件庫打包到我們的源碼中,造成了不必要的開銷赊窥。

不過很多組件庫已經(jīng)提供了現(xiàn)成的解決方案爆惧,如Element出品的[babel-plugin-component](https://link.zhihu.com/?target=https%3A//github.com/ElementUI/babel-plugin-component)和AntDesign出品的[babel-plugin-import](https://link.zhihu.com/?target=https%3A//github.com/ant-design/babel-plugin-import) 安裝以上插件后,在.babelrc配置中或babel-loader的參數(shù)中進行設(shè)置锨能,即可實現(xiàn)組件按需加載了伤为。

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

單頁應(yīng)用的按需加載 現(xiàn)在很多前端項目都是通過單頁應(yīng)用的方式開發(fā)的丰刊,但是隨著業(yè)務(wù)的不斷擴展,會面臨一個嚴峻的問題——首次加載的代碼量會越來越多,影響用戶的體驗僚祷。

通過import(*)語句來控制加載時機,webpack內(nèi)置了對于import(*)的解析佳遣,會將import(*)中引入的模塊作為一個新的入口在生成一個chunk奸鸯。 當代碼執(zhí)行到import(*)語句時,會去加載Chunk對應(yīng)生成的文件浸剩。import()會返回一個Promise對象钾军,所以為了讓瀏覽器支持,需要事先注入Promise polyfill

4. 必考:如何提高構(gòu)建速度绢要?

  • 多入口情況下吏恭,使用CommonsChunkPlugin來提取公共代碼
  • 通過externals配置來提取常用庫
  • 利用DllPlugin和DllReferencePlugin預(yù)編譯資源模塊 通過DllPlugin來對那些我們引用但是絕對不會修改的npm包來進行
  • 預(yù)編譯,再通過DllReferencePlugin將預(yù)編譯的模塊加載進來重罪。
  • 使用Happypack 實現(xiàn)多線程加速編譯(多核CPU進行打包)
  • 使用webpack-uglify-parallel來提升uglifyPlugin的壓縮速度樱哼。 原理上webpack-uglify-parallel采用了多核并行壓縮來提升壓縮速度
  • 使用Tree-shaking和Scope Hoisting來剔除多余代碼(Tree-Shaking不要說,說了會追問)

5. 義出的文件過大怎么辦蛆封?

  • commonsChunkPlugin: 提取通用模塊(最新的webpack已經(jīng)不使用了這個插件)
  • 壓縮 js,css,圖片
  • 使用動態(tài)加載:import()

9. 網(wǎng)絡(luò)安全

1. 考:什么是 XSS唇礁?如何預(yù)防?

XSS —— Cross-Site Scripting 跨站腳本惨篱。

用戶 A 提交評論「小谷你好」到服務(wù)器盏筐,然后用戶 B 來訪問網(wǎng)站,看到了 A 的評論「小谷你好」砸讳,這里沒有 XSS琢融。

惡意用戶 H 提交評論「<script>console.log(document.cookie)</script>」界牡,然后用戶 B 來訪問網(wǎng)站,這段腳本在 B 的瀏覽器直接執(zhí)行漾抬,惡意用戶 H 的腳本就可以任意操作 B 的 cookie宿亡,而 B 對此毫無察覺。有了 cookie纳令,惡意用戶 H 就可以偽造 B 的登錄信息挽荠,隨意訪問 B 的隱私了。而 B 始終被蒙在鼓里平绩。
防范方法:

    1. 后臺模板問題
<p>
評論內(nèi)容:<?php echo $content; ?>
</p>

$content 的內(nèi)容圈匆,沒有經(jīng)過任何過濾,原樣輸出捏雌。

要解決這個原因跃赚,只需要后臺輸出的時候,將可疑的符號 < 符號變成 < (HTML實體)就行性湿。

  • 前端代碼問題
$p.html(content)
或者

$p = $('<p>'+ content +'</p>')

content 內(nèi)容又被原樣輸出了纬傲。解決辦法就是不要自己拼 HTML,盡量使用 text 方法肤频。如果一定要使用 HTML叹括,就把可疑符號變成 HTML 實體。

2. 必考:什么是 CSRF着裹?如何預(yù)防领猾?

Cross Site Request Forgery,跨站請求偽造。其原理是攻擊者構(gòu)造網(wǎng)站后臺某個功能接口的請求地址骇扇,誘導用戶去點擊或者用特殊方法讓該請求地址自動加載摔竿。用戶在登錄狀態(tài)下這個請求被服務(wù)端接收后會被誤以為是用戶合法的操作。對于 GET 形式的接口地址可輕易被攻擊少孝,對于 POST 形式的接口地址也不是百分百安全继低,攻擊者可誘導用戶進入帶 Form 表單可用POST方式提交參數(shù)的頁面。


10. 開放題目

1. 必考:你遇到最難的問題是怎樣的稍走?

2. 你在團隊的突出貢獻是什么袁翁?

3. 最近在關(guān)注什么新技術(shù)

阮一峰的課本,(微博)婿脸。

4. 有沒有看什么源碼粱胜,看了后有什么記憶深刻的地方,有什么收獲

看一些源代碼狐树,命名規(guī)范的重要性焙压,從而提高代碼的可讀性。
設(shè)計模式,輪播思路涯曲。


11. 個性化題目

1. PWA

2. echarts.js / d3.js

3. three.js

4. flutter

5. SSR


12. 算法 + 數(shù)據(jù)庫


13. git 版本控制:

1. github創(chuàng)建倉庫:

 命令行:
git init
git commit -m "first commit"
git add --all
創(chuàng)建遠程倉庫(復制即可)
git push -u origin master

2. 查看版本:

git log (--prety=online //輸出信息太多時可以用) //顯示最近到最遠的提交日志
git checkout -b <new-branch-name>  //如果版本次數(shù)太多可以寫成  HEAD~100
//和上一步git checkout 一樣功能的命令行有 :
gitk  //功能和git checkout -b <new-branch-name>一樣野哭,一圖形化工具顯示顯示已提交版本
  • 注意:
    git log 很很多選項:
選項         說明
-p            按補丁格式顯示每個更新之間的差異
--word-diff       按 word diff 格式顯示差異
--stat          顯示每次更新的文件修改統(tǒng)計信息
--shortstat       只顯示 --stat 中最后的行數(shù)修改添加移除統(tǒng)計
--name-only       僅在提交信息后顯示已修改的文件清單
--name-status     顯示新增、修改幻件、刪除的文件清單
--abbrev-commit   僅顯示 SHA-1 的前幾個字符拨黔,而非所有的 40 個字符
--relative-date   使用較短的相對時間顯示(比如,“2 weeks ago”)
--graph        顯示 ASCII 圖形表示的分支合并歷史
--pretty        使用其他格式顯示歷史提交信息可用的選項包括oneline绰沥,short篱蝇,full,fuller 和format(后跟指定格式)
--oneline        `--pretty=oneline --abbrev-commit` 的簡化用法

3. 切換版本:

git reset --HEAD^ //返回第一個版本
git reflog 命令行提供了查詢commit id 的功能徽曲,查詢到的id 寫在git reset后面就會返回指定版本态兴。


14. 垃圾回收機質(zhì):

javascript有自動垃圾收集機制(GC:Garbage Collection),也就是說執(zhí)行環(huán)境會負責管理代碼執(zhí)行過程中使用的內(nèi)存,開發(fā)人員不用再過于擔心內(nèi)存使用的問題疟位,所需內(nèi)存的分配與無用內(nèi)存的回收完全實現(xiàn)了自動管理。
JS的垃圾回收機制是為了以防內(nèi)存泄漏喘垂,內(nèi)存泄漏的含義就是當已經(jīng)不需要某塊內(nèi)存時這塊內(nèi)存還存在著甜刻,垃圾回收機制就是間歇的不定期的尋找到不再使用的變量,并釋放掉它們所指向的內(nèi)存正勒。

  • 垃圾回收方式:
    1. 標記清除:大部分瀏覽器以此方式進行垃圾回收得院,當變量進入執(zhí)行環(huán)境(函數(shù)中聲明變量)的時候,垃圾回收器將其標記為“進入環(huán)境”章贞,當變量離開環(huán)境的時候(函數(shù)執(zhí)行結(jié)束)將其標記為“離開環(huán)境”祥绞,在離開環(huán)境之后還有的變量則是需要被刪除的變量。標記方式不定鸭限,可以是某個特殊位的反轉(zhuǎn)或維護一個列表等蜕径。
      垃圾收集器給內(nèi)存中的所有變量都加上標記,然后去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記败京。在此之后再被加上的標記的變量即為需要回收的變量兜喻,因為環(huán)境中的變量已經(jīng)無法訪問到這些變量。
    2. 引用計數(shù):這種方式常常會引起內(nèi)存泄漏赡麦,低版本的IE使用這種方式朴皆。機制就是跟蹤一個值的引用次數(shù),當聲明一個變量并將一個引用類型賦值給該變量時該值引用次數(shù)加1泛粹,當這個變量指向其他一個時該值的引用次數(shù)便減一遂铡。當該值引用次數(shù)為0時就會被回收。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晶姊,一起剝皮案震驚了整個濱河市扒接,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖珠增,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件超歌,死亡現(xiàn)場離奇詭異,居然都是意外死亡蒂教,警方通過查閱死者的電腦和手機巍举,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凝垛,“玉大人懊悯,你說我怎么就攤上這事∶纹ぃ” “怎么了炭分?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長剑肯。 經(jīng)常有香客問我捧毛,道長,這世上最難降的妖魔是什么让网? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任呀忧,我火速辦了婚禮,結(jié)果婚禮上溃睹,老公的妹妹穿的比我還像新娘而账。我一直安慰自己,他們只是感情好因篇,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布泞辐。 她就那樣靜靜地躺著,像睡著了一般竞滓。 火紅的嫁衣襯著肌膚如雪咐吼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天商佑,我揣著相機與錄音汽烦,去河邊找鬼。 笑死莉御,一個胖子當著我的面吹牛撇吞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播礁叔,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼牍颈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琅关?” 一聲冷哼從身側(cè)響起煮岁,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤讥蔽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后画机,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冶伞,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年步氏,在試婚紗的時候發(fā)現(xiàn)自己被綠了响禽。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡荚醒,死狀恐怖芋类,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情界阁,我是刑警寧澤侯繁,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站泡躯,受9級特大地震影響贮竟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜较剃,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一坝锰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧重付,春花似錦、人聲如沸凫乖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帽芽。三九已至删掀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間导街,已是汗流浹背披泪。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留搬瑰,地道東北人款票。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像泽论,于是被迫代替她去往敵國和親艾少。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容