面試完50我的後我寫下這篇總結

  2019年的春節來的彷佛格外的早,過完年相信不少童鞋都開始蠢蠢欲動了;筆者總結了多篇教程,結合平時本身的面試經歷,整理了這份文檔,但願幫助你們來突擊一下前端知識的盲區。文章很長很長很長。。。。(建議先收藏,技術大佬請Ctrl+F4,面向基礎css

整理不易,但願你們關注公衆號【前端壹讀】,更多前端原創好文等着你。html

1、CSS

盒模型

  CSS盒模型本質上是一個盒子,封裝周圍的HTML元素,它包括:邊距margin,邊框border,填充padding,和實際內容content。盒模型容許咱們在其它元素和周圍元素邊框之間的空間放置元素。前端

Box-Model.jpg

box-sizing: content-box(W3C盒模型,又名標準盒模型):元素的寬高大小表現爲內容的大小。 box-sizing: border-box(IE盒模型,又名怪異盒模型):元素的寬高表現爲內容 + 內邊距 + 邊框的大小。背景會延伸到邊框的外沿。vue

CSS3的新特性

  • word-wrap 文字換行
  • text-overflow 超過指定容器的邊界時如何顯示
  • text-decoration 文字渲染
  • text-shadow文字陰影
  • gradient漸變效果
  • transition過渡效果 transition-duration:過渡的持續時間
  • transform拉伸,壓縮,旋轉,偏移等變換
  • animation動畫

transition和animation的區別:node

  Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition須要觸發一個事件才能改變屬性,而animation不須要觸發任何事件的狀況下才會隨時間改變屬性值,而且transition爲2幀,從from .... to,而animation能夠一幀一幀的。react

CSS選擇器及其優先級

  • !important
  • 內聯樣式style=""
  • ID選擇器#id
  • 類選擇器/屬性選擇器/僞類選擇器.class.active[href=""]
  • 元素選擇器/關係選擇器/僞元素選擇器html+div>span::after
  • 通配符選擇器*

BFC

BFC(Block Formatting Context)格式化上下文,是Web頁面中盒模型佈局的CSS渲染模式,指一個獨立的渲染區域或者說是一個隔離的獨立容器。 webpack

BFC應用

  • 防止margin重疊
  • 清除內部浮動
  • 自適應兩(多)欄佈局
  • 防止字體環繞

觸發BFC條件

  • 根元素
  • float的值不爲none
  • overflow的值不爲visible
  • display的值爲inline-block、table-cell、table-caption
  • position的值爲absolute、fixed

BFC的特性

  • 內部的Box會在垂直方向上一個接一個的放置。
  • 垂直方向上的距離由margin決定
  • bfc的區域不會與float的元素區域重疊。
  • 計算bfc的高度時,浮動元素也參與計算
  • bfc就是頁面上的一個獨立容器,容器裏面的子元素不會影響外面元素。

div水平居中

  1. 行內元素
.parent {
    text-align: center;
}
複製代碼
  1. 塊級元素
.son {
    margin: 0 auto;
}
複製代碼
  1. flex佈局
.parent {
    display: flex;
    justify-content: center;
}
複製代碼
  1. 絕對定位定寬
.son {
    position: absolute;
    width: 寬度;
    left: 50%;
    margin-left: -0.5*寬度
}
複製代碼
  1. 絕對定位不定寬
.son {
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
}
複製代碼
  1. left/right: 0
.son {
    position: absolute;
    width: 寬度;
    left: 0;
    right: 0;
    margin: 0 auto;
}
複製代碼

div垂直居中

  1. 行內元素
.parent {
    height: 高度;
}
.son {
    line-height: 高度;
}
複製代碼
  1. table
.parent {
  display: table;
}
.son {
  display: table-cell;
  vertical-align: middle;
}
複製代碼
  1. flex
.parent {
    display: flex;
    align-items: center;
}
複製代碼
  1. 絕對定位定高
.son {
    position: absolute;
    top: 50%;
    height: 高度;
    margin-top: -0.5高度;
}
複製代碼
  1. 絕對定位不定高
.son {
    position: absolute;
    top: 50%;
    transform: translate( 0, -50%);
}
複製代碼
  1. top/bottom: 0;
.son {
    position: absolute;
    height: 高度;
    top: 0;
    bottom: 0;
    margin: auto 0;
}
複製代碼

絕對定位和相對定位

  • absolute 絕對定位 相對於最近的已定位的祖先元素, 有已定位(指position不是static的元素)祖先元素, 以最近的祖先元素爲參考標準。若是無已定位祖先元素, 以body元素爲偏移參照基準, 徹底脫離了標準文檔流。ios

  • fixed 固定定位的元素會相對於視窗來定位,這意味着即使頁面滾動,它仍是會停留在相同的位置。一個固定定位元素不會保留它本來在頁面應有的空隙。css3

共同點:改變行內元素的呈現方式,都脫離了文檔流;不一樣點:absolute的」根元素「是能夠設置的,fixed的「根元素」固定爲瀏覽器窗口web

flex佈局

採用 Flex 佈局的元素,稱爲 Flex 容器(flex container),簡稱"容器"。它的全部子元素自動成爲容器成員,稱爲 Flex 項目(flex item),簡稱「項目」。

flex.jpeg

  1. 父元素屬性
屬性名 屬性值 備註
display flex 定義了一個flex容器,它的直接子元素會接受這個flex環境
flex-direction row,row-reverse,column,column-reverse 決定主軸的方向
flex-wrap nowrap,wrap,wrap-reverse 若是一條軸線排不下,如何換行
flex-flow [flex-direction] , [flex-wrap] flex-direction屬性和flex-wrap屬性的簡寫形式,默認值爲row nowrap
justify-content flex-start,flex-end,center,space-between,space-around 設置或檢索彈性盒子元素在主軸(橫軸)方向上的對齊方式
align-items flex-start,flex-end,center,baseline,stretch 設置或檢索彈性盒子元素在側軸(縱軸)方向上的對齊方式
  1. 子元素屬性
屬性名 屬性值 備註
order [int] 默認狀況下flex order會按照書寫順訓呈現,能夠經過order屬性改變,數值小的在前面,還能夠是負數。
flex-grow [number] 設置或檢索彈性盒的擴展比率,根據彈性盒子元素所設置的擴展因子做爲比率來分配剩餘空間
flex-shrink [number] 設置或檢索彈性盒的收縮比率,根據彈性盒子元素所設置的收縮因子做爲比率來收縮空間
flex-basis [length], auto 設置或檢索彈性盒伸縮基準值
align-self auto,flex-start,flex-end,center,baseline,stretch 設置或檢索彈性盒子元素在側軸(縱軸)方向上的對齊方式,能夠覆蓋父容器align-items的設置

讓元素消失

visibility:hidden、display:none、z-index=-一、opacity:0

  1. opacity:0,該元素隱藏起來了,但不會改變頁面佈局,而且,若是該元素已經綁定了一些事件,如click事件也能觸發
  2. visibility:hidden,該元素隱藏起來了,但不會改變頁面佈局,可是不會觸發該元素已經綁定的事件
  3. display:none, 把元素隱藏起來,而且會改變頁面佈局,能夠理解成在頁面中把該元素刪掉
  4. z-index=-1置於其餘元素下面

清除浮動

  1. 在浮動元素後面添加 clear:both 的空 div 元素,
<div class="container">
    <div class="left"></div>
    <div class="right"></div>
    <div style="clear:both"></div>
</div>
複製代碼
  1. 給父元素添加 overflow:hidden 或者 auto 樣式,觸發BFC。
<div class="container">
    <div class="left"></div>
    <div class="right"></div>
</div>
複製代碼
.container{
    width: 300px;
    background-color: #aaa;
    overflow:hidden;
    zoom:1;   /*IE6*/
}
複製代碼
  1. 使用僞元素,也是在元素末尾添加一個點並帶有 clear: both 屬性的元素實現的。
<div class="container clearfix">
    <div class="left"></div>
    <div class="right"></div>
</div>
複製代碼
.clearfix{
    zoom: 1; /*IE6*/
}
.clearfix:after{
    content: ".";
    height: 0;
    clear: both;
    display: block;
    visibility: hidden;
}
複製代碼

推薦使用第三種方法,不會在頁面新增div,文檔結構更加清晰。

calc函數

calc函數是css3新增的功能,可使用calc()計算border、margin、pading、font-size和width等屬性設置動態值。

#div1 {
    position: absolute;
    left: 50px;
    width: calc( 100% / (100px * 2) );
    //兼容寫法
    width: -moz-calc( 100% / (100px * 2) );
    width: -webkit-calc( 100% / (100px * 2) );
    border: 1px solid black;
}
複製代碼

