1. 程式人生 > >2018web前端面試題總結

2018web前端面試題總結

以下內容純屬個人隨筆記錄,不喜勿噴,歡迎指教

web面試題

css面試

一、css盒模型
css中的盒子模型包括IE盒子模型和標準的W3C盒子模型。
border-sizing: border-box, inherit, content-box
標準盒子模型: 左右border+左右padding+contentwidth
IE盒子模型border-box: width = content+padding+border 元素指定的任何內邊距和邊框都將在已設定的寬度和高度內進行繪製
inherit: 從父類繼承box-sizing的值

二、前端一畫素問題(畫一條0.5px的線)
* transform: scaleY(0.5) 使用偽元素設定1px的邊框,然後對邊框進行縮放(s
caleY)
 實現思路:
1、設定目標元素的參考位置
2、給目標元素新增一個偽元素before或者after,並設定絕對定位
3、給偽元素新增1px的邊框
4、用box-sizing: border-box 屬性把邊框都包進寬和高裡面
5、寬和高設定為 200%
6、整個盒子模型縮小為0.5
7、調整盒子模型的位置,以左上角為基準 transform-origin: 0 0;
程式碼如下:
#box{position:relative;}
#box::after{
content:'';box-sizing:border-box;
position:absolute;top:0;left:0;
width:200%;height:200%;
border:1px solid red;
transform-origin:0 0;
transform:scale(0.5);
}
* border-image 設定圖片的邊框

三、4.transition和animation的區別
Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition需要觸發一個事件才能改變屬性,
而animation不需要觸發任何事件的情況下才會隨時間改變屬性值,並且transition為2幀,從from .... to,而animation可以一幀一幀的。

transition 規定動畫的名字 規定完成過渡效果需要多少秒或毫秒 規定速度效果 定義過渡效果何時開始
animation 指定要繫結到選擇器的關鍵幀的名稱

四、不定寬高的DIV居中
1.使用flex 在父盒子設定display: flex; justify-content: center;align-items: center
2.使用css的transform 父盒子設定:display:relative
Div 設定: transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;
3.display:table-cell 父盒子設定:display:table-cell; text-align:center;vertical-align:middle;
Div 設定: display:inline-block;vertical-align:middle;
4.position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;

五、浮動 https://juejin.im/post/5a954add6fb9a06348538c0d
特性:浮動元素影響的不僅是自己,他會影響周圍元素對其進行環繞
為什麼要清除浮動?(解決父元素高度坍陷問題)
一個塊級元素如果沒有設定height,其height由子元素撐開,對子元素使用了浮動之後,子元素就會脫離文件流
也就是說,父及元素中沒有內容可以撐開其高度,這樣父級元素height就會被忽略。這就是所謂的高度坍塌
如何清除浮動
1.給父級元素定義高度 2.讓父級元素也浮動 3.父級定義display:table 4.父元素設定overflow:hidden
clearfix:使用內容生成的方式清除浮動
.clearfix:after { // :after選擇器向選定的元素之後插入內容
content:""; // 生成內容為空
display: block; // 塊級元素顯示
clear:both; // 清除前面元素
}
不破壞文件流,沒有副作用

七、position
值:relative,static(預設值),absolute,sticky,fixed
absolute會根據上一級position的值不為static進行定位,如果向上一直沒有找到position,則相對整個body進行定位
fixe相對的是檢視的視窗,或者frame框架(setFram的子框架,一種html標籤)

