2019前端基礎(chǔ)面試秘籍(更新于5.13)

77777777777777777777777777777777777777777777777777777777777777777777777777

image

一、html和css部分

1、如何理解CSS的盒子模型蹂安?

標(biāo)準(zhǔn)盒子模型:寬度=內(nèi)容的寬度(content)+ border + padding

低版本IE盒子模型:寬度=內(nèi)容寬度(content+border+padding)

2亩进、BFC?

* 什么是 BFC

   BFC(Block Formatting Context)格式化上下文够颠,是 Web 頁面中盒模型布局的 CSS 渲染模式挟纱,指一個(gè)獨(dú)立的渲染區(qū)域或者說是一個(gè)隔離的獨(dú)立容器。
* 形成 BFC 的條件

   * 浮動元素状土,float 除 none 以外的值
   * 定位元素,position(absolute伺糠,fixed)
   * display 為以下其中之一的值 inline-block,table-cell,table-caption
   * overflow 除了 visible 以外的值(hidden减余,auto卫枝,scroll)
* BFC 的特性
   * 內(nèi)部的 Box 會在垂直方向上一個(gè)接一個(gè)的放置。
   * 垂直方向上的距離由 margin 決定
   * bfc 的區(qū)域不會與 float 的元素區(qū)域重疊舵揭。
   * 計(jì)算 bfc 的高度時(shí)谤专,浮動元素也參與計(jì)算
   * bfc 就是頁面上的一個(gè)獨(dú)立容器,容器里面的子元素不會影響外面元素午绳。

3置侍、如何清除浮動?

不清楚浮動會發(fā)生高度塌陷:浮動元素父元素高度自適應(yīng)(父元素不寫高度時(shí)拦焚,子元素寫了浮動后蜡坊,父元素會發(fā)生高度塌陷)
* clear清除浮動(添加空div法)在浮動元素下方添加空div,并給該元素寫css樣式:   {clear:both;height:0;overflow:hidden;}
* 給浮動元素父級設(shè)置高度
* 父級同時(shí)浮動(需要給父級同級元素添加浮動)
* 父級設(shè)置成inline-block,其margin: 0 auto居中方式失效
* 給父級添加overflow:hidden 清除浮動方法
* 萬能清除法 after偽類 清浮動(現(xiàn)在主流方法赎败,推薦使用)

.float_div:after{
    content:".";
    clear:both;
    display:block;
    height:0;
    overflow:hidden;
    visibility:hidden;
}
.float_div{
    zoom:1
} 

4秕衙、用純CSS創(chuàng)建一個(gè)三角形的原理是什么?

span {
    width: 0;
    height: 0;
    border-top: 40px solid transparent;
    border-left: 40px solid transparent;
    border-right: 40px solid transparent;
    border-bottom: 40px solid #ff0000;
}
image

5僵刮、css3實(shí)現(xiàn)0.5px的細(xì)線据忘?

/* css */
.line {
    position: relative;
}
.line:after {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 1px;
    background-color: #000000;
    -webkit-transform: scaleY(.5);
    transform: scaleY(.5);
}

/* html */
<div class="line"></div>

6、css實(shí)現(xiàn)三欄布局

左右固定搞糕,中間自適應(yīng)勇吊。