注意點:

  • 須要注意的是,運算符先後都須要保留一個空格,例如:width: calc(100% - 10px);
  • calc()函數支持 "+", "-", "*", "/" 運算;
  • 對於不支持 calc() 的瀏覽器,整個屬性值表達式將被忽略。不過咱們能夠對那些不支持 calc()的瀏覽器,使用一個固定值做爲回退。

移動端rem

rem官方定義『The font size of the root element』,即根元素的字體大小。rem是一個相對的CSS單位,1rem等於html元素上font-size的大小。因此,咱們只要設置html上font-size的大小,就能夠改變1rem所表明的大小。

(function () {
    var html = document.documentElement;
    function onWindowResize() {
        html.style.fontSize = html.getBoundingClientRect().width / 20 + 'px';
    }
    window.addEventListener('resize', onWindowResize);
    onWindowResize();
})();
複製代碼

移動端1px

通常來講,在PC端瀏覽器中,設備像素比(dpr)等於1,1個css像素就表明1個物理像素;可是在retina屏幕中,dpr廣泛是2或3,1個css像素再也不等於1個物理像素,所以比實際設計稿看起來粗很多。

  1. 僞元素+scale
<style> .box{ width: 100%; height: 1px; margin: 20px 0; position: relative; } .box::after{ content: ''; position: absolute; bottom: 0; width: 100%; height: 1px; transform: scaleY(0.5); transform-origin: 0 0; background: red; } </style>

<div class="box"></div>