八、css選擇器分類:
基本的:
1.id選擇器(id="name")
2.類選擇器(class="head")
3.標籤選擇器(body, div, ul, li)
4.全域性選擇器(*)
複雜的:
1.組合選擇器(.head .head_logo)
2.後代選擇器 (#head .nav ul li 從父集到子孫集)
3.群組選擇器 (div, span, img {color:Red} 具有相同樣式的標籤分組顯示)
4.繼承選擇器
5.偽類選擇器(連結樣式,a元素的偽類)
6.子選擇器(div>p, 帶大於號>)
7.CSS相鄰相鄰兄弟選擇器(h1+p, 帶加號+)

九、CSS優先順序
不同級別:總結排序:!important > 行內樣式>ID選擇器 > 類選擇器 > 標籤 > 萬用字元 > 繼承 > 瀏覽器預設屬性
1.屬性後面加!import 會覆蓋頁面內任何位置定義的元素樣式
2.作為style屬性寫在元素內的樣式
3.id選擇器
4.類選擇器
5.標籤選擇器
6.萬用字元選擇器(*)
7.瀏覽器自定義或繼承
同一級別:後寫的會覆蓋先寫的

css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以儘早的過濾掉一些不必要的樣式規則和元素

十、對於行內元素,font-size指定 他們的content area的高度,由於inline box = 上下的helf-leading,如果leading為0,在這種情況下,font-size指定了inline box的高度
font-size 指的是字型的高度,但是不能指定每個字形給定字型高度下的實際高度,導致了span的高度大於line-height

十一、z-index屬性 z-index 屬性設定元素的堆疊順序。擁有更高堆疊順序的元素總是會處於堆疊順序較低的元素的前面。
position的值的屬性大於z-index Z-index 僅能在定位元素上奏效(例如 position:absolute;)
元素可擁有負的 z-index 屬性值,父子關係的元素z-index設定無效

十二、塊元素和行內元素
1.塊元素會獨佔一行,預設情況下,其寬度自動填滿父元素寬度 行元素不會佔據一行,會一直排在一行,直到一行排不下
2.行元素沒有寬度和高度屬性,塊級元素即使設定了寬度,還是會獨佔一行
塊級元素: div p form ul li ol dl h1-h6
行內元素:span img a i s u b a strong em
行內塊元素:input

十三、如何畫一個三角形: 設定寬高,然後用border去畫
width:0;
height:0;
border:25px solid transparent;
border-top-color:red;

十四、偽類:link 表示連結正常情況下(即頁面載入完成時)顯示的顏色
hover:表示滑鼠懸停時顯示的顏色
visited:連結被點選時顯示的位置
focus:元素獲得游標焦點時的顏色
active: 元素處於啟用狀態
link -> visited -> hover -> focus -> active

十五、雪碧圖:多個圖片整合在一個圖片中的圖
使用雪碧圖可以減少網路請求的次數,加快允許的速度
通過background-position,去定點陣圖片在螢幕的哪個位置

十六: Margin-top和translate  50%的區別

Margin-top預設以左上角為目標運動

Translate 預設以中心點為目標運動

十七:2px和2區別

沒有單位可以用於縮放的位置ex: flex-grow

十八:line-height是針對誰設定的,繼承誰?

設定數字,此數字會與當前的字型尺寸相乘來設定行間距

 

佈局面試
一、flex彈性佈局,
可以簡單的使一個元素居中(包括水平和垂直居中)
柵格式系統佈局,bootstrap grid

二、聖盃和雙飛翼佈局 三欄是佈局(兩邊兩欄寬度固定,中間欄寬度自適應)
方案一:position(絕對定位法) center的div需要放在最後面
絕對定位法原理將左右兩邊使用absolute定位,因為絕對定位使其脫離文件流,後面的center會自然流動到他們的上面去,然後margin屬性,留出左右兩邊的寬度。就可以自適應了。
方案二:float 自身浮動法 center的div需要放到後面
自身浮動法的原理就是對左右使用float:left和float:right,float使左右兩個元素脫離文件流,中間的正常文件流中,使用margin指定左右外邊距對其進行一個定位。
聖盃佈局:原理就是margin負值法。使用聖盃佈局首先需要在center元素外部包含一個div,包含的div需要設定float屬性使其形成一個BFC,並且這個寬度和margin的負值進行匹配

三、左邊定寬,右邊自適應
方案一:左邊設定浮動,右邊寬度設定100%
.left{float:left;height: 150px;width: 150px;}
.right{width: 100%;height: 200px;margin-left: 150px;}
方案二:同上將float設定為position
方案三:父容器設定display:flex right部分是設定flex:1

四、水平居中
行內元素居中(父元素text-align:center)
塊狀元素居中(塊狀元素沒發用text-align)
1.寬度一定:margin:auto
2.寬度不定:塊級變行內,然後在父上text-aligin
float

四、BFC https://juejin.im/post/5909db2fda2f60005d2093db
理解:BFC是css佈局的一個概念,是一塊獨立的渲染區域,一個環境,裡面的元素不會影響到外部的元素
如何生成BFC:(脫離文件流)
【1】根元素,即HTML元素(最大的一個BFC)
【2】float的值不為none
【3】position的值為absolute或fixed
【4】overflow的值不為visible(預設值。內容不會被修剪,會呈現在元素框之外)
【5】display的值為inline-block、table-cell、table-caption
BFC佈局規則:1.內部的Box會在垂直方向,一個接一個地放置。
2.屬於同一個BFC的兩個相鄰的Box的margin會發生重疊
3.BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此, 文字環繞效果,設定float
4.BFC的區域不會與float box重疊。
5.計算BFC的高度,浮動元素也參與計算
BFC作用:1.自適應兩欄佈局
2.可以阻止元素被浮動元素覆蓋
3.可以包含浮動元素---清除內部浮動 原理::觸發父div的BFC屬性,使下面的子div都處在父div的同一個BFC區域之內
4.分屬於不同的BFC時,可以阻止margin重疊

js面試
一、 this的指向:https://www.cnblogs.com/pssp/p/5216085.html
1.作為普通函式,this指向window。ex: fn();//window
2.自動引用正在呼叫當前方法.前的物件ex: a.fn();//a
3.如果有巢狀的情況,則this繫結到最近的一層物件上;ex: o.a.fn();//a
4.構造器呼叫(型別.prototype.fun),this指向返回的這個物件(將來呼叫函式.前的子物件)。
5.箭頭函式 箭頭函式的this繫結看的是this所在函式定義在哪個物件下,就繫結哪個物件
注意:
1.this永遠指的是最後呼叫它的物件ex:var j=o.b.fn; j(); //window
2.new Fun() ,this指向的是正在建立的新物件;ex: var a=new fn();a.uname//a
3.this碰到retuen,呼叫方法裡return了一個物件,this指向return物件

怎麼改變this的指向呢? 1.使用es6的箭頭函式;2.在函式內部使用that = this;3.使用apply,call,bind; 4.new例項化一個物件

二、什麼是閉包和原型鏈
內部函式可以訪問定義他們外部函式的引數和變數。(作用域鏈的向上查詢,把外圍的作用域中的變數值儲存在記憶體中而不是在函式呼叫完畢後銷燬)設計私有的方法和變數,避免全域性變數的汙染
函式巢狀函式
本質是將函式內部和外部連線起來。優點是可以讀取函式內部的變數,讓這些變數的值始終儲存在記憶體中,不會在函式被呼叫之後自動清除
閉包的缺陷:
1.閉包的缺點就是常駐記憶體會增大記憶體使用量,並且使用不當容易造成記憶體洩漏
2.如果不是因為某些特殊任務而需要閉包,在沒有必要的情況下,在其它函式中建立函式是不明智的,因為閉包對指令碼效能具有負面影響,包括處理速度和記憶體消耗。


記憶體溢位和記憶體洩漏(給的不夠用| 用了不歸還)
記憶體溢位:在程式中申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位
記憶體洩漏:在程式申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩漏危害可以忽略,但記憶體洩漏堆積後果很嚴重,無論多少記憶體,遲到會被佔光

舉列子:閉包中的this,物件函式。匿名函式返回函式return function

作用域:(由當前環境與上層環境一系列的變數物件組成!!!保證 當先執行環境裡,有權訪問的變數和函式是有序的,作用域鏈變數只能被向上訪問)
定義:由當前環境與上層環境的一系列變數物件組成(函式巢狀函式,內部一級級往上有序訪問變數或物件)
作用是:保證當前執行環境裡,有權訪問的變數和函式時有序的,作用域鏈的變數只能被向上訪問
變數訪問到window物件及被終止,作用域鏈向下訪問是不允許的
1.改變作用域有 with try..中的catch,
2.所有為定義的直接賦值的變數自動宣告為全域性作用域

作用域:一套規則,管理引擎如何在當前作用域以及巢狀的子作用域中根據識別符號名稱
查詢變數(識別符號就是變數或者函式名)(只用全域性作用域和區域性作用域)(作用域在它建立的時候就存在了)

程式碼執行分為兩個階段:
1.程式碼編譯階段:有編譯器完成,將程式碼翻譯可執行的程式碼,這個階段會被確定
2.程式碼執行階段:有js引擎完成,主要執行可執行的大媽,這個階段執行上下文被建立(物件被建立)

執行上下文:一個看不見得物件,存在若干個屬性和變數,它被呼叫的時候建立的。函式被呼叫檢視的this指向的object,object就是上下文(只有被呼叫的時候建立)

作用域鏈: https://blog.csdn.net/yooungt13/article/details/20581635
· 當代碼在一個環境中執行時,會建立變數物件的一個作用域鏈,
舉例子:var name ="Tom"
function sayHi () {
alert('Hi,'+name)
}
sayHi() //Hi, Tom
函式sayHi()的執行環境為全域性環境,所以它的變數物件為window。當函式執行到name時,先查詢區域性環境,找到則換回,否則順著作用域查詢,在全域性環境中,
找到name返回,這一查詢變數的有序過程的依據就是作用域。

· 作用域鏈是保證執行環境有權訪問的所有變數和函式的有序訪問

原型鏈:函式的原型鏈物件constructor預設指向函式本身,原型物件除了有原型屬性外,為了實現繼承,還有一個原型鏈指標_proto_,
該指標是指向上一層的原型物件,而上一層的原型物件的結構依然類似。因此可以利用_proto_一直指向Object的原型物件上,而Object
原型物件用Object.prototype._proto_ = null表示原型鏈頂端。如此形成了js的原型鏈繼承。同時所有的js物件都有Object的基本防範

三、類的建立和繼承
(es5)new 一個function,在這個function的prototype裡增加屬性和方法, 類裡面有方法和屬性
(es6)中class, extends
繼承:
原型鏈繼承: function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; 無法實現多繼承
構造繼承: 使用父類的建構函式來增強子類例項。function Cat(name){Animal.call(this);this.name = name || 'Tom';} 無法繼承父類原型鏈上的屬性跟方法 installof去檢驗
例項繼承: 為父類例項新增新特性,作為子類例項的返回
拷貝繼承: 拷貝父類元素上的屬性跟方法
組合繼承:構造繼承 + 原型繼承的組合體
寄生組合繼承:通過寄生方式,在構造繼承上加一個Super函式(沒有例項和方法) 讓他的原型鏈指向父類的原型鏈
砍掉父類的例項屬性,這樣,在呼叫兩次父類的構造的時候,就不會初始化兩次例項方法/屬性
如何判斷是那種型別

四、非同步回撥(如何解決回撥地獄)
promise、generator、async/await

promise: 1.是一個物件,用來傳遞非同步操作的資訊。代表著某個未來才會知道結果的時間,並未這個事件提供統一的api,供進非同步處理
2.有了這個物件,就可以讓非同步操作以同步的操作的流程來表達出來,避免層層巢狀的回撥地獄
3.promise代表一個非同步狀態,有三個狀態pending(進行中),Resolve(以完成),Reject(失敗)
4.一旦狀態改變,就不會在變。任何時候都可以得到結果。從進行中變為以完成或者失敗
promise.all() 裡面狀態都改變,那就會輸出,得到一個數組
promise.race() 裡面只有一個狀態變為rejected或者fulfilled即輸出
promis.finally()不管指定不管Promise物件最後狀態如何,都會執行的操作(本質上還是then方法的特例)

五、前端事件流
事件流描述的是從頁面中接受事件的順序,事件 捕獲階段 處於目標階段 事件冒泡階段 addeventListener 最後這個布林值引數如果是true,表示在捕獲階段呼叫事件處理程式;如果是false,表示在冒泡階段呼叫事件處理程式。
1、事件捕獲階段:實際目標div在捕獲階段不會接受事件,也就是在捕獲階段,事件從document到<html>再到<body>就停止了。
2、處於目標階段:事件在div發生並處理,但是事件處理會被看成是冒泡階段的一部分。
3、冒泡階段:事件又傳播迴文檔
阻止冒泡事件event.stopPropagation()
function stopBubble(e) {
if (e && e.stopPropagation) { // 如果提供了事件物件event 這說明不是IE瀏覽器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
}
阻止預設行為event.preventDefault()
function stopDefault(e) {
if (e && e.preventDefault) {
e.preventDefault()
} else {
// IE瀏覽器阻止函式器預設動作的行為


window.event.returnValue = false
}
}
事件如何先捕獲後冒泡?
在DOM標準事件模型中,是先捕獲後冒泡。但是如果要實現先冒泡後捕獲的效果,
對於同一個事件,監聽捕獲和冒泡,分別對應相應的處理函式,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲後再執行捕獲事件。

哪些事件不支援冒泡事件:滑鼠事件:mouserleave mouseenter
焦點事件:blur focus
UI事件:scroll resize


六、事件委託(提高效能)
簡介:事件委託指的是,不在事件的(直接dom)上設定監聽函式,而是在其父元素上設定監聽函式。通過事件冒泡,父元素可以監聽到子元素上事件的觸發
通過判斷事件發生元素DOM的型別,來做出不同的響應。
舉例子: 最經典的就是ui和li標籤的事件監聽,比如我們在新增事件的時候,採用事件委託機制,不會在li標籤上直接新增,而是在ul父元素上新增
好處:可以比較合適動態元素的繫結,新新增的子元素也會監聽函式,也可以有事件觸發機制

七、js的new操作符做了什麼?
new操作符建立了一個空物件,這個物件原型指向建構函式的prototype,執行建構函式後返回這個物件(return this)。
如果不要父類的屬性跟方法,在函式的prototype上去new這個父類。

八、改變函式內部this指標的指向函式(bind,apply,call)
通過apply和call改變函式的this指向,他們兩個函式的第一個引數都是一樣的表示要改變指向的那個物件,第二個引數,apply是陣列,而call則是arg1,arg2...這種形式。

 

bind 一個是返回一個函式,並不會立即執行 第二個是帶引數(第一個引數要指向的this,後面的的引數用來傳遞

九、深拷貝和淺拷貝 https://juejin.im/post/5b00e85af265da0b7d0ba63f 從堆和棧都是記憶體中劃分出來用來儲存的區域開始講起
基本型別:undefined,null,Boolean,String,Number,Symbol 在記憶體中佔據固定大小,儲存在棧記憶體中
引用型別:Object,Array,Date,Function,RegExp等 引用型別的值是物件 儲存在堆記憶體中,棧記憶體儲存的是物件的變數識別符號以及物件在堆記憶體中的儲存地址。
基本型別的複製: 其實就是建立了一個新的副本給將這個值賦值給新變數, 改變值舊物件不會改變
引用型別的複製: 其實就是複製了指標,這個最終都將指向同一個物件,改變其值新物件也會改變
基本型別的比較 == 會進行型別轉換

淺拷貝:僅僅就是複製了引用,彼此操作不影響,slice() concat() object.assign
深拷貝:在堆中重新分配記憶體,不同的地址,相同的值,互不影響的 JSON.parse()將一個js物件序列化為一個json字串 JSON.stringify()將json字串反序列化為一個js物件 es6的展開 {...}
深拷貝和淺拷貝的主要區別是:在記憶體中的儲存型別不同
淺拷貝:重新在堆疊中建立記憶體,拷貝前後物件的基本型別互不影響。只拷貝一層,不能對物件進行子物件進行拷貝
深拷貝:對物件中的子物件進行遞迴拷貝,拷貝前後兩個物件互不影響

十、跨域
同源策略(協議+埠號+域名要相同)
1、jsonp跨域(只能解決get)
原理:動態建立一個script標籤。利用script標籤的src屬性不受同源策略限制,因為所有的src屬性和href屬性都不受同源策略的限制,可以請求第三方伺服器資源內容
步驟:1.去建立一個script標籤
2.script的src屬性設定介面地址
3.介面引數,必須要帶一個自定義函式名,要不然後臺無法返回資料
4.通過定義函式名去接受返回的資料

2、document.domain 基礎域名相同 子域名不同
3、window.name 利用在一個瀏覽器視窗內,載入所有的域名都是共享一個window.name
4、伺服器設定對CORS的支援
原理:伺服器設定Access-Control-Allow-Origin HTTP響應頭之後,瀏覽器將會允許跨域請求
5、利用h5新特性window.postMessage()

iframe元素建立包含另外一個文件的內聯框架(行內框架)(setTimeout進行非同步載入)
解釋:瀏覽器中的瀏覽器!用於設定文字或者圖形的浮動圖文框或容器
它和跨域
1、document.domain 實現主域名相同,子域名不同的網頁通訊
都設定為超域:document.domain = 'demo.com'
2、window.postMessageht(data, url),h5的API,啟動跨域通訊


十一、圖片的懶載入和預載入
預載入:提前載入圖片,當用戶需要檢視是可以直接從本地快取中渲染
為什麼要使用預載入:在網頁載入之前,對一些主要內容進行載入,以提供使用者更好的體驗,減少等待時間。
否則,如果一個頁面的內容過於龐大,會出現留白。
解決頁面留白的方案:1.預載入 2.使用svg站點陣圖片,將一些結構快速搭建起來,等待請求的資料來了之後,替換當前的佔位符
實現預載入的方法:
1.使用html標籤
2.使用Image物件
3.使用XMLHTTPRequest對像,但會精細控制預載入過程

 

懶載入(lazyload):客戶端優化,減少請求數和延遲請求數
提升使用者體驗,
減少無效資源的載入
防止併發載入的資源過多會阻塞js的載入,影響網站的正常使用
原理:首先將頁面上的圖片的src屬性設定為空字串,而圖片的真是路經則設定帶data-original屬性中,
當頁面滾動的時候需要去監聽scroll事件,在scroll事件的回撥中,判斷我們的懶載入的圖片是否進入到可視區域
,如果圖片在可視區域將圖片的src屬性設定為data-original的值,這樣就可以實現延遲載入。

十二、函式節流防抖
什麼是防抖:短時間內多次觸發同一個事件,只執行最後一次,或者在開始時執行,中間不執行。比如公交車上車,要等待最後一個乘客上車
什麼是節流:節流是連續觸發事件的過程中以一定時間間隔執行函式。節流會稀釋你的執行頻率,比如每間隔1秒鐘,只會執行一次函式,無論這1秒鐘內觸發了多少次事件
都為解決高頻事件而來, scroll mousewhell mousemover touchmove onresize

十三、將arguments類陣列轉化為陣列的方法
Array.apply(null, arguments)
Array.prototype.slice.apply(arguments)
Array.from(arguments)

十四、高階函式
一、函式作為引數傳遞 抽離出一部分容易變化的業務邏輯,把這部分業務邏輯放在函式引數中。這樣一來可以分離業務程式碼中變化與不變的部分
回撥函式
二、函式作為返回值傳遞

十五、如何判斷一個變數是物件還是陣列(prototype.toString.call())。
千萬不要使用typeof來判斷物件和陣列,因為這種型別都會返回object。
typeOf()是判斷基本型別的Boolean,Number,symbol, undefined, String。
對於引用型別:除function,都返回object null返回object。
installOf() 用來判斷A是否是B的例項,installof檢查的是原型。(arr instanceof Array)
toString() 是Object的原型方法,對於 Object 物件,直接呼叫 toString() 就能返回 [object Object] 。而對於其他物件,則需要通過 call / apply 來呼叫才能返回正確的型別資訊。

hasOwnProperty()方法返回一個布林值,指示物件自身屬性中是否具有指定的屬性,該方法會忽略掉那些從原型鏈上繼承到的屬性。

isProperty()方法測試一個物件是否存在另一個物件的原型鏈上。


十六、setTimeout 和 setInterval的機制
因為js是單執行緒的。瀏覽器遇到etTimeout 和 setInterval會先執行完當前的程式碼塊,在此之前會把定時器推入瀏覽器的
待執行時間佇列裡面,等到瀏覽器執行完當前程式碼之後會看下事件佇列裡有沒有任務,有的話才執行定時器裡的程式碼

十七、var let const
const:定義的變數不可修改,必須初始化 ,
var:定義的變數可以修改,如果不初始化輸出undefined,不會報錯
let:塊級作用域,函式內部使用let定義後,會函式外部無影響
let const 不會造成變數的提升

十八、js垃圾回收機制
1.JS具有自動垃圾收集的機制
2.JS的記憶體生命週期(變數的生命)
1.分配你所需要的空間 var a = 20
2.使用分配帶的記憶體(讀寫) alert(a + 10)
3.不適用的時候,釋放記憶體空間 a = null
3.JS的垃圾收集器每隔固定的時間就執行一次釋放操作,通用的是通過標記清除的演算法
4.在區域性作用域中,垃圾回收器很容易做出判斷並回收,全域性比較難,因此應避免全域性變數

標記清除演算法:js最常見的垃圾回收方式,當變數進入執行環境的時候,比如函式中宣告一個變數,垃圾回收器將他標記為'進入環境',
當變數離開(函式執行完後),就其標記為'離開環境'。垃圾回收器會在執行的時候給儲存在記憶體中的所有變數加上標記,
然後去掉環境中的變數以及被環境中該變數所引用的變數(閉包)。在這些完成之後仍存在標記的就是要刪除的變量了

十九、漸進增強和優雅降級
1.漸進增強就是針對低版本瀏覽器進行構建頁面,保證最基本的功能,然後對高階瀏覽器進行效果、互動等改進和最佳功能達到更好的使用者體驗
2.優雅降級:一開始構建完整的功能,然後對低版本的進行相容

二十、undefined 和 null
1.undefined型別只要一個,即undefined,當宣告變數還未被初始化時就是undefined
2.null型別也只有一個值,即null。null用來表示尚未存在的物件,常用來表示函式企圖返回一個不存在的物件
3.NaN 與任何值都是相比較的結果都是false

二十一、valueof和tostring
valueof:所有物件都有valueof,如果存在任意原始值,他就預設將物件轉化為表示它的原始值。
如果物件是複合值,而卻大部分物件無法真正表示一個原始值,因此預設的valueof()方法簡單的返回物件本身,而不是返回原始值。
陣列、函式和正則表示式簡單的繼承了這個more方法,返回物件本身

二十二、輸入框的change和input事件
onchange事件:要在input失去焦點的時候才觸發
oninput事件:要在使用者輸入的時觸發,他是元素值發生變化時立即觸發

二十三、同步和非同步
同步:由於js單執行緒,同步任務都在主執行緒上排隊執行,前面任務沒有執行完成,後面的任務會一直等待
非同步:不進入主執行緒,進入任務佇列,等待主執行緒任務執行完成,開始執行。最基本的非同步操作SetTimemot和SetInterval,等待主執行緒任務執行完,在開始執行裡面的函式


二十四、函式的柯里化
概念:一個函式接受函式A作為引數,執行後返回return function一個新的函式,並且可以處理A中的引數(只接受單一引數的函式)
意義:將函式完全變成了接受一個引數,返回一個引數的固定形式,便於討論和優化

二十五、while
while迴圈會在指定條件為真時迴圈執行程式碼

二十六、TypeScript的優點:
1、編譯時的強型別,變成了強型別語言,還是編譯成js 編譯的時候就可以檢驗
2、更好的模組化
3、更好的是實現面向物件的程式設計,類、介面、模組

二十七、js的阻塞特性:所有瀏覽器在下載JS的時候,會阻止一切其他活動,比如其他資源的下載,內容的呈現等等。
直到JS下載、解析、執行完畢後才開始繼續並行下載其他資源並呈現內容。
為了提高使用者體驗,新一代瀏覽器都支援並行下載JS,但是JS下載仍然會阻塞其它資源的下載(例如.圖片,css檔案等)。
css阻塞:因為瀏覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執行前先載入、解析完。
而嵌入的JS會阻塞後面的資源載入,所以就會出現上面CSS阻塞下載的情況。

二十八、meta元素可提供有關頁面的元資訊,比如針對搜尋引擎和更新頻度的描述和關鍵詞

 

二十九: POST提交資料時四種常見格式

服務端通常是根據請求頭(headers)中的 Content-Type 欄位來獲知請求中的訊息主體是用何種方式編碼,再對主體進行解析。

         setRequestHeader(“Content-type” , ”application/x-www-form-urlencoded”);

1)1. application/x-www-form-urlencoded 原生表單

2)2. multipart/form-data 表單上傳檔案

3)3. application/json

