前端面試總結(jié)

一、CSS相關(guān)問題

1骚露、 行內(nèi)元素,塊級(jí)元素,空元素

  • 行內(nèi)元素有:a b span select strong(強(qiáng)調(diào)的語氣)
  • 塊級(jí)元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
  • 行內(nèi)塊元素:img, input, textarea
  • 常見的空元素:
    <br> <hr> <img> <input> <link> <meta>
    鮮為人知的是:
    <area> <base> <col> <command> <embed> <keygen> <param> <source> <track> <wbr>

2、選擇器優(yōu)先級(jí)

important(1,0,0,0) > 內(nèi)聯(lián) > id(0,1,0,0) > class(0,0,1,0) = 屬性 = 偽類( 0,0,1,0) >標(biāo)簽(0,0,0,1) = 偽元素(0,0,0,1) > 通配符(* 0,0,0,0)

3、水平垂直居中

  • 定位 + transform
//父元素設(shè)置position: relative;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
  • 行內(nèi)塊元素 + 標(biāo)尺

1.給它的父元素寫text-align屬性愕鼓;
2.要居中的元素將其類型轉(zhuǎn)為inline-block蚓挤;
3.要居中的元素加vertical-align屬性;
4.添加一個(gè)“標(biāo)尺”馅袁,既同級(jí)元素(span等)抵窒,要居中的元素與其互相垂直居中
注意在編輯時(shí)標(biāo)尺與需要居中的元素之間不能有空格回車;
標(biāo)尺須加:

  display:inline-block朦拖;
  //目的是隱藏標(biāo)尺
  width:0富寿;
  //與父元素等高,中線位置既是居中位置
  height:100%;
  vertical-align:middle;
<style>
  *{
      margin: 0;
      padding: 0;
  }
  .div1{
      width: 200px;
      height: 150px;
      background: blue;
      margin: 20px 20px;
      text-align: center;
  }
  .div1-1{
      width: 100px;
      height: 100px;
      background: red;
      display: inline-block;
      vertical-align: middle;
  }
  .div1 span{
      display: inline-block;
      width: 0px;
      height: 100%;
      background: #0681D0;
      vertical-align: middle; 
  }
</style>
<div class="div1">div1
    <div class="div1-1">div2</div><span></span>
</div>

4链患、動(dòng)畫問題

5贸毕、寫個(gè)左右布局,左邊固定寬度,右邊自適應(yīng)

  • 左浮動(dòng) + 右不設(shè)寬(使用float需要注意清除浮動(dòng)造成父元素塌陷的問題)
  • 左定位 + 右不設(shè)寬
  • flex布局

6、寫六點(diǎn)篩子布局

image.png
  • flex布局
<style>
h2{
    text-align: center;
}

.main{
    display: flex;
    flex-wrap: wrap;
    width: 680px;
    justify-content: space-between;
}

.container{
    display: flex;
    width: 320px;
    height: 320px;
    flex-wrap: wrap;
    justify-content: space-between;
    align-content:space-between;
}

.box{
    width: 90px;
    height: 90px;
    background-color: #EEEEEE;
    padding: 5px;
    border-radius: 5px;
    display: flex;
    flex-wrap: wrap;            
}

.row{
    display: flex;
    flex-basis: 100%;
}

.item{
    width: 24px;
    height: 24px;
    background-color: #000000;
    margin: 3px;
    border-radius: 50%;
}
    

/*排列方向*/
.flex-direction-column{
     flex-direction: column;
}

/*水平排列*/
.justify-content-center{
    justify-content: center;
}

.justify-content-flex-end{
    justify-content: flex-end;
}

.justify-content-space-between{
    justify-content: space-between;
}
    
/*垂直排列*/
 .align-items-center{
     align-items: center;
 }

 .align-items-flex-end{
     align-items: flex-end;
 }

 .align-items-space-between{
     align-items: space-between;
 }

/*多軸對(duì)齊*/
 .align-content-space-between{
    align-content: space-between;
 }

 /*項(xiàng)目排列*/
 .align-self-center{
    align-self: center;
 }

 .align-self-flex-end{
    align-self: flex-end;
 }
</style>
<div class="container">
    <div class="box justify-content-center align-items-center">
        <span class="item"></span>
    </div>
    
    <div class="box justify-content-space-between">
        <span class="item"></span>
        <span class="item align-self-flex-end"></span>
    </div>
    
    <div class="box">
            <span class="item"></span>
            <span class="item align-self-center"></span>
            <span class="item align-self-flex-end"></span>
    </div>
    
    <div class="box align-content-space-between">
        <div class="row justify-content-space-between">
            <span class="item"></span>
            <span class="item"></span>
        </div>
        
        <div class="row justify-content-space-between">
            <span class="item"></span>
            <span class="item"></span>
        </div>
    </div>

    <div class="box">
        <div class="row justify-content-space-between">
            <span class="item"></span>
            <span class="item"></span>
        </div>
        
        <div class="row justify-content-center">
            <span class="item"></span>
        </div>

        <div class="row justify-content-space-between">
            <span class="item"></span>
            <span class="item"></span>
        </div>
    </div>

    <div class="box align-content-space-between flex-direction-column">
        <span class="item"></span>
        <span class="item"></span>
        <span class="item"></span>
        <span class="item"></span>
        <span class="item"></span>
        <span class="item"></span>
    </div>
</div>


二、JS

1议谷、js基本類型逼裆,如何判別類型

數(shù)據(jù)類型分為基本類型和引用類型:

  • 基本類型:String恢着、Number、Boolean盏求、Null荆烈、Undefined玫鸟、symbol(ES6)

  • 引用類型:Object、Array、Date、Function、Error掰烟、RegExp先馆、Math、Number宪拥、String仿野、Boolean、Globle她君。

  • js內(nèi)置類型有七種:String脚作、Number灭翔、Boolean、Null、Undefined售葡、Symbol(ES6)、Object

判斷數(shù)據(jù)類型的幾種方式優(yōu)缺點(diǎn)對(duì)比
不同類型的優(yōu)缺點(diǎn) typeof instanceof constructor object.prototype.toString.call()
優(yōu)點(diǎn) 使用簡(jiǎn)單 能檢測(cè)出引用類型 基本能檢測(cè)出所有類型(null和Undefined除外) 所有類型
缺點(diǎn) 基本類型(null不行) 基本類型不行昌跌,且不能跨iframe constructor易修改包竹,且不能跨iframe IE6以下null和Undefined為Object

2、js數(shù)組的方法都看下

image.png

注意: 可參考https://www.cnblogs.com/sqh17/p/8529401.html