複製代碼
  1. border-image
div{
    border-width: 1px 0px;
    -webkit-border-image: url(border.png) 2 0 stretch;
    border-image: url(border.png) 2 0 stretch;
}
複製代碼

兩邊寬度固定中間自適應的三欄佈局

聖盃佈局和雙飛翼佈局是前端工程師須要平常掌握的重要佈局方式。二者的功能相同,都是爲了實現一個兩側寬度固定,中間寬度自適應的三欄佈局。

聖盃佈局

<style> body{ min-width: 550px; } #container{ padding-left: 200px; padding-right: 150px; } #container .column{ float: left; } #center{ width: 100%; } #left{ width: 200px; margin-left: -100%; position: relative; right: 200px; } #right{ width: 150px; margin-right: -150px; } </style>
<div id="container">
    <div id="center" class="column">center</div>
    <div id="left" class="column">left</div>
    <div id="right" class="column">right</div>
</div>
複製代碼

Layout.gif

雙飛翼佈局

<style> body { min-width: 500px; } #container { width: 100%; } .column { float: left; } #center { margin-left: 200px; margin-right: 150px; } #left { width: 200px; margin-left: -100%; } #right { width: 150px; margin-left: -150px; } </style>
<div id="container" class="column">
    <div id="center">center</div>
</div>
<div id="left" class="column">left</div>
<div id="right" class="column">right</div>

複製代碼

僞類和僞元素

css引入僞類和僞元素概念是爲了格式化文檔樹之外的信息。也就是說,僞類和僞元素都是用來修飾不在文檔樹中的部分。

before-after.jpg

僞類

僞類存在的意義是爲了經過選擇器找到那些不存在DOM樹中的信息以及不能被常規CSS選擇器獲取到的信息。

  1. 獲取不存在與DOM樹中的信息。好比標籤的:link、visited等,這些信息不存在與DOM樹結構中,只能經過CSS選擇器來獲取;
  2. 獲取不能被常規CSS選擇器獲取的信息。好比:要獲取第一個子元素,咱們沒法用常規的CSS選擇器獲取,但能夠經過 :first-child 來獲取到。

weilei.png

僞元素

僞元素用於建立一些不在文檔樹中的元素,併爲其添加樣式。好比說,咱們能夠經過:before來在一個元素前增長一些文本,併爲這些文本添加樣式。雖然用戶能夠看到這些文本,可是這些文本實際上不在文檔樹中。常見的僞元素有:::before::after::first-line::first-letter::selection::placeholder

所以,僞類與僞元素的區別在於:有沒有建立一個文檔樹以外的元素。

::after和:after的區別

在實際的開發工做中,咱們會看到有人把僞元素寫成:after,這實際是 CSS2 與 CSS3新舊標準的規定不一樣而致使的。

CSS2 中的僞元素使用1個冒號,在 CSS3 中,爲了區分僞類和僞元素,規定僞元素使用2個冒號。因此,對於 CSS2 標準的老僞元素,好比:first-line:first-letter:before:after,寫一個冒號瀏覽器也能識別,但對於 CSS3 標準的新僞元素,好比::selection,就必須寫2個冒號了。

CSS畫圓半圓扇形三角梯形

/* 半圓 */
.half-circle{
    height: 50px;
    border-radius: 50px 50px 0 0;
}
/* 扇形 */
.sector{
    border-radius: 100px 0 0;
}
/* 三角 */
.triangle{
    width: 0px;
    height: 0px;
    background: none;
    border: 50px solid red;
    border-color: red transparent transparent transparent;
}
/* 梯形 */
.ladder{
    width: 50px;
    height: 0px;
    background: none;
    border: 50px solid red;
    border-color: red transparent transparent transparent;
}
複製代碼

2、JS

JS數據類型

JS基本有5種簡單數據類型:String,Number,Boolean,Null,Undefined。引用數據類型:Object,Array,Function。

判斷數據類型的方法

在寫業務邏輯的時候,常常要用到JS數據類型的判斷,面試常見的案例深淺拷貝也要用到數據類型的判斷。

typeof

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof undefined);       // undefined
console.log(typeof []);              // object 
console.log(typeof {});              // object
console.log(typeof function(){});    // function
console.log(typeof null);            // object
複製代碼

優勢:可以快速區分基本數據類型 缺點:不能將Object、Array和Null區分,都返回object

instanceof

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true
複製代碼

優勢:可以區分Array、Object和Function,適合用於判斷自定義的類實例對象 缺點:Number,Boolean,String基本數據類型不能判斷

Object.prototype.toString.call()

var toString = Object.prototype.toString;
 
console.log(toString.call(2));                      //[object Number]
console.log(toString.call(true));                   //[object Boolean]
console.log(toString.call('str'));                  //[object String]
console.log(toString.call([]));                     //[object Array]
console.log(toString.call(function(){}));           //[object Function]
console.log(toString.call({}));                     //[object Object]
console.log(toString.call(undefined));              //[object Undefined]
console.log(toString.call(null));                   //[object Null]
複製代碼

優勢:精準判斷數據類型 缺點:寫法繁瑣不容易記,推薦進行封裝後使用