4)4. text/xml

三十:   HTTP請求方法

GET:獲取資源      POST:傳輸文字

PUT:傳輸檔案      DELETE:刪除檔案

HEAD:獲得報文首部

OPTIONS:訪問伺服器端可以提交哪些請求方法

三十一: js實現圖片上傳到伺服器和回顯

<input type="file" value="" name="file" id = "input_file"

      accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"    onchange="imgPreview(this,0)">

function imgPreview(fileDom,i) {

var file = fileDom.files[0];  //獲取檔案

reader.onload = function(e) {

document.getElementsByClassName('file-box')[i].style.background="url("+e.target.result+")no-repeat";//回顯圖片

          document.getElementsByClassName('file-box')[i].style.backgroundSize='200px 160px';

}

reader.readAsDataURL(file); //轉碼儲存

}

//ajax請求

var formData = new FormData();

formData.append('photo', $('#input_file')[0].files[0]); 

$.ajax({})

三十二: 簡述瀏覽器渲染過程

解析html以構建dom樹 -> 構建render樹(加上css) -> 佈局render樹 -> 繪製render樹

三十三:  jQuery工作原理

1)jQuery採用的是建構函式模式進行開發的,jQuery是一個類

2)常用的方法(CSS、屬性、篩選、事件、動畫)都是定義在jQuery.prototype上的 ->只有jQuery的例項才能使用這些方法

