2018web前端面試題總結

 

web面試題javascript

css面試 css

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

2、前端一像素問題(畫一條0.5px的線)
* transform: scaleY(0.5) 使用僞元素設置1px的邊框,而後對邊框進行縮放(s
caleY)
 實現思路:
一、設定目標元素的參考位置
二、給目標元素添加一個僞元素before或者after,並設置絕對定位
三、給僞元素添加1px的邊框
四、用box-sizing: border-box 屬性把邊框都包進寬和高裏面
五、寬和高設置爲 200%
六、整個盒子模型縮小爲0.5
七、調整盒子模型的位置,以左上角爲基準 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 設置圖片的邊框前端

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

transition 規定動畫的名字 規定完成過渡效果須要多少秒或毫秒 規定速度效果 定義過渡效果什麼時候開始
animation 指定要綁定到選擇器的關鍵幀的名稱
vue

4、不定寬高的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;

5、浮動 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; // 清除前面元素
}
不破壞文檔流,沒有反作用java

7、position
值:relative,static(默認值),absolute,sticky,fixed
absolute會根據上一級position的值不爲static進行定位,若是向上一直沒有找到position,則相對整個body進行定位
fixe相對的是視圖的窗口,或者frame框架(setFram的子框架,一種html標籤)node

8、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, 帶加號+)react

9、CSS優先級
不一樣級別:總結排序:!important > 行內樣式>ID選擇器 > 類選擇器 > 標籤 > 通配符 > 繼承 > 瀏覽器默認屬性
1.屬性後面加!import 會覆蓋頁面內任何位置定義的元素樣式
2.做爲style屬性寫在元素內的樣式
3.id選擇器
4.類選擇器
5.標籤選擇器
6.通配符選擇器(*)
7.瀏覽器自定義或繼承
同一級別:後寫的會覆蓋先寫的webpack

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

10、對於行內元素,font-size指定 他們的content area的高度,因爲inline box = 上下的helf-leading,若是leading爲0,在這種狀況下,font-size指定了inline box的高度
font-size 指的是字體的高度,可是不能指定每一個字形給定字體高度下的實際高度,致使了span的高度大於line-heightes6

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

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

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

十4、僞類:link 表示連接正常狀況下(即頁面加載完成時)顯示的顏色
hover:表示鼠標懸停時顯示的顏色
visited:連接被點擊時顯示的位置
focus:元素得到光標焦點時的顏色
active: 元素處於激活狀態
link -> visited -> hover -> focus -> active

十5、雪碧圖:多個圖片集成在一個圖片中的圖
使用雪碧圖能夠減小網絡請求的次數,加快容許的速度
經過background-position,去定位圖片在屏幕的哪一個位置

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

Margin-top默認以左上角爲目標運動

Translate 默認以中心點爲目標運動

十七:2px和2區別

沒有單位能夠用於縮放的位置ex: flex-grow

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

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

 

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

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

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

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

4、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面試
1、 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實例化一個對象

2、什麼是閉包和原型鏈
內部函數能夠訪問定義他們外部函數的參數和變量。(做用域鏈的向上查找,把外圍的做用域中的變量值存儲在內存中而不是在函數調用完畢後銷燬)設計私有的方法和變量,避免全局變量的污染
函數嵌套函數
本質是將函數內部和外部鏈接起來。優勢是能夠讀取函數內部的變量,讓這些變量的值始終保存在內存中,不會在函數被調用以後自動清除
閉包的缺陷:
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的基本防範