image
  1. flex方式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            display: flex;
            justify-content: center;
            height: 200px;
        }
        .left {
            width: 200px;
            background-color: red;
            height: 100%;
        }
        .content {
            background-color: yellow;
            flex: 1;
        }
        .right {
            width: 200px;
            background-color: green;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="left"></div>
        <div class="content"></div>
        <div class="right"></div>
    </div>
</body>
</html>
  1. 絕對定位方式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            position: relative;
            height: 200px;
        }
        .left {
            width: 200px;
            background-color: red;
            left: 0;
            height: 100%;
            position: absolute;
        }
        .content {
            background-color: yellow;
            left: 200px;
            right: 200px;
            height: 100%;
            position: absolute;
        }
        .right {
            width: 200px;
            background-color: green;
            right: 0;
            height: 100%;
            position: absolute;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="left"></div>
        <div class="content"></div>
        <div class="right"></div>
    </div>
</body>
</html>
  1. 浮動方式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            height: 200px;
        }
        .left {
            width: 200px;
            background-color: red;
            float: left;
            height: 100%;
        }
        .content {
            background-color: yellow;
            height: 100%;
        }
        .right {
            width: 200px;
            background-color: green;
            float: right;
            height: 100%;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="left"></div>
        <div class="right"></div>
        <div class="content"></div>
    </div>
</body>
</html>

7、讓一個(gè)div垂直居中

image
  1. 寬度和高度已知的
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 400px;
            height: 200px;
            position: relative;
            background: red;
        }
        .content {
            width: 200px;
            height: 100px;
            position: absolute;
            top: 50%;
            left: 50%;
            margin-left: -100px;
            margin-top: -50px;
            background: green;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="content"></div>
    </div>
</body>
</html>
  1. 寬度和高度未知
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 400px;
            height: 200px;
            position: relative;
            background: red;
        }
        .content {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: green;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="content"></div>
    </div>
</body>
</html>
  1. flex布局
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 400px;
            height: 200px;
            background: red;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        .content {
            width: 200px;
            height: 100px;
            background: green;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="content"></div>
    </div>
</body>
</html>

二窍仰、JS

1萧福、閉包

閉包概念

能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
或簡單理解為定義在一個(gè)函數(shù)內(nèi)部的函數(shù)辈赋,內(nèi)部函數(shù)持有外部函數(shù)內(nèi)變量的引用鲫忍。

閉包用途

1膏燕、讀取函數(shù)內(nèi)部的變量
2、讓這些變量的值始終保持在內(nèi)存中悟民。不會再f1調(diào)用后被自動清除坝辫。
3、方便調(diào)用上下文的局部變量射亏。利于代碼封裝近忙。
原因:f1是f2的父函數(shù),f2被賦給了一個(gè)全局變量智润,f2始終存在內(nèi)存中及舍,f2的存在依賴f1,因此f1也始終存在內(nèi)存中窟绷,不會在調(diào)用結(jié)束后锯玛,被垃圾回收機(jī)制回收。

閉包缺點(diǎn)

1兼蜈、由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中攘残,內(nèi)存消耗很大,所以不能濫用閉包为狸,否則會造成網(wǎng)頁的性能問題歼郭,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是辐棒,在退出函數(shù)之前病曾,將不使用的局部變量全部刪除。
2漾根、閉包會在父函數(shù)外部知态,改變父函數(shù)內(nèi)部變量的值。所以立叛,如果你把父函數(shù)當(dāng)作對象(object)使用负敏,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value)秘蛇,這時(shí)一定要小心其做,不要隨便改變父函數(shù)內(nèi)部變量的值。

閉包應(yīng)用場景

閉包應(yīng)用場景之setTimeout

//setTimeout傳遞的第一個(gè)函數(shù)不能帶參數(shù)
setTimeout((param) => {
    alert(param)
}, 1000);


//通過閉包可以實(shí)現(xiàn)傳參效果
function func(param) {
    return function() {
        alert(param)
    }
}
var f1 = func('汪某');
setTimeout(f1, 1000)//汪某

2赁还、js中函數(shù)執(zhí)行

在 ES5.1 里面函數(shù)是這樣執(zhí)行的(不討論use strict和一些特殊情況妖泄,JS好復(fù)雜的),按如下順序執(zhí)行:

1. 確定“this”的值 (確切的來說艘策,this在JS里面不是一個(gè)變量名而是一個(gè)關(guān)鍵字)
2. 創(chuàng)建一個(gè)新的作用域
3. 處理形參/實(shí)參(沒有定義過才聲明蹈胡,無論如何都重新賦值,沒有對應(yīng)實(shí)參則賦值為"undefined"): 
對于每一個(gè)傳入的實(shí)參,按照從左往右的順序依次執(zhí)行:如果對應(yīng)的形參在本作用域中還沒有定義罚渐,則在本作用域中聲明形參却汉,并賦值。如果已經(jīng)定義過了荷并,則重新給其賦值合砂。(沒有對應(yīng)實(shí)參則賦值為"undefined")(沒有定義:就是“沒有聲明”的意思)
4. 處理函數(shù)定義(沒有定義過才聲明,無論如何都重新賦值): 
對該函數(shù)中所有的定義的函數(shù)源织,按照代碼寫的順序依次執(zhí)行:如果這個(gè)變量名在本作用域中還沒有定義翩伪,則在本作用域中聲明這個(gè)函數(shù)名,并且賦值為對應(yīng)的函數(shù)谈息,如果定義了這個(gè)變量缘屹,在可寫的情況下重新給這個(gè)變量賦值為這個(gè)函數(shù),否則拋出異常侠仇。
5. 處理 "arguments"(沒有定義過才聲明和賦值): 
如果在本作用域中沒有定義 arguments轻姿,則在本作用域中聲明arguments并給其賦值。
6. 處理變量聲明(沒有定義過才聲明傅瞻,不賦值):
對于所有變量聲明踢代,按照代碼寫的順序依次執(zhí)行:如果在本作用域中沒有定義這個(gè)變量盲憎,則在本作用域中聲明這個(gè)變量嗅骄,賦值為undefined
7. 然后執(zhí)行函數(shù)代碼。(當(dāng)然是去變量定義里面的 var 執(zhí)行)

3饼疙、new一個(gè)對象的過程中發(fā)生了什么嘛

1. 創(chuàng)建空對象溺森;
var obj = {};
2. 設(shè)置新對象的constructor屬性為構(gòu)造函數(shù)的名稱,設(shè)置新對象的__proto__屬性指向構(gòu)造函數(shù)的prototype對象窑眯;
obj.__proto__ = ClassA.prototype;
3. 使用新對象調(diào)用函數(shù)屏积,函數(shù)中的this被指向新實(shí)例對象:
ClassA.call(obj);//{}.構(gòu)造函數(shù)();          
4. 如果無返回值或者返回一個(gè)非對象值,則將新對象返回磅甩;如果返回值是一個(gè)新對象的話那么直接直接返回該對象炊林。

4、宏任務(wù)跟微任務(wù)

  • macro-task(宏任務(wù)):包括整體代碼script卷要,setTimeout渣聚,setInterval
  • micro-task(微任務(wù)):Promise,process.nextTick

這一次僧叉,徹底弄懂 JavaScript 執(zhí)行機(jī)制

5奕枝、防抖和節(jié)流

綜合應(yīng)用場景

  • 防抖(debounce):就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果在 n 秒內(nèi)又觸發(fā)了事件瓶堕,則會重新計(jì)算函數(shù)執(zhí)行時(shí)間隘道。
    • search搜索聯(lián)想,用戶在不斷輸入值時(shí),用防抖來節(jié)約請求資源谭梗。
    • window觸發(fā)resize的時(shí)候忘晤,不斷的調(diào)整瀏覽器窗口大小會不斷的觸發(fā)這個(gè)事件,用防抖來讓其只觸發(fā)一次
  • 節(jié)流(throttle):就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)默辨。節(jié)流會稀釋函數(shù)的執(zhí)行頻率德频。
    • 鼠標(biāo)不斷點(diǎn)擊觸發(fā),mousedown(單位時(shí)間內(nèi)只觸發(fā)一次)
    • 監(jiān)聽滾動事件缩幸,比如是否滑到底部自動加載更多壹置,用throttle來判斷
      所謂防抖,就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次表谊,如果在 n 秒內(nèi)又觸發(fā)了事件钞护,則會重新計(jì)算函數(shù)執(zhí)行時(shí)間。

防抖函數(shù)分為非立即執(zhí)行版和立即執(zhí)行版爆办。

  • 非立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)不會立即執(zhí)行难咕,而是在 n 秒后執(zhí)行,如果在 n 秒內(nèi)又觸發(fā)了事件距辆,則會重新計(jì)算函數(shù)執(zhí)行時(shí)間余佃。
  • 立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)會立即執(zhí)行,然后 n 秒內(nèi)不觸發(fā)事件才能繼續(xù)執(zhí)行函數(shù)的效果跨算。
/**
 * @desc 函數(shù)防抖
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @param immediate true 表立即執(zhí)行爆土,false 表非立即執(zhí)行
 */
function debounce(func,wait,immediate) {
    let timeout;

    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(() => {
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}

所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)诸蚕。 節(jié)流會稀釋函數(shù)的執(zhí)行頻率步势。

對于節(jié)流,一般有兩種方式可以實(shí)現(xiàn)背犯,分別是時(shí)間戳版和定時(shí)器版坏瘩。

  • 時(shí)間戳版的函數(shù)觸發(fā)是在時(shí)間段內(nèi)開始的時(shí)候
  • 定時(shí)器版的函數(shù)觸發(fā)是在時(shí)間段內(nèi)結(jié)束的時(shí)候。
/**
 * @desc 函數(shù)節(jié)流
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @param type 1 表時(shí)間戳版漠魏,2 表定時(shí)器版
 */
function throttle(func, wait ,type) {
    if(type===1){
        var previous = 0;
    }else if(type===2){
        var timeout;
    }
    return function() {
        let context = this;
        let args = arguments;
        if(type===1){
            let now = Date.now();

            if (now - previous > wait) {
                func.apply(context, args);
                previous = now;
            }
        }else if(type===2){
            if (!timeout) {
                timeout = setTimeout(() => {
                    timeout = null;
                    func.apply(context, args)
                }, wait)
            }
        }
    }
}

6倔矾、數(shù)組的常用方法

改變原數(shù)組的方法

  • splice() 添加/刪除數(shù)組元素
語法:arrayObject.splice(index,howmany,item1,.....,itemX)
參數(shù):
   1.index:必需。整數(shù)柱锹,規(guī)定添加/刪除項(xiàng)目的位置哪自,使用負(fù)數(shù)可從數(shù)組結(jié)尾處規(guī)定位置。
   2.howmany:可選奕纫。要?jiǎng)h除的項(xiàng)目數(shù)量提陶。如果設(shè)置為 0,則不會刪除項(xiàng)目匹层。
   3.item1, ..., itemX: 可選隙笆。向數(shù)組添加的新項(xiàng)目锌蓄。