三十四: Sessionid如何生成,由誰產生,儲存在哪裡?

sessionid是一個會話的key,瀏覽器第一次訪問伺服器會在伺服器端生成一個session,有一個sessionid和它對應。程式呼叫 HttpServletRequest.getSession(true)這樣的語句時才被建立。存放:伺服器端的記憶體中

三十五: Session和Cookie的區別與聯絡:

1、cookie資料存放在客戶的瀏覽器上,session資料放在伺服器上。

2、cookie不是很安全,別人可以分析存放在本地的cookie並進行cookie欺騙,考慮到安全應當使用session。

3、session會在一定時間內儲存在伺服器上。當訪問增多,會比較佔用你伺服器的效能,考慮到減輕伺服器效能方面,應當使用cookie。

4、單個cookie儲存的資料不能超過4K,很多瀏覽器都限制一個站點最多儲存20個cookie。

5、可以考慮將登陸資訊等重要資訊存放為session,其他資訊如果需要保留,可以放在cookie中。

三十六: JSON.parse()與JSON.stringify()的區別

JSON.parse()從一個字串中解析出json物件

JSON.stringify()從一個物件中解析出字串

三十七:NaN 是什麼?它的型別是什麼?如何可靠地測試一個值是否等於 NaN ?

NAN:不是數字               型別:number