3、類的建立和繼承
(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函數(沒有實例和方法) 讓他的原型鏈指向父類的原型鏈
砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實例方法/屬性
如何判斷是那種類型

4、異步回調(如何解決回調地獄)
promise、generator、async/await

promise: 1.是一個對象,用來傳遞異步操做的信息。表明着某個將來纔會知道結果的時間,並未這個事件提供統一的api,供進異步處理
2.有了這個對象,就可讓異步操做以同步的操做的流程來表達出來,避免層層嵌套的回調地獄
3.promise表明一個異步狀態,有三個狀態pending(進行中),Resolve(以完成),Reject(失敗)
4.一旦狀態改變,就不會在變。任什麼時候候均可以獲得結果。從進行中變爲以完成或者失敗
promise.all() 裏面狀態都改變,那就會輸出,獲得一個數組
promise.race() 裏面只有一個狀態變爲rejected或者fulfilled即輸出
promis.finally()無論指定無論Promise對象最後狀態如何,都會執行的操做(本質上仍是then方法的特例)

5、前端事件流
事件流描述的是從頁面中接受事件的順序,事件 捕獲階段 處於目標階段 事件冒泡階段 addeventListener 最後這個布爾值參數若是是true,表示在捕獲階段調用事件處理程序;若是是false,表示在冒泡階段調用事件處理程序。
一、事件捕獲階段:實際目標div在捕獲階段不會接受事件,也就是在捕獲階段,事件從document到<html>再到<body>就中止了。
二、處於目標階段:事件在div發生並處理,可是事件處理會被當作是冒泡階段的一部分。
三、冒泡階段:事件又傳播迴文檔
阻止冒泡事件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


6、事件委託(提升性能)
簡介:事件委託指的是,不在事件的(直接dom)上設置監聽函數,而是在其父元素上設置監聽函數。經過事件冒泡,父元素能夠監聽到子元素上事件的觸發
經過判斷事件發生元素DOM的類型,來作出不一樣的響應。
舉例子: 最經典的就是ui和li標籤的事件監聽,好比咱們在添加事件的時候,採用事件委託機制,不會在li標籤上直接添加,而是在ul父元素上添加
好處:能夠比較合適動態元素的綁定,新添加的子元素也會監聽函數,也能夠有事件觸發機制

7、js的new操做符作了什麼?
new操做符建立了一個空對象,這個對象原型指向構造函數的prototype,執行構造函數後返回這個對象(return this)。
若是不要父類的屬性跟方法,在函數的prototype上去new這個父類。

8、改變函數內部this指針的指向函數(bind,apply,call)
經過apply和call改變函數的this指向,他們兩個函數的第一個參數都是同樣的表示要改變指向的那個對象,第二個參數,apply是數組,而call則是arg1,arg2...這種形式。

 

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

9、深拷貝和淺拷貝 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的展開 {...}
深拷貝和淺拷貝的主要區別是:在內存中的存儲類型不一樣
淺拷貝:從新在堆棧中建立內存,拷貝先後對象的基本類型互不影響。只拷貝一層,不能對對象進行子對象進行拷貝
深拷貝:對對象中的子對象進行遞歸拷貝,拷貝先後兩個對象互不影響

10、跨域
同源策略(協議+端口號+域名要相同)
一、jsonp跨域(只能解決get)
原理:動態建立一個script標籤。利用script標籤的src屬性不受同源策略限制,由於全部的src屬性和href屬性都不受同源策略的限制,能夠請求第三方服務器資源內容
步驟:1.去建立一個script標籤
2.script的src屬性設置接口地址
3.接口參數,必需要帶一個自定義函數名,要否則後臺沒法返回數據
4.經過定義函數名去接受返回的數據

二、document.domain 基礎域名相同 子域名不一樣
三、window.name 利用在一個瀏覽器窗口內,載入全部的域名都是共享一個window.name
四、服務器設置對CORS的支持
原理:服務器設置Access-Control-Allow-Origin HTTP響應頭以後,瀏覽器將會容許跨域請求
五、利用h5新特性window.postMessage()

iframe元素建立包含另一個文檔的內聯框架(行內框架)(setTimeout進行異步加載)
解釋:瀏覽器中的瀏覽器!用於設置文本或者圖形的浮動圖文框或容器
它和跨域
一、document.domain 實現主域名相同,子域名不一樣的網頁通訊
都設置爲超域:document.domain = 'demo.com'
二、window.postMessageht(data, url),h5的API,啓動跨域通訊


11、圖片的懶加載和預加載
預加載:提早加載圖片,當用戶須要查看是能夠直接從本地緩存中渲染
爲何要使用預加載:在網頁加載以前,對一些主要內容進行加載,以提供用戶更好的體驗,減小等待時間。
不然,若是一個頁面的內容過於龐大,會出現留白。
解決頁面留白的方案:1.預加載 2.使用svg站位圖片,將一些結構快速搭建起來,等待請求的數據來了以後,替換當前的佔位符
實現預加載的方法:
1.使用html標籤
2.使用Image對象
3.使用XMLHTTPRequest對像,但會精細控制預加載過程

 

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

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

十3、將arguments類數組轉化爲數組的方法
Array.apply(null, arguments)
Array.prototype.slice.apply(arguments)
Array.from(arguments)

十4、高階函數
1、函數做爲參數傳遞 抽離出一部分容易變化的業務邏輯,把這部分業務邏輯放在函數參數中。這樣一來能夠分離業務代碼中變化與不變的部分
回調函數
2、函數做爲返回值傳遞

十5、如何判斷一個變量是對象仍是數組(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()方法測試一個對象是否存在另外一個對象的原型鏈上。


十6、setTimeout 和 setInterval的機制
由於js是單線程的。瀏覽器遇到etTimeout 和 setInterval會先執行完當前的代碼塊,在此以前會把定時器推入瀏覽器的
待執行時間隊列裏面,等到瀏覽器執行完當前代碼以後會看下事件隊列裏有沒有任務,有的話才執行定時器裏的代碼

十7、var let const
const:定義的變量不可修改,必須初始化 ,
var:定義的變量能夠修改,若是不初始化輸出undefined,不會報錯
let:塊級做用域,函數內部使用let定義後,會函數外部無影響
let const 不會形成變量的提高

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

標記清除算法:js最多見的垃圾回收方式,當變量進入執行環境的時候,好比函數中聲明一個變量,垃圾回收器將他標記爲'進入環境',
當變量離開(函數執行完後),就其標記爲'離開環境'。垃圾回收器會在運行的時候給存儲在內存中的全部變量加上標記,
而後去掉環境中的變量以及被環境中該變量所引用的變量(閉包)。在這些完成以後仍存在標記的就是要刪除的變量了

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

二10、undefined 和 null
1.undefined類型只要一個,即undefined,當聲明變量還未被初始化時就是undefined
2.null類型也只有一個值,即null。null用來表示還沒有存在的對象,經常使用來表示函數企圖返回一個不存在的對象
3.NaN 與任何值都是相比較的結果都是false

二11、valueof和tostring
valueof:全部對象都有valueof,若是存在任意原始值,他就默認將對象轉化爲表示它的原始值。
若是對象是複合值,而卻大部分對象沒法真正表示一個原始值,所以默認的valueof()方法簡單的返回對象自己,而不是返回原始值。
數組、函數和正則表達式簡單的繼承了這個more方法,返回對象自己

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

二十3、同步和異步
同步:因爲js單線程,同步任務都在主線程上排隊執行,前面任務沒有執行完成,後面的任務會一直等待
異步:不進入主線程,進入任務隊列,等待主線程任務執行完成,開始執行。最基本的異步操做SetTimemot和SetInterval,等待主線程任務執行完,在開始執行裏面的函數


二十4、函數的柯里化
概念:一個函數接受函數A做爲參數,運行後返回return function一個新的函數,而且能夠處理A中的參數(只接受單一參數的函數)
意義:將函數徹底變成了接受一個參數,返回一個參數的固定形式,便於討論和優化

二十5、while
while循環會在指定條件爲真時循環執行代碼

二十6、TypeScript的優勢:
一、編譯時的強類型,變成了強類型語言,仍是編譯成js 編譯的時候就能夠檢驗
二、更好的模塊化
三、更好的是實現面向對象的編程,類、接口、模塊

二十7、js的阻塞特性:全部瀏覽器在下載JS的時候,會阻止一切其餘活動,好比其餘資源的下載,內容的呈現等等。
直到JS下載、解析、執行完畢後纔開始繼續並行下載其餘資源並呈現內容。
爲了提升用戶體驗,新一代瀏覽器都支持並行下載JS,可是JS下載仍然會阻塞其它資源的下載(例如.圖片,css文件等)。
css阻塞:由於瀏覽器會維持html中css和js的順序,樣式表必須在嵌入的JS執行前先加載、解析完。
而嵌入的JS會阻塞後面的資源加載,因此就會出現上面CSS阻塞下載的狀況。

二十8、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的區別與聯繫:

一、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。

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

三、session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,考慮到減輕服務器性能方面,應當使用cookie。

四、單個cookie保存的數據不能超過4K,不少瀏覽器都限制一個站點最多保存20個cookie。

五、能夠考慮將登錄信息等重要信息存放爲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():有返回值,返回值組成一個新的數組

四十二:ES6語法

箭頭函數 ()=>{}

Var let const

解構

let {name,age} = {name: "lisi", age: "20"};

console.log(name); //lisi              

模板字符串

For in && for of

New promise()

四十三.如何合併對象

Object.assign(o1,o2,o3,…)

四十四.不徹底結構

Let [x,y]=[1,2,3] ; x=1,y=2

四十五.var/let/const的區別

Let/const 只在聲明塊級做用域內有效

Let定義變量,const定義常量,必須初始化,不可改變

Var 全局變量,會聲明提早值留原地,屢次賦值,例如循環中新值會替換舊值



node面試
1、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面試
1、介紹下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 。

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

vuex 是將數據單獨的抽離出來,一種狀態管理工具,它借鑑的是Flux、redux的基本思想,將轉態抽離到全局造成一個store

3、watch:
對屬性進行監聽,容許咱們執行異步操做,限制咱們執行該操做的頻率(debounce),並在咱們獲得結果前,設置中間轉態。

4、Vue的雙向數據綁定實現原理
1.核心就是數據劫持 + 發佈/訂閱者模式:vue使用的是Object.defineProperty()經過監聽他的get/set事件,監聽對數據的操做,從而觸發數據同步

Object.defineProperty缺陷的:
1.只能對屬性進行數據劫持,而且須要深度遍歷整個對象
2.對於數組不能監聽數據的變化
而proxy原生支持監聽數組的變化,而且能夠直接對整個對象進行攔截,全部Vue在下個版本中用proxy替換object.defineProperty


5、nextTick原理

6、生命週期函數 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進入緩存組件的鉤子中
7、keep-alive
在被keep-alive包含的組件/路由,會多出兩個生命週期:activated 和 deactivated
actived在組件第一次渲染時會被調用,以後再每次緩存組件被激活時調用 調用機制:第一次進入緩存路由/組件,在mounted後面,beforeRouteEnter守衛傳給 next 的回調函數以前調用:

8、Vue的SPA 如何優化加載速度
1.減小入口文件體積
2.靜態資源本地緩存
3.開啓Gzip壓縮
4.使用SSR,nuxt.js

9、模塊化
基本概念: 1.在js中,一個模塊就是實現特定功能的文件(js文件)
2.遵循模塊的機制,想要什麼就加載什麼模塊
3.模塊化開發須要遵循規範

js實現模塊化規範
1.AMD 瀏覽器 requirejs 模塊被異步加載,模塊加載不影響後面語句的運行 默認使用baseURL+ paths的路經解析方式
2.CommonJS nodejs
3.ES6的import/export
4.CMD 瀏覽器端

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

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

12、VUE如何自定義屬性

全局自定義:

Vue.directive(‘focus’,{

         Inserted:function(el){

                   el.focus()  //聚焦函數

}       

})

組件自定義

directive{

         inserted:function(el){

                   el.focus() 

}

}

十3、.Vue和vuex 有什麼區別

Vue是框架,vuex是插件,vuex是專門爲vue應用程序開發的狀態管理模式

十4、.Vuex中actions和mutations的區別

Mutations的更改是同步更改,用於用戶執行直接數據更改,this.$store.commit(‘名’)觸發

Actions的更改是異步操做,用於須要與後端交互的數據更改,this.$store.dispath(「名」)觸發

注意:

1):定義actions方法建立一個更改函數時,這個函數必須攜帶一個context參數,用於觸發mutations方法,context.commit(‘修改函數名’ , ’異步請求值’);

2):mutations第一個參數必須傳入state,第二個參數是新值