返回值: 如果有元素被刪除,返回包含被刪除項(xiàng)目的新數(shù)組。
  • sort() 數(shù)組排序
語法:arrayObject.sort(sortby)
參數(shù):
   1.sortby 可選撑柔。規(guī)定排序順序瘸爽。必須是函數(shù)。铅忿。

返回值: 返回包排序后的新數(shù)組剪决。
  • pop() 刪除一個(gè)數(shù)組中的最后的一個(gè)元素
語法:arrayObject.pop()
參數(shù):無

返回值: 返回被刪除的元素。
  • shift() 刪除數(shù)組的第一個(gè)元素
語法:arrayObject.shift()
參數(shù):無

返回值: 返回被刪除的元素檀训。
  • push() 向數(shù)組的末尾添加元素
語法:arrayObject.push(newelement1,newelement2,....,newelementX)
參數(shù):
   1.newelement1    必需柑潦。要添加到數(shù)組的第一個(gè)元素。
   2.newelement2    可選峻凫。要添加到數(shù)組的第二個(gè)元素渗鬼。
   3.newelementX    可選∮恚可添加若干個(gè)元素譬胎。

返回值: arrayObject 的新長度。
  • unshift() 向數(shù)組的開頭添加一個(gè)或更多元素
語法:arrayObject.unshift(newelement1,newelement2,....,newelementX)
參數(shù):
   1.newelement1    必需命锄。要添加到數(shù)組的第一個(gè)元素堰乔。
   2.newelement2    可選。要添加到數(shù)組的第二個(gè)元素脐恩。
   3.newelementX    可選镐侯。可添加若干個(gè)元素被盈。

返回值: arrayObject 的新長度析孽。
  • reverse() 顛倒數(shù)組中元素的順序
語法:arrayObject.reverse()
參數(shù):無

返回值: 顛倒后的新數(shù)組搭伤。
  • copyWithin() 指定位置的成員復(fù)制到其他位置
語法: array.copyWithin(target, start = 0, end = this.length)
參數(shù):
   1.target(必需):從該位置開始替換數(shù)據(jù)只怎。如果為負(fù)值,表示倒數(shù)怜俐。
   2.start(可選):從該位置開始讀取數(shù)據(jù)身堡,默認(rèn)為 0。如果為負(fù)值拍鲤,表示倒數(shù)贴谎。
   3.end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度季稳。如果為負(fù)值擅这,表示倒數(shù)。

返回值: 返回當(dāng)前數(shù)組景鼠。
  • fill() 填充數(shù)組
語法: array.fill(value, start, end)
參數(shù):
   1.value  必需仲翎。填充的值。
   2.start  可選。開始填充位置溯香。
   3.end    可選鲫构。停止填充位置 (默認(rèn)為 array.length)

返回值: 返回當(dāng)前數(shù)組。

不改變原數(shù)組的方法

  • slice() 淺拷貝數(shù)組的元素
語法: array.slice(begin, end);
參數(shù):
   1.begin(可選): 索引數(shù)值,接受負(fù)值玫坛,從該索引處開始提取原數(shù)組中的元素,默認(rèn)值為0结笨。
   2.end(可選):索引數(shù)值(不包括),接受負(fù)值,在該索引處前結(jié)束提取原數(shù)組元素湿镀,默認(rèn)值為數(shù)組末尾(包括最后一個(gè)元素)炕吸。

返回值: 返回一個(gè)從開始到結(jié)束(不包括結(jié)束)選擇的數(shù)組的一部分淺拷貝到一個(gè)新數(shù)組對象,且原數(shù)組不會被修改勉痴。
  • join() 數(shù)組轉(zhuǎn)字符串
語法:array.join(str)
參數(shù):
   1.str(可選): 指定要使用的分隔符算途,默認(rèn)使用逗號作為分隔符。

返回值: 返回生成的字符串蚀腿。
  • concat() 合并兩個(gè)或多個(gè)數(shù)組
語法: var newArr =oldArray.concat(arrayX,arrayX,......,arrayX)
參數(shù):
   1.arrayX(必須):該參數(shù)可以是具體的值嘴瓤,也可以是數(shù)組對象±蚋疲可以是任意多個(gè)廓脆。

返回值: 返回返回合并后的新數(shù)組。
  • indexOf() 查找數(shù)組是否存在某個(gè)元素
語法:array.indexOf(searchElement,fromIndex)
參數(shù):
   1.searchElement(必須):被查找的元素
   2.fromIndex(可選):開始查找的位置(不能大于等于數(shù)組的長度磁玉,返回-1)停忿,接受負(fù)值,默認(rèn)值為0蚊伞。

返回值: 返回下標(biāo)
  • lastIndexOf() 查找指定元素在數(shù)組中的最后一個(gè)位置
語法:arr.lastIndexOf(searchElement,fromIndex)
參數(shù):
   1.searchElement(必須): 被查找的元素
   2.fromIndex(可選): 逆向查找開始位置席赂,默認(rèn)值數(shù)組的長度-1,即查找整個(gè)數(shù)組时迫。

返回值: 方法返回指定元素,在數(shù)組中的最后一個(gè)的索引颅停,如果不存在則返回 -1年缎。(從數(shù)組后面往前查找)
  • includes() 查找數(shù)組是否包含某個(gè)元素
語法: array.includes(searchElement,fromIndex=0)
參數(shù):
   1.searchElement(必須):被查找的元素
   2.fromIndex(可選):默認(rèn)值為0师枣,參數(shù)表示搜索的起始位置,接受負(fù)值铣猩。正值超過數(shù)組長度溺欧,數(shù)組不會被搜索喊熟,返回false。負(fù)值絕對值超過長數(shù)組度姐刁,重置從0開始搜索芥牌。

返回值: 返回布爾

7、立即執(zhí)行函數(shù)

聲明一個(gè)匿名函數(shù)聂使,馬上調(diào)用這個(gè)匿名函數(shù)壁拉。目的是保護(hù)內(nèi)部變量不受污染拐叉。