數(shù)組方法 作用 返回值 備注
arr.push() 從后面添加元素 添加完后的數(shù)組的長(zhǎng)度
arr.pop() 從后面刪除元素 刪除的元素 只能刪除一個(gè)
arr.shift() 從前面刪除元素 刪除的元素 只能刪除一個(gè)
arr.unshift() 從前面添加元素 添加完后的數(shù)組的長(zhǎng)度
arr.splice(i,n) 刪除從i(索引值)開始之后的那個(gè)元素 刪除的元素
arr.concat(i,n) 連接兩個(gè)數(shù)組 連接后的新數(shù)組
arr.split() 將字符串轉(zhuǎn)化為數(shù)組 數(shù)組
arr.sort() 將數(shù)組進(jìn)行排序 排好的數(shù)組 默認(rèn)是按照最左邊的數(shù)字進(jìn)行排序(1,10,2)
arr.reverse() 將數(shù)組反轉(zhuǎn) 反轉(zhuǎn)后的數(shù)組
arr.slice(start,end) 切去索引值start到索引值end的數(shù)組孤个,不包含end索引的值 切出來的數(shù)組
arr.forEach(callback) 遍歷數(shù)組,無return 會(huì)影響原來的數(shù)組
arr.map(callback) 映射數(shù)組(遍歷數(shù)組) 返回一個(gè)新數(shù)組 數(shù)組長(zhǎng)度與原數(shù)組相同(不滿足同條件的為空)
arr.filter(callback) 過濾數(shù)組 返回一個(gè)新數(shù)組 實(shí)際滿足條件的數(shù)組
arr.every(callback) 依據(jù)判斷條件煌寇,數(shù)組的元素是否全滿足 ture/false 全滿足返回true
arr.some() 依據(jù)判斷條件,數(shù)組的元素是否全滿足 ture/false 若有一個(gè)滿足則返回ture
arr.find(callback) 找到第一個(gè)符合條件的數(shù)組成員
arr.reduce(callback, initialValue) 迭代數(shù)組的所有項(xiàng)奈惑,累加器姆坚,數(shù)組中的每個(gè)值(從左到右)合并没宾,最終計(jì)算為一個(gè)值 返回一個(gè)值
arr.indexOf() 查找某個(gè)元素的索引值 若有重復(fù)的奸鬓,則返回第一個(gè)查到的索引值若不存在梳毙,則返回 -1 從前向后查找
arr.lastIndexOf() 查找某個(gè)元素的索引值 若有重復(fù)的,則返回第一個(gè)查到的索引值若不存在,則返回 -1 從后往前查找
Array.from() 將偽數(shù)組變成數(shù)組 數(shù)組 就是只要有l(wèi)ength的就可以轉(zhuǎn)成數(shù)組(ES6)
Array.of() 將一組值轉(zhuǎn)換成數(shù)組巨缘,類似于聲明數(shù)組
arr.copyWithin() 在當(dāng)前數(shù)組內(nèi)部端三,將制定位置的數(shù)組復(fù)制到其他位置 返回當(dāng)前數(shù)組 會(huì)覆蓋原數(shù)組項(xiàng)
arr.findIndex(callback) 找到第一個(gè)符合條件的數(shù)組成員的索引值
arr.fill(target, start, end) 使用給定的值,填充一個(gè)數(shù)組 填充完后會(huì)改變?cè)瓟?shù)組
arr.includes() 判斷數(shù)中是否包含給定的值 返回的是布爾值
arr.keys() 遍歷數(shù)組的鍵名
arr.values() 遍歷數(shù)組鍵值
arr.entries() 遍歷數(shù)組的鍵名和鍵值
    let a = [1,2,3,4];
    let b = [1,2,3,4];
    let c = [1,2,3,4];
    let d = [1,2,3,4];
    let e = [1,2,3,4];
    let newA = [];

    a.forEach(item => {
        if (item > 2){
            newA.push(item)
        }
    })
    console.log(newA, a);

    let newB = b.map(item => {
        if (item > 2){
            return item
        }
    })
    console.log(newB, b);

    let newC = c.filter(item => {
        if (item > 2){
            return item
        }
    })
    console.log(newC, c)

    let D= d.every(item => {
        return item > 2
    })
    console.log(D, d)

    let E = e.some(item => {
        return item > 2
    })
    console.log(E, e)
image.png

3、原型鏈 new的作用

3.1械蹋、原型鏈

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象斥滤,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針巷嚣,而實(shí)例都包含一個(gè)指向原型對(duì)象的內(nèi)部指針。那么假如我們讓原型對(duì)象等于另一個(gè)類型的實(shí)例钳吟,結(jié)果會(huì)怎樣廷粒?顯然,此時(shí)的原型對(duì)象將包含一個(gè)指向另一個(gè)原型的指針砸抛,相應(yīng)地评雌,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針。假如另一個(gè)原型又是另一個(gè)類型的實(shí)例直焙,那么上述關(guān)系依然成立景东。如此層層遞進(jìn),就構(gòu)成了實(shí)例與原型的鏈條奔誓。這就是所謂的原型鏈的基本概念斤吐。——摘自《javascript高級(jí)程序設(shè)計(jì)》

image.png
3.2厨喂、new的作用

1.創(chuàng)建一個(gè)空對(duì)象 p
2.把這個(gè)空對(duì)象 p 的屬性 __proto__ 指向函數(shù) Person 的 prototype
3.將構(gòu)造函數(shù) Person 的作用域賦給新對(duì)象 p和措,即 this 指向了 p
4.執(zhí)行Person 中的代碼,為p添加屬性 name
5.返回新對(duì)象蜕煌。

4派阱、js有哪些作用域 閉包問題 寫防抖函數(shù)

4.1 作用域

1、定義:作用域是在運(yùn)行時(shí)代碼中的某些特定部分中變量斜纪,函數(shù)和對(duì)象的可訪問性贫母。換句話說,能夠訪問另一個(gè)函數(shù)作用域的變量的函數(shù)
2盒刚、全局作用域腺劣、函數(shù)作用域、塊級(jí)作用域(ES6)

4.2 閉包
4.2.1因块、定義

當(dāng)內(nèi)部函數(shù)被保存到外部時(shí)橘原,會(huì)形成閉包;閉包會(huì)導(dǎo)致原始作用域鏈不釋放涡上,造成內(nèi)存泄漏(占用)趾断;

function a() {
    var i = '初始值';
    i = i + "—_執(zhí)行a"
    // 此處的函數(shù)b訪問了父級(jí)函數(shù)a中的局部變量i,成為了一個(gè)閉包
    function b() {
        i = i + "_執(zhí)行b"
        console.log(i)
    }
    return b;
}
var c = a(); // 此時(shí) i 的值為 :初始值—_執(zhí)行a
c()          // 此時(shí) i 的值為 :初始值—_執(zhí)行a_執(zhí)行b
c()          // 此時(shí) i 的值為 :初始值—_執(zhí)行a_執(zhí)行b_執(zhí)行b

以上方代碼為例:

  • 將函數(shù)a賦值給全局變量c時(shí),a會(huì)執(zhí)行一次吩愧,局部變量 i 的值變?yōu)?code>初始值—_執(zhí)行a芋酌,最終返回函數(shù)b,此時(shí)全局變量c的值為閉包函數(shù)b的引用耻警。
    此時(shí)函數(shù)a雖然已執(zhí)行完,但因?yàn)閮?nèi)部包含閉包函數(shù)b,所以函數(shù) a 的執(zhí)行期上下文會(huì)繼續(xù)保留在內(nèi)存中甘穿,不會(huì)被銷毀腮恩,所以局部變量 i 仍是初始值—_執(zhí)行a

執(zhí)行期上下文:當(dāng)函數(shù)執(zhí)行時(shí),會(huì)創(chuàng)建一個(gè)執(zhí)行期上下文的內(nèi)部對(duì)象温兼。每調(diào)用一次函數(shù)秸滴,就會(huì)創(chuàng)建一個(gè)新的上下文對(duì)象,他們之間是相互獨(dú)立的募判。當(dāng)函數(shù)執(zhí)行完畢荡含,它所產(chǎn)生的執(zhí)行期上下文會(huì)被銷毀

  • 1、第一次執(zhí)行 c() 時(shí)届垫,閉包函數(shù)b第一次執(zhí)行释液,局部變量 i 的值變?yōu)?code>初始值—_執(zhí)行a_執(zhí)行b
  • 2、第二次執(zhí)行 c() 時(shí)装处,閉包函數(shù)b第二次執(zhí)行误债,局部變量 i 的值變?yōu)?code>初始值—_執(zhí)行a_執(zhí)行b_執(zhí)行b
4.2.2、閉包的特點(diǎn)
  • 1.被閉包函數(shù)訪問的父級(jí)及以上的函數(shù)的局部變量(如范例中的局部變量 i )會(huì)一直存在于內(nèi)存中妄迁,不會(huì)被JS的垃圾回收機(jī)制回收寝蹈。
  • 2.閉包函數(shù)實(shí)現(xiàn)了對(duì)其他函數(shù)內(nèi)部變量的訪問。(函數(shù)內(nèi)部的變量對(duì)外是無法訪問的登淘,閉包通過這種變通的方法箫老,實(shí)現(xiàn)了訪問。)
4.2.3黔州、Javascript的垃圾回收機(jī)制
  • 如果一個(gè)對(duì)象不再被引用耍鬓,那么這個(gè)對(duì)象就會(huì)被GC回收。
  • 如果兩個(gè)對(duì)象互相引用辩撑,而不再被第三者所引用界斜,那么這兩個(gè)對(duì)象都會(huì)被回收。
    eg:
function person(name) {
    function say(content) {
        console.log(name + ':' + content)
    }
    return say
}

a = person("張三")
b = person("李四")
a("在干啥合冀?")
b("沒干啥各薇。")
a("出去玩嗎?")
b("去哪熬伞峭判?")
4.2.4、優(yōu)缺點(diǎn)
  • 優(yōu)點(diǎn):
    可以減少全局變量的定義棕叫,避免全局變量的污染
    能夠讀取函數(shù)內(nèi)部的變量
    在內(nèi)存中維護(hù)一個(gè)變量林螃,可以用做緩存

  • 缺點(diǎn):
    1)造成內(nèi)存泄露
    閉包會(huì)使函數(shù)中的變量一直保存在內(nèi)存中,內(nèi)存消耗很大俺泣,所以不能濫用閉包疗认,否則會(huì)造成網(wǎng)頁的性能問題完残,在IE中可能導(dǎo)致內(nèi)存泄露。(解決方法——使用完變量后横漏,手動(dòng)將它賦值為null谨设;)
    2)閉包可能在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值缎浇。
    3)造成性能損失
    由于閉包涉及跨作用域的訪問扎拣,所以會(huì)導(dǎo)致性能損失。
    (解決方法——通過把跨作用域變量存儲(chǔ)在局部變量中素跺,然后直接訪問局部變量二蓝,來減輕對(duì)執(zhí)行速度的影響)