React
1、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同一個文件

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

3、react的refs
refs就想一個逃生窗,容許咱們之間訪問dom元素或者組件實例,能夠向組件添加一個ref屬性的值是一個回調函數,
它將接受地城dom元素或組件的已掛在實例,做爲第一個參數

4、react中的keys
幫組咱們跟蹤哪些項目已更改、添加、從列表中刪除,key是獨一無二的,可讓咱們高效的去定位元素,而且操做它

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

6、React子組件向父組件傳值
父組件經過props 給子組件傳遞數據,子組件則是經過調用父組件傳給它的函數給父組件傳遞數據。

7、React數據流

8、爲何虛擬DOM會提升性能 https://www.zhihu.com/question/29504639?sort=created
虛擬DOM至關於在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的doom操做,從而提升性能
具體實現步驟:
·用JavaScript對象結構表示DOM樹的結構;而後用這個樹構建一個真正的DOM樹,插到文檔中
·當狀態變動的時候,從新構造一棵樹的對象樹,而後用新的樹和舊的樹進行對比,記錄兩棵樹差別
·把2所記錄的差別應用到步驟1所構建的真正的DOM樹上,試圖就更新了。

9、diff算法
1.把樹形結構按照層級分解,只比較同級元素
2.給列表結構的每一個單元添加key屬性,方便比較。在實際代碼中,會對新舊兩棵樹進行一個深度優先的遍歷,這樣每一個節點都會有一個標記
3.在深度優先遍歷的時候,每遍歷到一個節點就把該節點和新的樹進行對比。若是有差別的話就記錄到一個對象裏面
Vritual DOM 算法主要實現上面步驟的三個函數:element, diff, patch。而後就能夠實際的進行使用
react只會匹配相同的class的component(這裏的class指的是組件的名字)
合併操做,條用component的setState方法的時候,React將其標記爲dirty.到每個時間循環借宿,React檢查全部標記dirty的component從新繪製
4.選擇性子樹渲染。能夠重寫shouldComponentUpdate提升diff的性能