(function(n1, n2) {
    console.log("這是匿名函數(shù)的自執(zhí)行的第一種寫法,結(jié)果為:" + (n1 + n2))
})(10, 100);
(function start(n1, n2) {
    console.log("這是函數(shù)聲明方式的自執(zhí)行的第一種寫法扇商,結(jié)果為:" + (n1 + n2))
})(10, 100);
(function(n1, n2) {
    console.log("這是匿名函數(shù)的自執(zhí)行的第二種寫法凤瘦,結(jié)果為:" + (n1 + n2))
}(10, 100));
(function start(n1, n2) {
    console.log("這是函數(shù)聲明方式的自執(zhí)行的第二種寫法,結(jié)果為:" + (n1 + n2))
}(10, 100));

8案铺、js原型和原型鏈

每個(gè)對象都會在其內(nèi)部初始化一個(gè)屬性蔬芥,就是prototype(原型),當(dāng)我們訪問一個(gè)對象的屬性時(shí)控汉,如果這個(gè)對象內(nèi)部不存在這個(gè)屬性笔诵,那么他就會去prototype里找這個(gè)屬性,這個(gè)prototype又會有自己的prototype姑子,于是就這樣一直找下去乎婿,也就是我們平時(shí)所說的原型鏈的概念。

關(guān)系:instance.constructor.prototype = instance.proto

特點(diǎn):JavaScript對象是通過引用來傳遞的街佑,我們創(chuàng)建的每個(gè)新對象實(shí)體中并沒有一份屬于自己的原型副本谢翎,當(dāng)我們修改原型時(shí),與之相關(guān)的對象也會繼承這一改變沐旨。
當(dāng)我們需要一個(gè)屬性時(shí)森逮,JavaScript引擎會先看當(dāng)前對象中是否有這個(gè)屬性,如果沒有的話磁携,就會查找它的prototype對象是否有這個(gè)屬性褒侧,如此遞推下去,一致檢索到Object內(nèi)建對象谊迄。


function Func(){}
Func.prototype.name = "汪某";
Func.prototype.getInfo = function() {
   return this.name;
}
var person = new Func();
console.log(person.getInfo());//"汪某"
console.log(Func.prototype);//Func { name = "汪某", getInfo = function() }

參考:js原型和原型鏈

9闷供、js中call,apply,bind

參考:JavaScript中call,apply,bind方法的總結(jié)。

10统诺、Promise

一句話概括Promise:Promise對象用于異步操作歪脏,它表示一個(gè)尚未完成且預(yù)計(jì)在未來完成的異步操作。

promise是用來解決兩個(gè)問題的:

  • 回調(diào)地獄篙议,代碼難以維護(hù)唾糯,常常第一個(gè)的函數(shù)的輸出是第二個(gè)函數(shù)的輸入這種現(xiàn)象
  • promise可以支持多個(gè)并發(fā)的請求怠硼,獲取并發(fā)請求中的數(shù)據(jù)

這個(gè)promise可以解決異步的問題鬼贱,本身不能說promise是異步的

/*Promise 的簡單實(shí)現(xiàn)*/

class MyPromise {
    constructor(fn) {
        this.resolvedCallbacks = [];
        this.rejectedCallbacks = [];
        this.state = "PADDING";
        this.value = "";
        fn(this.resolve.bind(this), this.reject.bind(this));
    }
    resolve(value) {
        if (this.state === "PADDING") {
            this.state = "RESOLVED";
            this.value = value;
            this.resolvedCallbacks.forEach(cb => cb());
        }
    }
    reject(value) {
        if (this.state === "PADDING") {
            this.state = "REJECTED";
            this.value = value;
            this.rejectedCallbacks.forEach(cb => cb());
        }
    }
    then(resolve = function() {}, reject = function() {}) {
        if (this.state === "PADDING") {
            this.resolvedCallbacks.push(resolve);
            this.rejectedCallbacks.push(reject);
        }
        if (this.state === "RESOLVED") {
            resolve(this.value);
        }
        if (this.state === "REJECTED") {
            reject(this.value);
        }
    }
}

11、async/await

如何使用 Async 函數(shù)

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

上面代碼指定50毫秒以后香璃,輸出hello world这难。 進(jìn)一步說,async函數(shù)完全可以看作多個(gè)異步操作葡秒,包裝成的一個(gè) Promise 對象姻乓,而await命令就是內(nèi)部then命令的語法糖嵌溢。

待補(bǔ)充。蹋岩。赖草。

12、深拷貝剪个、淺拷貝

淺拷貝和深拷貝都只針對于引用數(shù)據(jù)類型秧骑,淺拷貝只復(fù)制指向某個(gè)對象的指針,而不復(fù)制對象本身扣囊,新舊對象還是共享同一塊內(nèi)存乎折;但深拷貝會另外創(chuàng)造一個(gè)一模一樣的對象,新對象跟原對象不共享內(nèi)存侵歇,修改新對象不會改到原對象骂澄;

區(qū)別:淺拷貝只復(fù)制對象的第一層屬性、深拷貝可以對對象的屬性進(jìn)行遞歸復(fù)制惕虑;

image

淺拷貝的實(shí)現(xiàn)方式

  1. 自定義函數(shù)
function simpleCopy (initalObj) {
   var obj = {};
   for ( var i in initalObj) {
    obj[i] = initalObj[i];
   }
   return obj;
}
  1. ES6 的 Object.assign()
let newObj = Object.assign({}, obj);
  1. ES6 的對象擴(kuò)展
let newObj = {...obj};

深拷貝的實(shí)現(xiàn)方式

  1. JSON.stringify 和 JSON.parse

用 JSON.stringify 把對象轉(zhuǎn)換成字符串坟冲,再用 JSON.parse 把字符串轉(zhuǎn)換成新的對象。

let newObj = JSON.parse(JSON.stringify(obj));
  1. lodash

用 lodash 函數(shù)庫提供的 _.cloneDeep 方法實(shí)現(xiàn)深拷貝溃蔫。

var _ = require('lodash');
var newObj = _.cloneDeep(obj);
  1. 自己封裝