4.3、函數(shù)防抖(debounce)

當(dāng)持續(xù)觸發(fā)事件時(shí)指厌,一定時(shí)間段內(nèi)沒有再觸發(fā)事件刊愚,事件處理函數(shù)才會(huì)執(zhí)行一次,如果設(shè)定的時(shí)間到來之前仑乌,又一次觸發(fā)了事件百拓,就重新開始延時(shí)。

實(shí)際場(chǎng)景:
連續(xù)的事件晰甚,只需觸發(fā)一次的回調(diào)場(chǎng)景有:
1衙传、搜索框搜索輸入。
2厕九、只需要用戶最后一次輸入完再發(fā)送請(qǐng)求 手機(jī)號(hào)蓖捶、郵箱格式的輸入驗(yàn)證檢測(cè)
3、窗口大小的resize 扁远。只需窗口調(diào)整完成后俊鱼,計(jì)算窗口的大小,防止重復(fù)渲染

function debounce(fn, wait) {    
    var timeout = null;    
    return function() {        
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}
// 處理函數(shù)
function handle() {    
    console.log(Math.random()); 
}
// 滾動(dòng)事件
window.addEventListener('scroll', debounce(handle, 1000));
//當(dāng)持續(xù)觸發(fā)scroll事件時(shí)畅买,事件處理函數(shù)handle只在停止?jié)L動(dòng)1000毫秒之后才會(huì)調(diào)用一次并闲,也就是說在持續(xù)觸發(fā)scroll事件的過程中,事件處理函數(shù)handle一直沒有執(zhí)行谷羞。
4.4帝火、 函數(shù)節(jié)流(throttle)

當(dāng)持續(xù)觸發(fā)事件時(shí),保證一定時(shí)間段內(nèi)只調(diào)用一次事件處理函數(shù)湃缎。

間隔一段時(shí)間執(zhí)行一次回調(diào)的場(chǎng)景有:
1犀填、滾動(dòng)加載,加載更多或滾動(dòng)到底部監(jiān)聽嗓违;
2九巡、谷歌搜索框,搜索聯(lián)想功能蹂季;
3冕广、高頻點(diǎn)擊提交疏日,表單重復(fù)提交
4、省市信息對(duì)應(yīng)字母快速選擇

//節(jié)流 時(shí)間戳的方式實(shí)現(xiàn)
var throttle = function(func, delay) {            
  var prev = Date.now();            
  return function() {                
    var context = this;                
    var args = arguments;                
    var now = Date.now();                
    if (now - prev >= delay) {                    
      func.apply(context, args);                    
      prev = Date.now();                
    }            
  }        
}        
function handle() {            
  console.log(Math.random());        
}        
window.addEventListener('scroll', throttle(handle, 1000));


// 節(jié)流throttle代碼(定時(shí)器):
var throttle = function(func, delay) {            
    var timer = null;            
    return function() {                
        var context = this;               
        var args = arguments;                
        if (!timer) {                    
            timer = setTimeout(function() {                        
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}        
function handle() {            
    console.log(Math.random());        
}        
window.addEventListener('scroll', throttle(handle, 1000));

5撒汉、promise的使用 原理 所擁有的方法

1制恍、Promise 的含義
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大神凑。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn)何吝,統(tǒng)一了用法溉委,原生提供了Promise對(duì)象。

2爱榕、基本用法
ES6 規(guī)定瓣喊,Promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來生成Promise實(shí)例黔酥。
Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù)藻三,該函數(shù)的兩個(gè)參數(shù)分別是resolve(成功)和reject(失敗)跪者。它們是兩個(gè)函數(shù)棵帽,將異步操作的結(jié)果,作為參數(shù)傳遞出去

3渣玲、所擁有的方法
Promise.prototype.catch() catch方法是.then(null, rejection)的別名逗概,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)
Promise.prototype.finally() finally方法用于指定不管 Promise 對(duì)象最后狀態(tài)如何,都會(huì)執(zhí)行的操作
Promise.all() all方法用于將多個(gè) Promise 實(shí)例忘衍,包裝成一個(gè)新的 Promise 實(shí)例(所有的都成功了才執(zhí)行)
Promise.race()race方法同樣是將多個(gè) Promise 實(shí)例逾苫,包裝成一個(gè)新的 Promise 實(shí)例
Promise.resolve()將現(xiàn)有對(duì)象轉(zhuǎn)為 Promise 對(duì)象,Promise.resolve方法就起到這個(gè)作用
Promise.reject()將現(xiàn)有對(duì)象轉(zhuǎn)為 Promise 對(duì)象枚钓,Promise.reject方法就起到這個(gè)作用(參數(shù)作為reject的理由)
Promise.try()為所有操作提供了統(tǒng)一的處理機(jī)制,可以更好地管理異常
詳情見http://www.reibang.com/p/d8a901dd72ac

6铅搓、es6有哪些特性 箭頭函數(shù)和普通函數(shù)區(qū)別

1、箭頭函數(shù)
1.1 更簡(jiǎn)潔的語法
1.2 沒有this
1.3 不能使用new 構(gòu)造函數(shù)
1.4 不綁定arguments搀捷,用rest參數(shù)...解決
1.5 使用call()和apply()調(diào)用
1.6 捕獲其所在上下文的 this 值星掰,作為自己的 this 值
1.7 箭頭函數(shù)沒有原型屬性
1.8 不能簡(jiǎn)單返回對(duì)象字面量
1.9 箭頭函數(shù)不能當(dāng)做Generator函數(shù),不能使用yield關(guān)鍵字
1.10 箭頭函數(shù)不能換行

//1、沒有形參的時(shí)候
let fun = () => console.log('我是箭頭函數(shù)'); 
fun();
//2指煎、只有一個(gè)形參的時(shí)候()可以省略
let fun2 = a => console.log(a); 
fun2('aaa');

//3蹋偏、倆個(gè)及倆個(gè)以上的形參的時(shí)候
let fun3 = (x,y) =>console.log(x,y);  //函數(shù)體只包含一個(gè)表達(dá)式則省略return 默認(rèn)返回
fun3(24,44);

//4、倆個(gè)形參以及函數(shù)體多條語句表達(dá)式
let fun4 = (x,y) => {
  console.log(x,y);
  return x+y; //必須加return才有返回值
}
//5至壤、如果要返回對(duì)象時(shí)需要用小括號(hào)包起來威始,因?yàn)榇罄ㄌ?hào)被占用解釋為代碼塊了惋啃,正確寫法
let fun5 = ()=>({ foo: x })   //如果x => { foo: x }  //則語法出錯(cuò)

7剩燥、函數(shù)柯里化 純函數(shù)

自己百度吧较鼓, 看不懂鲤看。
http://www.reibang.com/p/2975c25e4d71

8、數(shù)據(jù)不可變 immutable原理

自己百度吧脓斩, 看不懂木西。
https://segmentfault.com/a/1190000016404944

9、js bind函數(shù)的性能問題(https://blog.csdn.net/ywl570717586/article/details/74231402)

10随静、js怎么定義一個(gè)不可改值的對(duì)象

Javascipt的數(shù)據(jù)屬性有一個(gè)名為Writable的特征, 可以用于設(shè)置屬性值是否可以被修改(Object.defineProperty方法接收三個(gè)參數(shù):需要添加或修改屬性的對(duì)象八千,屬性名稱,屬性描述options(writable:false))

11燎猛、const 定義常量可以改變嗎

const所說的常量恋捆,是指,對(duì)應(yīng)的指針或者說地址是常量
const定義的基本數(shù)據(jù)類型的變量不可以修改,但其它復(fù)雜數(shù)據(jù)類型是可以修改的
用const定義的數(shù)組重绷,里面的元素是可變的

如何定義不可改變的數(shù)組:
Object.preventExtendsion(obj) 用來禁止對(duì)象可擴(kuò)展其它屬性(阻止對(duì)象新增屬性沸停,但可改變)
Object.seal(obj)用來禁止對(duì)象刪除其它屬性和擴(kuò)展其它屬性(阻止對(duì)象刪除屬性,但可改變)
Object.freeze(obj)用來凍結(jié)對(duì)象昭卓,就是所有的屬性不能夠更改和新增(阻止對(duì)象更改和新增屬性)

詳情見:https://blog.csdn.net/weixin_33697898/article/details/91371632

12愤钾、深拷貝/淺拷貝

  • 1、基本類型--名值存儲(chǔ)在棧內(nèi)存中候醒,例如let a=1;
  • 2能颁、引用數(shù)據(jù)類型--名存在棧內(nèi)存中,值存在于堆內(nèi)存中倒淫,但是棧內(nèi)存會(huì)提供一個(gè)引用的地址指向堆內(nèi)存中的值

三劲装、瀏覽器

1、cookie安全

指某些網(wǎng)站為了辨別用戶身份昌简、進(jìn)行session跟蹤而存儲(chǔ)在用戶本地終端上的數(shù)據(jù)(通常經(jīng)過加密)

生命周期:
創(chuàng)建cookie的時(shí)候占业,會(huì)給cookie指定一個(gè)值:Expire,它就是指定cookie的有效期纯赎,也就是cookie的生命周期谦疾,超出設(shè)置的這個(gè)生命周期,cookie就會(huì)被清除犬金。如果給這個(gè)值Expire設(shè)置為0或者負(fù)值念恍,那么這樣的設(shè)置就是在關(guān)閉瀏覽器時(shí),就會(huì)清除cookie晚顷,這種方式更加安全峰伙。

如何解決cookie安全性問題
第一步:設(shè)置cookie有效期不要過長(zhǎng),合適即可
第二步:設(shè)置HttpOnly屬性為true(可以防止js腳本讀取cookie信息该默,有效的防止XSS攻擊)瞳氓。
第三步:設(shè)置復(fù)雜的cookie,加密cookie(盡可能使得加密后的cookie更難解密栓袖,也是保護(hù)了cookie中的信息)
(1)cookie的key使用uuid匣摘,隨機(jī)生成店诗;
(2)cookie的value可以使用復(fù)雜組合,比如:用戶名+當(dāng)前時(shí)間+cookie有效時(shí)間+隨機(jī)數(shù)音榜。
第四步:用戶第一次登錄時(shí)庞瘸,保存ip+cookie加密后的token(每次請(qǐng)求,都去將當(dāng)前cookie和ip組合起來加密后的token與保存的token作對(duì)比赠叼,只有完全對(duì)應(yīng)才能驗(yàn)證成功)
第五步:session和cookie同時(shí)使用(sessionId雖然放在cookie中擦囊,但是相對(duì)的session更安全,可以將相對(duì)重要的信息存入session)
第六步:如果網(wǎng)站支持https嘴办,盡可能使用https(為cookie設(shè)置Secure屬性為true霜第,它的意思是,cookie只能使用https協(xié)議發(fā)送給服務(wù)器户辞,而https比http更加安全)

2、宏任務(wù) 微任務(wù)

setTimeout(() => {
  //宏任務(wù)癞谒,放到Event Queue(宏任務(wù)隊(duì)列)中
  console.log('1')
});

new  Promise((resolve) => {
  //主線程底燎,直接執(zhí)行
  console.log('2');
  resolve();
}).then(() => {
  //微任務(wù) 放到Event Queue(微任務(wù)隊(duì)列)中
  console.log('3')
});
//主線程,直接執(zhí)行
 console.log('4');

執(zhí)行結(jié)果: 2弹砚,4双仍,3,1
解釋如下:
先看執(zhí)行的代碼是同步任務(wù)還是異步任務(wù)桌吃,同步的主線程直接執(zhí)行朱沃,異步任務(wù)放到任務(wù)隊(duì)列中。

image.png

任務(wù)隊(duì)列中茅诱,先執(zhí)行一個(gè)宏任務(wù)逗物,若有微任務(wù),執(zhí)行所有的微任務(wù)之后瑟俭,再做新的宏任務(wù)翎卓。

image.png

image.png

https://www.cnblogs.com/wangziye/p/9566454.html

3、頁面加載過程

  • 1摆寄、輸入的網(wǎng)址在通過DNS解析后得到服務(wù)器地址瀏覽器向服務(wù)器發(fā)起http請(qǐng)求失暴,經(jīng)過TCP/IP三次握手確認(rèn)鏈接后,服務(wù)器將需要的代碼發(fā)回給瀏覽器微饥。
  • 2逗扒、瀏覽器接收到代碼后進(jìn)行解析,經(jīng)過三大步驟:DOM構(gòu)造欠橘、布局以及繪制頁面
  • 2.1矩肩、DOM構(gòu)造
    瀏覽器首先將收到的html代碼,通過html解析器解析構(gòu)建為一顆DOM樹肃续。數(shù)據(jù)結(jié)構(gòu)中有許多的樹蛮拔,而DOM樹就像是一顆倒長(zhǎng)著的大樹述暂,這樣的對(duì)象模型決定了節(jié)點(diǎn)之間都有一定的關(guān)聯(lián)它們關(guān)系可能有父子、有兄弟建炫,我們可以順著這顆樹做出許多操作畦韭。
    接著將接收到的css代碼,通過css解析器構(gòu)建出樣式表規(guī)則將這些規(guī)則分別放到對(duì)應(yīng)的DOM樹節(jié)點(diǎn)上肛跌,得到一顆帶有樣式屬性的DOM樹艺配。
  • 2.2、布局
    瀏覽器按從上到下衍慎,從左到右的順序转唉,讀取DOM樹的文檔節(jié)點(diǎn),順序存放到一條虛擬的傳送帶上稳捆。傳送帶上的盒子就是節(jié)點(diǎn)赠法,而這條流動(dòng)的傳送帶就是文檔流。如果我們讀取到的節(jié)點(diǎn)是屬于另一個(gè)節(jié)點(diǎn)下的子節(jié)點(diǎn)乔夯,那么在放入傳送帶的時(shí)候砖织,就應(yīng)該按順序放到該節(jié)點(diǎn)盒子的內(nèi)部。如果子節(jié)點(diǎn)下還有子節(jié)點(diǎn)末荐,在傳送帶上的時(shí)候就繼續(xù)套到子一級(jí)的盒子內(nèi)部侧纯。根據(jù)它在DOM樹上的結(jié)構(gòu),可以嵌套的層級(jí)沒有限制的哦甲脏。文檔流排完之后眶熬,開始獲取計(jì)算節(jié)點(diǎn)的坐標(biāo)和大小等CSS屬性,作為盒子的包裝說明块请。然后把盒子在倉庫里一一擺放娜氏,這就將節(jié)點(diǎn)布局到了頁面。
  • 2.3墩新、繪制頁面
    布局完成之后牍白,我們?cè)陧撁嫔掀鋵?shí)是看不到任何內(nèi)容的瀏覽器只是計(jì)算出了每一個(gè)節(jié)點(diǎn)對(duì)象應(yīng)該被放到頁面的哪個(gè)位置上,但并沒有可視化抖棘。因此最后一步就是將所有內(nèi)容繪制出來茂腥,完成整個(gè)頁面的渲染。
    https://www.zhihu.com/question/30218438

4切省、https ssl加密如何實(shí)現(xiàn)

5最岗、跨域如何解決

  • 1、 通過jsonp跨域(jsonp缺點(diǎn):只能實(shí)現(xiàn)get一種請(qǐng)求)
  • 2朝捆、 document.domain + iframe跨域(此方案僅限主域相同般渡,子域不同的跨域應(yīng)用場(chǎng)景。)
  • 3、 location.hash + iframe
  • 4驯用、 window.name + iframe跨域(window.name屬性的獨(dú)特之處:name值在不同的頁面(甚至不同域名)加載后依舊存在脸秽,并且可以支持非常長(zhǎng)的 name 值2MB)

總結(jié):通過iframe的src屬性由外域轉(zhuǎn)向本地域,跨域數(shù)據(jù)即由iframe的window.name從外域傳遞到本地域蝴乔。這個(gè)就巧妙地繞過了瀏覽器的跨域訪問限制记餐,但同時(shí)它又是安全操作。

  • 5薇正、 postMessage跨域

postMessage是HTML5 XMLHttpRequest Level 2中的API片酝,且是為數(shù)不多可以跨域操作的window屬性之一,它可用于解決以下方面的問題:
a.) 頁面和其打開的新窗口的數(shù)據(jù)傳遞
b.) 多窗口之間消息傳遞
c.) 頁面與嵌套的iframe消息傳遞
d.) 上面三個(gè)場(chǎng)景的跨域數(shù)據(jù)傳遞
用法
postMessage(data,origin)方法接受兩個(gè)參數(shù)
data: html5規(guī)范支持任意基本類型或可復(fù)制的對(duì)象挖腰,但部分瀏覽器只支持字符串雕沿,所以傳參時(shí)最好用JSON.stringify()序列化。
origin: 協(xié)議+主機(jī)+端口號(hào)猴仑,也可以設(shè)置為"*"审轮,表示可以傳遞給任意窗口,如果要指定和當(dāng)前窗口同源的話設(shè)置為"/"

  • 6辽俗、 跨域資源共享(CORS)

  • 7疾渣、 nginx代理跨域

  • 8、 nodejs中間件代理跨域


    image.png
  • 9榆苞、 WebSocket協(xié)議跨域