10、super

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

12、reac性能優化是哪一個週期函
shouldComponentUpdate 這個方法用來判斷是否須要調用render方法從新描繪dom.由於dom的描繪很是消耗性能,
若是咱們在shouldComponentUpdate方法中可以寫出更優化的dom diff算法,能夠極大的提升性能

十3、react怎麼劃分業務組件和技術組件
根據組件的職責一般把組件分爲UI組件和容器組件
UI組件負責UI的呈現,容器組件負責管理數據和邏輯
二者經過React-redux提供connect方法聯繫起來

十4、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);
}


性能優化

1、webpack打包文件體積過大?(最終打包爲一個js文件)
1.異步加載模塊
2.提取第三庫
3.代碼壓縮
4.去除沒必要要的插件

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

3、減小檢索路經:resolve.alias能夠配置webpack模塊解析的別名,對於比較深的解析路經,能夠對其配置alias


2、咱們把開發中的全部資源(圖片,js、css文件)都當作模塊,經過loader和plugins來對資源進行處理,打包成符合生產環節部署的前端資源。

3、移動端的性能優化
一、首屏加載和按需加載,懶加載
二、資源預加載
三、圖片壓縮處理,使用base64內嵌圖片
四、合理緩存dom對象
五、使用touchstart代替click(click 300毫秒的延遲)
六、利用transform:translateZ(0),開啓硬件GUP加速
七、不濫用web字體,不濫用float(佈局計算消耗性能),減小font-size聲明
八、使用viewport固定屏幕渲染,加速頁面渲染內容
九、儘可能使用事件代理,避免直接事件綁定