function deepClone(obj) {
    let objClone = Array.isArray(obj) ? [] : {};
    if (obj && typeof obj === "object") {
        // for...in 會把繼承的屬性一起遍歷
        for (let key in obj) {
            // 判斷是不是自有屬性樱衷,而不是繼承屬性
            if (obj.hasOwnProperty(key)) {
                //判斷ojb子元素是否為對象或數(shù)組,如果是酒唉,遞歸復(fù)制
                if (obj[key] && typeof obj[key] === "object") {
                    objClone[key] = this.deepClone(obj[key]);
                } else {
                    //如果不是矩桂,簡單復(fù)制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}

13、跨域

跨域需要針對瀏覽器的同源策略來理解痪伦,同源策略指的是請求必須是同一個(gè)端口侄榴,同一個(gè)協(xié)議,同一個(gè)域名网沾,不同源的客戶端腳本在沒有明確授權(quán)的情況下癞蚕,不能讀寫對方資源。

受瀏覽器同源策略的影響辉哥,不是同源的腳本不能操作其他源下面的對象桦山。想要操作另一個(gè)源下的對象是就需要跨域。

  • jsonp
  • iframe
  • 跨域資源共享(CORS)
  • nginx 代理跨域

14醋旦、for in 和 for of

  • for in
1.一般用于遍歷對象的可枚舉屬性恒水。以及對象從構(gòu)造函數(shù)原型中繼承的屬性。對于每個(gè)不同的屬性饲齐,語句都會被執(zhí)行钉凌。
2.不建議使用for in 遍歷數(shù)組,因?yàn)檩敵龅捻樞蚴遣还潭ǖ摹?3.如果迭代的對象的變量值是null或者undefined, for in不執(zhí)行循環(huán)體捂人,建議在使用for in循環(huán)之前御雕,先檢查該對象的值是不是null或者undefined
  • for of
1.for…of 語句在可迭代對象(包括 Array矢沿,Map,Set酸纲,String捣鲸,TypedArray,arguments 對象等等)上創(chuàng)建一個(gè)迭代循環(huán)闽坡,調(diào)用自定義迭代鉤子摄狱,并為每個(gè)不同屬性的值執(zhí)行語句

遍歷對象

var s = {
    a: 1,
    b: 2,
    c: 3
}
var s1 = Object.create(s);
for (var prop in s1) {
    console.log(prop); //a b c
    console.log(s1[prop]); //1 2 3
}
for (let prop of s1) {
    console.log(prop); //報(bào)錯(cuò)如下 Uncaught TypeError: s1 is not iterable 
}
for (let prop of Object.keys(s1)) {
    console.log(prop); // a b c
    console.log(s1[prop]); //1 2 3
}

15、如何阻止冒泡无午?

冒泡型事件:事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對象)的順序觸發(fā)媒役。

w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true宪迟。

//阻止冒泡行為 
function stopBubble(e) { 
//如果提供了事件對象酣衷,則這是一個(gè)非IE瀏覽器 
if ( e && e.stopPropagation ) 
    //因此它支持W3C的stopPropagation()方法 
    e.stopPropagation(); 
else 
    //否則,我們需要使用IE的方式來取消事件冒泡 
    window.event.cancelBubble = true; 
}

16次泽、如何阻止默認(rèn)事件穿仪?

w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false

//阻止瀏覽器的默認(rèn)行為 
function stopDefault( e ) { 
    //阻止默認(rèn)瀏覽器動作(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函數(shù)器默認(rèn)動作的方式 
    else 
        window.event.returnValue = false; 
    return false; 
}

17意荤、var,let,const

//變量提升
console.log(a);  // undefined
console.log(b);  // 報(bào)錯(cuò)
console.log(c);  // 報(bào)錯(cuò)
var a = 1;
let b = 2;
const c = 3;

// 全局聲明
console.log(window.a) //  1 

// 重復(fù)聲明
let b  = 200;//報(bào)錯(cuò)

其實(shí)這里很容易理解啊片,var是可以變量提升的。而let和const是必須聲明后才能調(diào)用的玖像。 對于let和const來說紫谷,這里就是暫緩性死區(qū)。


image

18捐寥、Class

es6新增的Class其實(shí)也是語法糖笤昨,js底層其實(shí)沒有class的概念的,其實(shí)也是原型繼承的封裝握恳。

class People {
    constructor(props) {
        this.props = props;
        this.name = '汪某';
    }
    callMyName() {
        console.log(this.name);
    }
}
class Name extends People { // extends 其實(shí)就是繼承了哪個(gè)類
    constructor(props) {
        //  super相當(dāng)于 把類的原型拿過來 
        //  People.call(this, props)
        super(props)
    }
    callMyApple() {
        console.log('我是汪某瞒窒!')
    }
}

let a = new Name('啊啊啊')
a.callMyName(); //汪某
a.callMyApple(); // 我是汪某!

19乡洼、Set

<font color=red>Set</font>數(shù)據(jù)結(jié)構(gòu)類似數(shù)組崇裁,但所有成員的值唯一。

let a = new Set();
[1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x));
for(let k of a){
    console.log(k)
};
// 1 2 3 4 5

基本使用

let a = new Set([1,2,3,3,4]);
[...a]; // [1,2,3,4]
a.size; // 4

// 數(shù)組去重
[...new Set([1,2,3,4,4,4])];// [1,2,3,4]

方法

  • add(value):添加某個(gè)值束昵,返回 Set 結(jié)構(gòu)本身拔稳。
  • delete(value):刪除某個(gè)值,返回一個(gè)布爾值妻怎,表示刪除是否成功壳炎。
  • has(value):返回一個(gè)布爾值,表示該值是否為Set的成員逼侦。
  • clear():清除所有成員匿辩,沒有返回值。
let a = new Set();
a.add(1).add(2); // a => Set(2) {1, 2}
a.has(2);        // true
a.has(3);        // false
a.delete(2);     // true  a => Set(1) {1}
a.clear();       // a => Set(0) {}

20榛丢、Map

<font color=red>Map</font>結(jié)構(gòu)提供了“值—值”的對應(yīng)铲球,是一種更完善的 Hash 結(jié)構(gòu)實(shí)現(xiàn)。

let a = new Map();
let b = {name: 'leo' };
a.set(b,'my name'); // 添加值
a.get(b);           // 獲取值
a.size;      // 獲取總數(shù)
a.has(b);    // 查詢是否存在
a.delete(b); // 刪除一個(gè)值
a.clear();   // 清空所有成員 無返回

基本使用

  • 傳入數(shù)組作為參數(shù)晰赞,指定鍵值對的數(shù)組稼病。
let a = new Map([
    ['name','wzx'],
    ['age',23]
])
  • 如果對同一個(gè)鍵多次賦值,后面的值將覆蓋前面的值掖鱼。
let a = new Map();
a.set(1,'aaa').set(1,'bbb');
a.get(1); // 'bbb'
  • 如果讀取一個(gè)未知的鍵然走,則返回undefined。
new Map().get('asdsad'); // undefined
  • 同樣的值的兩個(gè)實(shí)例戏挡,在 Map 結(jié)構(gòu)中被視為兩個(gè)鍵芍瑞。
let a = new Map();
let a1 = ['aaa'];
let a2 = ['aaa'];
a.set(a1,111).set(a2,222);
a.get(a1); // 111
a.get(a2); // 222

方法

  • keys():返回鍵名的遍歷器。
  • values():返回鍵值的遍歷器褐墅。
  • entries():返回所有成員的遍歷器拆檬。
  • forEach():遍歷 Map 的所有成員。
let a = new Map([
    ['name', 'leo'],
    ['age', 18]
])
for (let i of a.keys()) {
    console.log(i)
};
//name 
//age

for (let i of a.values()) {
    console.log(i)
};
//leo 
//18

for (let i of a.entries()) {
    console.log(i)
};
//["name", "leo"]

a.forEach((v, k, m) => {
    console.log(`key:${k},value:${v},map:${m}`)
})
//["age", 18]

三妥凳、手?jǐn)]代碼