https://segmentfault.com/a/1190000011145364

四、框架

4.1霞捡、react

1坐漏、react生命周期,原理碧信,虛擬dom理解赊琳,diff算法原理

2、react版本都更新了什么砰碴,最新版本去掉什么生命周期加入什么生命周期躏筏,為什么

3、組件渲染優(yōu)化

4呈枉、如何理解高階組件

5趁尼、redux理念是什么 單數(shù)據(jù)流如何改變的

6、webpack有哪些配置屬性 原理 插件如何實(shí)現(xiàn)

7猖辫、bable的配置屬于有哪些 瀏覽器兼容性

8酥泞、AST語法樹

9、小程序父子組件通訊啃憎,wepy父子組件通訊

10芝囤、react創(chuàng)建組件的方法(React.createClass React.Component 函數(shù)定義無狀態(tài)組件)

11、react無狀態(tài)組件和pureComponent區(qū)別

12、react什么時(shí)候setstate是同步的(一步操作中調(diào)用)

13悯姊、react組件間怎么通訊---react原生方法(都是事件機(jī)制啊實(shí)在找不到)

14羡藐、react父組件拿子組件ref(this.refs.xxx.refs.textinput

15、react將組件渲染到指定dom節(jié)點(diǎn)(https://blog.csdn.net/neoveee/article/details/57399834

16悯许、webpack插件有哪些(extract-text-webpack-plugin單獨(dú)打包c(diǎn)ss)仆嗦,怎么多個(gè)入口,怎么打包成內(nèi)聯(lián)樣式岸晦?欧啤?? 启上,不打包某個(gè)文件邢隧??

17冈在、React如何實(shí)現(xiàn)vue中的插件模式???

react沒有實(shí)際開發(fā)經(jīng)驗(yàn)倒慧,等有經(jīng)驗(yàn)了再整理吧

4.2、vue

9包券、vue的雙向數(shù)據(jù)流如何實(shí)現(xiàn)

vue數(shù)據(jù)雙向綁定是通過數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式來實(shí)現(xiàn)的

Object.defineProperty()這個(gè)方法重新定義了對(duì)象獲取屬性值(get)和設(shè)置屬性值(set)的操作來實(shí)現(xiàn)的纫谅。


var obj = { };
var name;
//第一個(gè)參數(shù):定義屬性的對(duì)象。
//第二個(gè)參數(shù):要定義或修改的屬性的名稱溅固。
//第三個(gè)參數(shù):將被定義或修改的屬性描述符付秕。
Object.defineProperty(obj, "data",  {
//獲取值get: 
function () { return name; },
//設(shè)置值set: 
function (val) {
    name = val;
    console.log(val)}
})
//賦值調(diào)用
setobj.data = 'aaa';
//取值調(diào)用
getconsole.log(obj.data);
// 代碼演示:defineProperty的雙向綁定
var obj = {};
Object.defineProperty(obj, 'val', {
    set: function (newVal) {
        document.getElementById("a").value = newVal == undefined ? '' : newVal;
        document.getElementById("b").innerHTML = newVal == undefined ? '' : newVal;
    }
});
document.getElementById("a").addEventListener("keyup", function (e) {
    obj.val = e.target.value;
})

computed 計(jì)算屬性與method方法的區(qū)別

computed中的計(jì)算屬性可以寫在method中,區(qū)別就是method調(diào)用要加()而computed不用

computed中必須要加return

computed里面的方法不是通過事件去觸發(fā)的侍郭,而是當(dāng)屬性(必須是data中的屬性)發(fā)生改變的時(shí)候那么當(dāng)前函數(shù)就會(huì)被觸發(fā)

最大的區(qū)別是询吴,computed中有緩存,相同的值會(huì)直接拿已經(jīng)緩存的亮元,提高性能猛计,但是method沒有緩存,一樣的值還是會(huì)重新獲取

1爆捞、Vue循環(huán)為什么要加key

key屬性可以用來提升v-for渲染的效率奉瘤,vue中使用v-for渲染數(shù)據(jù)的時(shí)候,并不會(huì)去改變?cè)械脑睾蛿?shù)據(jù)煮甥,而是創(chuàng)建新的元素盗温,再把新的數(shù)據(jù)渲染進(jìn)去。