4、Vue的SPA 如何優化加載速度
1.減小入口文件體積
2.靜態資源本地緩存
3.開啓Gzip壓縮
4.使用SSR,nuxt.js

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

6、頁面的重構;在不改變外部行爲的前提下,簡化結構、添加可讀性

服務器端
1、狀態碼:

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

2、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?
一、由於若是在一秒鐘以內對一個文件進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
二、某些服務器不能精確的獲得文件的最後修改時間
三、一些文件也行會週期新的更改,可是他的內容並不改變(僅僅改變修改的事件),這個時候咱們並不但願客戶端認爲文件被修改,而從新Get

ETag,爲何還要用Last-Modified?
一、二者互補,ETag的判斷的缺陷,好比一些圖片等靜態文件的修改
二、若是每次掃描內容都生成ETag比較,顯然要比直接比較修改時間慢的多。


ETag是被請求變量的實體值(文件的索引節,大小和最後修改的時間的Hash值)
一、ETag的值服務器端對文件的索引節,大小和最後的修改的事件進行Hash後獲得的。

3、get/post的區別
1.get數據是存放在url以後,以?分割url和傳輸數據,參數之間以&相連; post方法是把提交的數據放在http包的Body中
2.get提交的數據大小有限制,(由於瀏覽器對url的長度有限制),post的方法提交的數據沒有限制
3.get須要request.queryString來獲取變量的值,而post方式經過request.from來獲取變量的值
4.get的方法提交數據,會帶來安全問題,好比登陸一個頁面,經過get的方式提交數據,用戶名和密碼就會出如今url上

4、http協議的理解
1.超文本的傳輸協議,是用於從萬維網服務器超文本傳輸到本地資源的傳輸協議
2.基於TCP/IP通訊協議來傳遞數據(HTML,圖片資源)
3.基於運用層的面向對象的協議,因爲其簡潔、快速的方法、適用於分佈式超媒體信息系統
4.http請求信息request:
請求行(request line)、請求頭部(header),空行和請求數據四部分構成

請求行,用來講明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,用來講明服務器要使用的附加信息
空行,請求頭部後面的空行是必須的
請求數據也叫主體,能夠添加任意的其餘數據。
5.http相應信息Response
狀態行、消息報頭、空行和響應正文

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


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

5、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請求數據的時候,服務器會順便把一些客戶端須要的資源一塊兒推送到客戶端,省得客戶端再次建立鏈接發送請求到服務器端獲取。這種方式很是合適加載靜態資源

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