var,let,const的區別

letES6 新添加申明變量的命令,它相似於 var,可是有如下不一樣:

  • var 聲明的變量,其做用域爲該語句所在的函數內,且存在變量提高現象
  • let 聲明的變量,其做用域爲該語句所在的代碼塊內,不存在變量提高
  • const聲明的變量不容許修改

null和undefined區別

Undefined類型只有一個值,即undefined。當聲明的變量還未被初始化時,變量的默認值爲undefined。用法:

  • 變量被聲明瞭,但沒有賦值時,就等於undefined。
  • 調用函數時,應該提供的參數沒有提供,該參數等於undefined。
  • 對象沒有賦值的屬性,該屬性的值爲undefined。
  • 函數沒有返回值時,默認返回undefined。

Null類型也只有一個值,即null。null用來表示還沒有存在的對象,經常使用來表示函數企圖返回一個不存在的對象。用法

  • 做爲函數的參數,表示該函數的參數不是對象。
  • 做爲對象原型鏈的終點。

定義函數的方法

  1. 函數聲明
//ES5
function getSum(){}
function (){}//匿名函數
//ES6
()=>{}
複製代碼
  1. 函數表達式
//ES5
var getSum=function(){}
//ES6
let getSum=()=>{}
複製代碼
  1. 構造函數
const getSum = new Function('a', 'b' , 'return a + b')
複製代碼

JS做用域的理解

JS中的做用域分爲兩種:全局做用域和函數做用域。函數做用域中定義的變量,只能在函數中調用,外界沒法訪問。沒有塊級做用域致使了if或for這樣的邏輯語句中定義的變量能夠被外界訪問,所以ES6中新增了let和const命令來進行塊級做用域的聲明。

更多做用域的瞭解能夠看JS做用域

閉包的理解

簡單來講閉包就是在函數裏面聲明函數,本質上說就是在函數內部和函數外部搭建起一座橋樑,使得子函數能夠訪問父函數中全部的局部變量,可是反之不能夠,這只是閉包的做用之一,另外一個做用,則是保護變量不受外界污染,使其一直存在內存中,在工做中咱們仍是少使用閉包的好,由於閉包太消耗內存,不到萬不得已的時候儘可能不使用。

更多閉包的內容能夠看JS閉包

數組去重

let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];
function unique1(arr){
	let result = [arr[0]];
	for (let i = 1; i < arr.length; i++) {
		let item = arr[i];
		if(result.indexOf(item) == -1){
			result.push(item);
		}
	}
	return result;
}
console.log(unique1(arr));
複製代碼

更多JS去重的方法JS數組去重

call,apply和bind區別

三個函數的做用都是將函數綁定到上下文中,用來改變函數中this的指向;三者的不一樣點在於語法的不一樣。

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
複製代碼

因此applycall的區別是call方法接受的是若干個參數列表,而apply接收的是一個包含多個參數的數組。

而bind()方法建立一個新的函數, 當被調用時,將其this關鍵字設置爲提供的值,在調用新函數時,在任何提供以前提供一個給定的參數序列。

var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()
複製代碼

Demos:

var name = 'window';
var sayName = function (param) {
    console.log('my name is:' + this.name + ',my param is ' + param)
};
//my name is:window,my param is window param
sayName('window param')

var callObj = {
    name: 'call'
};
//my name is:call,my param is call param
sayName.call(callObj, 'call param');


var applyObj = {
    name: 'apply'
};
//my name is:apply,my param is apply param
sayName.apply(applyObj, ['apply param']);

var bindObj = {
    name: 'bind'
}
var bindFn = sayName.bind(bindObj, 'bind param')
//my name is:bind,my param is bind param
bindFn();
複製代碼

==和===區別

  • ==, 兩邊值類型不一樣的時候,要先進行類型轉換,再比較
  • ===,不作類型轉換,類型不一樣的必定不等。

==類型轉換過程:

  1. 若是類型不一樣,進行類型轉換
  2. 判斷比較的是不是 null 或者是 undefined, 若是是, 返回 true .
  3. 判斷二者類型是否爲 string 和 number, 若是是, 將字符串轉換成 number
  4. 判斷其中一方是否爲 boolean, 若是是, 將 boolean 轉爲 number 再進行判斷
  5. 判斷其中一方是否爲 object 且另外一方爲 string、number 或者 symbol , 若是是, 將 object 轉爲原始類型再進行判斷

深拷貝和淺拷貝

淺拷貝

function simpleClone(obj) {
    var result = {};
    for (var i in obj) {
        result[i] = obj[i];
    }
    return result;
}
複製代碼

深拷貝,遍歷對象中的每個屬性

function deepClone(obj) {
    let result;
    if (typeof obj == 'object') {
        result = isArray(obj) ? [] : {}
        for (let i in obj) {
            //isObject(obj[i]) ? deepClone(obj[i]) : obj[i]
            //多謝"朝歌在掘金"指出,多維數組會有問題
            result[i] = isObject(obj[i])||isArray(obj[i])?deepClone(obj[i]):obj[i]
        }
    } else {
        result = obj
    }
    return result
}
function isObject(obj) {
    return Object.prototype.toString.call(obj) == "[object Object]"
}
function isArray(obj) {
    return Object.prototype.toString.call(obj) == "[object Array]"
}
複製代碼