2成肘、Vue循環(huán)為什么不用index作為key

index 作為 key肌访,和沒寫基本上沒區(qū)別,因?yàn)椴还苣銛?shù)組的順序怎么顛倒艇劫,index 都是 0, 1, 2 這樣排列吼驶,導(dǎo)致 Vue 虛擬DOM的復(fù)用會(huì)映射到錯(cuò)誤的舊子節(jié)點(diǎn)惩激,做很多額外的工作,影響效率蟹演。

vue原理 數(shù)據(jù)劫持 路由守衛(wèi)怎么用 axios怎么寫請(qǐng)求攔截 響應(yīng)攔截

10vuex如何數(shù)據(jù)綁定的

11vue有哪些框架優(yōu)缺點(diǎn)

五风钻、Reactnative

1有哪些坑,怎么解決

2熱更新問題

3性能問題酒请,比如列表

4首屏白屏怎么解決

5自己封裝過什么組件

6js和原生通訊方法有哪些 jsbridge原理

Node

1用來做什么

2用過哪些框架

3express如何解決異步問題

4node從哪個(gè)版本開始有Async和Await

5node數(shù)據(jù)流如何理解

6如何理解中間價(jià)

7node如何確保穩(wěn)定性骡技,進(jìn)程死了如何自動(dòng)修復(fù)

六、網(wǎng)絡(luò)

1tcp三次握手

2分析請(qǐng)求頭

算法

1隨機(jī)一個(gè)數(shù)組羞反,數(shù)組每個(gè)值區(qū)間2-32

2最長(zhǎng)回文字段

開放性問題

1flutter有使用過嗎布朦,你感覺如何

2全局有console的地方全部換成彈框顯示

3如何優(yōu)化pc和app

4項(xiàng)目如何發(fā)布部署,如何本地開發(fā)昼窗,git使用等

函數(shù)式編程

函數(shù)式編程(縮寫為 FP)是一種通過組合純函數(shù)來構(gòu)建軟件的過程是趴,避免狀態(tài)共享、可變數(shù)據(jù)及副作用的產(chǎn)生澄惊。

1唆途、函數(shù)式編程定義

image.png

2、函數(shù)式編程的特點(diǎn)

    1. 函數(shù)是"第一等公民"
      把它想象成一個(gè)數(shù)據(jù)類型掸驱,可以聲明肛搬、賦值給其他變量、當(dāng)參數(shù)傳給函數(shù)等等
    1. 只用"表達(dá)式"毕贼,不用"語句"
      "表達(dá)式"(expression):是一個(gè)單純的運(yùn)算過程温赔,總是有返回值;
      "語句"(statement):是執(zhí)行某種操作鬼癣,沒有返回值陶贼。
      函數(shù)式編程要求,只使用表達(dá)式扣溺,不使用語句骇窍。也就是說瓜晤,每一步都是單純的運(yùn)算锥余,而且都有返回值。
    1. 沒有"副作用"
      所謂"副作用"痢掠,指的是函數(shù)內(nèi)部與外部互動(dòng)(最典型的情況驱犹,就是修改全局變量的值),產(chǎn)生運(yùn)算以外的其他結(jié)果足画。
      函數(shù)式編程強(qiáng)調(diào)沒有"副作用"雄驹,意味著函數(shù)要保持獨(dú)立,所有功能就是返回一個(gè)新的值淹辞,沒有其他行為医舆,尤其是不得修改外部變量的值。
    1. 不修改狀態(tài)
      函數(shù)式編程只是返回新的值,不修改系統(tǒng)變量蔬将。因此爷速,不修改變量,也是它的一個(gè)重要特點(diǎn)霞怀。
    1. 引用透明
      引用透明(Referential transparency)惫东,指的是函數(shù)的運(yùn)行不依賴于外部變量或"狀態(tài)",只依賴于輸入的參數(shù)毙石,任何時(shí)候只要參數(shù)相同廉沮,引用函數(shù)所得到的返回值總是相同的。
      方法傳入的參數(shù)類型與返回值類型是一樣的(類比map徐矩,same方法滞时,傳入一個(gè)數(shù)組同時(shí)返回的也是一個(gè)數(shù)組)
      來自:http://www.ruanyifeng.com/blog/2012/04/functional_programming.html