7、web緩存
1.web緩存就是存在於客戶端與服務器之間的一個副本、當你第一個發出請求後,緩存根據請求保存輸出內容的副本
2.緩存的好處
(1)減小沒必要要的請求
(2)下降服務器的壓力,減小服務器的消耗
(3)下降網絡延遲,加快頁面打開速度(直接讀取瀏覽器的數據)

8、常見的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代替用戶完成指定的動做,須要知道其餘頁面的代碼和數據包

9、CDN(內容分發網絡)
1.儘量的避開互聯網有可能影響數據傳輸速度和穩定性的瓶頸和環節。使內容傳輸的更快更穩定。
2.關鍵技術:內容存儲和分發技術中
3.基本原理:普遍採用各類緩存服務器,將這些緩存服務器分佈到用戶訪問相對的地區或者網絡中。當用戶訪問網絡時利用全局負載技術
將用戶的訪問指向距離最近的緩存服務器,由緩存服務器直接相應用戶的請求(全局負載技術)


10、TCP三次握手 (客服端和服務器端都須要確認各自可收發)
客服端發c起請求鏈接服務器端s確認,服務器端也發起鏈接確認客服端確認。
第一次握手:客服端發送一個請求鏈接,服務器端只能確認本身能夠接受客服端發送的報文段
第二次握手: 服務端向客服端發送一個連接,確認客服端收到本身發送的報文段
第三次握手: 服務器端確認客服端收到了本身發送的報文段

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

12、瀏覽器渲染原理及流程 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): 當渲染書中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變而須要從新構建,這就是迴流。
每一個頁面都須要一次迴流,就是頁面第一次渲染的時候

重排必定會影響重繪,可是重繪不必定會影響重排


十3、爲何css放在頂部而js寫在後面
1.瀏覽器預先加載css後,能夠沒必要等待HTML加載完畢就能夠渲染頁面了
2.其實HTML渲染並不會等到徹底加載完在渲染頁面,而是一邊解析DOM一邊渲染。
3.js寫在尾部,主要是由於js主要扮演事件處理的功能,一方面不少操做是在頁面渲染後才執行的。另外一方面能夠節省加載時間,使頁面可以更加的加載,提升用戶的良好體驗

可是隨着JS技術的發展,JS也開始承擔頁面渲染的工做。好比咱們的UI其實能夠分被對待,把渲染頁面的js放在前面,時間處理的js放在後面

 

設計模式

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

2、發佈-訂閱者 有一個信息中介,過濾 耦合性低
它定義了一種一對多的關係,能夠使多個觀察者對象對一個主題對象進行監聽,當這個主題對象發生改變時,依賴的全部對象都會被通知到。

二者的區別:
1.觀察者模式中,觀察者知道Subject ,二者是相關聯的,而發發布訂閱者只有經過信息代理進行通訊
2.在發佈訂閱模式中,組件式鬆散耦合的。正好和觀察者模式相反。
3.觀察者大部分是同步的,好比事件的觸發。Subject就會調用觀察者的方法。而發佈訂閱者大多數是異步的()
4.觀察者模式須要在單個應用程序地址空間中實現,而發佈訂閱者更像交叉應用模式。

1004001111
數據結構和算法

1、兩個棧實現一個隊列,兩個隊列實現一個棧 https://www.cnblogs.com/MrListening/p/5697459.html

2、紅黑樹(解決二叉樹依次插入多個節點時的線型排列) https://juejin.im/post/5a27c6946fb9a04509096248

3、最小棧的實現(查找最小元素,用兩個棧配合棧內元素的下標)https://juejin.im/post/5a2ff8c651882533d0230a85

4、十大排序
1.冒泡排序:重複走訪過要排序的數列,一次比較兩個元素,若是他們的順序錯誤就把它們交換過來。
實現過程:1.比較相鄰的元素。若是第一個比第二個大,就交換他們兩個
2.對每一對相鄰元素做一樣的工做,從開始第一對到結尾的最後一對,這樣在最後的元素應該會是最大的數
3.針對全部的元素重複以上的步驟,除了最後一個
4.重複步驟1-3,直到排序完成。
2.選擇排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,而後,在從剩下未排序元素中繼續尋找最小值,而後放在與排序序列的末尾
實現過程:

3.插入排序:構建有序序列,對於未排序數據,在已排序序列中衝後向前掃描,找到相應位置並插入
實現過程:1.從第一個元素開始,該元素能夠認爲已經被排序
2.取出下一個元素,在已排序的元素序列中衝後向前掃描
3.若是該元素(以排序)大於新元素,將元素向後移一位