防抖和節流

debounce_throttle.png

防抖

function debounce(fn, delay) {
  let timer = null;
  return function () {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments);
    }, delay);
  }
}
複製代碼

節流

function throttle(fn, cycle) {
  let start = Date.now();
  let now;
  let timer;
  return function () {
    now = Date.now();
    clearTimeout(timer);
    if (now - start >= cycle) {
      fn.apply(this, arguments);
      start = now;
    } else {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
      }, cycle);
    }
  }
}

複製代碼

cookie,sessionStorage和localStorage

  • cookie用來保存登陸信息,大小限制爲4KB左右
  • localStorage是Html5新增的,用於本地數據存儲,保存的數據沒有過時時間,通常瀏覽器大小限制在5MB
  • sessionStorage接口方法和localStorage相似,但保存的數據的只會在當前會話中保存下來,頁面關閉後會被清空。
名稱 生命期 大小限制 與服務器通訊
cookie 通常由服務器生成,可設置失效時間。若是在瀏覽器端生成Cookie,默認是關閉瀏覽器後失效 4KB 每次都會攜帶在HTTP頭中,若是使用cookie保存過多數據會帶來性能問題
localStorage 除非被清除,不然永久保存 5MB 僅在瀏覽器中保存,不與服務器通訊
sessionStorage 僅在當前會話下有效,關閉頁面或瀏覽器後被清除 5MB 僅在瀏覽器中保存,不與服務器通訊

0.1+0.2!=0.3怎麼處理

把須要計算的數字升級(乘以10的n次冪)成計算機可以精確識別的整數,等計算完成後再進行降級(除以10的n次冪),即:

(0.1*10 + 0.2*10)/10 == 0.3 //true
複製代碼

更多關於浮點數精度處理請看JS中浮點數精度問題

JS實現繼承

首先建立一個父類

// 定義一個動物類
function Animal(name, color) {
    // 屬性
    this.name = name || 'Animal';
    this.color = color || ['black'];
    // 實例方法
    this.sleep = function () {
        console.log(this.name + '正在睡覺!');
    }
}
// 原型方法
Animal.prototype.eat = function (food) {
    console.log(this.name + '正在吃:' + food);
};
複製代碼

原型鏈繼承

new了一個空對象,這個空對象指向Animal而且Cat.prototype指向了這個空對象,這種就是基於原型鏈的繼承。

function Cat(name) {
    this.name = name || 'tom'
}
Cat.prototype = new Animal()

var cat = new Cat()
cat.color.push('red')
cat.sleep() //tom正在睡覺!
cat.eat('fish') //tom正在吃:fish
console.log(cat.color) //["black", "red"]
console.log(cat instanceof Animal) //true
console.log(cat instanceof Cat) //true
var new_cat = new Cat()
console.log(new_cat.color) //["black", "red"]
複製代碼
  • 特色:基於原型鏈,既是父類的實例,也是子類的實例。
  • 缺點:1.沒法實現多繼承;2.全部新實例都會共享父類實例的屬性。

構造繼承

function Dog(name) {
    Animal.call(this)
    this.name = name || 'mica'
}
var dog = new Dog()
dog.color.push('blue')
dog.sleep() // mica正在睡覺!
dog.eat('bone') //Uncaught TypeError: dog.eat is not a function
console.log(dog.color) //["black", "blue"]
console.log(dog instanceof Animal) //false
console.log(dog instanceof Dog) //true
var new_dog = new Dog()
console.log(new_dog.color) //["black"]
複製代碼
  • 特色:能夠實現多繼承(call多個),解決了全部實例共享父類實例屬性的問題。
  • 缺點:1.只能繼承父類實例的屬性和方法;2.不能繼承原型上的屬性和方法。

組合繼承

function Mouse(name){
    Animal.call(this)
    this.name = name || 'jerry'
}
Mouse.prototype = new Animal()
Mouse.prototype.constructor = Mouse