undenfine 和null 有什么區(qū)別 做if判斷會(huì)怎樣

http://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html

image.png

vue數(shù)據(jù)劫持

  • 針對(duì) Object 類型,采用 Object.defineProperty() 方法劫持屬性的讀取和設(shè)置方法丧蘸;
  • 針對(duì) Array 類型漂洋,采用原型相關(guān)的知識(shí)劫持常用的函數(shù),從而知曉當(dāng)前數(shù)組發(fā)生變化力喷。
    注意: Object.defineProperty() 方法存在以下缺陷:
    每次只能設(shè)置一個(gè)具體的屬性刽漂,導(dǎo)致需要遍歷對(duì)象來設(shè)置屬性,同時(shí)也導(dǎo)致了無法探測(cè)新增屬性弟孟;
    屬性描述符 configurable 對(duì)其的影響是致命的贝咙。而 ES6 中的 Proxy 可以完美的解決這些問題

raw-loader:加載文件原始內(nèi)容(utf-8)
file-loader:把文件輸出到一個(gè)文件夾中,在代碼中通過相對(duì) URL 去引用輸出的文件 (處理圖片和字體)
url-loader:與 file-loader 類似拂募,區(qū)別是用戶可以設(shè)置一個(gè)閾值庭猩,大于閾值會(huì)交給 file-loader 處理,小于閾值時(shí)返回文件 base64 形式編碼 (處理圖片和字體)
source-map-loader:加載額外的 Source Map 文件陈症,以方便斷點(diǎn)調(diào)試
svg-inline-loader:將壓縮后的 SVG 內(nèi)容注入代碼中
image-loader:加載并且壓縮圖片文件
json-loader 加載 JSON 文件(默認(rèn)包含)
handlebars-loader: 將 Handlebars 模版編譯成函數(shù)并返回
babel-loader:把 ES6 轉(zhuǎn)換成 ES5
ts-loader: 將 TypeScript 轉(zhuǎn)換成 JavaScript
awesome-typescript-loader:將 TypeScript 轉(zhuǎn)換成 JavaScript蔼水,性能優(yōu)于 ts-loader
sass-loader:將SCSS/SASS代碼轉(zhuǎn)換成CSS
css-loader:加載 CSS,支持模塊化录肯、壓縮趴腋、文件導(dǎo)入等特性
style-loader:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS
postcss-loader:擴(kuò)展 CSS 語法论咏,使用下一代 CSS优炬,可以配合 autoprefixer 插件自動(dòng)補(bǔ)齊 CSS3 前綴
eslint-loader:通過 ESLint 檢查 JavaScript 代碼
tslint-loader:通過 TSLint檢查 TypeScript 代碼
mocha-loader:加載 Mocha 測(cè)試用例的代碼
coverjs-loader:計(jì)算測(cè)試的覆蓋率
vue-loader:加載 Vue.js 單文件組件
i18n-loader: 國(guó)際化
cache-loader: 可以在一些性能開銷較大的 Loader 之前添加,目的是將結(jié)果緩存到磁盤里
有哪些常見的Plugin厅贪?你用過哪些Plugin蠢护?
define-plugin:定義環(huán)境變量 (Webpack4 之后指定 mode 會(huì)自動(dòng)配置)
ignore-plugin:忽略部分文件
html-webpack-plugin:簡(jiǎn)化 HTML 文件創(chuàng)建 (依賴于 html-loader)
web-webpack-plugin:可方便地為單頁應(yīng)用輸出 HTML,比 html-webpack-plugin 好用
uglifyjs-webpack-plugin:不支持 ES6 壓縮 (Webpack4 以前)
terser-webpack-plugin: 支持壓縮 ES6 (Webpack4)
webpack-parallel-uglify-plugin: 多進(jìn)程執(zhí)行代碼壓縮养涮,提升構(gòu)建速度
mini-css-extract-plugin: 分離樣式文件葵硕,CSS 提取為獨(dú)立文件眉抬,支持按需加載 (替代extract-text-webpack-plugin)
serviceworker-webpack-plugin:為網(wǎng)頁應(yīng)用增加離線緩存功能
clean-webpack-plugin: 目錄清理
ModuleConcatenationPlugin: 開啟 Scope Hoisting
speed-measure-webpack-plugin: 可以看到每個(gè) Loader 和 Plugin 執(zhí)行耗時(shí) (整個(gè)打包耗時(shí)、每個(gè) Plugin 和 Loader 耗時(shí))
webpack-bundle-analyzer: 可視化 Webpack 輸出文件的體積 (業(yè)務(wù)組件懈凹、依賴第三方模塊)
Loader和Plugin的區(qū)別吐辙?
Loader 本質(zhì)就是一個(gè)函數(shù),在該函數(shù)中對(duì)接收到的內(nèi)容進(jìn)行轉(zhuǎn)換蘸劈,返回轉(zhuǎn)換后的結(jié)果昏苏。 因?yàn)?Webpack 只認(rèn)識(shí) JavaScript,所以 Loader 就成了翻譯官威沫,對(duì)其他類型的資源進(jìn)行轉(zhuǎn)譯的預(yù)處理工作贤惯。
Plugin 就是插件,基于事件流框架 Tapable棒掠,插件可以擴(kuò)展 Webpack 的功能孵构,在 Webpack 運(yùn)行的生命周期中會(huì)廣播出許多事件,Plugin 可以監(jiān)聽這些事件烟很,在合適的時(shí)機(jī)通過 Webpack 提供的 API 改變輸出結(jié)果颈墅。
Loader 在 module.rules 中配置,作為模塊的解析規(guī)則雾袱,類型為數(shù)組恤筛。每一項(xiàng)都是一個(gè) Object,內(nèi)部包含了 test(類型文件)芹橡、loader毒坛、options (參數(shù))等屬性。
Plugin 在 plugins 中單獨(dú)配置林说,類型為數(shù)組煎殷,每一項(xiàng)是一個(gè) Plugin 的實(shí)例,參數(shù)都通過構(gòu)造函數(shù)傳入腿箩。

const HtmlWebpackPlugin = require('html-webpack-plugin');
// 有時(shí)我們會(huì)指定打包文件中帶有 hash豪直,那么每次生成的 js 文件名會(huì)有所不同,不能讓我們每次都人工去修改 html珠移,
// 我們可以使用 html-webpack-plugin 插件來幫助我們完成這些事情弓乙。
// 有時(shí)候,我們的腳手架不僅僅給自己使用剑梳,也許還提供給其它業(yè)務(wù)使用唆貌,html 文件的可配置性可能很重要滑潘,比如:你公司有專門的部門提供M頁的公共頭部/公共尾部垢乙,埋點(diǎn)jssdk以及分享的jssdk等等,但是不是每個(gè)業(yè)務(wù)都需要這些內(nèi)容语卤。
// 一個(gè)功能可能對(duì)應(yīng)多個(gè) js 或者是 css 文件追逮,如果每次都是業(yè)務(wù)自行修改 public/index.html 文件酪刀,也挺麻煩的。首先他們得搞清楚每個(gè)功能需要引入的文件钮孵,然后才能對(duì) index.html 進(jìn)行修改骂倘。
// 此時(shí)我們可以增加一個(gè)配置文件,業(yè)務(wù)通過設(shè)置 true 或 false 來選出自己需要的功能巴席,我們?cè)俑鶕?jù)配置文件的內(nèi)容历涝,為每個(gè)業(yè)務(wù)生成相應(yīng)的 html 文件,豈不是美美的漾唉。

const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    // 每次 clean-webpack-plugin 都會(huì)幫我們先清空一波 dist 目錄的插件
const CopyWebpackPlugin = require('copy-webpack-plugin');
    // 靜態(tài)資源拷貝插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 抽離CSS荧库,即將CSS文件單獨(dú)打包的插件,這可能是因?yàn)榇虬梢粋€(gè)JS文件太大赵刑,影響加載速度分衫,也有可能是為了緩存