value!==value 為true就是nan(只有nan才會和自己不相等)

Number.isNaN()

三十八:javascript建立陣列時,Array()和[]有什麼區別

Array()通過呼叫陣列建構函式生成,可以(8)直接定義陣列長度,記憶體中開闢一個儲存空間,比較耗資源

[]通過字面量定義陣列,直接在記憶體中開闢一個儲存欄位,不耗資源

三十九: 定義函式時用 var foo = function () {} 和 function foo() {}有什麼區別?

前者聲明瞭一個變數,這個變數是個方法,是可以改變的

後者聲明瞭一個方法,這個方法名字無法改變

本質變數和方法宣告提前的問題

四十:寫一個按照下面方式呼叫都能正常工作的sum方法

console.log(sum(2,3));  //輸出Outputs 5

console.log(sum(2)(3)); //輸出Outputs 5

function sum() {

          var num = arguments[0];

          if(arguments.length === 2) {

            return arguments[0] + arguments[1]

          } else {

            return function(sec) {

               return num + sec;

            }

          } 

        }

四十一:如果一個函式沒有返回語句,此函式返回值是什麼?

無返回語句返回Undefined

return; 返回null,起到中斷方法執行效果

四十二: forEach()和map()的區別

Foreach:沒有返回值,遍歷陣列對每個值進行處理

Map():有返回值,返回值組成一個新的陣列