1竟贯、實(shí)現(xiàn)一個(gè)new操作符

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return;
        ret;
    }
    return;
    res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);

2、實(shí)現(xiàn)一個(gè)call或 apply

  • call
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}
  • apply
Function.prototype.apply2 = function (context, arr) {
    var context = Object(context) || window;
    context.fn = this;

    var result;
    if (!arr) {
        result = context.fn();
    }
    else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push('arr[' + i + ']');
        }
        result = eval('context.fn(' + args + ')')
    }

    delete context.fn
    return result;
}

參考:JavaScript深入之call和apply的模擬實(shí)現(xiàn)

3逝钥、實(shí)現(xiàn)一個(gè)Function.bind

Function.prototype.bind2 = function (context) {
    if (typeof this !== "function") {
      throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
    }
    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);
    var fNOP = function () {};
    var fbound = function () {
        self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
    }
    fNOP.prototype = this.prototype;
    fbound.prototype = new fNOP();
    return fbound;
}

參考:JavaScript深入之bind的模擬實(shí)現(xiàn)

4屑那、實(shí)現(xiàn)一個(gè)繼承

function Parent(name) {
    this.name = name;
}

Parent.prototype.sayName = function() {
    console.log('parent name:', this.name);
}

function Child(name, parentName) {
    Parent.call(this, parentName);
    this.name = name;
}

function create(proto) {
    function F() {}
    F.prototype = proto;
    return new F();
}
Child.prototype = create(Parent.prototype);
Child.prototype.sayName = function() {
    console.log('child name:', this.name);
}

Child.prototype.constructor = Child;
var parent = new Parent('汪某');
parent.sayName();// parent name: 汪某
var child = new Child('son', '汪某');

5、手寫一個(gè)Promise(中高級必考)

面試夠用版

function myPromise(constructor) {
    let self = this;
    self.status = "pending"
        //定義狀態(tài)改變前的初始狀態(tài)
    self.value = undefined;
    //定義狀態(tài)為resolved的時(shí)候的狀態(tài)
    self.reason = undefined;
    //定義狀態(tài)為rejected的時(shí)候的狀態(tài)
    function resolve(value) {
        //兩個(gè)==="pending"艘款,保證了狀態(tài)的改變是不可逆的
        if (self.status === "pending") {
            self.value = value;
            self.status = "resolved";
        }
    }
    function reject(reason) {
        //兩個(gè)==="pending"齐莲,保證了狀態(tài)的改變是不可逆的
        if (self.status === "pending") {
            self.reason = reason;
            self.status = "rejected";
        }
    }
    //捕獲構(gòu)造異常
    try {
        constructor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

//同時(shí),需要在 myPromise的原型上定義鏈?zhǔn)秸{(diào)用的 then方法:
myPromise.prototype.then = function(onFullfilled, onRejected) {
    let self = this;
    switch (self.status) {
        case "resolved":
            onFullfilled(self.value);
            break;
        case "rejected":
            onRejected(self.reason);
            break;
        default:
    }
}

//測試一下:
var p = new myPromise(function(resolve, reject) {
    resolve(1)
});
p.then(function(x) {
    console.log(x)
})

高級版請參考:史上最最最詳細(xì)的手寫Promise教程

6磷箕、手寫防抖(Debouncing)和節(jié)流(Throttling)

完整版詳見上方选酗,此處給出面試版

// 防抖函數(shù)
function debounce(fn, wait) {
    let timer;
    return function() {
        if (timer) clearTimeout(timer)
        timer = setTimeout(() => {
            fn.apply(this, arguments)
        }, wait)
    }
}
// 節(jié)流函數(shù)
function throttle(fn, wait) {
    let prev = new Date();
    return function() {
        const args = arguments;
        const now = new Date();
        if (now - prev > wait) {
            fn.apply(this, args);
            prev = new Date();
        }
    }
}

7、手寫一個(gè)JS深拷貝

面試版

function deepCopy(obj) {
    //判斷是否是簡單數(shù)據(jù)類型岳枷,
    if (typeof obj == "object") {
        //復(fù)雜數(shù)據(jù)類型
        var result = obj.constructor == Array ? [] : {};
        for (let i in obj) {
            result[i] = typeof obj[i] == "object" ? deepCopy(obj[i]) : obj[i];
        }
    } else {
        //簡單數(shù)據(jù)類型 直接 == 賦值
        var result = obj;
    }
    return result;
}

四芒填、VUE

1、Vue2.0的雙向數(shù)據(jù)綁定原理是什么空繁?

vue.js 是采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式殿衰,通過Object.defineProperty()來劫持各個(gè)屬性的setter,getter盛泡,在數(shù)據(jù)變動時(shí)發(fā)布消息給訂閱者闷祥,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。

//vue實(shí)現(xiàn)數(shù)據(jù)雙向綁定的原理就是用Object.defineproperty()重新定義(set方法)對象設(shè)置屬性值和(get方法)獲取屬性值的操縱來實(shí)現(xiàn)的。
//Object.property()方法的解釋:Object.property(參數(shù)1凯砍,參數(shù)2箱硕,參數(shù)3)  返回值為該對象obj
//其中參數(shù)1為該對象(obj),參數(shù)2為要定義或修改的對象的屬性名悟衩,參數(shù)3為屬性描述符剧罩,屬性描述符是一個(gè)對象,主要有兩種形式:數(shù)據(jù)描述符和存取描述符座泳。這兩種對象只能選擇一種使用惠昔,不能混合使用。而get和set屬于存取描述符對象的屬性挑势。
//這個(gè)方法會直接在一個(gè)對象上定義一個(gè)新屬性或者修改對象上的現(xiàn)有屬性镇防,并返回該對象。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <div id="myapp">
        <input v-model="message" /><br>
        <span v-bind="message"></span>
    </div>
    <script type="text/javascript">
        var model = {
            message: ""
        };
        var models = myapp.querySelectorAll("[v-model=message]");
        for (var i = 0; i < models.length; i++) {
            models[i].onkeyup = function() {
                model[this.getAttribute("v-model")] = this.value;
            }
        }
        // 觀察者模式 / 鉤子函數(shù)
        // defineProperty 來定義一個(gè)對象的某個(gè)屬性
        Object.defineProperty(model, "message", {
            set: function(newValue) {
                var binds = myapp.querySelectorAll("[v-bind=message]");
                for (var i = 0; i < binds.length; i++) {
                    binds[i].innerHTML = newValue;
                };
                var models = myapp.querySelectorAll("[v-model=message]");
                for (var i = 0; i < models.length; i++) {
                    models[i].value = newValue;
                };
                this.value = newValue;
            },
            get: function() {
                return this.value;
            }
        })
    </script>
</body>
</html>

Vue3.0將用原生Proxy替換Object.defineProperty

為什么要替換Object.defineProperty潮饱?

  • 在Vue中来氧,Object.defineProperty無法監(jiān)控到數(shù)組下標(biāo)的變化,導(dǎo)致直接通過數(shù)組的下標(biāo)給數(shù)組設(shè)置值饼齿,不能實(shí)時(shí)響應(yīng)饲漾。
  • Object.defineProperty只能劫持對象的屬性,因此我們需要對每個(gè)對象的每個(gè)屬性進(jìn)行遍歷。

什么是Proxy

  • Proxy是 ES6 中新增的一個(gè)特性缕溉,翻譯過來意思是"代理"考传,用在這里表示由它來“代理”某些操作。 Proxy 讓我們能夠以簡潔易懂的方式控制外部對對象的訪問证鸥。其功能非常類似于設(shè)計(jì)模式中的代理模式僚楞。
  • Proxy 可以理解成,在目標(biāo)對象之前架設(shè)一層“攔截”枉层,外界對該對象的訪問泉褐,都必須先通過這層攔截,因此提供了一種機(jī)制鸟蜡,可以對外界的訪問進(jìn)行過濾和改寫膜赃。
  • 使用 Proxy 的核心優(yōu)點(diǎn)是可以交由它來處理一些非核心邏輯(如:讀取或設(shè)置對象的某些屬性前記錄日志;設(shè)置對象的某些屬性值前揉忘,需要驗(yàn)證跳座;某些屬性的訪問控制等)。 從而可以讓對象只需關(guān)注于核心邏輯泣矛,達(dá)到關(guān)注點(diǎn)分離疲眷,降低對象復(fù)雜度等目的。

2您朽、請?jiān)敿?xì)說下你對vue生命周期的理解狂丝?