const OptimizeCssPlugin = require('optimize-css-assets-webpack-plugin');
// 使用 mini-css-extract-plugin,CSS 文件默認(rèn)不會(huì)被壓縮般此,如果想要壓縮蚪战,需要配置 optimization插件

// import() 語法,
// 按需加載
// 需要 @babel/plugin-syntax-dynamic-import 的插件支持铐懊,
// 但是因?yàn)楫?dāng)前 @babel/preset-env 預(yù)設(shè)中已經(jīng)包含了 @babel/plugin-syntax-dynamic-import邀桑,因此我們不需要再單獨(dú)安裝和配置。

const webpack = require('webpack');
const path = require('path');
const isDev = process.env.NODE_ENV === 'development';
const config = require('./public/config')[isDev ? 'dev' : 'build'];

module.exports = {
    mode: isDev ? 'development' : 'production',
    // mode 配置項(xiàng)科乎,告知 webpack 使用相應(yīng)模式的內(nèi)置優(yōu)化概漱。
    // mode 配置項(xiàng),支持以下兩個(gè)配置:
    // development:將 process.env.NODE_ENV 的值設(shè)置為 development喜喂,啟用 NamedChunksPlugin 和 NamedModulesPlugin
    // production:將 process.env.NODE_ENV 的值設(shè)置為 production瓤摧,啟用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin
    
    
    entry: {
        index: './src/index.js',
        login: './src/login.js'
    },
    // entry 的值可以是一個(gè)字符串,一個(gè)數(shù)組或是一個(gè)對(duì)象玉吁。
    // 字符串的情況無需多說照弥,就是以對(duì)應(yīng)的文件為入口。
    // 為數(shù)組時(shí)进副,表示有“多個(gè)主入口”这揣,想要多個(gè)依賴文件一起注入時(shí)
    
    
    output: {
        path: path.resolve(__dirname, 'dist'), //必須是絕對(duì)路徑
        filename: 'bundle.[hash:6].js',
        publicPath: '/' //通常是CDN地址
    },
    // 例如,你最終編譯出來的代碼部署在 CDN 上影斑,資源的地址為: 'https://AAA/BBB/YourProject/XXX'给赞,那么可以將生產(chǎn)的 publicPath 配置為: //AAA/BBB/。
// 編譯時(shí)矫户,可以不配置片迅,或者配置為 /〗粤桑可以在我們之前提及的 config.js 中指定 publicPath(config.js 中區(qū)分了 dev 和 public)柑蛇, 當(dāng)然還可以區(qū)分不同的環(huán)境指定配置文件來設(shè)置芥挣,或者是根據(jù) isDev 字段來設(shè)置。
    

    module: {
        // loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)耻台,用于對(duì)源代碼進(jìn)行轉(zhuǎn)換
        rules: [
            {
                test: /\.jsx?$/, //匹配規(guī)則空免,針對(duì)符合規(guī)則的文件進(jìn)行處理。
                use: {
                    loader: 'babel-loader', 
                    options: {      //這里盆耽,我們可以在 .babelrc 中編寫 babel 的配置蹋砚,也可以在 webpack.config.js 中進(jìn)行配置。
                        presets: ["@babel/preset-env"],
                        plugins: [
                            [
                                "@babel/plugin-transform-runtime",
                                {
                                    "corejs": 3
                                }
                            ]
                        ]
                    }
                },
                exclude: /node_modules/ //排除 node_modules 目錄
            },
            // 講js轉(zhuǎn)譯為低版本
            {
                test: /.html$/,
                use: 'html-withimg-loader'
            },
            // 處理在html中引入的本地圖片
            
            // use 字段有幾種寫法
            // 可以是一個(gè)字符串摄杂,例如上面的 use: 'html-withimg-loader'
            // use 字段可以是一個(gè)數(shù)組都弹,例如處理CSS文件時(shí),use: ['style-loader', 'css-loader']
            // use 數(shù)組的每一項(xiàng)既可以是字符串也可以是一個(gè)對(duì)象匙姜,當(dāng)我們需要在webpack 的配置文件中對(duì) loader 進(jìn)行配置畅厢,就需要將其編寫為一個(gè)對(duì)象,
            // 并且在此對(duì)象的 options 字段中進(jìn)行配置氮昧。
            // loader 的執(zhí)行順序是從右向左執(zhí)行的框杜,也就是后面的 loader 先執(zhí)行,下面 loader 的執(zhí)行順序?yàn)? less-loader ---> postcss-loader ---> css-loader ---> style-loader
            // 當(dāng)然袖肥,loader 其實(shí)還有一個(gè)參數(shù)咪辱,可以修改優(yōu)先級(jí),enforce 參數(shù)椎组,其值可以為: pre(優(yōu)先執(zhí)行) 或 post (滯后執(zhí)行)油狂。
            {
                test: /\.(le|c)ss$/,
                use: [
                    // 'style-loader', 
                    MiniCssExtractPlugin.loader, //替換之前的 style-loader
                    'css-loader', {
                    loader: 'postcss-loader',
                    options: {
                        plugins: function () {
                            return [
                                require('autoprefixer')()
                            ]
                        }
                    }
                }, 'less-loader'],
                exclude: /node_modules/
            },
             // style-loader 動(dòng)態(tài)創(chuàng)建 style 標(biāo)簽,將 css 插入到 head 中.
             // css-loader 負(fù)責(zé)處理 @import 等語句寸癌。
             // postcss-loader 和 autoprefixer专筷,自動(dòng)生成瀏覽器兼容性前綴 
             // less-loader 負(fù)責(zé)處理編譯 .less 文件,將其轉(zhuǎn)為 css
            {
                test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240, //10K
                            esModule: false,
                            outpath:'assets'
                        }
                    }
                ],
                exclude: /node_modules/
            },
            // 我們可以使用 url-loader 或者 file-loader 來處理本地的資源文件。
            // url-loader 和 file-loader 的功能類似蒸苇,
            // 但是 url-loader 可以指定在文件大小小于指定的限制時(shí)磷蛹,返回 DataURL,
            // 因此溪烤,個(gè)人會(huì)優(yōu)先選擇使用 url-loader
            // 當(dāng)本地資源較多時(shí)味咳,我們有時(shí)會(huì)希望它們能打包在一個(gè)文件夾下,這也很簡(jiǎn)單檬嘀,我們只需要在 url-loader 的 options 中指定 outpath槽驶,如: outputPath: 'assets'
            // 此處設(shè)置 limit 的值大小為 10240,即資源大小小于 10K 時(shí)鸳兽,將資源轉(zhuǎn)換為 base64掂铐,超過 10K,將圖片拷貝到 dist 目錄。
            // esModule 設(shè)置為 false堡纬,否則,<img src={require('XXX.jpg')} /> 會(huì)出現(xiàn) <img src=[Module Object] />
            // 將資源轉(zhuǎn)換為 base64 可以減少網(wǎng)絡(luò)請(qǐng)求次數(shù)蒿秦,但是 base64 數(shù)據(jù)較大烤镐,如果太多的資源是 base64,會(huì)導(dǎo)致加載變慢棍鳖,
            // 因此設(shè)置 limit 值時(shí)炮叶,需要二者兼顧。

           
        ]
    },
    devtool: isDev ? 'cheap-module-eval-source-map' : 'source-map',
    // devtool 中的一些設(shè)置渡处,可以幫助我們將編譯后的代碼映射回原始源代碼镜悉。不同的值會(huì)明顯影響到構(gòu)建和重新構(gòu)建的速度郭变。
    // 能夠定位到源碼的行即可暑劝,因此,綜合構(gòu)建速度印屁,在開發(fā)模式下醇份,設(shè)置 devtool 的值是 cheap-module-eval-source-map稼锅。
    // 生產(chǎn)環(huán)境可以使用 none 或者是 source-map,使用 source-map 最終會(huì)單獨(dú)打包出一個(gè) .map 文件僚纷,我們可以根據(jù)報(bào)錯(cuò)信息和此 map 文件矩距,進(jìn)行錯(cuò)誤解析,定位到源代碼怖竭。
    // source-map 和 hidden-source-map 都會(huì)打包生成單獨(dú)的 .map 文件锥债,區(qū)別在于,source-map 會(huì)在打包出的js文件中增加一個(gè)引用注釋痊臭,以便開發(fā)工具知道在哪里可以找到它哮肚。hidden-source-map 則不會(huì)在打包的js中增加引用注釋。
    // 但是我們一般不會(huì)直接將 .map 文件部署到CDN广匙,因?yàn)闀?huì)直接映射到源碼绽左,更希望將.map 文件傳到錯(cuò)誤解析系統(tǒng),然后根據(jù)上報(bào)的錯(cuò)誤信息艇潭,直接解析到出錯(cuò)的源碼位置拼窥。


    plugins: [
        //數(shù)組 放著所有的webpack插件
        new HtmlWebpackPlugin({
            template: './public/index.html',
            filename: 'index.html', //打包后的文件名
            config: config.template,  //讀取config配置文件生成不同的文件
            // hash: true //是否加上hash,默認(rèn)是 false
            chunks: ['index'] //配置此參數(shù)僅會(huì)將數(shù)組中指定的js引入到html文件中蹋凝,此外鲁纠,如果你需要引入多個(gè)JS文件,僅有少數(shù)不想引入鳍寂,還可以指定 excludeChunks 參數(shù)改含,它接受一個(gè)數(shù)組。
        }),
        new HtmlWebpackPlugin({
            template: './public/login.html',
            filename: 'login.html', //打包后的文件名
            chunks: ['login']
        }),
        // 多頁面應(yīng)用打包
        // 如果需要配置多個(gè) HtmlWebpackPlugin迄汛,
        // 那么 filename 字段不可缺省捍壤,否則默認(rèn)生成的都是 index.html骤视,
        // 如果你希望 html 的文件名中也帶有 hash,那么直接修改 fliename 字段即可鹃觉,例如: filename: 'login.[hash:6].html'专酗。

        new CleanWebpackPlugin({
            cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] //不刪除dll目錄下的文件
        }),
        new CopyWebpackPlugin({
            patterns: [
                { 
                    from: 'public/js/*.js',   //將 public/js 目錄拷貝至 dist/js 目錄
                    to: path.resolve(__dirname, 'dist', 'js'),
                    flatten: true, //設(shè)置為 true,那么它只會(huì)拷貝文件盗扇,而不會(huì)把文件夾路徑都拷貝上祷肯,
                    // ignore: ['other.js'] 忽略掉 js 目錄下的 other.js 文件
                }
            ],
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
            //個(gè)人習(xí)慣將css文件放在單獨(dú)目錄下
            //publicPath:'../'   //如果你的output的publicPath配置的是 './' 這種相對(duì)路徑,那么如果將css文件放在單獨(dú)目錄下疗隶,記得在這里指定一下publicPath 
        }),
        new OptimizeCssPlugin(),    //壓縮css插件
        
        new webpack.HotModuleReplacementPlugin(), //熱更新插件

        new webpack.DefinePlugin({              //定義環(huán)境變量插件      \
            DEV: JSON.stringify('dev'), //字符串
            //index.js
               // if(DEV === 'dev') {
                //     //開發(fā)環(huán)境
                // }else {
                //     //生產(chǎn)環(huán)境
                // }
            FLAG: 'true' //FLAG 是個(gè)布爾類型
        })
     
    ],

    devServer: {
        // port: '8888', //默認(rèn)是8080
        // quiet: false, //默認(rèn)不啟用
        // inline: true, //默認(rèn)開啟 inline 模式佑笋,如果設(shè)置為false,開啟 iframe 模式
        // stats: "errors-only", //終端僅打印 error
        // overlay: false, //默認(rèn)不啟用
        // clientLogLevel: "silent", //日志等級(jí)
        // compress: true //是否啟用 gzip 壓縮
        hot:true //熱更新
    },
    // 啟用 quiet 后,除了初始啟動(dòng)信息之外的任何內(nèi)容都不會(huì)被打印到控制臺(tái)斑鼻。這也意味著來自 webpack 的錯(cuò)誤或警告在控制臺(tái)不可見 ,不建議開啟
    // stats: "errors-only" 蒋纬,終端中僅打印出 error,注意當(dāng)啟用了 quiet 或者是 noInfo 時(shí)坚弱,此屬性不起作用颠锉。
    // 啟用 overlay 后,當(dāng)編譯出錯(cuò)時(shí)史汗,會(huì)在瀏覽器窗口全屏輸出錯(cuò)誤琼掠,默認(rèn)是關(guān)閉的。
    resolve: {
        modules: ['./src/components', 'node_modules'], //從左到右依次查找
        // resolve 配置 webpack 如何尋找模塊所對(duì)應(yīng)的文件停撞。
        // webpack 內(nèi)置 JavaScript 模塊化語法解析功能瓷蛙,默認(rèn)會(huì)采用模塊化標(biāo)準(zhǔn)里約定好的規(guī)則去尋找,但你可以根據(jù)自己的需要修改默認(rèn)的規(guī)則戈毒。
        extensions: ['web.js', '.js'] //當(dāng)然艰猬,你還可以配置 .json, .css        
// extensions適配多端的項(xiàng)目中,可能會(huì)出現(xiàn) .web.js, .wx.js埋市,例如在轉(zhuǎn)web的項(xiàng)目中冠桃,我們希望首先找 .web.js,如果沒有道宅,再找 .js食听。我們可以這樣配置
    }
}