node面試
一、koa中介軟體執行機制
1.新增中介軟體的方式是使用Koa例項的use方法,並傳入一個generator函式,這個generator函式接受一個next引數
2.use的原理:function Application () {this.middleware = [] // 這個陣列就是用來裝一個個中間間的}
3.每次執行use方法,就把外面傳進來的generator函式push到middleware陣列中
app.use = function (fn) {this.middleware.push(fn)}
4.koa中是預先通過use方法,將請求可能會經過的中間間裝在一個數組中。
5.callback函式就是請求到來的時候執行的回撥。把裝著中介軟體middleware的陣列作為引數傳遞為compose這個方法。
6.componse把毫無關係的一個個中介軟體給收尾串起來了,就好比我們平常的烤麵筋
7.componse將中介軟體從最後一個開始處理,並一直往前知道第一個中介軟體。其實最關鍵的就是將最後一箇中間件得到generator
作為引數傳遞給前一箇中間件。當最後一箇中間件的引數next是空的generator函式生成物件

中介軟體是怎麼跑起來的:https://juejin.im/post/591c8b4544d904006c90a2cb

 


vue面試
一、介紹下MVVM(資料的雙向繫結)
M: model資料模型
V: view 介面
MV:作為橋樑負責溝通view跟model
只關心資料的流傳,減少強耦合性。最關鍵的就是資料的雙向繫結
關鍵步驟:1.實現資料監聽器Observer,用object.defineProperty()重寫資料的get/set。值更新就在set中通知訂閱者更新資料
2.實現模板編譯compile,深度遍歷dom樹,對每個元素節點的指令模板替換資料以及訂閱資料
3.實現watch用於連線Observer和compile,能夠訂閱並接受每一個屬性的變動的通知,執行指令繫結的相應的回撥函式,從而更新資料

mvc和mvvm其實區別並不大。都是一種設計思想。主要就是mvc中Controller演變成mvvm中的viewModel。mvvm主要解決了mvc中大量的DOM 操作使頁面渲染效能降低,
載入速度變慢,影響使用者體驗。和當 Model 頻繁發生變化,開發者需要主動更新到View 。

二、 eventBus vuex
原理:eventbus 解決了兄弟元件之間事件傳遞問題,本質是訂閱釋出者模式,從而擺脫了兄弟之間需要父元件轉而傳遞的複雜。還有一種方法是vuex資料流,單一狀態樹,rootState樹根
名詞,專車。訂閱者跟釋出者都引用專車,這個vue例項,來完成訂閱釋出者。 emit(釋出) on(訂閱一個元件)
npm包 vue-event-proxy

vuex 是將資料單獨的抽離出來,一種狀態管理工具,它借鑑的是Flux、redux的基本思想,將轉態抽離到全域性形成一個store

三、watch:
對屬性進行監聽,允許我們執行非同步操作,限制我們執行該操作的頻率(debounce),並在我們得到結果前,設定中間轉態。

四、Vue的雙向資料繫結實現原理
1.核心就是資料劫持 + 釋出/訂閱者模式:vue使用的是Object.defineProperty()通過監聽他的get/set事件,監聽對資料的操作,從而觸發資料同步

Object.defineProperty缺陷的:
1.只能對屬性進行資料劫持,並且需要深度遍歷整個物件
2.對於陣列不能監聽資料的變化
而proxy原生支援監聽陣列的變化,並且可以直接對整個物件進行攔截,所有Vue在下個版本中用proxy替換object.defineProperty


五、nextTick原理

六、生命週期函式 https://juejin.im/post/5b41bdef6fb9a04fe63765f1
new Vue(建立一個Vue物件)--> beforeCreate --> observer Data(開始監控data物件資料變化) --> init event(vue內部初始化事件)

--> created() --> compile(編譯模板,把data裡面的資料和模板生成html) --> beforeMount(還沒有生成HTML到元素上) -->

mounted(掛載完成,也就是模板中的html渲染到了html頁面中) --> beforeUpdate (Vritual Dom) --> updated --> beforeDestroy --> destroyed

1.ajax請求最好放在created裡面,頁面可以訪問到this了
2.關於dom的操作要放在mounted裡面,在mounted前面還沒有生成dom
3.每次進入/離開元件都要做一些事情,用什麼鉤子函式:
不快取:進入的時候可以用created和mounted鉤子,離開的時候可以使用beforedDestory(可以訪問this)和destoryed


快取:快取了元件之後,在次進入元件不會觸發beforeCreate,created, beforeMount,mounted
如果你想每次進入元件都做一些事情的話,你可以放在activated進入快取元件的鉤子中
七、keep-alive
在被keep-alive包含的元件/路由,會多出兩個生命週期:activated 和 deactivated
actived在元件第一次渲染時會被呼叫,之後再每次快取元件被啟用時呼叫 呼叫機制:第一次進入快取路由/元件,在mounted後面,beforeRouteEnter守衛傳給 next 的回撥函式之前呼叫:

八、Vue的SPA 如何優化載入速度
1.減少入口檔案體積
2.靜態資源本地快取
3.開啟Gzip壓縮
4.使用SSR,nuxt.js

九、模組化
基本概念: 1.在js中,一個模組就是實現特定功能的檔案(js檔案)
2.遵循模組的機制,想要什麼就載入什麼模組
3.模組化開發需要遵循規範

js實現模組化規範
1.AMD 瀏覽器 requirejs 模組被非同步載入,模組載入不影響後面語句的執行 預設使用baseURL+ paths的路經解析方式
2.CommonJS nodejs
3.ES6的import/export
4.CMD 瀏覽器端

解決的問題:1.命名衝突 2.檔案依賴 3.模組的複用 4.統一規範和開發方式

十、談談Vue和React元件化的思想
1.我們在各個頁面開發的時候,會產生很多重複的功能,比如element中的xxxx。像這種純粹非頁面的UI,便成為我們常用的UI元件,最初的前端元件也就僅僅指的是UI元件
2.隨著業務邏輯變得越來多是,我們就想要我們的元件可以處理很多事,這就是我們常說的元件化,這個元件就不是UI元件了,而是包具體業務的業務元件
3.這種開發思想就是分而治之。最大程度的降低開發難度和維護成本的效果。並且可以多人協作,每個人寫不同的元件,最後像撘積木一樣的把它構成一個頁面

十一、vue的依賴收集和watch原理


React
一、react和vue的區別
=> 相同點:
1.資料驅動頁面,提供響應式的試圖元件
2.都有virtual DOM,元件化的開發,通過props引數進行父子之間元件傳遞資料,都實現了webComponents規範
3.資料流動單向,都支援伺服器的渲染SSR
4.都有支援native的方法,react有React native, vue有wexx
=> 不同點:
1.資料繫結:Vue實現了雙向的資料繫結,react資料流動是單向的
2.資料渲染:大規模的資料渲染,react更快
3.使用場景:React配合Redux架構適合大規模多人協作複雜專案,Vue適合小快的專案
4.開發風格:react推薦做法jsx + inline style把html和css都寫在js了
vue是採用webpack + vue-loader單檔案元件格式,html, js, css同一個檔案

二、redux中的reducer(純函式)
Redux資料流裡,reduces其實是根據之前的狀態(previous state)和現有的action(current action)更新state(這個state可以理解為上下累加器的結果)
每次redux reducer被執行時,state和action被傳入,這個state根據action進行累加或者是'自身消減'(reduce),進而返回最新的state,這也就是典型reduce函式的用法:state -> action -> state

三、react的refs
refs就想一個逃生窗,允許我們之間訪問dom元素或者元件例項,可以向元件新增一個ref屬性的值是一個回撥函式,
它將接受地城dom元素或元件的已掛在例項,作為第一個引數

四、react中的keys
幫組我們跟蹤哪些專案已更改、新增、從列表中刪除,key是獨一無二的,可以讓我們高效的去定位元素,並且操作它

五、React的生命週期
三個狀態:Mounting(已插入真實的DOM)
Updating(正在被重新渲染)
Unmounting(已移除真實的DOM)
componentDIdMount 在第一次渲染後呼叫,只在客服端。之後元件已經生成對應的DOM結構,
componentDidUpdate 在元件完成更新後立即呼叫,在出初始化是不會呼叫

六、React子元件向父元件傳值
父元件通過props 給子元件傳遞資料,子元件則是通過呼叫父元件傳給它的函式給父元件傳遞資料。

七、React資料流

八、為什麼虛擬DOM會提高效能 https://www.zhihu.com/question/29504639?sort=created
虛擬DOM相當於在js和真實dom中間加了一個快取,利用dom diff演算法避免了沒有必要的doom操作,從而提高效能
具體實現步驟:
·用JavaScript物件結構表示DOM樹的結構;然後用這個樹構建一個真正的DOM樹,插到文件中
·當狀態變更的時候,重新構造一棵樹的物件樹,然後用新的樹和舊的樹進行對比,記錄兩棵樹差異
·把2所記錄的差異應用到步驟1所構建的真正的DOM樹上,試圖就更新了。

九、diff演算法
1.把樹形結構按照層級分解,只比較同級元素
2.給列表結構的每個單元新增key屬性,方便比較。在實際程式碼中,會對新舊兩棵樹進行一個深度優先的遍歷,這樣每個節點都會有一個標記
3.在深度優先遍歷的時候,每遍歷到一個節點就把該節點和新的樹進行對比。如果有差異的話就記錄到一個物件裡面
Vritual DOM 演算法主要實現上面步驟的三個函式:element, diff, patch。然後就可以實際的進行使用
react只會匹配相同的class的component(這裡的class指的是元件的名字)
合併操作,條用component的setState方法的時候,React將其標記為dirty.到每一個時間迴圈借宿,React檢查所有標記dirty的component重新繪製
4.選擇性子樹渲染。可以重寫shouldComponentUpdate提高diff的效能

十、super

十一、簡述下flux的思想
flux的最大特點,就是資料的‘單向流動’
1.使用者訪問View
2.View發出使用者的Action
3.Dispatcher收到Action,要求state進行相應的更新
4.store更新後,發出一個‘change’事件後,更新頁面

十二、reac效能優化是哪個週期函
shouldComponentUpdate 這個方法用來判斷是否需要呼叫render方法重新描繪dom.因為dom的描繪非常消耗效能,
如果我們在shouldComponentUpdate方法中能夠寫出更優化的dom diff演算法,可以極大的提高效能

十三、react怎麼劃分業務元件和技術元件
根據元件的職責通常把元件分為UI元件和容器元件
UI元件負責UI的呈現,容器元件負責管理資料和邏輯
兩者通過React-redux提供connect方法聯絡起來

十四、setState
setState通過一個佇列機制實現state更新,當執行setState時,會將需要更新的state很後放入狀態佇列
而不會立即更新this.state,佇列機制可以高效地批量更新state。如果不通過setState而直接修改this.state的值
那麼該state將不會被放入狀態佇列中。當下次呼叫setState並對狀態佇列進行合併時,就會忽略之前修改的state,造成不可預知的錯誤

同時,也利用了佇列機制實現了setState的非同步更新,避免了頻繁的重複更新state

同步更新state:
setState 函式並不會阻塞等待狀態更新完畢,因此 setNetworkActivityIndicatorVisible 有可能先於資料渲染完畢就執行。第二個引數是一個回撥函式,在setState的非同步操作結束並且元件已經重新渲染的時候執行
也就是說,我們可以通過這個回撥來拿到更新的state的值,實現程式碼的同步

例子:componentDidMount() {

fetch('https://test.com')

.then((res) => res.json())

.then(
(data) => {
this.setState({ data:data });

StatusBar.setNetworkActivityIndicatorVisible(false);
}


效能優化

一、webpack打包檔案體積過大?(最終打包為一個js檔案)
1.非同步載入模組
2.提取第三庫
3.程式碼壓縮
4.去除不必要的外掛

如何優化webpack構建的效能
一、減少程式碼體積 1.使用CommonsChunksPlugin 提取多個chunk之間的通用模組,減少總體程式碼體積
2.把部分依賴轉移到CDN上,避免每次編譯過程都由Webpack處理
3.對一些元件庫採用按需載入,避免無用的程式碼
二、減少目錄檢索範圍
·在使用loader的時候,通過制定exclude和include選項,減少loader遍歷的目錄範圍,從而加快webpack編譯速度

三、減少檢索路經:resolve.alias可以配置webpack模組解析的別名,對於比較深的解析路經,可以對其配置alias


二、我們把開發中的所有資源(圖片,js、css檔案)都看成模組,通過loader和plugins來對資源進行處理,打包成符合生產環節部署的前端資源。

三、移動端的效能優化
1、首屏載入和按需載入,懶載入
2、資源預載入
3、圖片壓縮處理,使用base64內嵌圖片
4、合理快取dom物件
5、使用touchstart代替click(click 300毫秒的延遲)
6、利用transform:translateZ(0),開啟硬體GUP加速
7、不濫用web字型,不濫用float(佈局計算消耗效能),減少font-size宣告
8、使用viewport固定螢幕渲染,加速頁面渲染內容
9、儘量使用事件代理,避免直接事件繫結

四、Vue的SPA 如何優化載入速度
1.減少入口檔案體積
2.靜態資源本地快取
3.開啟Gzip壓縮
4.使用SSR,nuxt.js

五、移動端300ms延遲
由來:300毫米延遲解決的是雙擊縮放。雙擊縮放,手指在螢幕快速點選兩次。safari瀏覽器就會將網頁縮放值原始比例。
由於使用者可以雙擊縮放或者是滾動的操作,當用戶點選螢幕一次之後,瀏覽器並不會判斷使用者確實要開啟至這個連結,還是想要進行雙擊操作
因次,safair瀏覽器就會等待300ms,用來判斷使用者是否在次點選了螢幕
解決方案:1.禁用縮放,設定meta標籤 user-scalable=no
2.fastclick.js
原理:FastClick的實現原理是在檢查到touchend事件的時候,會通過dom自定義事件立即
發出click事件,並把瀏覽器在300ms之後真正的click事件阻止掉
fastclick.js還可以解決穿透問題

六、頁面的重構;在不改變外部行為的前提下,簡化結構、新增可讀性

伺服器端
一、狀態碼:

2XX(成功處理了請求狀態)
200 伺服器已經成功處理請求,並提供了請求的網頁
201 使用者新建或修改資料成功
202 一個請求已經進入後臺
204 使用者刪除成功
3XX(每次請求使用的重定向不要超過5次)
304 網頁上次請求沒有更新,節省頻寬和開銷
4XX(表示請求可能出錯,妨礙了伺服器的處理)
400 伺服器不理解請求的語法
401 使用者沒有許可權(使用者名稱,密碼輸入錯誤)
403 使用者得到授權(401相反),但是訪問被禁止
404 伺服器找不到請求的網頁,
5XX(表示伺服器在處理請求的時候發生內部錯誤)
500 伺服器遇到錯誤,無法完成請求
503 伺服器目前無法使用(超載或停機維護)

二、304的快取原理(新增Etag標籤.last-modified) 304 網頁上次請求沒有更新,節省頻寬和開銷
1.伺服器首先產生Etag,伺服器可在稍後使用它來判斷頁面是否被修改。本質上,客戶端通過該記號傳回伺服器要求伺服器驗證(客戶端)快取)
2.304是 HTTP的狀態碼,伺服器用來標識這個檔案沒有被修改,不返回內容,瀏覽器接受到這個狀態碼會去去找瀏覽器快取的檔案
3.流程:客戶端請求一個頁面A。伺服器返回頁面A,並在A上加一個Tage客服端渲染該頁面,並把Tage也儲存在快取中。客戶端再次請求頁面A
並將上次請求的資源和ETage一起傳遞給伺服器。伺服器檢查Tage.並且判斷出該頁面自上次客戶端請求之後未被修改。直接返回304

last-modified: 客服端請求資源,同時有一個last-modified的屬性標記此檔案在伺服器最後修改的時間
客服端第二次請求此url時,根據http協議。瀏覽器會向伺服器傳送一個If-Modified-Since報頭,
詢問該事件之後檔案是否被修改,沒修改返回304

有了Last-Modified,為什麼還要用ETag?
1、因為如果在一秒鐘之內對一個檔案進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
2、某些伺服器不能精確的得到檔案的最後修改時間
3、一些檔案也行會週期新的更改,但是他的內容並不改變(僅僅改變修改的事件),這個時候我們並不希望客戶端認為檔案被修改,而重新Get

ETag,為什麼還要用Last-Modified?
1、兩者互補,ETag的判斷的缺陷,比如一些圖片等靜態檔案的修改
2、如果每次掃描內容都生成ETag比較,顯然要比直接比較修改時間慢的多。


ETag是被請求變數的實體值(檔案的索引節,大小和最後修改的時間的Hash值)
1、ETag的值伺服器端對檔案的索引節,大小和最後的修改的事件進行Hash後得到的。

三、get/post的區別
1.get資料是存放在url之後,以?分割url和傳輸資料,引數之間以&相連; post方法是把提交的資料放在http包的Body中
2.get提交的資料大小有限制,(因為瀏覽器對url的長度有限制),post的方法提交的資料沒有限制
3.get需要request.queryString來獲取變數的值,而post方式通過request.from來獲取變數的值
4.get的方法提交資料,會帶來安全問題,比如登入一個頁面,通過get的方式提交資料,使用者名稱和密碼就會出現在url上

四、http協議的理解
1.超文字的傳輸協議,是用於從全球資訊網伺服器超文字傳輸到本地資源的傳輸協議
2.基於TCP/IP通訊協議來傳遞資料(HTML,圖片資源)
3.基於運用層的面向物件的協議,由於其簡潔、快速的方法、適用於分散式超媒體資訊系統
4.http請求資訊request:
請求行(request line)、請求頭部(header),空行和請求資料四部分構成

請求行,用來說明請求型別,要訪問的資源以及所使用的HTTP版本.
請求頭部,用來說明伺服器要使用的附加資訊
空行,請求頭部後面的空行是必須的
請求資料也叫主體,可以新增任意的其他資料。
5.http相應資訊Response
狀態行、訊息報頭、空行和響應正文

狀態行,由HTTP協議版本號, 狀態碼, 狀態訊息 三部分組成
訊息報頭,用來說明客戶端要使用的一些附加資訊
空行,訊息報頭後面的空行是必須的
響應正文,伺服器返回給客戶端的文字資訊。


五、http和https
https:是以安全為目標的HTTP通道,簡單講是HTTP的安全版本,通過SSL加密
http:超文字傳輸協議。是一個客服端和伺服器端請求和應答的標準(tcp),使瀏覽器更加高效,使網路傳輸減少

五、http1.0 1.1 2.0的區別
長連線:HTTP1.0需要使用keep-alive引數來告知伺服器建立一個長連線,而HTP1.1預設支援長連線
節約寬頻:HTTP1.1支援只發送一個header資訊(不帶任何body資訊)
host域(設定虛擬站點,也就是說,web server上的多個虛擬站點可以共享同一個ip埠):HTTP1.0沒有host域

1.http2採用的二進位制文字傳輸資料,而非http1文字格式,二進位制在協議的解析和擴充套件更好
2.資料壓縮:對資訊頭採用了HPACK進行壓縮傳輸,節省了資訊頭帶來的網路流量
3.多路複用:一個連線可以併發處理多個請求
4.伺服器推送:我們對支援HTTP2.0的web server請求資料的時候,伺服器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次建立連線傳送請求到伺服器端獲取。這種方式非常合適載入靜態資源

六、koa和express的區別
1.非同步流程的控制。express採用callback來處理非同步,koa2採用的是async/await
2.錯誤處理。express採用callback捕獲異常,對深層次的異常捕獲不了。koa採用try/catch

七、web快取
1.web快取就是存在於客戶端與伺服器之間的一個副本、當你第一個發出請求後,快取根據請求儲存輸出內容的副本
2.快取的好處
(1)減少不必要的請求
(2)降低伺服器的壓力,減少伺服器的消耗
(3)降低網路延遲,加快頁面開啟速度(直接讀取瀏覽器的資料)

八、常見的web安全及防護原理
1.sql注入原理:通郭sql命令插入到web表單遞交或者輸入活命,達到欺騙伺服器執行的惡意sql命令
防範:1.對使用者輸入進行校驗
2.不適用動態拼接sql
2.XSS(跨站指令碼攻擊):往web頁面插入惡意的html標籤或者js程式碼。
舉例子:在論壇放置一個看是安全的連結,竊取cookie中的使用者資訊
防範:1.儘量採用post而不使用get提交表單
2.避免cookie中洩漏使用者的隱式
3.CSRF(跨站請求偽裝):通過偽裝來自受信任使用者的請求
舉例子:黃軼老師的webapp音樂請求資料就是利用CSRF跨站請求偽裝來獲取QQ音樂的資料
防範:在客服端頁面增加偽隨機數,通過驗證碼
XSS和CSRF的區別:
1.XSS是獲取資訊,不需要提前知道其他使用者頁面的程式碼和資料包
2.CSRF代替使用者完成指定的動作,需要知道其他頁面的程式碼和資料包

九、CDN(內容分發網路)
1.儘可能的避開網際網路有可能影響資料傳輸速度和穩定性的瓶頸和環節。使內容傳輸的更快更穩定。
2.關鍵技術:內容儲存和分發技術中
3.基本原理:廣泛採用各種快取伺服器,將這些快取伺服器分佈到使用者訪問相對的地區或者網路中。當用戶訪問網路時利用全域性負載技術
將使用者的訪問指向距離最近的快取伺服器,由快取伺服器直接相應使用者的請求(全域性負載技術)


十、TCP三次握手 (客服端和伺服器端都需要確認各自可收發)
客服端發c起請求連線伺服器端s確認,伺服器端也發起連線確認客服端確認。
第一次握手:客服端傳送一個請求連線,伺服器端只能確認自己可以接受客服端傳送的報文段
第二次握手: 服務端向客服端傳送一個連結,確認客服端收到自己傳送的報文段
第三次握手: 伺服器端確認客服端收到了自己傳送的報文段

十一、從輸入url到獲取頁面的完整過程 https://blog.csdn.net/samjustin1/article/details/52650520
1.查詢NDS(域名解析),獲取域名對應的IP地址
查詢瀏覽器快取
2.瀏覽器與伺服器建立tcp連結(三次握手)
3.瀏覽器向伺服器傳送http請求(請求和傳輸資料)
4.伺服器接受到這個請求後,根據路經引數,經過後端的一些處理生成html程式碼返回給瀏覽器
5.瀏覽器拿到完整的html頁面程式碼開始解析和渲染,如果遇到外部的css或者js,圖片一樣的步驟
6.瀏覽器根據拿到的資源對頁面進行渲染,把一個完整的頁面呈現出來

十二、瀏覽器渲染原理及流程 DOM -> CSSOM -> render -> layout -> print
流程:解析html以及構建dom樹 -> 構建render樹 -> 佈局render樹 -> 繪製render樹
概念:1.構建DOM樹: 渲染引擎解析HTML文件,首先將標籤轉換成DOM樹中的DOM node(包括js生成的標籤)生成內容樹
2.構建渲染樹: 解析對應的css樣式檔案資訊(包括js生成的樣式和外部的css)
3.佈局渲染樹:從根節點遞迴呼叫,計算每一個元素的大小,位置等。給出每個節點所在的螢幕的精準位置
4.繪製渲染樹:遍歷渲染樹,使用UI後端層來繪製每一個節點

重繪:當盒子的位置、大小以及其他屬性,例如顏色、字型大小等到確定下來之後,瀏覽器便把這些顏色都按照各自的特性繪製一遍,將內容呈現在頁面上
觸發重繪的條件:改變元素外觀屬性。如:color,background-color等
重繪是指一個元素外觀的改變所觸發的瀏覽器行為,瀏覽器會根據元素的新屬性重新繪製,使元素呈現新的外觀
注意:table及其內部元素需要多次計算才能確定好其在渲染樹中節點的屬性值,比同等元素要多發時間,要儘量避免使用table佈局

重排(重構/迴流/reflow): 當渲染書中的一部分(或全部)因為元素的規模尺寸,佈局,隱藏等改變而需要重新構建,這就是迴流。
每個頁面都需要一次迴流,就是頁面第一次渲染的時候

重排一定會影響重繪,但是重繪不一定會影響重排


十三、為什麼css放在頂部而js寫在後面
1.瀏覽器預先載入css後,可以不必等待HTML載入完畢就可以渲染頁面了
2.其實HTML渲染並不會等到完全載入完在渲染頁面,而是一邊解析DOM一邊渲染。
3.js寫在尾部,主要是因為js主要扮演事件處理的功能,一方面很多操作是在頁面渲染後才執行的。另一方面可以節省載入時間,使頁面能夠更加的載入,提高使用者的良好體驗

但是隨著JS技術的發展,JS也開始承擔頁面渲染的工作。比如我們的UI其實可以分被對待,把渲染頁面的js放在前面,時間處理的js放在後面

 

設計模式

一、觀察者模式:https://juejin.im/post/5a14e9edf265da4312808d86 https://juejin.im/post/5af05d406fb9a07a9e4d2799
在軟體開發設計中是一個物件(subject),維護一系列依賴他的物件(observer),當任何狀態發生改變自動通知他們。強依賴關係
簡單理解:資料發生改變時,對應的處理函式就會自動執行。一個Subjet,用來維護Observers,為某些event來通知(notify)觀察者

二、釋出-訂閱者 有一個資訊中介,過濾 耦合性低
它定義了一種一對多的關係,可以使多個觀察者物件