var mouse = new Mouse()
mouse.color.push('yellow)
mouse.sleep() //jerry正在睡覺!
mouse.eat('carrot') //jerry正在吃:carrot
console.log(mouse instanceof Animal)//true
console.log(mouse instanceof Mouse)//true
var new_mouse = new Mouse()
console.log(new_mouse.color) //["black"]
複製代碼
  • 特色:能夠繼承實例屬性/方法,也能夠繼承原型屬性/方法
  • 缺點:調用了兩次父類構造函數,生成了兩份實例

3、vue

mvc和mvvm理解

MVC

MVC即Model View Controller,簡單來講就是經過controller的控制去操做model層的數據,而且返回給view層展現。

mvc.png

  • View 接受用戶交互請求
  • View 將請求轉交給Controller處理
  • Controller 操做Model進行數據更新保存
  • 數據更新保存以後,Model會通知View更新
  • View 更新變化數據使用戶獲得反饋

MVVM

MVVM即Model-View-ViewModel,將其中的 View 的狀態和行爲抽象化,讓咱們能夠將UI和業務邏輯分開。MVVM的優勢是低耦合、可重用性、獨立開發。

mvvm.jpg

  • View 接收用戶交互請求
  • View 將請求轉交給ViewModel
  • ViewModel 操做Model數據更新
  • Model 更新完數據,通知ViewModel數據發生變化
  • ViewModel 更新View數據

MVVM模式和MVC有些相似,但有如下不一樣

  • ViewModel 替換了 Controller,在UI層之下
  • ViewModel 向 View 暴露它所須要的數據和指令對象
  • ViewModel 接收來自 Model 的數據

歸納起來,MVVM是由MVC發展而來,經過在Model之上而在View之下增長一個非視覺的組件未來自Model的數據映射到View中。

響應原理

vue採用數據劫持結合發佈者-訂閱者模式的方式,經過Object.defineProperty劫持data屬性的setter,getter,在數據變更時發佈消息給訂閱者,觸發相應的監聽回調。

生命週期函數

  • beforeCreate(建立前) vue實例的掛載元素$el和數據對象 data都是undefined, 還未初始化
  • created(建立後) 完成了 data數據初始化, el還未初始化
  • beforeMount(載入前) vue實例的$el和data都初始化了, 相關的render函數首次被調用
  • mounted(載入後) 此過程當中進行ajax交互
  • beforeUpdate(更新前)
  • updated(更新後)
  • beforeDestroy(銷燬前)
  • destroyed(銷燬後)

組件data爲何返回函數

組件中的data寫成一個函數,數據以函數返回值形式定義,這樣每複用一次組件,就會返回一份新的data。若是單純的寫成對象形式,就使得全部組件實例共用了一份data,形成了數據污染。

vue給對象新增屬性頁面沒有響應

因爲Vue會在初始化實例時對屬性執行getter/setter轉化,因此屬性必須在data對象上存在才能讓Vue將它轉換爲響應式的。Vue提供了$set方法用來觸發視圖更新。

export default {
    data(){
        return {
            obj: {
                name: 'fei'
            }
        }
    },
    mounted(){
        this.$set(this.obj, 'sex', 'man')
    }

}
複製代碼

v-if和v-show區別

v-if 是真正的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建;也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。

v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 的 「display」 屬性進行切換。

因此,v-if 適用於在運行時不多改變條件,不須要頻繁切換條件的場景;v-show 則適用於須要很是頻繁切換條件的場景。

v-model雙向綁定原理

v-model本質上是語法糖,v-model 在內部爲不一樣的輸入元素使用不一樣的屬性並拋出不一樣的事件。

  • text 和 textarea 元素使用 value 屬性和 input 事件
  • checkbox 和 radio 使用 checked 屬性和 change 事件
  • select 字段將 value 做爲 prop 並將 change 做爲事件

因此咱們能夠v-model進行以下改寫:

<input v-model="sth" />
// 等同於
<input :value="sth" @input="sth = $event.target.value" />
複製代碼

這個語法糖必須是固定的,也就是說屬性必須爲value,方法名必須爲:input。

知道了v-model的原理,咱們能夠在自定義組件上實現v-model。

//Parent
<template>
    {{num}}
    <Child v-model="num">
</template>
export default {
    data(){
        return {
            num: 0
        }
    }
}

//Child
<template>
    <div @click="add">Add</div>
</template>
export default {
    props: ['value'],
    methods:{
        add(){
            this.$emit('input', this.value + 1)
        }
    }
}
複製代碼

key的做用

  1. 讓vue精準的追蹤到每個元素,高效的更新虛擬DOM
  2. 觸發過渡
<transition>
  <span :key="text">{{ text }}</span>
</transition>
複製代碼

當text改變時,這個元素的key屬性就發生了改變,在渲染更新時,Vue會認爲這裏新產生了一個元素,而老的元素因爲key不存在了,因此會被刪除,從而觸發了過渡。

scoped屬性做用

在Vue文件中的style標籤上有一個特殊的屬性,scoped。當一個style標籤擁有scoped屬性時候,它的css樣式只能用於當前的Vue組件,可使組件的樣式不相互污染。若是一個項目的全部style標籤都加上了scoped屬性,至關於實現了樣式的模塊化。

scoped屬性的實現原理是給每個dom元素添加了一個獨一無二的動態屬性,給css選擇器額外添加一個對應的屬性選擇器,來選擇組件中的dom。

<template>
    <div class="box">dom</div>
</template>
<style lang="scss" scoped>
.box{
    background:red;
}
</style>
複製代碼

vue將代碼轉譯成以下:

.box[data-v-11c6864c]{
    background:red;
}
<template>
    <div class="box" data-v-11c6864c>dom</div>
</template>
複製代碼

scoped樣式穿透

scoped雖然避免了組件間樣式污染,可是不少時候咱們須要修改組件中的某個樣式,可是又不想去除scoped屬性。

  1. 使用/deep/
//Parent
<template>
<div class="wrap">
    <Child />
</div>
</template>

<style lang="scss" scoped>
.wrap /deep/ .box{
    background: red;
}
</style>

//Child
<template>
    <div class="box"></div>
</template>
複製代碼
  1. 使用兩個style標籤
//Parent
<template>
<div class="wrap">
    <Child />
</div>
</template>

<style lang="scss" scoped>
//其餘樣式
</style>
<style lang="scss">
.wrap .box{
    background: red;
}
</style>

//Child
<template>
    <div class="box"></div>
</template>
複製代碼

ref的做用

  1. 獲取dom元素this.$refs.box
  2. 獲取子組件中的datathis.$refs.box.msg
  3. 調用子組件中的方法this.$refs.box.open()

computed和watch區別

1.當頁面中有某些數據依賴其餘數據進行變更的時候,可使用計算屬性computed。

computed.png

<template>{{fullName}}</template>
export default {
    data(){
        return {
            firstName: 'xie',
            lastName: 'yu fei',
        }
    },
    computed:{
        fullName: function(){
            return this.firstName + ' ' + this.lastName
        }
    }
}
複製代碼

2.watch用於觀察和監聽頁面上的vue實例,若是要在數據變化的同時進行異步操做或者是比較大的開銷,那麼watch爲最佳選擇。

watch.png

<template>{{fullName}}</template>
export default {
    data(){
        return {
            firstName: 'xie',
            lastName: 'xiao fei',
            firstName: 'xie xiao fei'
        }
    },
    watch:{
        firstName(val) {
            this.fullName = val + ' ' + this.lastName
        },
        lastName(val) {
            this.fullName = this.firstName + ' ' + val
        }
    }
}
複製代碼

vue路由有幾種模式

  1. hash模式
  2. history模式

組件之間的傳值通訊

  1. 父組件給子組件傳值經過props
  2. 子組件給父組件傳值經過$emit觸發回調
  3. 兄弟組件通訊,經過實例一個vue實例eventBus做爲媒介,要相互通訊的兄弟組件之中,都引入eventBus
//main.js
import Vue from 'vue'
export const eventBus = new Vue()

//brother1.vue
import eventBus from '@/main.js'
export default{
	methods: {
	    toBus () {
	        eventBus.$emit('greet', 'hi brother')
	    }
	}
}

//brother2
import eventBus from '@/main.js'
export default{
    mounted(){
        eventBus.$on('greet', (msg)=>{
            this.msg = msg
        })
    }
}
複製代碼

axios攔截器怎麼配

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    // 在發送請求以前作些什麼
    return config;
}, function (error) {
    // 對請求錯誤作些什麼
    return Promise.reject(error);
});
// 添加響應攔截器
axios.interceptors.response.use(function (response) {
    // 對響應數據作點什麼
    return response;
  }, function (error) {
    // 對響應錯誤作點什麼
    return Promise.reject(error);
  });