// 區(qū)分不同的環(huán)境
// 目前為止我們 webpack 的配置,都定義在了 webpack.config.js 中污茵,對(duì)于需要區(qū)分是開發(fā)環(huán)境還是生產(chǎn)環(huán)境的情況樱报,
// 我們根據(jù) process.env.NODE_ENV 去進(jìn)行了區(qū)分配置,但是配置文件中如果有多處需要區(qū)分環(huán)境的配置泞当,這種顯然不是一個(gè)好辦法迹蛤。
// 更好的做法是創(chuàng)建多個(gè)配置文件,如: webpack.base.js、webpack.dev.js盗飒、webpack.prod.js嚷量。
// 然后修改我們的 package.json,指定對(duì)應(yīng)的 config 文件

// webpack.base.js 定義公共的配置
// webpack.dev.js:定義開發(fā)環(huán)境的配置
// webpack.prod.js:定義生產(chǎn)環(huán)境的配置

// webpack-merge 專為 webpack 設(shè)計(jì)逆趣,提供了一個(gè) merge 函數(shù)蝶溶,用于連接數(shù)組,合并對(duì)象汗贫。
// const merge = require('webpack-merge');
// merge({
//     devtool: 'cheap-module-eval-source-map',
//     module: {
//         rules: [
//             {a: 1}
//         ]
//     },
//     plugins: [1,2,3]
// }, {
//     devtool: 'none',
//     mode: "production",
//     module: {
//         rules: [
//             {a: 2},
//             {b: 1}
//         ]
//     },
//     plugins: [4,5,6],
// });
// //合并后的結(jié)果為
// {
//     devtool: 'none',
//     mode: "production",
//     module: {
//         rules: [
//             {a: 1},
//             {a: 2},
//             {b: 1}
//         ]
//     },
//     plugins: [1,2,3,4,5,6]
// }

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末身坐,一起剝皮案震驚了整個(gè)濱河市秸脱,隨后出現(xiàn)的幾起案子落包,更是在濱河造成了極大的恐慌,老刑警劉巖摊唇,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咐蝇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡巷查,警方通過查閱死者的電腦和手機(jī)有序,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岛请,“玉大人旭寿,你說我怎么就攤上這事〕绨埽” “怎么了盅称?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)后室。 經(jīng)常有香客問我缩膝,道長(zhǎng),這世上最難降的妖魔是什么岸霹? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任疾层,我火速辦了婚禮,結(jié)果婚禮上贡避,老公的妹妹穿的比我還像新娘痛黎。我一直安慰自己,他們只是感情好刮吧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布舅逸。 她就那樣靜靜地躺著,像睡著了一般皇筛。 火紅的嫁衣襯著肌膚如雪琉历。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音旗笔,去河邊找鬼彪置。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蝇恶,可吹牛的內(nèi)容都是我干的拳魁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼撮弧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼潘懊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贿衍,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤授舟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后贸辈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體释树,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年擎淤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奢啥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘴拢,死狀恐怖桩盲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情席吴,我是刑警寧澤赌结,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站抢腐,受9級(jí)特大地震影響姑曙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜迈倍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一伤靠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啼染,春花似錦宴合、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至斜棚,卻和暖如春阀蒂,著一層夾襖步出監(jiān)牢的瞬間该窗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工蚤霞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酗失,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓昧绣,卻偏偏與公主長(zhǎng)得像规肴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夜畴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

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