4.桶排序:將數據分佈到有限數量的桶裏,每一個桶在分別排序

1.快速排序:快速排序使用分治法把一個串(list)分爲兩個子串(sub-lists).具體算法實現
實現過程:1.從數組中挑出一個元素,成爲一個基準
2.從新排列數組,全部元素比基準小的擺在基準前面,全部元素比基準大的擺在基準後面(相同的能夠擺在一邊)
這個分區退出以後,該基準就處於數列的中間位置。成爲分區操做。
3.遞歸的把小於基準值的子數列和大於基準值元素的子數列排序
算法實現: function quickSort (arr) {
if (arr.length <= 1) {return arr}
var destIndex = Math.floor(arr.length/2)
var left = [], right = [];
var dest = arr.splice(destIndex,1)[0];
for (var i =0;i<arr.length;i++){
if (arr[i]<dest) {
left.push(arr[i])
} else {
right.push(arr[i]) }
return quickSort(left).concat([dest],quickSort(right)

2.堆排序:利用對這種數據結構所涉及的一種排序算法,堆積是一個近乎徹底二叉樹的結構,並同時知足堆積的性質:即子節點的鍵值或索引老是小於(或大於)它的父節點。
實現過程:1.

5、數組去重 https://juejin.im/post/5aed6110518825671b026bed#heading-6
1.雙重循環
var arr=[1,3,6,1,3,5];
var newArr=[];
for(var i=0;i<arr.length;i++){
var flag=true;
for(var j=0;j<newArr.length;j++){
if(newArr[j]===arr[i]){
flag=false;
break
}
}
if(flag){
newArr.push(arr[i])
}
}
console.log(newArr)
2.indexOf
var arr=[1,3,6,1,3,5];
var newArr=[];
for(var i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i])==-1){
newArr.push(arr[i]);
}
}
console.log(newArr)
3.數組排序去重 最快你Olong
var arr=[1,3,6,1,3,5];
var newArr=[];
arr=arr.sort();
for(var i=0;i<arr.length;i++){
if(arr[i]!=arr[i-1]){
newArr.push(arr[i]);
}
}
console.log(newArr);
4.ES6語法Set去重
var arr=[1,3,6,1,3,5];
console.log([...new Set(arr)]);
或者
console.log(Array.from(new Set(arr)));

6、字符串
判斷迴文字符串:(遞歸的思想)
1.字符串分隔,倒轉,聚合[...obj].reverse().join('')
2.字符串頭部和尾部,逐次向中間檢測
實現:function isPalindrome(line) {
line += '';
for (var i=0,j=line.length-1;i<j;i++,j--) {
if (line.chartAt(i) !== line.chartAt(j) {
return false
}

3.遞歸

7、二分查找(有序數組的查找)
// 二分查找能夠解決已排序數組的查找問題,即只要數組中包含T(要查找的值),那麼經過不斷的縮小包含T的數據範圍,就能夠最終要找到的數
// (1) 一開始,數據範圍覆蓋整個數組。
// (2) 將數組的中間項與T進行比較,若是T比數組的中間項小,則到數組的前半部分繼續查找,反之,則到數組的後半部分繼續查找。
// (3) 就這樣,每次查找均可以排除一半元素,至關於範圍縮小一半。這樣反覆比較,反覆縮小範圍,最終會在數組中找到T
代碼實現:function binarySearch (data, dest, start, end){
var end = end || data.length-1;
var start = start || 0;
var m = Math.floor((start+end)/2);
if (dest<data[m]){
return binarySearch(data, dest,0, m-1)
} else {
return binarySearch(data, dest, m+1, end)
}}
return false

 

手寫代碼

1、動手實現一個bind(原理經過apply,call)
一句話歸納:1.bind()返回一個新函數,並不會當即執行。
2.bind的第一個參數將做爲他運行時的this,以後的一系列參數將會在傳遞的實參前傳入做爲他的參數
3.bind返回函數做爲構造函數,就是能夠new的,bind時指定的this值就會消失,但傳入的參數依然生效
Function.prototype.bind = function (obj, arg) {
var arg = Array.prototype.slice.call(arguments, 1);
var context = this;
var bound = function (newArg) {
arg = arg.concat(Array.prototype.slice.call(newArg);
return context.apply(obj, arg)
}
var F = function () {} // 在new一個bind會生成新函數,必須的條件就是要繼承原函數的原型,所以用到寄生繼承來完成咱們的過程
F.prototype = context.prototype;00.......................
bound.prototype = new F();
return bound;
}

2、 AJAX (異步的javascript和xml)
ajax的原理:至關於在用戶和服務器之間加一箇中間層(ajax引擎),使用戶操做與服務器響應異步化。
優勢:在不刷新整個頁面的前提下與服務器通訊維護數據。不會致使頁面的重載
能夠把前端服務器的任務轉嫁到客服端來處理,減輕服務器負擔,節省寬帶
劣勢:不支持back。對搜索引擎的支持比較弱;不容易調試
怎麼解決呢?經過location.hash值來解決Ajax過程當中致使的瀏覽器前進後退按鍵失效,
解決之前被人常遇到的重複加載的問題。主要比較先後的hash值,看其是否相等,在判斷是否觸發ajax
function getData(url) {
var xhr = new XMLHttpRequest(); // 建立一個對象,建立一個異步調用的對象
xhr.open('get', url, true) // 設置一個http請求,設置請求的方式,url以及驗證身份
xhr.send() //發送一個http請求
xhr.onreadystatechange = function () { //設置一個http請求狀態的函數
if (xhr.readyState == 4 && xhr.status ==200) {
console.log(xhr.responseText) // 獲取異步調用返回的數據
}
}
}
Promise(getData(url)).resolve(data => data)

AJAX狀態碼:0 - (未初始化)尚未調用send()方法
1 - (載入)已調用send方法,正在發送請求
2 - (載入完成呢)send()方法執行完成
3 - (交互)正在解析相應內容
4 - (完成)響應內容解析完成,能夠在客戶端調用了


3、函數節流(throttle)
function throttle (func, wait) {
var timeout;
var previous = 0;
return function () {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context,args)
}, wait);
}
}
}

}