總共分為8個(gè)階段創(chuàng)建前/后,載入前/后,更新前/后几颜,銷毀前/后

  • beforeCreate 創(chuàng)建前執(zhí)行(vue實(shí)例的掛載元素$el和數(shù)據(jù)對象data都為undefined倍试,還未初始化)
  • created 完成創(chuàng)建 (完成了data數(shù)據(jù)初始化,el還未初始化)
  • beforeMount 載入前(vue實(shí)例的$el和data都初始化了菠剩,但還是掛載之前為虛擬的dom節(jié)點(diǎn)易猫,data.message還未替換耻煤。)
  • mounted 載入后html已經(jīng)渲染(vue實(shí)例掛載完成具壮,data.message成功渲染。)
  • beforeUpdate 更新前狀態(tài)(view層的數(shù)據(jù)變化前哈蝇,不是data中的數(shù)據(jù)改變前)
  • updated 更新狀態(tài)后
  • beforeDestroy 銷毀前
  • destroyed 銷毀后 (在執(zhí)行destroy方法后棺妓,對data的改變不會再觸發(fā)周期函數(shù),說明此時(shí)vue實(shí)例已經(jīng)解除了事件監(jiān)聽以及和dom的綁定炮赦,但是dom結(jié)構(gòu)依然存在)

說一下每一個(gè)階段可以做的事情

  • beforeCreate:可以在這里加一個(gè)loading事件怜跑,在加載實(shí)例時(shí)觸發(fā)。
  • created:初始化完成時(shí)的事件寫這里吠勘,如果這里結(jié)束了loading事件性芬,異步請求也在這里調(diào)用。
  • mounted:掛在元素剧防,獲取到DOM節(jié)點(diǎn)
  • updated:對數(shù)據(jù)進(jìn)行處理的函數(shù)寫這里植锉。
  • beforeDestroy:可以寫一個(gè)確認(rèn)停止事件的確認(rèn)框。

附上一張中文解析圖


image

3峭拘、動態(tài)路由定義和獲取

在 router 目錄下的 index.js 文件中俊庇,對 path 屬性加上 /:id。

使用 router 對象的 params.id 獲取

4鸡挠、vue-router 有哪幾種導(dǎo)航鉤子?

三種

  1. 全局導(dǎo)航鉤子(跳轉(zhuǎn)前進(jìn)行判斷攔截)
    • router.beforeEach(to, from, next),
    • router.beforeResolve(to, from, next),
    • router.afterEach(to, from ,next)
  2. 組件內(nèi)鉤子
    • beforeRouteEnter
    • beforeRouteUpdate
    • beforeRouteLeave
  3. 單獨(dú)路由獨(dú)享組件
    • beforeEnter

5辉饱、組件之間的傳值通信?

  • 父組件向子組件傳值:
    • 子組件在props中創(chuàng)建一個(gè)屬性拣展,用來接收父組件傳過來的值彭沼;
    • 在父組件中注冊子組件链沼;
    • 在子組件標(biāo)簽中添加子組件props中創(chuàng)建的屬性参淫;
    • 把需要傳給子組件的值賦給該屬性
  • 子組件向父組件傳值:
    • 子組件中需要以某種方式(如點(diǎn)擊事件)的方法來觸發(fā)一個(gè)自定義的事件窝爪;
    • 將需要傳的值作為$emit的第二個(gè)參數(shù)陕见,該值將作為實(shí)參傳給響應(yīng)事件的方法浪读;
    • 在父組件中注冊子組件并在子組件標(biāo)簽上綁定自定義事件的監(jiān)聽纷纫。

6牲尺、vuex

是一個(gè)能方便vue實(shí)例及其組件傳輸數(shù)據(jù)的插件 方便傳輸數(shù)據(jù)宪卿,作為公共存儲數(shù)據(jù)的一個(gè)庫

state: 狀態(tài)中心

mutations: 更改狀態(tài)乘寒,同步的

actions: 異步更改狀態(tài)

getters: 獲取狀態(tài)

modules: 將state分成多個(gè)modules望众,便于管理

應(yīng)用場景:單頁應(yīng)用中,組件之間的狀態(tài)。音樂播放烂翰、登錄狀態(tài)夯缺、加入購物車。

網(wǎng)上找的一個(gè)通俗易懂的了解vuex的例子

公司有個(gè)倉庫

1.State(公司的倉庫)

2.Getter(只能取出物品甘耿,包裝一下踊兜,不能改變物品任何屬性)

3.Muitation(倉庫管理員,只有他可以直接存儲到倉庫)