複製代碼

4、瀏覽器

瀏覽器渲染機制

  1. 構建DOM樹(parse):渲染引擎解析HTML文檔,首先將標籤轉換成DOM樹中的DOM node
  2. 構建渲染樹(construct):解析對應的CSS樣式文件信息
  3. 佈局渲染樹(reflow/layout):從根節點遞歸調用,計算每個元素的大小、位置等,給出每一個節點所應該在屏幕上出現的精確座標;
  4. 繪製渲染樹(paint/repaint):遍歷渲染樹,使用UI後端層來繪製每一個節點。

重繪和重排的區別

重繪(repaint或redraw):當盒子的位置、大小以及其餘屬性,例如顏色、字體大小等都肯定下來以後,瀏覽器便把這些原色都按照各自的特性繪製一遍,將內容呈如今頁面上。重繪是指一個元素外觀的改變所觸發的瀏覽器行爲,瀏覽器會根據元素的新屬性從新繪製,使元素呈現新的外觀。

重繪發生在元素的可見的外觀被改變,但並無影響到佈局的時候。好比,僅修改DOM元素的字體顏色(只有Repaint,由於不須要調整佈局)

重排(重構/迴流/reflow):當渲染樹中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建, 這就稱爲迴流(reflow)。每一個頁面至少須要一次迴流,就是在頁面第一次加載的時候。

觸發重排的條件:任何頁面佈局和幾何屬性的改變都會觸發重排:

  • 頁面渲染初始化(沒法避免)
  • 添加或刪除可見的DOM元素
  • 元素位置的改變,或者使用動畫
  • 元素尺寸的改變——大小,外邊距,邊框
  • 瀏覽器窗口尺寸的變化
  • 填充內容的改變,好比文本的改變或圖片大小改變而引發的計算值寬度和高度的改變

重排一定會引起重繪,但重繪不必定會引起重排。

幾種請求方法

GET、POST、HEAD、PUT、DELETE、CONNECT、OPTIONS、TRACE

get和post區別

請求方式 GET POST
參數位置 參數拼接到url的後面 參數在請求體中
參數大小 受限於瀏覽器url大小,通常不超過32K 1G
服務器數據接收 接收1次 根據數據大小,可分屢次接收
適用場景 從服務器端獲取數據 向服務器提交數據
安全性 參數攜帶在url中,安全性低 相對於GET請求,安全性更高

如何解決跨域

  1. CORS
  2. jsonp
  3. 服務器代理