4、函數防抖(dobounce)
function debounce (func, wait) {
var timeout;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context,args)
}, wait);
}
}

5、實現一個函數clone,能夠對JavaScript中的5種主要的數據類型(包括Number、String、Object、Array、Boolean)進行值複製

Object.prototype.clone = function() {
var newObject = this.constructor === Array ? [] : {} //對象的深拷貝 獲取對應的構造函數 [] 或者 {}
for (let e in this) { //遍歷對象的屬性 in this[e]
newObject[e] = typeof this[e] === 'object' ? this[e].clone() : this[e] //對象中的屬性若是仍是對象 那就繼續遞歸 不然就返回基本的數據類型
}
return newObject
}

6、實現一個簡單的Promise https://juejin.im/post/5b2f02cd5188252b937548ab
class Promise {
constructor (executor) { // executor裏面有兩個參數,一個叫resolve(成功),一個叫reject(失敗)。
this.status = 'pending',
this.value = undefined;
this.reason = undefined;
// 成功存放的數組
this.onResolvedCallbacks = [];
// 失敗存放法數組
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.status == 'pending') {
this.status = 'resolve';
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn())
}
}

let reject = (reason) => {
if (this.status == 'pending') {
this.status = 'reject';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try{
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then (onFullFilled,onRejected) {
if (this.status == 'resolved') {
onFullFilled(this.value)
}
if (this.status == 'rejectd') {
onRejected(this.reason);
}
if (this.status == 'pending') {
this.onResolvedCallbacks.push(()=>{
onFullFilled(this.value);
})
this.onRejectedCallbacks.push(()=> {
onRejected(this.reason);
})
}

}
}

const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('hello world')
}, 1000);
})
p.then((data) =>{
console.log(data)
},(err) =>{
console.log(err);
})

7、發佈訂閱者模式(觀察者模式)

var event = {}; // 發佈者
event.clientList = [] //發佈者的緩存列表

event.listen = function (fn) { // 增長訂閱者函數
this.clientList.push(fn)
}

event.trigger = function () { // 發佈信息
for (var i =0;i<this.clientList.length;i++) {
var fn = this.clientList[i];
fn.apply(this, arguments);
}
}

event.listen (function(time) {
console.log('正式上班時間爲:' +time)
})
event.trigger ('2018/7')

8、手動寫一個node服務器const http = require('http');const fs = require('fs');const server = http.createServer((req,res) => { if (reu.url == '/') { const indexFile = fs.createReadStream('./index.html') req.writeHead(200,{'context-Type':'text/html;charset = utf8}) indexFile.pipe(res)}server.listen(8080)

相關文章
相關標籤/搜索