4.Action(公司的物料采購員佳恬,負(fù)責(zé)從外面買東西和接貨捏境, 要往倉庫存東西,告訴倉庫管理員要存什么)

非常要注意的地方:只要刷新或者退出瀏覽器毁葱,倉庫清空垫言。

7、Vue hash 路由和 history 路由的區(qū)別

hash模式url里面永遠(yuǎn)帶著#號倾剿,我們在開發(fā)當(dāng)中默認(rèn)使用這個(gè)模式筷频。那么什么時(shí)候要用history模式呢?如果用戶考慮url的規(guī)范那么就需要使用history模式前痘,因?yàn)閔istory模式?jīng)]有#號凛捏,是個(gè)正常的url適合推廣宣傳。當(dāng)然其功能也有區(qū)別芹缔,比如我們在開發(fā)app的時(shí)候有分享頁面坯癣,那么這個(gè)分享出去的頁面就是用vue或是react做的,咱們把這個(gè)頁面分享到第三方的app里乖菱,有的app里面url是不允許帶有#號的坡锡,所以要將#號去除那么就要使用history模式,但是使用history模式還有一個(gè)問題就是窒所,在訪問二級頁面的時(shí)候鹉勒,做刷新操作,會出現(xiàn)404錯(cuò)誤吵取,那么就需要和后端人配合讓他配置一下apache或是nginx的url重定向禽额,重定向到你的首頁路由上就ok啦。

router有兩種模式:hash模式(默認(rèn))皮官、history模式(需配置mode: 'history')
 | hash | history
-|-|-
url顯示 | 有#脯倒,很Low | 無#,好看 |
回車刷新 | 可以加載到hash值對應(yīng)頁面 | 一般就是404掉了 |
支持版本 | 支持低版本瀏覽器和IE瀏覽器 | 支持低版本瀏覽器和IE瀏覽器 |

8捺氢、diff算法

參考:詳解vue的diff算法

五藻丢、計(jì)算機(jī)

1、DNS 解析的詳細(xì)過程

當(dāng)我們在瀏覽器中輸入一個(gè)URL摄乒,例如”www.google.com”時(shí)悠反,這個(gè)地址并不是谷歌網(wǎng)站真正意義上的地址残黑。互聯(lián)網(wǎng)上每一臺計(jì)算機(jī)的唯一標(biāo)識是它的IP地址斋否,因此我們輸入的網(wǎng)址首先需要先解析為IP地址梨水,這一過程叫做DNS解析。

DNS解析是一個(gè)遞歸查詢的過程茵臭。例如疫诽,我們需要解析”www.google.com”時(shí),會經(jīng)歷以下步驟:

  • 在本地域名服務(wù)器中查詢IP地址旦委,未找到域名奇徒;
  • 本地域名服務(wù)器回向根域名服務(wù)器發(fā)送請求,未找到域名社证;
  • 本地域名服務(wù)器向.com頂級域名服務(wù)器發(fā)送請求逼龟,未找到域名评凝;
  • 本地域名服務(wù)器向.google.com域名服務(wù)器發(fā)送請求追葡,找到該域名,將對應(yīng)的IP返回給本地域名服務(wù)器奕短。

2宜肉、簡述三次握手

HTTP協(xié)議是使用TCP協(xié)議作為其傳輸層協(xié)議的,在拿到服務(wù)器的IP地址后翎碑,瀏覽器客戶端會與服務(wù)器建立TCP連接谬返。該過程包括三次握手:

  • 第一次握手:建立連接時(shí),客戶端向服務(wù)端發(fā)送請求報(bào)文
  • 第二次握手:服務(wù)器收到請求報(bào)文后日杈,如同意連接遣铝,則向客戶端發(fā)送確認(rèn)報(bào)文
  • 第三次握手,客戶端收到服務(wù)器的確認(rèn)后莉擒,再次向服務(wù)器給出確認(rèn)報(bào)文酿炸,完成連接。

三次握手主要是為了防止已經(jīng)失效的請求報(bào)文字段發(fā)送給服務(wù)器涨冀,浪費(fèi)資源填硕。

3、四次揮手

客戶端與服務(wù)器四次揮手鹿鳖,斷開tcp連接扁眯。

  • 第一次揮手:客戶端想分手,發(fā)送消息給服務(wù)器
  • 第二次揮手:服務(wù)器通知客戶端已經(jīng)接受到分手請求翅帜,但還沒做好分手準(zhǔn)備
  • 第三次回收:服務(wù)器已經(jīng)做好分手準(zhǔn)備姻檀,通知客戶端
  • 第四次揮手:客戶端發(fā)送消息給服務(wù)器,確定分手涝滴,服務(wù)器關(guān)閉連接

最后

以上為本小白個(gè)人總結(jié)绣版,如有不對的地方周荐,歡迎各位大佬在評論區(qū)指正,共勉僵娃!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末概作,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子默怨,更是在濱河造成了極大的恐慌讯榕,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匙睹,死亡現(xiàn)場離奇詭異愚屁,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)痕檬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門霎槐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人梦谜,你說我怎么就攤上這事丘跌。” “怎么了唁桩?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵闭树,是天一觀的道長。 經(jīng)常有香客問我荒澡,道長报辱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任单山,我火速辦了婚禮碍现,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘米奸。我一直安慰自己昼接,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布躏升。 她就那樣靜靜地躺著辩棒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膨疏。 梳的紋絲不亂的頭發(fā)上一睁,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機(jī)與錄音佃却,去河邊找鬼者吁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饲帅,可吹牛的內(nèi)容都是我干的复凳。 我是一名探鬼主播瘤泪,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼育八!你這毒婦竟也來了对途?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤髓棋,失蹤者是張志新(化名)和其女友劉穎实檀,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體按声,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膳犹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了签则。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片须床。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖渐裂,靈堂內(nèi)的尸體忽然破棺而出豺旬,到底是詐尸還是另有隱情,我是刑警寧澤芯义,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布哈垢,位于F島的核電站,受9級特大地震影響扛拨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜举塔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一绑警、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧央渣,春花似錦计盒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拔第,卻和暖如春咕村,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蚊俺。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工懈涛, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泳猬。 一個(gè)月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓批钠,卻偏偏與公主長得像宇植,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子埋心,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

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

  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,926評論 6 13
  • vue概述 在官方文檔中指郁,有一句話對Vue的定位說的很明確:Vue.js 的核心是一個(gè)允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,193評論 0 25
  • 一:什么是閉包?閉包的用處拷呆? (1)閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)坡氯。在本質(zhì)上,閉包就 是將函數(shù)內(nèi)部和函數(shù)外...
    xuguibin閱讀 9,539評論 1 52
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,104評論 0 21
  • ??JavaScript 與 HTML 之間的交互是通過事件實(shí)現(xiàn)的。 ??事件啥供,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,474評論 1 11