web前端面试总结(自认为还算全面哈哈哈哈哈!!!)
一、CSS問題
1.flex布局
display:flex; 在父元素設置,子元素受彈性盒影響,默認排成一行,如果超出一行,按比例壓縮
flex:1; 子元素設置,設置子元素如何分配父元素的空間,flex:1,子元素寬度占滿整個父元素align-items:center 定義子元素在父容器中的對齊方式,center 垂直居中justify-content:center 設置子元素在父元素中居中,前提是子元素沒有把父元素占滿,讓子元素水平居中。
2.css3的新特性
transtion
transition-property 規定設置過渡效果的 CSS 屬性的名稱。
transition-duration 規定完成過渡效果需要多少秒或毫秒。
transition-timing-function 規定速度效果的速度曲線。
transition-delay 定義過渡效果何時開始。
animation屬性可以像Flash制作動畫一樣,通過控制關鍵幀來控制動畫的每一步,實現更為復雜的動畫效果。
ainimation實現動畫效果主要由兩部分組成:
通過類似Flash動畫中的幀來聲明一個動畫;
在animation屬性中調用關鍵幀聲明的動畫。
translate 3D建模效果
3.img中alt和title的區別
圖片中的 alt屬性是在圖片不能正常顯示時出現的文本提示。
圖片中的 title屬性是在鼠標在移動到元素上的文本提示。
4.用純CSS創建一個三角形
<style>div {width: 0;height: 0;border-top: 40px solid transparent;border-left: 40px solid transparent;border-right: 40px solid transparent;border-bottom: 40px solid #ff0000;}</style> </head> <body><div></div> </body>5.如何理解CSS的盒子模型?
標準盒子模型:寬度=內容的寬度(content)+ border + padding
低版本IE盒子模型:寬度=內容寬度(content+border+padding)
6.如何讓一個div水平居中
已知寬度,block元素 ,添加添加margin:0 auto屬性。
已知寬度,絕對定位的居中 ,上下左右都為0,margin:auto
7.如何讓一個div水平垂直居中
div { position: relative / fixed; /* 相對定位或絕對定位均可 */ width:500px; height:300px; top: 50%; left: 50%; margin-top:-150px; margin-left:-250px;外邊距為自身寬高的一半 */ background-color: pink; /* 方便看效果 */}.container { display: flex; align-items: center; /* 垂直居中 */ justify-content: center; /* 水平居中 */} .container div { width: 100px; /* 可省 */ height: 100px; /* 可省 */ background-color: pink; /* 方便看效果 */ }8.如何清除浮動?
clear清除浮動(添加空div法)在浮動元素下方添加空div,并給該元素寫css樣式
{clear:both;height:0;overflow:hidden;}
給浮動元素父級設置高度
父級同時浮動(需要給父級同級元素添加浮動)
父級設置成inline-block,其margin: 0 auto居中方式失效
給父級添加overflow:hidden 清除浮動方法
萬能清除法 after偽類 清浮動(現在主流方法,推薦使用)
float_div:after{ content:"."; clear:both; display:block; height:0; overflow:hidden; visibility:hidden; } .float_div{ zoom:1 }9.css3實現三欄布局,左右固定,中間自適應
圣杯布局/雙飛翼布局
<style>* {margin: 0;padding: 0;}.middle,.left,.right {position: relative;float: left;min-height: 130px;}.container {padding: 0 220px 0 200px;overflow: hidden;}.left {margin-left: -100%;left: -200px;width: 200px;background: red;}.right {margin-left: -220px;right: -220px;width: 220px;background: green;}.middle {width: 100%;background: blue;word-break: break-all;}</style> </head> <body><div class='container'><div class='middle'></div><div class='left'></div><div class='right'></div></div> </body>10.display:none 和 visibility: hidden的區別
display:none 隱藏對應的元素,在文檔布局中不再給它分配空間,它各邊的元素會合攏,就當他從來不存在。
visibility:hidden 隱藏對應的元素,但是在文檔布局中仍保留原來的空間。
11.CSS中 link 和@import 的區別是?
link屬于HTML標簽,而@import是CSS提供的頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
import只在IE5以上才能識別,而link是HTML標簽,無兼容問題
link方式的樣式的權重 高于@import的權重.
12.position的absolute與fixed共同點與不同點
共同點:
改變行內元素的呈現方式,display被置為block
讓元素脫離普通流,不占據空間
默認會覆蓋到非定位元素上
不同點:
absolute的”根元素“是可以設置的
fixed的”根元素“固定為瀏覽器窗口。當你滾動網頁,fixed元素與瀏覽器窗口之間的距離是不變的。
13…transition和animation的區別
Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition需要觸發一個事件才能改變屬性,
而animation不需要觸發任何事件的情況下才會隨時間改變屬性值,并且transition為2幀,從from … to,而animation可以一幀一幀的。
transition 規定動畫的名字 規定完成過渡效果需要多少秒或毫秒 規定速度效果 定義過渡效果何時開始
animation 指定要綁定到選擇器的關鍵幀的名稱
14.CSS優先級
不同級別:總結排序:!important > 行內樣式>ID選擇器 > 類選擇器 > 標簽 > 通配符 > 繼承 > 瀏覽器默認屬性1.屬性后面加!import 會覆蓋頁面內任何位置定義的元素樣式2.作為style屬性寫在元素內的樣式3.id選擇器4.類選擇器5.標簽選擇器6.通配符選擇器(*)7.瀏覽器自定義或繼承 **同一級別:后寫的會覆蓋先寫的**css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以盡早的過濾掉一些不必要的樣式規則和元素
15.雪碧圖:
多個圖片集成在一個圖片中的圖使用雪碧圖可以減少網絡請求的次數,加快允許的速度通過background-position,去定位圖片在屏幕的哪個位置二、JS問題
1.typeof和instance of 檢測數據類型有什么區別?
相同點:
都常用來判斷一個變量是否為空,或者是什么類型的。
不同點:
typeof 返回值是一個字符串,用來說明變量的數據類型
instanceof 用于判斷一個變量是否屬于某個對象的實例.
16.使元素消失的方法
visibility:hidden、display:none、z-index=-1、opacity:0 1.opacity:0,該元素隱藏起來了,但不會改變頁面布局,并且,如果該元素已經綁定了一些事件,如click事件也能觸發 2.visibility:hidden,該元素隱藏起來了,但不會改變頁面布局,但是不會觸發該元素已經綁定的事件 3.display:node, 把元素隱藏起來,并且會改變頁面布局,可以理解成在頁面中把該元素刪掉.談一談深克隆和淺克隆?
淺克隆:
只是拷貝了基本類型的數據,而引用類型數據,復制后也是會發生引用,我們把這種拷貝叫做“(淺復制)淺拷貝”,換句話說,淺復制僅僅是指向被復制的內存地址,如果原地址中對象被改變了,那么淺復制出來的對象也會相應改變。
深克隆:
創建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。
JSON.parse、JSON.stringify()
3.es6的新特性都有哪些?
let定義塊級作用域變量
沒有變量的提升,必須先聲明后使用
let聲明的變量,不能與前面的let,var,conset聲明的變量重名
const 定義只讀變量
const聲明變量的同時必須賦值,const聲明的變量必須初始化,一旦初始化完畢就不允許修改
const聲明變量也是一個塊級作用域變量
const聲明的變量沒有“變量的提升”,必須先聲明后使用
const聲明的變量不能與前面的let, var , const聲明的變量重
const定義的對象\數組中的屬性值可以修改,基礎數據類型不可以
ES6可以給形參函數設置默認值
在數組之前加上三個點(…)展開運算符
數組的解構賦值、對象的解構賦值
箭頭函數的特點
箭頭函數相當于匿名函數,是不能作為構造函數的,不能被new
箭頭函數沒有arguments實參集合,取而代之用…剩余運算符解決
箭頭函數沒有自己的this。他的this是繼承當前上下文中的this
箭頭函數沒有函數原型
箭頭函數不能當做Generator函數,不能使用yield關鍵字
不能使用call、apply、bind改變箭頭函數中this指向
Set數據結構,數組去重
4.和=區別是什么?
=賦值
==返回一個布爾值;相等返回true,不相等返回false;
允許不同數據類型之間的比較;
如果是不同類型的數據進行,會默認進行數據類型之間的轉換;
如果是對象數據類型的比較,比較的是空間地址
=== 只要數據類型不一樣,就返回false;
5.常見的設計模式有哪些?
1、js工廠模式 2、js構造函數模式 3、js原型模式 4、構造函數+原型的js混合模式 5、構造函數+原型的動態原型模式 6、觀察者模式 7、發布訂閱模式6.call bind apply 的區別?
call() 和apply()的第一個參數相同,就是指定的對象。這個對象就是該函數的執行上下文。
call()和apply()的區別就在于,兩者之間的參數。
call()在第一個參數之后的 后續所有參數就是傳入該函數的值。
apply() 只有兩個參數,第一個是對象,第二個是數組,這個數組就是該函數的參數。
bind() 方法和前兩者不同在于: bind() 方法會返回執行上下文被改變的函數而不會立即執行,而前兩者是 直接執行該函數。他的參數和call()相同。
7.js繼承方式有哪些?
原型鏈繼承
核心: 將父類的實例作為子類的原型
構造繼承
核心:使用父類的構造函數來增強子類實例,等于是復制父類的實例屬性給子類
實例繼承
核心:為父類實例添加新特性,作為子類實例返回
拷貝繼承
組合繼承
核心:通過調用父類構造,繼承父類的屬性并保留傳參的優點,然后通過將父類實例作為子類原型,實現 函數復用
寄生組合繼承
核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實 例方法/屬性,避免的組合繼承的缺點
8.你怎樣看待閉包?
個人感覺,簡單來說閉包就是在函數里面聲明函數,本質上說就是在函數內部和函數外部搭建起一座橋梁,使得子函數可以訪問父函數中所有的局部變量,但是反之不可以,這只是閉包的作用之一,另一個作用,則是保護變量不受外界污染,使其一直存在內存中,在工作中我們還是少使用閉包的好,因為閉包太消耗內存,不到萬不得已的時候盡量不使用。
9.你是如何理解原型和原型鏈的?
把所有的對象共用的屬性全部放在堆內存的一個對象(共用屬性組成的對象),然后讓每一個對象的 __proto__存儲這個「共用屬性組成的對象」的地址。而這個共用屬性就是原型,原型出現的目的就是為了減少不必要的內存消耗。而原型鏈就是對象通過__proto__向當前實例所屬類的原型上查找屬性或方法的機制,如果找到Object的原型上還是沒有找到想要的屬性或者是方法則查找結束,最終會返回undefined
10.瀏覽器渲染的主要流程是什么?
將html代碼按照深度優先遍歷來生成DOM樹。
css文件下載完后也會進行渲染,生成相應的CSSOM。
當所有的css文件下載完且所有的CSSOM構建結束后,就會和DOM一起生成Render Tree。
接下來,瀏覽器就會進入Layout環節,將所有的節點位置計算出來。
最后,通過Painting環節將所有的節點內容呈現到屏幕上。
11.從輸入url地址到頁面相應都發生了什么?
1、瀏覽器的地址欄輸入URL并按下回車。 2、瀏覽器查找當前URL是否存在緩存,并比較緩存是否過期。3、DNS解析URL對應的IP。 4、根據IP建立TCP連接(三次握手)。 5、HTTP發起請求。 6、服務器處理請求,瀏覽器接收HTTP響應。 7、渲染頁面,構建DOM樹。 8、關閉TCP連接(四次揮手)12.session、cookie、localStorage的區別
相同點
都是保存在瀏覽器端,且同源的。
不同點
- cookie數據始終在同源的http請求中攜帶,即cookie在瀏覽器和服務器間來回傳遞。
- 而sessionStorage和localStorage不會自動把數據發給服務器,僅在本地保存。
- cookie數據還有路徑(path)的概念,可以限制cookie只屬于某個路徑下。
存儲大小限制也不同,cookie數據不能超過4k,同時因為每次http請求都會攜帶cookie,所以cookie只適合保存很小的數據。 - sessionStorage和localStorage 雖然也有存儲大小的限制,但比cookie大得多,可以達到5M或更大。
數據有效期不同,sessionStorage:僅在當前瀏覽器窗口關閉前有效,自然也就不可能持久保持; - localStorage:始終有效,窗口或瀏覽器關閉也一直保存,因此用作持久數據;
- cookie只在設置的cookie過期時間之前一直有效,即使窗口或瀏覽器關閉。
作用域不同,sessionStorage不在不同的瀏覽器窗口中共享,即使是同一個頁面; - localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
13.js中跨域方法
同源策略(協議+端口號+域名要相同)
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()
14.前端有哪些頁面優化方法?
- 減少 HTTP請求數
- 從設計實現層面簡化頁面
- 合理設置 HTTP緩存
- 資源合并與壓縮
- 合并 CSS圖片,減少請求數的又一個好辦法。
- 將外部腳本置底(將腳本內容在頁面信息內容加載后再加載)
- 多圖片網頁使用圖片懶加載。
- 在js中盡量減少閉包的使用
- 盡量合并css和js文件
- 盡量使用字體圖標或者SVG圖標,來代替傳統的PNG等格式的圖片
- 減少對DOM的操作
- 在JS中避免“嵌套循環”和 “死循環”
- 盡可能使用事件委托(事件代理)來處理事件綁定的操作
15.Ajax的四個步驟
1.創建ajax實例
2.執行open 確定要訪問的鏈接 以及同步異步
3.監聽請求狀態
4.發送請求
16.數組去重的方法
ES6的set對象
先將原數組排序,在與相鄰的進行比較,如果不同則存入新數組
17.ajax中get和post請求的區別
- get 一般用于獲取數據
- get請求如果需要傳遞參數,那么會默認將參數拼接到url的后面;然后發送給服務器;
- get請求傳遞參數大小是有限制的;是瀏覽器的地址欄有大小限制;
- get安全性較低
- get 一般會走緩存,為了防止走緩存,給url后面每次拼的參數不同;放在?后面,一般用個時間戳
- post 一般用于發送數據
- post傳遞參數,需要把參數放進請求體中,發送給服務器;
- post請求參數放進了請求體中,對大小沒有要求;
- post安全性比較高;
- post請求不會走緩存;
18.ajax的狀態碼
2開頭
- 200 : 代表請求成功;
3開頭
- 301 : 永久重定向;
- 302: 臨時轉移
- 304 : 讀取緩存 [表示瀏覽器端有緩存,并且服務端未更新,不再向服務端請求資源]
- 307:臨時重定向
以4開頭的都是客戶端的問題;
- 400 :數據/格式錯誤
- 401: 權限不夠;(身份不合格,訪問網站的時候,登錄和不登錄是不一樣的)
- 404 : 路徑錯誤,找不到文件
以5開頭都是服務端的問題
- 500 : 服務器的問題
- 503: 超負荷;
19.移動端的兼容問題
- 給移動端添加點擊事件會有300S的延遲
如果用點擊事件,需要引一個fastclick.js文件,解決300s的延遲
一般在移動端用ontouchstart、ontouchmove、ontouchend - 移動端點透問題,touchstart 早于 touchend 早于click,click的觸發是有延遲的,這個時間大概在300ms左右,也就是說我們tap觸發之后蒙層隱藏, 此時 click還沒有觸發,300ms之后由于蒙層隱藏,我們的click觸發到了下面的a鏈接上
盡量都使用touch事件來替換click事件。例如用touchend事件(推薦)。
用fastclick,https://github.com/ftlabs/fastclick
用preventDefault阻止a標簽的click
消除 IE10 里面的那個叉號
input:-ms-clear{display:none;} - 設置緩存
手機頁面通常在第一次加載后會進行緩存,然后每次刷新會使用緩存而不是去重新向服務器發送請求。如果不希望使用緩存可以設置no-cache。
- 圓角BUG
某些Android手機圓角失效
background-clip: padding-box;
防止手機中網頁放大和縮小
這點是最基本的,做為手機網站開發者來說應該都知道的,就是設置meta中的viewport
- 設置用戶截止縮放,一般寫視口的時候就已經寫好了。
20.JS中同步和異步,以及js的事件流
同步:在同一時間內做一件事情
異步:在同一時間內做多個事情
JS是單線程的,每次只能做一件事情,JS運行在瀏覽器中,瀏覽器是多線程的,可以在同一時間執行多個任務。
21.JS中常見的異步任務
定時器、ajax、事件綁定、回調函數、async await、promise
22.TCP的三次握手和四次揮手
三次握手
- 第一次握手:客戶端發送一個SYN碼給服務器,要求建立數據連接;
- 第二次握手: 服務器SYN和自己處理一個SYN(標志);叫SYN+ACK(確認包);發送給客戶端,可以建立連接
- 第三次握手: 客戶端再次發送ACK向服務器,服務器驗證ACK沒有問題,則建立起連接;
四次揮手
- 第一次揮手: 客戶端發送FIN(結束)報文,通知服務器數據已經傳輸完畢;
- 第二次揮手: 服務器接收到之后,通知客戶端我收到了SYN,發送ACK(確認)給客戶端,數據還沒有傳輸完成
- 第三次揮手: 服務器已經傳輸完畢,再次發送FIN通知客戶端,數據已經傳輸完畢
- 第四次揮手: 客戶端再次發送ACK,進入TIME_WAIT狀態;服務器和客戶端關閉連接;
23.為什么建立連接是三次握手,而斷開連接是四次揮手呢?
建立連接的時候, 服務器在LISTEN狀態下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發送給客戶端。
而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,而自己也未必全部數據都發送給對方了,所以己方可以立即關閉,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送,從而導致多了一次。
24.DOM diff原理
- 如果元素類型發生變化,直接替換
- 如果是文本,則比較文本里面的內容,是否有差異,如果是元素就需要比較當前元素的屬性是否相等,會先比較key, 在比較類型 為什么 react中循環 建議不要使用索引 ,如果純為了展示 那可以使用索引
25.作用域
全局作用域
- 瀏覽器打開一個頁面時,瀏覽器會給JS代碼提供一個全局的運行環境,那么這個環境就是全局作用域
一個頁面只有一個全局作用域,全局作用域下有一個window對象
window是全局作用域下的最大的一個內置對象(全局作用域下定義的變量和函數都會存儲在window下)
如果是全局變量,都會給window新增一個鍵值對;屬性名就是變量名,屬性值就是變量所存儲的值
如果變量只被var過,那么存儲值是undefined
在私有作用域中是可以獲取到全局變量的,但是在全局作用域中不能獲取私有變量
私有作用域
- 函數執行會形成一個新的私有的作用域(執行多次,形成多個私有作用域)
私有作用域在全局作用域中形成,具有包含的關系;
在一個全局作用域中,可以有很多個私有作用域
在私有作用域下定義的變量都是私有變量
形參也是私有變量
函數體中通過function定義的函數也是私有的,在全局作用域不能使用;
塊級作用域
- es6中新引入的一種作用域
在js中常見到的if{}、for{}、while{}、try{}、catch{}、switch case{}都是塊級作用域
var obj = {} //對象的大括號不是塊級作用域
塊級作用域中的同一變量不能被重復聲明(塊級下var和function不能重名,否則會報錯)
作用域鏈
上級作用域
- 函數在哪里定義,他的上一級作用域就是哪,和函數在哪個作用域下執行沒有關系
作用域鏈:當獲取變量所對應的值時,首先看變量是否是私有變量,如果不是私有變量,要繼續向上一級作用域中查找,如果上一級也沒有,那么會繼續向上一級查找,直到找到全局作用域為止;如果全局作用域也沒有,則會報錯;這樣一級一級向上查找,就會形成作用域鏈
當前作用域沒有的,則會繼續向上一級作用域查找
當前函數的上一級作用域跟函數在哪個作用域下執行沒有關系,只跟函數在哪定義有關(重點)
26.Promise處理異步
他是ES6中新增加的一個類(new Promise),目的是為了管理JS中的異步編程的,所以把他稱為“Promise設計模式”
new Promise 經歷三個狀態:padding(準備狀態:初始化成功、開始執行異步的任務)、fullfilled(成功狀態)、rejected(失敗狀態)==
Promise本身是同步編程的,他可以管理異步操作的(重點),new Promise的時候,會把傳遞的函數立即執行
Promise函數天生有兩個參數,resolve(當異步操作執行成功,執行resolve方法),rejected(當異步操作失敗,執行reject方法)
then()方法中有兩個函數,第一個傳遞的函數是resolve,第二個傳遞的函數是reject
ajax中false代表同步,true代表異步,如果使用異步,不等ajax徹底完成
27.map和forEach的區別
相同點
- 都是循環遍歷數組中的每一項
forEach和map方法里每次執行匿名函數都支持3個參數,參數分別是item(當前每一項)、index(索引值)、arr(原數組),需要用哪個的時候就寫哪個
匿名函數中的this都是指向window
只能遍歷數組
不同點
- map方法返回一個新的數組,數組中的元素為原始數組調用函數處理后的值。(原數組進行處理之后對應的一個新的數組。)
map()方法不會改變原始數組
map()方法不會對空數組進行檢測
forEach()方法用于調用數組的每個元素,將元素傳給回調函數.(沒有return,返回值是undefined)
注意:forEach對于空數組是不會調用回調函數的。
28.async await函數
async/await函數是異步代碼的新方式
async/await是基于promise實現的
async/await使異步代碼更像同步代碼
await 只能在async函數中使用,不能再普通函數中使用,要成對出現
默認返回一個promise實例,不能被改變
await下面的代碼是異步,后面的代碼是同步的
29.this指向
- 全局作用域下的this指向window
- 如果給元素的事件行為綁定函數,那么函數中的this指向當前被綁定的那個元素
- 函數中的this,要看函數執行前有沒有 . , 有 . 的話,點前面是誰,this就指向誰,如果沒有點,指向window
- 自執行函數中的this永遠指向window
- 定時器中函數的this指向window
- 構造函數中的this指向當前的實例
- call、apply、bind可以改變函數的this指向
- 箭頭函數中沒有this,如果輸出this,就會輸出箭頭函數定義時所在的作用域中的this
30.原型
所有的函數數據類型都天生自帶一個prototype屬性,該屬性的屬性值是一個對象
prototype的屬性值中天生自帶一個constructor屬性,其constructor屬性值指向當前原型所屬的類
所有的對象數據類型,都天生自帶一個_proto_屬性,該屬性的屬性值指向當前實例所屬類的原型
31.異步回調(如何解決回調地獄)
promise、generator、async/awaitpromise: 1.是一個對象,用來傳遞異步操作的信息。代表著某個未來才會知道結果的時間,并未這個事件提供統一的api,供進異步處理2.有了這個對象,就可以讓異步操作以同步的操作的流程來表達出來,避免層層嵌套的回調地獄3.promise代表一個異步狀態,有三個狀態pending(進行中),Resolve(以完成),Reject(失敗)4.一旦狀態改變,就不會在變。任何時候都可以得到結果。從進行中變為以完成或者失敗promise.all() 里面狀態都改變,那就會輸出,得到一個數組promise.race() 里面只有一個狀態變為rejected或者fulfilled即輸出promis.finally()不管指定不管Promise對象最后狀態如何,都會執行的操作(本質上還是then方法的特例)32.前端事件流
事件流描述的是從頁面中接受事件的順序,事件 捕獲階段 處于目標階段 事件冒泡階段 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}}33.事件如何先捕獲后冒泡?
在DOM標準事件模型中,是先捕獲后冒泡。但是如果要實現先冒泡后捕獲的效果,
對于同一個事件,監聽捕獲和冒泡,分別對應相應的處理函數,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲后再執行捕獲事件。
- 哪些事件不支持冒泡事件:鼠標事件:mouserleave mouseenter
焦點事件:blur focus
UI事件:scroll resize
34. 如何判斷一個變量是對象還是數組(prototype.toString.call())。
千萬不要使用typeof來判斷對象和數組,因為這種類型都會返回object。typeOf()是判斷基本類型的Boolean,Number,symbol, undefined, String。
對于引用類型:除function,都返回object null返回object。
installOf() 用來判斷A是否是B的實例,installof檢查的是原型。
toString() 是Object的原型方法,對于 Object 對象,直接調用 toString() 就能返回 [Object Object] 。而對于其他對象,則需要通過 call / apply 來調用才能返回正確的類型信息。
hasOwnProperty()方法返回一個布爾值,指示對象自身屬性中是否具有指定的屬性,該方法會忽略掉那些從原型鏈上繼承到的屬性。
isProperty()方法測試一個對象是否存在另一個對象的原型鏈上。
35.setTimeout 和 setInterval的機制
因為js是單線程的。瀏覽器遇到etTimeout 和 setInterval會先執行完當前的代碼塊,在此之前會把定時器推入瀏覽器的 待執行時間隊列里面,等到瀏覽器執行完當前代碼之后會看下事件隊列里有沒有任務,有的話才執行定時器里的代碼36.splice和slice、map和forEach、 filter()、reduce()的區別
1.slice(start,end):方法可以從已有數組中返回選定的元素,返回一個新數組,包含從start到end(不包含該元素)的數組方法注意:該方法不會更新原數組,而是返回一個子數組2.splice():該方法想或者從數組中添加或刪除項目,返回被刪除的項目。(該方法會改變原數組)splice(index, howmany,item1,...itemx)·index參數:必須,整數規定添加或刪除的位置,使用負數,從數組尾部規定位置·howmany參數:必須,要刪除的數量,·item1..itemx:可選,向數組添加新項目 3.map():會返回一個全新的數組。使用于改變數據值的時候。會分配內存存儲空間數組并返回,forEach()不會返回數據 4.forEach(): 不會返回任何有價值的東西,并且不打算改變數據,單純的只是想用數據做一些事情,他允許callback更改原始數組的元素 5.reduce(): 方法接收一個函數作為累加器,數組中的每一個值(從左到右)開始縮減,最終計算一個值,不會改變原數組的值 6.filter(): 方法創建一個新數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素。它里面通過function去做處理VUE問題
1.聊聊對vue的理解
vue是一個漸進式的JS框架。他易用,靈活,高效;
可以把一個頁面分隔成多個組件;當其他頁面有類似功能時,直接讓封裝的組件進行復用;
他是構建用戶界面的聲明式框架,只關心圖層;不關心具體是如何實現的
2.V-model的原理是什么?
Vue的雙向數據綁定是由數據劫持結合發布者訂閱者實現的。
數據劫持是通過Object.defineProperty()來劫持對象數據的setter和getter操作。
在數據變動時作你想做的事
- 原理
通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達到數據變化->視圖更新
在初始化vue實例時,遍歷data這個對象,給每一個鍵值對利用Object.definedProperty對data的鍵值對新增get和set方法,利用了事件監聽DOM的機制,讓視圖去改變數據
3.談談對生命周期的理解
- beforeCreate階段:vue實例的掛載元素el和數據對象data都是undefined,還沒有初始化。
- created階段:vue實例的數據對象data有了,可以訪問里面的數據和方法,未掛載到DOM,el還沒有
- beforeMount階段:vue實例的el和data都初始化了,但是掛載之前為虛擬的dom節點
- mounted階段:vue實例掛載到真實DOM上,就可以通過DOM獲取DOM節點
- beforeUpdate階段:響應式數據更新時調用,發生在虛擬DOM打補丁之前,適合在更新之前訪問現有的DOM,比如手動移除已添加的事件監聽器
- updated階段:虛擬DOM重新渲染和打補丁之后調用,組成新的DOM已經更新,避免在這個鉤子函數中操作數據,防止死循環
- beforeDestroy階段:實例銷毀前調用,實例還可以用,this能獲取到實例,常用于銷毀定時器,解綁事件
- destroyed階段:實例銷毀后調用,調用后所有事件監聽器會被移除,所有的子實例都會被銷毀
4.VUE和REACT有什么區別?
react整體是函數式的思想,把組件設計成純組件,狀態和邏輯通過參數傳入,所以在react中,是單向數據流;
vue的思想是響應式的,也就是基于是數據可變的,通過對每一個屬性建立Watcher來監聽,當屬性變化的時候,響應式的更新對應的虛擬dom。
5.vuex的流程
頁面通過mapAction異步提交事件到action。action通過commit把對應參數同步提交到mutation。 mutation會修改state中對于的值。 最后通過getter把對應值跑出去,在頁面的計算屬性中 通過mapGetter來動態獲取state中的值6.vuex有哪幾種狀態和屬性
- state中保存著共有數據,數據是響應式的
- getter可以對state進行計算操作,主要用來過濾一些數據,可以在多組件之間復用
- mutations定義的方法動態修改state中的數據,通過commit提交方法,方法必須是同步的
- actions將mutations里面處理數據的方法變成異步的,就是異步操作數據,通store.dispatch來分發actions,把異步的方法寫在actions中,通過commit提交mutations,進行修改數據。
- modules:模塊化vuex
7.vue路由的兩種模式
- hash ——即地址欄URL中的#符號(此hsah 不是密碼學里的散列運算)
hash 雖然出現URL中,但不會被包含在HTTP請求中,對后端完全沒有影響,因此改變hash不會重新加載頁面。 - history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法
這兩個方法應用于瀏覽器的歷史記錄站,在當前已有的back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改是,雖然改變了當前的URL,但你瀏覽器不會立即向后端發送請求。
8.vue中 key 值的作用
當 Vue.js 用v-for正在更新已渲染過的元素列表時,它默認用“就地復用”策略。
如果數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序,而是簡單復用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。
key的作用主要是為了高效的更新虛擬DOM。
9$route和$router的區別
- $route是“路由信息對象”,包括path,params,hash,query,fullPath,matched,name等路由信息參數。
- $router是“路由實例”對象包括了路由的跳轉方法,鉤子函數等。
10.vue-router守衛
- 導航守衛 router.beforeEach 全局前置守衛
- to: Route: 即將要進入的目標(路由對象)
- from: Route: 當前導航正要離開的路由
- next: Function: 一定要調用該方法來 resolve 這個鉤子。(一定要用這個函數才能去到下一個路由,如果不用就攔截)
執行效果依賴 next 方法的調用參數。 - next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
- next(false): 取消進入路由,url地址重置為from路由地址(也就是將要離開的路由地址)。
路由獨享的守衛 你可以在路由配置上直接定義 beforeEnter 守衛
const router = new VueRouter({routes: [{path: '/foo',component: Foo,beforeEnter: (to, from, next) => {// ...}}] })組件內的守衛 你可以在路由組件內直接定義以下路由導航守衛
const Foo = {template: `...`,beforeRouteEnter (to, from, next) {// 在渲染該組件的對應路由被 confirm 前調用// 不!能!獲取組件實例 `this`// 因為當守衛執行前,組件實例還沒被創建},beforeRouteUpdate (to, from, next) {// 在當前路由改變,但是該組件被復用時調用// 舉例來說,對于一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,// 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。// 可以訪問組件實例 `this`},beforeRouteLeave (to, from, next) {// 導航離開該組件的對應路由時調用,我們用它來禁止用戶離開// 可以訪問組件實例 `this`// 比如還未保存草稿,或者在用戶離開前,將setInterval銷毀,防止離開之后,定時器還在調用。} }11.axios是什么?怎么使用?描述使用它實現登錄功能的流程?
請求后臺資源的模塊。
$ npm install axios -S裝好然后發送的是跨域,需在配置文件中config/index.js進行設置。后臺如果是Tp5則定義一個資源路由。
js中使用import進來,然后.get或.post。返回在.then函數中如果成功,失敗則是在.catch函數中
12.vue修飾符
- stop:阻止事件的冒泡
- prevent:阻止事件的默認行為
- once:只觸發一次
- self:只觸發自己的事件行為時,才會執行
13.vue項目中的性能優化
1.不要在模板里面寫過多表達式
2.循環調用子組件時添加key
3.頻繁切換的使用v-show,不頻繁切換的使用v-if
4.盡量少用float,可以用flex
5.按需加載,可以用require或者import()按需加載需要的組件
6.路由懶加載
14.vue.extend和vue.component
- extend
是構造一個組件的語法器。
然后這個組件你可以作用到Vue.component這個全局注冊方法里
還可以在任意vue模板里使用組件。
也可以作用到vue實例或者某個組件中的components屬性中并在內部使用apple組件。 - Vue.component
你可以創建 ,也可以取組件。
常見的兼容問題
png24位的圖片在iE6瀏覽器上出現背景
解決方案是做成PNG8.也可以引用一段腳本處理.
瀏覽器默認的margin和padding不同。
解決方案是加一個全局的*{margin:0;padding:0;}來統一。
IE6雙邊距bug:塊屬性標簽float后,又有橫行的margin情況下,在ie6顯示margin比設置的大。
浮動ie產生的雙倍距離(IE6雙邊距問題:在IE6下,如果對元素設置了浮動,同時又設置了margin-left或margin-right,margin值會加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}
React問題
1.react和vue的區別
=> 相同點:1.數據驅動頁面,提供響應式的試圖組件2.都有virtual DOM,組件化的開發,通過props參數進行父子之間組件傳遞數據,都實現了webComponents規范3.數據流動單向,都支持服務器的渲染SSR4.都有支持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 -> state3.react的refs
refs就想一個逃生窗,允許我們之間訪問dom元素或者組件實例,可以向組件添加一個ref屬性的值是一個回調函數, 它將接受地城dom元素或組件的已掛在實例,作為第一個參數4.react中的keys
幫組我們跟蹤哪些項目已更改、添加、從列表中刪除,key是獨一無二的,可以讓我們高效的去定位元素,并且操作它5.React的生命周期
三個狀態:Mounting(已插入真實的DOM)Updating(正在被重新渲染)Unmounting(已移除真實的DOM) componentDIdMount 在第一次渲染后調用,只在客服端。之后組件已經生成對應的DOM結構, componentDidUpdate 在組件完成更新后立即調用,在出初始化是不會調用6.React子組件向父組件傳值
父組件通過props 給子組件傳遞數據,子組件則是通過調用父組件傳給它的函數給父組件傳遞數據。7.為什么虛擬DOM會提高性能 https://www.zhihu.com/question/29504639?sort=created
虛擬DOM相當于在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的doom操作,從而提高性能 具體實現步驟:·用JavaScript對象結構表示DOM樹的結構;然后用這個樹構建一個真正的DOM樹,插到文檔中·當狀態變更的時候,重新構造一棵樹的對象樹,然后用新的樹和舊的樹進行對比,記錄兩棵樹差異·把2所記錄的差異應用到步驟1所構建的真正的DOM樹上,試圖就更新了。8.diff算法
1.把樹形結構按照層級分解,只比較同級元素 2.給列表結構的每個單元添加key屬性,方便比較。在實際代碼中,會對新舊兩棵樹進行一個深度優先的遍歷,這樣每個節點都會有一個標記 3.在深度優先遍歷的時候,每遍歷到一個節點就把該節點和新的樹進行對比。如果有差異的話就記錄到一個對象里面 Vritual DOM 算法主要實現上面步驟的三個函數:element, diff, patch。然后就可以實際的進行使用 react只會匹配相同的class的component(這里的class指的是組件的名字) 合并操作,條用component的setState方法的時候,React將其標記為dirty.到每一個時間循環借宿,React檢查所有標記dirty的component重新繪制 4.選擇性子樹渲染。可以重寫shouldComponentUpdate提高diff的性能9.簡述下flux的思想
flux的最大特點,就是數據的‘單向流動’ 1.用戶訪問View 2.View發出用戶的Action 3.Dispatcher收到Action,要求state進行相應的更新 4.store更新后,發出一個‘change’事件后,更新頁面10.reac性能優化是哪個周期函
shouldComponentUpdate 這個方法用來判斷是否需要調用render方法重新描繪dom.因為dom的描繪非常消耗性能, 如果我們在shouldComponentUpdate方法中能夠寫出更優化的dom diff算法,可以極大的提高性能11.react怎么劃分業務組件和技術組件
根據組件的職責通常把組件分為UI組件和容器組件 UI組件負責UI的呈現,容器組件負責管理數據和邏輯 兩者通過React-redux提供connect方法聯系起來12.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三、移動端的性能優化
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=no2.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.并且判斷出該頁面自上次客戶端請求之后未被修改。直接返回304last-modified: 客服端請求資源,同時有一個last-modified的屬性標記此文件在服務器最后修改的時間客服端第二次請求此url時,根據http協議。瀏覽器會向服務器發送一個If-Modified-Since報頭,詢問該事件之后文件是否被修改,沒修改返回304有了Last-Modified,為什么還要用ETag?1、因為如果在一秒鐘之內對一個文件進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)2、某些服務器不能精確的得到文件的最后修改時間3、一些文件也行會周期新的更改,但是他的內容并不改變(僅僅改變修改的事件),這個時候我們并不希望客戶端認為文件被修改,而重新GetETag,為什么還要用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請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器端獲取。這種方式非常合適加載靜態資源七、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放在后面十四、存儲方式與傳輸方式
1.indexBD: 是h5的本地存儲庫,把一些數據存儲到瀏覽器中,沒網絡,瀏覽器可以從這里讀取數據,離線運用。5m 2.Cookie: 通過瀏覽器記錄信息確認用戶身份,最大4kb,這也就限制了傳輸的數據,請求的性能會受到影響 3.Session: 服務器端使用的一種記錄客戶狀態的機制(session_id存在set_cookie發送到客服端,保存為cookie) 4.localStroage: h5的本地存儲,數據永久保存在客服端cookie,sessionStorage,localStorage
1、cookie,sessionStorage,localStorage是存放在客戶端,session對象數據是存放在服務器上
實際上瀏覽器和服務器之間僅需傳遞session id即可,服務器根據session-id找到對應的用戶session對象
session存儲數據更安全一些,一般存放用戶信息,瀏覽器只適合存儲一般的數據
2、cookie數據始終在同源的http請求中攜帶,在瀏覽器和服務器來回傳遞,里面存放著session-id
sessionStorage,localStorage僅在本地保存
3、大小限制區別,cookie數據不超過4kb,localStorage在谷歌瀏覽中2.6MB
4、數據有效期不同,cookie在設置的(服務器設置)有效期內有效,不管窗口和瀏覽器關閉
sessionStorage僅在當前瀏覽器窗口關閉前有效,關閉即銷毀(臨時存儲)
localStorage始終有效
SessionStorage和localStorage區別:
1.sessionStorage用于本地存儲一個會話(session)中的數據,這些數據只有在用一個會話的頁面中才能被訪問(也就是說在第一次通信過程中)
并且在會話結束后數據也隨之銷毀,不是一個持久的本地存儲,會話級別的儲存
2.localStorage用于持久化的本地存儲,除非主動刪除數據,否則不會過期
token、cookie、session三者的理解???!!!
1、token就是令牌,比如你授權(登錄)一個程序時,他就是個依據,判斷你是否已經授權該軟件(最好的身份認證,安全性好,且是唯一的)用戶身份的驗證方式 2、cookie是寫在客戶端一個txt文件,里面包括登錄信息之類的,這樣你下次在登錄某個網站,就會自動調用cookie自動登錄用戶名服務器生成,發送到瀏覽器、瀏覽器保存,下次請求再次發送給服務器(存放著登錄信息)3、session是一類用來客戶端和服務器之間保存狀態的解決方案,會話完成被銷毀(代表的就是服務器和客戶端的一次會話過程)cookie中存放著sessionID,請求會發送這個id。sesion因為request對象而產生。基于Token的身份驗證:(最簡單的token: uid用戶唯一的身份識別 + time當前事件戳 + sign簽名)
1、用戶通過用戶名和密碼發送請求2、服務器端驗證3、服務器端返回一個帶簽名的token,給客戶端4、客戶端儲存token,并且每次用于發送請求5、服務器驗證token并且返回數據每一次請求都需要tokencookie與session區別
1、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙考慮到安全應當使用session。3、session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能考慮到減輕服務器性能方面,應當使用COOKIE。4、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。session與token區別
1、session認證只是把簡單的User的信息存儲Session里面,sessionID不可預測,一種認證手段。只存在服務端,不能共享到其他的網站和第三方App2、token是oAuth Token,提供的是認證和授權,認證針對用戶,授權是針對App,目的就是讓某APP有權訪問某用戶的的信息。Token是唯一的,token不能轉移到其他的App,也不能轉到其他用戶上。(適用于App)3、session的狀態是存在服務器端的,客戶端只存在session id, Token狀態是存儲在客戶端的Cookie的弊端有哪些???(優勢:保存客戶端數據,分擔了服務器存儲的負擔)
1、數量和長度的限制。每個特定的域名下最多生成20個cookie(chorme和safari沒有限制)2、安全性問題。設計模式
一、觀察者模式:https://juejin.im/post/5a14e9edf265da4312808d86 https://juejin.im/post/5af05d406fb9a07a9e4d2799
在軟件開發設計中是一個對象(subject),維護一系列依賴他的對象(observer),當任何狀態發生改變自動通知他們。強依賴關系
簡單理解:數據發生改變時,對應的處理函數就會自動執行。一個Subjet,用來維護Observers,為某些event來通知(notify)觀察者
二、發布-訂閱者 有一個信息中介,過濾 耦合性低
它定義了一種一對多的關系,可以使多個觀察者對象對一個主題對象進行監聽,當這個主題對象發生改變時,依賴的所有對象都會被通知到。
- -兩者的區別:
1.觀察者模式中,觀察者知道Subject ,兩者是相關聯的,而發發布訂閱者只有通過信息代理進行通信
2.在發布訂閱模式中,組件式松散耦合的。正好和觀察者模式相反。
3.觀察者大部分是同步的,比如事件的觸發。Subject就會調用觀察者的方法。而發布訂閱者大多數是異步的()
4.觀察者模式需要在單個應用程序地址空間中實現,而發布訂閱者更像交叉應用模式。
數據結構和算法
一、兩個棧實現一個隊列,兩個隊列實現一個棧 https://www.cnblogs.com/MrListening/p/5697459.html
二、紅黑樹(解決二叉樹依次插入多個節點時的線型排列) https://juejin.im/post/5a27c6946fb9a04509096248
三、最小棧的實現(查找最小元素,用兩個棧配合棧內元素的下標)https://juejin.im/post/5a2ff8c651882533d0230a85
四、十大排序
1.冒泡排序:重復走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把它們交換過來。實現過程:1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個2.對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對,這樣在最后的元素應該會是最大的數3.針對所有的元素重復以上的步驟,除了最后一個4.重復步驟1-3,直到排序完成。 2.選擇排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,然后,在從剩下未排序元素中繼續尋找最小值,然后放在與排序序列的末尾實現過程:3.插入排序:構建有序序列,對于未排序數據,在已排序序列中沖后向前掃描,找到相應位置并插入實現過程:1.從第一個元素開始,該元素可以認為已經被排序2.取出下一個元素,在已排序的元素序列中沖后向前掃描3.如果該元素(以排序)大于新元素,將元素向后移一位4.在取出一個元素,比較之前的,直到找到自己合適的位置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.五、數組去重 https://juejin.im/post/5aed6110518825671b026bed#heading-6
1.雙重循環 2.indexOf 3.數組排序去重 最快你Olong六、字符串
判斷回文字符串:(遞歸的思想)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.遞歸七、二分查找(有序數組的查找)
二分查找可以解決已排序數組的查找問題,即只要數組中包含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手寫代碼
一、動手實現一個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;bound.prototype = new F();return bound; }二、 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 - (完成)響應內容解析完成,可以在客戶端調用了 ```#### 三、函數節流(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);}}}} ```#### 四、函數防抖(dobounce) ```function debounce (func, wait) {var timeout;return function() {var context = this;var args = arguments;clearTimeout(timeout);timeout = setTimeout(() => {func.apply(context,args)}, wait);}} ```#### 五、實現一個函數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} ```#### 六、實現一個簡單的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); }) ```#### 七、發布訂閱者模式(觀察者模式) ``` 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') ```#### 八、手動寫一個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) ```總結
以上是生活随笔為你收集整理的web前端面试总结(自认为还算全面哈哈哈哈哈!!!)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人教版初中计算机教案全本,人教版初中信息
- 下一篇: win 10键盘快捷方式就是按键或按键组