更多CORS請看完全讀懂前端跨域CORS

JSONP原理

因爲瀏覽器的同源策略限制,不容許跨域請求;可是頁面中的 script、img、iframe標籤是例外,不受同源策略限制。

Jsonp 就是利用script標籤跨域特性進行請求。

JSONP 的原理就是,先在全局註冊一個回調函數,定義回調數據的處理;與服務端約定好一個同名回調函數名,服務端接收到請求後,將返回一段 Javascript,在這段 Javascript 代碼中調用了約定好的回調函數,而且將數據做爲參數進行傳遞。當網頁接收到這段 Javascript 代碼後,就會執行這個回調函數。

JSONP缺點:它只支持GET請求,而不支持POST請求等其餘類型的HTTP請求。

緩存的理解

緩存分爲強緩存和協商緩存。強緩存不過服務器,協商緩存須要過服務器,協商緩存返回的狀態碼是304。兩類緩存機制能夠同時存在,強緩存的優先級高於協商緩存。當執行強緩存時,如若緩存命中,則直接使用緩存數據庫中的數據,再也不進行緩存協商。

  1. 強緩存
  • Expires
  • cache-control
  1. 協商緩存
  • Last-Modified 和 If-Modified-Since
  • Etag 和 If-None-Match

更多緩存內容請看前端也要懂Http緩存機制

XSS和CSRF區別

  1. 跨站腳本攻擊(Cross Site Scripting),爲了避免和層疊樣式表 CSS 混淆,故將跨站腳本攻擊縮寫爲 XSS。惡意攻擊者往 Web 頁面裏插入惡意 Script 代碼,當用戶瀏覽該頁之時,嵌入其中 Web 裏面的 Script 代碼會被執行,從而達到惡意攻擊用戶的目的。

  2. 跨站請求僞造(Cross-site request forgery),是僞造請求,冒充用戶在站內的正常操做。咱們知道,絕大多數網站是經過 cookie 等方式辨識用戶身份,再予以受權的。因此要僞造用戶的正常操做,最好的方法是經過 XSS 或連接欺騙等途徑,讓用戶在本機(即擁有身份 cookie 的瀏覽器端)發起用戶所不知道的請求。

區別:

  • 原理不一樣,CSRF是利用網站A自己的漏洞,去請求網站A的api;XSS是向目標網站注入JS代碼,而後執行JS裏的代碼。
  • CSRF須要用戶先登陸目標網站獲取cookie,而XSS不須要登陸
  • CSRF的目標是用戶,XSS的目標是服務器
  • XSS是利用合法用戶獲取其信息,而CSRF是僞形成合法用戶發起請求

HTTP與HTTPS的區別

  • HTTP的URL由http://起始且默認使用端口80,而HTTPS的URL由https://起始且默認使用端口443
  • HTTP是超文本傳輸協議,信息是明文傳輸,HTTPS則是具備安全性的 SSL 加密傳輸協議
  • HTTP的鏈接很簡單,是無狀態的,HTTPS 協議是由 SSL+HTTP 協議構建的可進行加密傳輸、身份認證的網絡協議,比 http 協議安全

HTTP狀態碼

1xx表示客戶端應該繼續發送請求

2xx表示成功的請求

  • 200表示OK,正常返回信息
  • 201表示請求成功且服務器建立了新的資源
  • 202表示服務器已經接受了請求,但還未處理

3xx表示重定向

  • 301表示永久重定向,請求的網頁已經永久移動到新位置
  • 302表示臨時重定向
  • 304表示自從上一次請求以來,頁面的內容沒有改變過

4xx表示客戶端錯誤

  • 401表示服務器沒法理解請求的格式
  • 402表示請求未受權
  • 403表示禁止訪問
  • 404表示請求的資源不存在,通常是路徑寫錯了

5xx表示服務器錯誤

  • 500表示最多見的服務器錯誤
  • 503表示服務器暫時沒法處理請求

5、性能優化

  • 使用CDN
  • gzip壓縮
  • 文本壓縮
  • 合併請求
  • 雪碧圖
  • 圖片懶加載
  • 緩存資源
  • 減小DOM操做

更多前端資料請關注公衆號【前端壹讀】。整理不易,且看且珍惜。

若是以爲寫得還不錯,請關注個人掘金主頁。更多文章請訪問謝小飛的博客

PS:看到評論區好多同窗批評我說整理得太簡單了,react,webpack,Promise都沒有,怎麼能算面試題呢?首先感謝你們的評論,我會更加努力整理深刻的知識點,其次,前端的東西多而雜,我整理這篇文章花了大概一個月時間,有些基礎的知識點我可能工做了一段時間都沒有用到過,因此偏向基礎一點,請技術大佬忽略本文。

更多內容待續。。。

參考

flex

CSS清除浮動

聖盃佈局和雙飛翼佈局的理解與思考

一圖秒懂函數防抖和函數節流

web前端面試總結

公司要求會使用框架vue,面試題會被問及哪些

30道Vue面試題

總結了17年初到18年初百場前端面試的面試經驗

面試分享:兩年工做經驗成功面試阿里P6總結

相關文章
相關標籤/搜索