Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
var topBtn = document.getElementById('top');
// 獲取視窗高度
var winHeight = document.documentElement.clientHeight;
window.onscroll = function () {
// 獲取頁面向上滾動距離,chrome瀏覽器識別document.body.scrollTop,而火狐識別document.documentElement.scrollTop,這里做了兼容處理
var toTop = document.documentElement.scrollTop || document.body.scrollTop;
// 如果滾動超過一屏,返回頂部按鈕出現(xiàn),反之隱藏
if(toTop>=winHeight){
topBtn.style.display = 'block';
}else {
topBtn.style.display = 'none';
}
}
topBtn.onclick=function () {
var timer = setInterval(function () {
var toTop = document.documentElement.scrollTop || document.body.scrollTop;
// 判斷是否到達(dá)頂部,到達(dá)頂部停止?jié)L動,沒到達(dá)頂部繼續(xù)滾動
if(toTop == 0){
clearInterval(timer);
}else {
// 設(shè)置滾動速度
var speed = Math.ceil(toTop/5);
// 頁面向上滾動
document.documentElement.scrollTop=document.body.scrollTop=toTop-speed;
}
},50);
}
言
金九銀十跳槽季,offer快到碗里來,前端面試考點眾多,而網(wǎng)上各個知識點的博客文章又太多,看的眼花繚亂...所以我整理了一下常見知識點的精華文章,每個知識點的文章控制在3篇以內(nèi),盡量覆蓋該知識點的下容易被面試到的所有內(nèi)容,文章都是之前自己讀過的,確定是精華干貨。文章會一直更新,也歡迎大家推薦精華文章,大家共同學(xué)習(xí)進(jìn)步呀!
display:flex; 在父元素設(shè)置,子元素受彈性盒影響,默認(rèn)排成一行,如果超出一行,按比例壓縮 flex:1; 子元素設(shè)置,設(shè)置子元素如何分配父元素的空間,flex:1,子元素寬度占滿整個父元素align-items:center 定義子元素在父容器中的對齊方式,center 垂直居中justify-content:center 設(shè)置子元素在父元素中居中,前提是子元素沒有把父元素占滿,讓子元素水平居中。
transtion transition-property 規(guī)定設(shè)置過渡效果的 CSS 屬性的名稱。
transition-duration 規(guī)定完成過渡效果需要多少秒或毫秒。
transition-timing-function 規(guī)定速度效果的速度曲線。
transition-delay 定義過渡效果何時開始。
animation屬性可以像Flash制作動畫一樣,通過控制關(guān)鍵幀來控制動畫的每一步,實現(xiàn)更為復(fù)雜的動畫效果。
ainimation實現(xiàn)動畫效果主要由兩部分組成:
通過類似Flash動畫中的幀來聲明一個動畫;
在animation屬性中調(diào)用關(guān)鍵幀聲明的動畫。
translate 3D建模效果
圖片中的 alt屬性是在圖片不能正常顯示時出現(xiàn)的文本提示。alt有利于SEO優(yōu)化
圖片中的 title屬性是在鼠標(biāo)在移動到元素上的文本提示。
復(fù)制代碼 <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>
標(biāo)準(zhǔn)盒子模型:寬度=內(nèi)容的寬度(content)+ border + padding
低版本IE盒子模型:寬度=內(nèi)容寬度(content+border+padding)
已知寬度,block元素 ,添加添加margin:0 auto屬性。
已知寬度,絕對定位的居中 ,上下左右都為0,margin:auto
復(fù)制代碼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; /* 方便看效果 */
}
clear清除浮動(添加空div法)在浮動元素下方添加空div,并給該元素寫css樣式 {clear:both;height:0;overflow:hidden;}
給浮動元素父級設(shè)置高度
父級同時浮動(需要給父級同級元素添加浮動)
父級設(shè)置成inline-block,其margin: 0 auto居中方式失效
給父級添加overflow:hidden 清除浮動方法
萬能清除法 after偽類 清浮動(現(xiàn)在主流方法,推薦使用)
復(fù)制代碼float_div:after{
content:".";
clear:both;
display:block;
height:0;
overflow:hidden;
visibility:hidden;
}
.float_div{
zoom:1
}
圣杯布局/雙飛翼布局
復(fù)制代碼 <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>
display:none 隱藏對應(yīng)的元素,在文檔布局中不再給它分配空間,它各邊的元素會合攏,就當(dāng)他從來不存在。
visibility:hidden 隱藏對應(yīng)的元素,但是在文檔布局中仍保留原來的空間。
link屬于HTML標(biāo)簽,而@import是CSS提供的頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
import只在IE5以上才能識別,而link是HTML標(biāo)簽,無兼容問題
link方式的樣式的權(quán)重 高于@import的權(quán)重.
共同點: 改變行內(nèi)元素的呈現(xiàn)方式,display被置為block 讓元素脫離普通流,不占據(jù)空間 默認(rèn)會覆蓋到非定位元素上
不同點: absolute的”根元素“是可以設(shè)置的 fixed的”根元素“固定為瀏覽器窗口。當(dāng)你滾動網(wǎng)頁,fixed元素與瀏覽器窗口之間的距離是不變的。
Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區(qū)別是transition需要觸發(fā)一個事件才能改變屬性, 而animation不需要觸發(fā)任何事件的情況下才會隨時間改變屬性值,并且transition為2幀,從from .... to,而animation可以一幀一幀的。
transition 規(guī)定動畫的名字 規(guī)定完成過渡效果需要多少秒或毫秒 規(guī)定速度效果 定義過渡效果何時開始 animation 指定要綁定到選擇器的關(guān)鍵幀的名稱
復(fù)制代碼不同級別:總結(jié)排序:!important > 行內(nèi)樣式>ID選擇器 > 類選擇器 > 標(biāo)簽 > 通配符 > 繼承 > 瀏覽器默認(rèn)屬性
1.屬性后面加!import 會覆蓋頁面內(nèi)任何位置定義的元素樣式
2.作為style屬性寫在元素內(nèi)的樣式
3.id選擇器
4.類選擇器
5.標(biāo)簽選擇器
6.通配符選擇器(*)
7.瀏覽器自定義或繼承
**同一級別:后寫的會覆蓋先寫的**
css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以盡早的過濾掉一些不必要的樣式規(guī)則和元素
復(fù)制代碼 多個圖片集成在一個圖片中的圖
使用雪碧圖可以減少網(wǎng)絡(luò)請求的次數(shù),加快允許的速度
通過background-position,去定位圖片在屏幕的哪個位置
相同點: 都常用來判斷一個變量是否為空,或者是什么類型的。
不同點: typeof 返回值是一個字符串,用來說明變量的數(shù)據(jù)類型 instanceof 用于判斷一個變量是否屬于某個對象的實例.
復(fù)制代碼visibility:hidden、display:none、z-index=-1、opacity:0
1.opacity:0,該元素隱藏起來了,但不會改變頁面布局,并且,如果該元素已經(jīng)綁定了一些事件,如click事件也能觸發(fā)
2.visibility:hidden,該元素隱藏起來了,但不會改變頁面布局,但是不會觸發(fā)該元素已經(jīng)綁定的事件
3.display:node, 把元素隱藏起來,并且會改變頁面布局,可以理解成在頁面中把該元素刪掉
淺克隆: 只是拷貝了基本類型的數(shù)據(jù),而引用類型數(shù)據(jù),復(fù)制后也是會發(fā)生引用,我們把這種拷貝叫做“(淺復(fù)制)淺拷貝”,換句話說,淺復(fù)制僅僅是指向被復(fù)制的內(nèi)存地址,如果原地址中對象被改變了,那么淺復(fù)制出來的對象也會相應(yīng)改變。
深克隆: 創(chuàng)建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。 JSON.parse、JSON.stringify()
let定義塊級作用域變量 沒有變量的提升,必須先聲明后使用 let聲明的變量,不能與前面的let,var,conset聲明的變量重名
const 定義只讀變量 const聲明變量的同時必須賦值,const聲明的變量必須初始化,一旦初始化完畢就不允許修改 const聲明變量也是一個塊級作用域變量 const聲明的變量沒有“變量的提升”,必須先聲明后使用 const聲明的變量不能與前面的let, var , const聲明的變量重 const定義的對象\數(shù)組中的屬性值可以修改,基礎(chǔ)數(shù)據(jù)類型不可以
ES6可以給形參函數(shù)設(shè)置默認(rèn)值
在數(shù)組之前加上三個點(...)展開運算符
數(shù)組的解構(gòu)賦值、對象的解構(gòu)賦值
箭頭函數(shù)的特點 箭頭函數(shù)相當(dāng)于匿名函數(shù),是不能作為構(gòu)造函數(shù)的,不能被new 箭頭函數(shù)沒有arguments實參集合,取而代之用...剩余運算符解決 箭頭函數(shù)沒有自己的this。他的this是繼承當(dāng)前上下文中的this 箭頭函數(shù)沒有函數(shù)原型 箭頭函數(shù)不能當(dāng)做Generator函數(shù),不能使用yield關(guān)鍵字 不能使用call、apply、bind改變箭頭函數(shù)中this指向 Set數(shù)據(jù)結(jié)構(gòu),數(shù)組去重
=賦值
==返回一個布爾值;相等返回true,不相等返回false; 允許不同數(shù)據(jù)類型之間的比較; 如果是不同類型的數(shù)據(jù)進(jìn)行,會默認(rèn)進(jìn)行數(shù)據(jù)類型之間的轉(zhuǎn)換; 如果是對象數(shù)據(jù)類型的比較,比較的是空間地址
=== 只要數(shù)據(jù)類型不一樣,就返回false;
復(fù)制代碼1、js工廠模式
2、js構(gòu)造函數(shù)模式
3、js原型模式
4、構(gòu)造函數(shù)+原型的js混合模式
5、構(gòu)造函數(shù)+原型的動態(tài)原型模式
6、觀察者模式
7、發(fā)布訂閱模式
call() 和apply()的第一個參數(shù)相同,就是指定的對象。這個對象就是該函數(shù)的執(zhí)行上下文。
call()和apply()的區(qū)別就在于,兩者之間的參數(shù)。
call()在第一個參數(shù)之后的 后續(xù)所有參數(shù)就是傳入該函數(shù)的值。
apply() 只有兩個參數(shù),第一個是對象,第二個是數(shù)組,這個數(shù)組就是該函數(shù)的參數(shù)。 bind() 方法和前兩者不同在于: bind() 方法會返回執(zhí)行上下文被改變的函數(shù)而不會立即執(zhí)行,而前兩者是 直接執(zhí)行該函數(shù)。他的參數(shù)和call()相同。
原型鏈繼承 核心: 將父類的實例作為子類的原型
構(gòu)造繼承 核心:使用父類的構(gòu)造函數(shù)來增強(qiáng)子類實例,等于是復(fù)制父類的實例屬性給子類
實例繼承 核心:為父類實例添加新特性,作為子類實例返回
拷貝繼承
組合繼承 核心:通過調(diào)用父類構(gòu)造,繼承父類的屬性并保留傳參的優(yōu)點,然后通過將父類實例作為子類原型,實現(xiàn) 函數(shù)復(fù)用
寄生組合繼承 核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調(diào)用兩次父類的構(gòu)造的時候,就不會初始化兩次實 例方法/屬性,避免的組合繼承的缺點
個人感覺,簡單來說閉包就是在函數(shù)里面聲明函數(shù),本質(zhì)上說就是在函數(shù)內(nèi)部和函數(shù)外部搭建起一座橋梁,使得子函數(shù)可以訪問父函數(shù)中所有的局部變量,但是反之不可以,這只是閉包的作用之一,另一個作用,則是保護(hù)變量不受外界污染,使其一直存在內(nèi)存中,在工作中我們還是少使用閉包的好,因為閉包太消耗內(nèi)存,不到萬不得已的時候盡量不使用。
把所有的對象共用的屬性全部放在堆內(nèi)存的一個對象(共用屬性組成的對象),然后讓每一個對象的 __proto__存儲這個「共用屬性組成的對象」的地址。而這個共用屬性就是原型,原型出現(xiàn)的目的就是為了減少不必要的內(nèi)存消耗。而原型鏈就是對象通過__proto__向當(dāng)前實例所屬類的原型上查找屬性或方法的機(jī)制,如果找到Object的原型上還是沒有找到想要的屬性或者是方法則查找結(jié)束,最終會返回undefined
將html代碼按照深度優(yōu)先遍歷來生成DOM樹。 css文件下載完后也會進(jìn)行渲染,生成相應(yīng)的CSSOM。 當(dāng)所有的css文件下載完且所有的CSSOM構(gòu)建結(jié)束后,就會和DOM一起生成Render Tree。 接下來,瀏覽器就會進(jìn)入Layout環(huán)節(jié),將所有的節(jié)點位置計算出來。 最后,通過Painting環(huán)節(jié)將所有的節(jié)點內(nèi)容呈現(xiàn)到屏幕上。
復(fù)制代碼1、瀏覽器的地址欄輸入URL并按下回車。
2、瀏覽器查找當(dāng)前URL是否存在緩存,并比較緩存是否過期。3、DNS解析URL對應(yīng)的IP。
4、根據(jù)IP建立TCP連接(三次握手)。
5、HTTP發(fā)起請求。
6、服務(wù)器處理請求,瀏覽器接收HTTP響應(yīng)。
7、渲染頁面,構(gòu)建DOM樹。
8、關(guān)閉TCP連接(四次揮手)
相同點 都是保存在瀏覽器端,且同源的。
不同點
同源策略(協(xié)議+端口號+域名要相同)
1、jsonp跨域(只能解決get) 原理:動態(tài)創(chuàng)建一個script標(biāo)簽。利用script標(biāo)簽的src屬性不受同源策略限制,因為所有的src屬性和href屬性都不受同源策略的限制,可以請求第三方服務(wù)器資源內(nèi)容
步驟: 1).去創(chuàng)建一個script標(biāo)簽 2).script的src屬性設(shè)置接口地址 3).接口參數(shù),必須要帶一個自定義函數(shù)名,要不然后臺無法返回數(shù)據(jù) 4).通過定義函數(shù)名去接受返回的數(shù)據(jù)
2、document.domain 基礎(chǔ)域名相同 子域名不同
3、window.name 利用在一個瀏覽器窗口內(nèi),載入所有的域名都是共享一個window.name
4、服務(wù)器設(shè)置對CORS的支持 原理:服務(wù)器設(shè)置Access-Control-Allow-Origin HTTP響應(yīng)頭之后,瀏覽器將會允許跨域請求
5、利用h5新特性window.postMessage()
1.創(chuàng)建ajax實例
2.執(zhí)行open 確定要訪問的鏈接 以及同步異步
3.監(jiān)聽請求狀態(tài)
4.發(fā)送請求
ES6的set對象 先將原數(shù)組排序,在與相鄰的進(jìn)行比較,如果不同則存入新數(shù)組
復(fù)制代碼function unique(arr){
var arr2 = arr.sort();
var res = [arr2[0]];
for(var i=1;i<arr2.length;i++){
if(arr2[i] !== res[res.length-1]){
res.push(arr2[i]);
}
}
return res;
}
利用下標(biāo)查詢
function unique(arr){
var newArr = [arr[0]];
for(var i=1;i<arr.length;i++){
if(newArr.indexOf(arr[i]) == -1){
newArr.push(arr[i]);
}
}
return newArr;
}
2開頭
3開頭
以4開頭的都是客戶端的問題;
以5開頭都是服務(wù)端的問題
同步:在同一時間內(nèi)做一件事情
異步:在同一時間內(nèi)做多個事情 JS是單線程的,每次只能做一件事情,JS運行在瀏覽器中,瀏覽器是多線程的,可以在同一時間執(zhí)行多個任務(wù)。
定時器、ajax、事件綁定、回調(diào)函數(shù)、async await、promise
三次握手
四次揮手
建立連接的時候, 服務(wù)器在LISTEN狀態(tài)下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發(fā)送給客戶端。 而關(guān)閉連接時,服務(wù)器收到對方的FIN報文時,僅僅表示對方不再發(fā)送數(shù)據(jù)了但是還能接收數(shù)據(jù),而自己也未必全部數(shù)據(jù)都發(fā)送給對方了,所以己方可以立即關(guān)閉,也可以發(fā)送一些數(shù)據(jù)給對方后,再發(fā)送FIN報文給對方來表示同意現(xiàn)在關(guān)閉連接,因此,己方ACK和FIN一般都會分開發(fā)送,從而導(dǎo)致多了一次。
如果元素類型發(fā)生變化,直接替換 如果是文本,則比較文本里面的內(nèi)容,是否有差異,如果是元素就需要比較當(dāng)前元素的屬性是否相等,會先比較key, 在比較類型 為什么 react中循環(huán) 建議不要使用索引 ,如果純?yōu)榱苏故?那可以使用索引
全局作用域
私有作用域
塊級作用域
上級作用域
他是ES6中新增加的一個類(new Promise),目的是為了管理JS中的異步編程的,所以把他稱為“Promise設(shè)計模式” new Promise 經(jīng)歷三個狀態(tài):padding(準(zhǔn)備狀態(tài):初始化成功、開始執(zhí)行異步的任務(wù))、fullfilled(成功狀態(tài))、rejected(失敗狀態(tài))== Promise本身是同步編程的,他可以管理異步操作的(重點),new Promise的時候,會把傳遞的函數(shù)立即執(zhí)行 Promise函數(shù)天生有兩個參數(shù),resolve(當(dāng)異步操作執(zhí)行成功,執(zhí)行resolve方法),rejected(當(dāng)異步操作失敗,執(zhí)行reject方法) then()方法中有兩個函數(shù),第一個傳遞的函數(shù)是resolve,第二個傳遞的函數(shù)是reject ajax中false代表同步,true代表異步,如果使用異步,不等ajax徹底完成
相同點
不同點
注意:forEach對于空數(shù)組是不會調(diào)用回調(diào)函數(shù)的。
async/await函數(shù)是異步代碼的新方式
async/await是基于promise實現(xiàn)的
async/await使異步代碼更像同步代碼
await 只能在async函數(shù)中使用,不能再普通函數(shù)中使用,要成對出現(xiàn)
默認(rèn)返回一個promise實例,不能被改變
await下面的代碼是異步,后面的代碼是同步的
全局作用域下的this指向window 如果給元素的事件行為綁定函數(shù),那么函數(shù)中的this指向當(dāng)前被綁定的那個元素 函數(shù)中的this,要看函數(shù)執(zhí)行前有沒有 . , 有 . 的話,點前面是誰,this就指向誰,如果沒有點,指向window 自執(zhí)行函數(shù)中的this永遠(yuǎn)指向window 定時器中函數(shù)的this指向window 構(gòu)造函數(shù)中的this指向當(dāng)前的實例 call、apply、bind可以改變函數(shù)的this指向 箭頭函數(shù)中沒有this,如果輸出this,就會輸出箭頭函數(shù)定義時所在的作用域中的this
所有的函數(shù)數(shù)據(jù)類型都天生自帶一個prototype屬性,該屬性的屬性值是一個對象 prototype的屬性值中天生自帶一個constructor屬性,其constructor屬性值指向當(dāng)前原型所屬的類 所有的對象數(shù)據(jù)類型,都天生自帶一個_proto_屬性,該屬性的屬性值指向當(dāng)前實例所屬類的原型
復(fù)制代碼promise、generator、async/await
promise: 1.是一個對象,用來傳遞異步操作的信息。代表著某個未來才會知道結(jié)果的時間,并未這個事件提供統(tǒng)一的api,供進(jìn)異步處理
2.有了這個對象,就可以讓異步操作以同步的操作的流程來表達(dá)出來,避免層層嵌套的回調(diào)地獄
3.promise代表一個異步狀態(tài),有三個狀態(tài)pending(進(jìn)行中),Resolve(以完成),Reject(失敗)
4.一旦狀態(tài)改變,就不會在變。任何時候都可以得到結(jié)果。從進(jìn)行中變?yōu)橐酝瓿苫蛘呤? promise.all() 里面狀態(tài)都改變,那就會輸出,得到一個數(shù)組
promise.race() 里面只有一個狀態(tài)變?yōu)閞ejected或者fulfilled即輸出
promis.finally()不管指定不管Promise對象最后狀態(tài)如何,都會執(zhí)行的操作(本質(zhì)上還是then方法的特例)
復(fù)制代碼事件流描述的是從頁面中接受事件的順序,事件 捕獲階段 處于目標(biāo)階段 事件冒泡階段 addeventListener 最后這個布爾值參數(shù)如果是true,表示在捕獲階段調(diào)用事件處理程序;如果是false,表示在冒泡階段調(diào)用事件處理程序。
1、事件捕獲階段:實際目標(biāo)div在捕獲階段不會接受事件,也就是在捕獲階段,事件從document到<html>再到<body>就停止了。
2、處于目標(biāo)階段:事件在div發(fā)生并處理,但是事件處理會被看成是冒泡階段的一部分。
3、冒泡階段:事件又傳播回文檔
阻止冒泡事件event.stopPropagation()
function stopBubble(e) {
if (e && e.stopPropagation) { // 如果提供了事件對象event 這說明不是IE瀏覽器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
}
阻止默認(rèn)行為event.preventDefault()
function stopDefault(e) {
if (e && e.preventDefault) {
e.preventDefault()
} else {
// IE瀏覽器阻止函數(shù)器默認(rèn)動作的行為
window.event.returnValue = false
}
}
在DOM標(biāo)準(zhǔn)事件模型中,是先捕獲后冒泡。但是如果要實現(xiàn)先冒泡后捕獲的效果, 對于同一個事件,監(jiān)聽捕獲和冒泡,分別對應(yīng)相應(yīng)的處理函數(shù),監(jiān)聽到捕獲事件,先暫緩執(zhí)行,直到冒泡事件被捕獲后再執(zhí)行捕獲事件。
復(fù)制代碼千萬不要使用typeof來判斷對象和數(shù)組,因為這種類型都會返回object。
typeOf()是判斷基本類型的Boolean,Number,symbol, undefined, String。 對于引用類型:除function,都返回object null返回object。
installOf() 用來判斷A是否是B的實例,installof檢查的是原型。
toString() 是Object的原型方法,對于 Object 對象,直接調(diào)用 toString() 就能返回 [Object Object] 。而對于其他對象,則需要通過 call / apply 來調(diào)用才能返回正確的類型信息。
hasOwnProperty()方法返回一個布爾值,指示對象自身屬性中是否具有指定的屬性,該方法會忽略掉那些從原型鏈上繼承到的屬性。
isProperty()方法測試一個對象是否存在另一個對象的原型鏈上。
復(fù)制代碼因為js是單線程的。瀏覽器遇到etTimeout 和 setInterval會先執(zhí)行完當(dāng)前的代碼塊,在此之前會把定時器推入瀏覽器的
待執(zhí)行時間隊列里面,等到瀏覽器執(zhí)行完當(dāng)前代碼之后會看下事件隊列里有沒有任務(wù),有的話才執(zhí)行定時器里的代碼
復(fù)制代碼 1.slice(start,end):方法可以從已有數(shù)組中返回選定的元素,返回一個新數(shù)組,
包含從start到end(不包含該元素)的數(shù)組方法
注意:該方法不會更新原數(shù)組,而是返回一個子數(shù)組
2.splice():該方法想或者從數(shù)組中添加或刪除項目,返回被刪除的項目。(該方法會改變原數(shù)組)
splice(index, howmany,item1,...itemx)
·index參數(shù):必須,整數(shù)規(guī)定添加或刪除的位置,使用負(fù)數(shù),從數(shù)組尾部規(guī)定位置
·howmany參數(shù):必須,要刪除的數(shù)量,
·item1..itemx:可選,向數(shù)組添加新項目
3.map():會返回一個全新的數(shù)組。使用于改變數(shù)據(jù)值的時候。會分配內(nèi)存存儲空間數(shù)組并返回,forEach()不會返回數(shù)據(jù)
4.forEach(): 不會返回任何有價值的東西,并且不打算改變數(shù)據(jù),單純的只是想用數(shù)據(jù)做一些事情,他允許callback更改原始數(shù)組的元素
5.reduce(): 方法接收一個函數(shù)作為累加器,數(shù)組中的每一個值(從左到右)開始縮減,最終計算一個值,不會改變原數(shù)組的值
6.filter(): 方法創(chuàng)建一個新數(shù)組,新數(shù)組中的元素是通過檢查指定數(shù)組中符合條件的所有元素。它里面通過function去做處理
vue是一個漸進(jìn)式的JS框架。他易用,靈活,高效; 可以把一個頁面分隔成多個組件;當(dāng)其他頁面有類似功能時,直接讓封裝的組件進(jìn)行復(fù)用; 他是構(gòu)建用戶界面的聲明式框架,只關(guān)心圖層;不關(guān)心具體是如何實現(xiàn)的
Vue的雙向數(shù)據(jù)綁定是由數(shù)據(jù)劫持結(jié)合發(fā)布者訂閱者實現(xiàn)的。 數(shù)據(jù)劫持是通過Object.defineProperty()來劫持對象數(shù)據(jù)的setter和getter操作。 在數(shù)據(jù)變動時作你想做的事
原理 通過Observer來監(jiān)聽自己的model數(shù)據(jù)變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達(dá)到數(shù)據(jù)變化->視圖更新 在初始化vue實例時,遍歷data這個對象,給每一個鍵值對利用Object.definedProperty對data的鍵值對新增get和set方法,利用了事件監(jiān)聽DOM的機(jī)制,讓視圖去改變數(shù)據(jù)
react整體是函數(shù)式的思想,把組件設(shè)計成純組件,狀態(tài)和邏輯通過參數(shù)傳入,所以在react中,是單向數(shù)據(jù)流;
vue的思想是響應(yīng)式的,也就是基于是數(shù)據(jù)可變的,通過對每一個屬性建立Watcher來監(jiān)聽,當(dāng)屬性變化的時候,響應(yīng)式的更新對應(yīng)的虛擬dom。
復(fù)制代碼頁面通過mapAction異步提交事件到action。action通過commit把對應(yīng)參數(shù)同步提交到mutation。
mutation會修改state中對于的值。 最后通過getter把對應(yīng)值跑出去,在頁面的計算屬性中
通過mapGetter來動態(tài)獲取state中的值
state中保存著共有數(shù)據(jù),數(shù)據(jù)是響應(yīng)式的 getter可以對state進(jìn)行計算操作,主要用來過濾一些數(shù)據(jù),可以在多組件之間復(fù)用 mutations定義的方法動態(tài)修改state中的數(shù)據(jù),通過commit提交方法,方法必須是同步的 actions將mutations里面處理數(shù)據(jù)的方法變成異步的,就是異步操作數(shù)據(jù),通store.dispatch來分發(fā)actions,把異步的方法寫在actions中,通過commit提交mutations,進(jìn)行修改數(shù)據(jù)。 modules:模塊化vuex
hash ——即地址欄URL中的#符號(此hsah 不是密碼學(xué)里的散列運算) hash 雖然出現(xiàn)URL中,但不會被包含在HTTP請求中,對后端完全沒有影響,因此改變hash不會重新加載頁面。 history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法
這兩個方法應(yīng)用于瀏覽器的歷史記錄站,在當(dāng)前已有的back、forward、go 的基礎(chǔ)之上,它們提供了對歷史記錄進(jìn)行修改的功能。只是當(dāng)它們執(zhí)行修改是,雖然改變了當(dāng)前的URL,但你瀏覽器不會立即向后端發(fā)送請求。
當(dāng) Vue.js 用v-for正在更新已渲染過的元素列表時,它默認(rèn)用“就地復(fù)用”策略。 如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序,而是簡單復(fù)用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。
key的作用主要是為了高效的更新虛擬DOM。
$route是“路由信息對象”,包括path,params,hash,query,fullPath,matched,name等路由信息參數(shù)。 $router是“路由實例”對象包括了路由的跳轉(zhuǎn)方法,鉤子函數(shù)等。
導(dǎo)航守衛(wèi) router.beforeEach 全局前置守衛(wèi)
復(fù)制代碼// main.js 入口文件
import router from './router'; // 引入路由
router.beforeEach((to, from, next) => {
next();
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
console.log('afterEach 全局后置鉤子');
});
路由獨享的守衛(wèi) 你可以在路由配置上直接定義 beforeEnter 守衛(wèi)
復(fù)制代碼const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
組件內(nèi)的守衛(wèi) 你可以在路由組件內(nèi)直接定義以下路由導(dǎo)航守衛(wèi)
復(fù)制代碼const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應(yīng)路由被 confirm 前調(diào)用
// 不!能!獲取組件實例 `this`
// 因為當(dāng)守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建
},
beforeRouteUpdate (to, from, next) {
// 在當(dāng)前路由改變,但是該組件被復(fù)用時調(diào)用
// 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時候,
// 由于會渲染同樣的 Foo 組件,因此組件實例會被復(fù)用。而這個鉤子就會在這個情況下被調(diào)用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導(dǎo)航離開該組件的對應(yīng)路由時調(diào)用,我們用它來禁止用戶離開
// 可以訪問組件實例 `this`
// 比如還未保存草稿,或者在用戶離開前,
將setInterval銷毀,防止離開之后,定時器還在調(diào)用。
}
}
請求后臺資源的模塊。
復(fù)制代碼$ npm install axios -S裝好
然后發(fā)送的是跨域,需在配置文件中config/index.js進(jìn)行設(shè)置。后臺如果是Tp5則定義一個資源路由。 js中使用import進(jìn)來,然后.get或.post。返回在.then函數(shù)中如果成功,失敗則是在.catch函數(shù)中
1.不要在模板里面寫過多表達(dá)式
2.循環(huán)調(diào)用子組件時添加key
3.頻繁切換的使用v-show,不頻繁切換的使用v-if
4.盡量少用float,可以用flex
5.按需加載,可以用require或者import()按需加載需要的組件
6.路由懶加載
extend 是構(gòu)造一個組件的語法器。 然后這個組件你可以作用到Vue.component這個全局注冊方法里 還可以在任意vue模板里使用組件。 也可以作用到vue實例或者某個組件中的components屬性中并在內(nèi)部使用apple組件。 Vue.component 你可以創(chuàng)建 ,也可以取組件。
png24位的圖片在iE6瀏覽器上出現(xiàn)背景 解決方案是做成PNG8.也可以引用一段腳本處理.
瀏覽器默認(rèn)的margin和padding不同。 解決方案是加一個全局的*{margin:0;padding:0;}來統(tǒng)一。
IE6雙邊距bug:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在ie6顯示margin比設(shè)置的大。
浮動ie產(chǎn)生的雙倍距離(IE6雙邊距問題:在IE6下,如果對元素設(shè)置了浮動,同時又設(shè)置了margin-left或margin-right,margin值會加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}
復(fù)制代碼 => 相同點:
1.數(shù)據(jù)驅(qū)動頁面,提供響應(yīng)式的試圖組件
2.都有virtual DOM,組件化的開發(fā),通過props參數(shù)進(jìn)行父子之間組件傳遞數(shù)據(jù),都實現(xiàn)了webComponents規(guī)范
3.數(shù)據(jù)流動單向,都支持服務(wù)器的渲染SSR
4.都有支持native的方法,react有React native, vue有wexx
=> 不同點:
1.數(shù)據(jù)綁定:Vue實現(xiàn)了雙向的數(shù)據(jù)綁定,react數(shù)據(jù)流動是單向的
2.數(shù)據(jù)渲染:大規(guī)模的數(shù)據(jù)渲染,react更快
3.使用場景:React配合Redux架構(gòu)適合大規(guī)模多人協(xié)作復(fù)雜項目,Vue適合小快的項目
4.開發(fā)風(fēng)格:react推薦做法jsx + inline style把html和css都寫在js了
vue是采用webpack + vue-loader單文件組件格式,html, js, css同一個文件
復(fù)制代碼Redux數(shù)據(jù)流里,reduces其實是根據(jù)之前的狀態(tài)(previous state)和現(xiàn)有的action(current action)
更新state(這個state可以理解為上下累加器的結(jié)果)
每次redux reducer被執(zhí)行時,state和action被傳入,這個state根據(jù)action進(jìn)行累加或者是'自身消減'(reduce),
進(jìn)而返回最新的state,這也就是典型reduce函數(shù)的用法:state -> action -> state
復(fù)制代碼refs就想一個逃生窗,允許我們之間訪問dom元素或者組件實例,可以向組件添加一個ref屬性的值是一個回調(diào)函數(shù),
它將接受地城dom元素或組件的已掛在實例,作為第一個參數(shù)
復(fù)制代碼幫組我們跟蹤哪些項目已更改、添加、從列表中刪除,key是獨一無二的,可以讓我們高效的去定位元素,并且操作它
復(fù)制代碼三個狀態(tài):Mounting(已插入真實的DOM)
Updating(正在被重新渲染)
Unmounting(已移除真實的DOM)
componentDIdMount 在第一次渲染后調(diào)用,只在客服端。之后組件已經(jīng)生成對應(yīng)的DOM結(jié)構(gòu),
componentDidUpdate 在組件完成更新后立即調(diào)用,在出初始化是不會調(diào)用
復(fù)制代碼父組件通過props 給子組件傳遞數(shù)據(jù),子組件則是通過調(diào)用父組件傳給它的函數(shù)給父組件傳遞數(shù)據(jù)。
復(fù)制代碼虛擬DOM相當(dāng)于在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的doom操作,從而提高性能
具體實現(xiàn)步驟:
·用JavaScript對象結(jié)構(gòu)表示DOM樹的結(jié)構(gòu);然后用這個樹構(gòu)建一個真正的DOM樹,插到文檔中
·當(dāng)狀態(tài)變更的時候,重新構(gòu)造一棵樹的對象樹,然后用新的樹和舊的樹進(jìn)行對比,記錄兩棵樹差異
·把2所記錄的差異應(yīng)用到步驟1所構(gòu)建的真正的DOM樹上,試圖就更新了。
復(fù)制代碼1.把樹形結(jié)構(gòu)按照層級分解,只比較同級元素
2.給列表結(jié)構(gòu)的每個單元添加key屬性,方便比較。在實際代碼中,會對新舊兩棵樹進(jìn)行一個深度優(yōu)先的遍歷,這樣每個節(jié)點都會有一個標(biāo)記
3.在深度優(yōu)先遍歷的時候,每遍歷到一個節(jié)點就把該節(jié)點和新的樹進(jìn)行對比。如果有差異的話就記錄到一個對象里面
Vritual DOM 算法主要實現(xiàn)上面步驟的三個函數(shù):element, diff, patch。然后就可以實際的進(jìn)行使用
react只會匹配相同的class的component(這里的class指的是組件的名字)
合并操作,條用component的setState方法的時候,React將其標(biāo)記為dirty.到每一個時間循環(huán)借宿,React檢查所有標(biāo)記dirty的component重新繪制
4.選擇性子樹渲染。可以重寫shouldComponentUpdate提高diff的性能
復(fù)制代碼flux的最大特點,就是數(shù)據(jù)的‘單向流動’
1.用戶訪問View
2.View發(fā)出用戶的Action
3.Dispatcher收到Action,要求state進(jìn)行相應(yīng)的更新
4.store更新后,發(fā)出一個‘change’事件后,更新頁面
復(fù)制代碼shouldComponentUpdate 這個方法用來判斷是否需要調(diào)用render方法重新描繪dom.因為dom的描繪非常消耗性能,
如果我們在shouldComponentUpdate方法中能夠?qū)懗龈鼉?yōu)化的dom diff算法,可以極大的提高性能
復(fù)制代碼根據(jù)組件的職責(zé)通常把組件分為UI組件和容器組件
UI組件負(fù)責(zé)UI的呈現(xiàn),容器組件負(fù)責(zé)管理數(shù)據(jù)和邏輯
兩者通過React-redux提供connect方法聯(lián)系起來
復(fù)制代碼setState通過一個隊列機(jī)制實現(xiàn)state更新,當(dāng)執(zhí)行setState時,會將需要更新的state很后放入狀態(tài)隊列
而不會立即更新this.state,隊列機(jī)制可以高效地批量更新state。如果不通過setState而直接修改this.state的值
那么該state將不會被放入狀態(tài)隊列中。當(dāng)下次調(diào)用setState并對狀態(tài)隊列進(jìn)行合并時,就會忽略之前修改的state,造成不可預(yù)知的錯誤
同時,也利用了隊列機(jī)制實現(xiàn)了setState的異步更新,避免了頻繁的重復(fù)更新state
同步更新state:
setState 函數(shù)并不會阻塞等待狀態(tài)更新完畢,因此 setNetworkActivityIndicatorVisible 有可能先于數(shù)據(jù)渲染完畢就執(zhí)行。
第二個參數(shù)是一個回調(diào)函數(shù),在setState的異步操作結(jié)束并且組件已經(jīng)重新渲染的時候執(zhí)行
也就是說,我們可以通過這個回調(diào)來拿到更新的state的值,實現(xiàn)代碼的同步
例子:componentDidMount() {
fetch('https://test.com')
.then((res) => res.json())
.then(
(data) => {
this.setState({ data:data });
StatusBar.setNetworkActivityIndicatorVisible(false);
}
復(fù)制代碼1.異步加載模塊
2.提取第三庫
3.代碼壓縮
4.去除不必要的插件
復(fù)制代碼一、減少代碼體積 1.使用CommonsChunksPlugin 提取多個chunk之間的通用模塊,減少總體代碼體積
2.把部分依賴轉(zhuǎn)移到CDN上,避免每次編譯過程都由Webpack處理
3.對一些組件庫采用按需加載,避免無用的代碼
二、減少目錄檢索范圍
·在使用loader的時候,通過制定exclude和include選項,減少loader遍歷的目錄范圍,從而加快webpack編譯速度
三、減少檢索路經(jīng):resolve.alias可以配置webpack模塊解析的別名,對于比較深的解析路經(jīng),可以對其配置alias
復(fù)制代碼 1、首屏加載和按需加載,懶加載
2、資源預(yù)加載
3、圖片壓縮處理,使用base64內(nèi)嵌圖片
4、合理緩存dom對象
5、使用touchstart代替click(click 300毫秒的延遲)
6、利用transform:translateZ(0),開啟硬件GUP加速
7、不濫用web字體,不濫用float(布局計算消耗性能),減少font-size聲明
8、使用viewport固定屏幕渲染,加速頁面渲染內(nèi)容
9、盡量使用事件代理,避免直接事件綁定
復(fù)制代碼1.減少入口文件體積
2.靜態(tài)資源本地緩存
3.開啟Gzip壓縮
4.使用SSR,nuxt.js
復(fù)制代碼由來:
300毫米延遲解決的是雙擊縮放。雙擊縮放,手指在屏幕快速點擊兩次。safari瀏覽器就會將網(wǎng)頁縮放值原始比例。由于用戶可以雙擊縮放或者是滾動的操作,
當(dāng)用戶點擊屏幕一次之后,瀏覽器并不會判斷用戶確實要打開至這個鏈接,還是想要進(jìn)行雙擊操作
因此,safair瀏覽器就會等待300ms,用來判斷用戶是否在次點擊了屏幕
解決方案:1.禁用縮放,設(shè)置meta標(biāo)簽 user-scalable=no
2.fastclick.js
原理:FastClick的實現(xiàn)原理是在檢查到touchend事件的時候,會通過dom自定義事件立即
發(fā)出click事件,并把瀏覽器在300ms之后真正的click事件阻止掉
fastclick.js還可以解決穿透問題
在不改變外部行為的前提下,簡化結(jié)構(gòu)、添加可讀性
復(fù)制代碼 2XX(成功處理了請求狀態(tài))
200 服務(wù)器已經(jīng)成功處理請求,并提供了請求的網(wǎng)頁
201 用戶新建或修改數(shù)據(jù)成功
202 一個請求已經(jīng)進(jìn)入后臺
204 用戶刪除成功
3XX(每次請求使用的重定向不要超過5次)
304 網(wǎng)頁上次請求沒有更新,節(jié)省帶寬和開銷
4XX(表示請求可能出錯,妨礙了服務(wù)器的處理)
400 服務(wù)器不理解請求的語法
401 用戶沒有權(quán)限(用戶名,密碼輸入錯誤)
403 用戶得到授權(quán)(401相反),但是訪問被禁止
404 服務(wù)器找不到請求的網(wǎng)頁,
5XX(表示服務(wù)器在處理請求的時候發(fā)生內(nèi)部錯誤)
500 服務(wù)器遇到錯誤,無法完成請求
503 服務(wù)器目前無法使用(超載或停機(jī)維護(hù))
復(fù)制代碼1.服務(wù)器首先產(chǎn)生Etag,服務(wù)器可在稍后使用它來判斷頁面是否被修改。本質(zhì)上,客戶端通過該記號傳回服務(wù)器要求服務(wù)器驗證(客戶端)緩存)
2.304是 HTTP的狀態(tài)碼,服務(wù)器用來標(biāo)識這個文件沒有被修改,不返回內(nèi)容,瀏覽器接受到這個狀態(tài)碼會去去找瀏覽器緩存的文件
3.流程:客戶端請求一個頁面A。服務(wù)器返回頁面A,并在A上加一個Tage客服端渲染該頁面,并把Tage也存儲在緩存中。客戶端再次請求頁面A
并將上次請求的資源和ETage一起傳遞給服務(wù)器。服務(wù)器檢查Tage.并且判斷出該頁面自上次客戶端請求之后未被修改。直接返回304
last-modified: 客服端請求資源,同時有一個last-modified的屬性標(biāo)記此文件在服務(wù)器最后修改的時間
客服端第二次請求此url時,根據(jù)http協(xié)議。瀏覽器會向服務(wù)器發(fā)送一個If-Modified-Since報頭,
詢問該事件之后文件是否被修改,沒修改返回304
有了Last-Modified,為什么還要用ETag?
1、因為如果在一秒鐘之內(nèi)對一個文件進(jìn)行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
2、某些服務(wù)器不能精確的得到文件的最后修改時間
3、一些文件也行會周期新的更改,但是他的內(nèi)容并不改變(僅僅改變修改的事件),這個時候我們并不希望客戶端認(rèn)為文件被修改,而重新Get
ETag,為什么還要用Last-Modified?
1、兩者互補(bǔ),ETag的判斷的缺陷,比如一些圖片等靜態(tài)文件的修改
2、如果每次掃描內(nèi)容都生成ETag比較,顯然要比直接比較修改時間慢的多。
ETag是被請求變量的實體值(文件的索引節(jié),大小和最后修改的時間的Hash值)
1、ETag的值服務(wù)器端對文件的索引節(jié),大小和最后的修改的事件進(jìn)行Hash后得到的。
復(fù)制代碼1.get數(shù)據(jù)是存放在url之后,以?分割url和傳輸數(shù)據(jù),參數(shù)之間以&相連; post方法是把提交的數(shù)據(jù)放在http包的Body中
2.get提交的數(shù)據(jù)大小有限制,(因為瀏覽器對url的長度有限制),post的方法提交的數(shù)據(jù)沒有限制
3.get需要request.queryString來獲取變量的值,而post方式通過request.from來獲取變量的值
4.get的方法提交數(shù)據(jù),會帶來安全問題,比如登錄一個頁面,通過get的方式提交數(shù)據(jù),用戶名和密碼就會出現(xiàn)在url上
復(fù)制代碼1.超文本的傳輸協(xié)議,是用于從萬維網(wǎng)服務(wù)器超文本傳輸?shù)奖镜刭Y源的傳輸協(xié)議
2.基于TCP/IP通信協(xié)議來傳遞數(shù)據(jù)(HTML,圖片資源)
3.基于運用層的面向?qū)ο蟮膮f(xié)議,由于其簡潔、快速的方法、適用于分布式超媒體信息系統(tǒng)
4.http請求信息request:
請求行(request line)、請求頭部(header),空行和請求數(shù)據(jù)四部分構(gòu)成
請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,用來說明服務(wù)器要使用的附加信息
空行,請求頭部后面的空行是必須的
請求數(shù)據(jù)也叫主體,可以添加任意的其他數(shù)據(jù)。
5.http相應(yīng)信息Response
狀態(tài)行、消息報頭、空行和響應(yīng)正文
狀態(tài)行,由HTTP協(xié)議版本號, 狀態(tài)碼, 狀態(tài)消息 三部分組成
消息報頭,用來說明客戶端要使用的一些附加信息
空行,消息報頭后面的空行是必須的
響應(yīng)正文,服務(wù)器返回給客戶端的文本信息。
復(fù)制代碼https:是以安全為目標(biāo)的HTTP通道,簡單講是HTTP的安全版本,通過SSL加密
http:超文本傳輸協(xié)議。是一個客服端和服務(wù)器端請求和應(yīng)答的標(biāo)準(zhǔn)(tcp),使瀏覽器更加高效,使網(wǎng)絡(luò)傳輸減少
復(fù)制代碼長連接:HTTP1.0需要使用keep-alive參數(shù)來告知服務(wù)器建立一個長連接,而HTP1.1默認(rèn)支持長連接
節(jié)約寬帶:HTTP1.1支持只發(fā)送一個header信息(不帶任何body信息)
host域(設(shè)置虛擬站點,也就是說,web server上的多個虛擬站點可以共享同一個ip端口):HTTP1.0沒有host域
1.http2采用的二進(jìn)制文本傳輸數(shù)據(jù),而非http1文本格式,二進(jìn)制在協(xié)議的解析和擴(kuò)展更好
2.數(shù)據(jù)壓縮:對信息頭采用了HPACK進(jìn)行壓縮傳輸,節(jié)省了信息頭帶來的網(wǎng)絡(luò)流量
3.多路復(fù)用:一個連接可以并發(fā)處理多個請求
4.服務(wù)器推送:我們對支持HTTP2.0的web server請求數(shù)據(jù)的時候,服務(wù)器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創(chuàng)建連接發(fā)送請求到服務(wù)器端獲取。這種方式非常合適加載靜態(tài)資源
復(fù)制代碼1.web緩存就是存在于客戶端與服務(wù)器之間的一個副本、當(dāng)你第一個發(fā)出請求后,緩存根據(jù)請求保存輸出內(nèi)容的副本
2.緩存的好處
(1)減少不必要的請求
(2)降低服務(wù)器的壓力,減少服務(wù)器的消耗
(3)降低網(wǎng)絡(luò)延遲,加快頁面打開速度(直接讀取瀏覽器的數(shù)據(jù))
復(fù)制代碼1.sql注入原理:是將sql代碼偽裝到輸入?yún)?shù)中,傳遞到服務(wù)器解析并執(zhí)行的一種攻擊手法。也就是說,
在一些對server端發(fā)起的請求參數(shù)中植入一些sql代碼,server端在執(zhí)行sql操作時,會拼接對應(yīng)參數(shù),
同時也將一些sql注入攻擊的“sql”拼接起來,導(dǎo)致會執(zhí)行一些預(yù)期之外的操作。
防范:1.對用戶輸入進(jìn)行校驗
2.不適用動態(tài)拼接sql
2.XSS(跨站腳本攻擊):往web頁面插入惡意的html標(biāo)簽或者js代碼。
舉例子:在論壇放置一個看是安全的鏈接,竊取cookie中的用戶信息
防范:1.盡量采用post而不使用get提交表單
2.避免cookie中泄漏用戶的隱式
3.CSRF(跨站請求偽裝):通過偽裝來自受信任用戶的請求
舉例子:黃軼老師的webapp音樂請求數(shù)據(jù)就是利用CSRF跨站請求偽裝來獲取QQ音樂的數(shù)據(jù)
防范:在客服端頁面增加偽隨機(jī)數(shù),通過驗證碼
XSS和CSRF的區(qū)別:
1.XSS是獲取信息,不需要提前知道其他用戶頁面的代碼和數(shù)據(jù)包
2.CSRF代替用戶完成指定的動作,需要知道其他頁面的代碼和數(shù)據(jù)包
復(fù)制代碼1.盡可能的避開互聯(lián)網(wǎng)有可能影響數(shù)據(jù)傳輸速度和穩(wěn)定性的瓶頸和環(huán)節(jié)。使內(nèi)容傳輸?shù)母旄€(wěn)定。
2.關(guān)鍵技術(shù):內(nèi)容存儲和分發(fā)技術(shù)中
3.基本原理:廣泛采用各種緩存服務(wù)器,將這些緩存服務(wù)器分布到用戶訪問相對的地區(qū)或者網(wǎng)絡(luò)中。當(dāng)用戶訪問網(wǎng)絡(luò)時利用全局負(fù)載技術(shù)
將用戶的訪問指向距離最近的緩存服務(wù)器,由緩存服務(wù)器直接相應(yīng)用戶的請求(全局負(fù)載技術(shù))
復(fù)制代碼客服端發(fā)c起請求連接服務(wù)器端s確認(rèn),服務(wù)器端也發(fā)起連接確認(rèn)客服端確認(rèn)。
第一次握手:客服端發(fā)送一個請求連接,服務(wù)器端只能確認(rèn)自己可以接受客服端發(fā)送的報文段
第二次握手: 服務(wù)端向客服端發(fā)送一個鏈接,確認(rèn)客服端收到自己發(fā)送的報文段
第三次握手: 服務(wù)器端確認(rèn)客服端收到了自己發(fā)送的報文段
復(fù)制代碼1.查詢NDS(域名解析),獲取域名對應(yīng)的IP地址 查詢?yōu)g覽器緩存
2.瀏覽器與服務(wù)器建立tcp鏈接(三次握手)
3.瀏覽器向服務(wù)器發(fā)送http請求(請求和傳輸數(shù)據(jù))
4.服務(wù)器接受到這個請求后,根據(jù)路經(jīng)參數(shù),經(jīng)過后端的一些處理生成html代碼返回給瀏覽器
5.瀏覽器拿到完整的html頁面代碼開始解析和渲染,如果遇到外部的css或者js,圖片一樣的步驟
6.瀏覽器根據(jù)拿到的資源對頁面進(jìn)行渲染,把一個完整的頁面呈現(xiàn)出來
復(fù)制代碼流程:解析html以及構(gòu)建dom樹 -> 構(gòu)建render樹 -> 布局render樹 -> 繪制render樹
概念:1.構(gòu)建DOM樹: 渲染引擎解析HTML文檔,首先將標(biāo)簽轉(zhuǎn)換成DOM樹中的DOM node(包括js生成的標(biāo)簽)生成內(nèi)容樹
2.構(gòu)建渲染樹: 解析對應(yīng)的css樣式文件信息(包括js生成的樣式和外部的css)
3.布局渲染樹:從根節(jié)點遞歸調(diào)用,計算每一個元素的大小,位置等。給出每個節(jié)點所在的屏幕的精準(zhǔn)位置
4.繪制渲染樹:遍歷渲染樹,使用UI后端層來繪制每一個節(jié)點
重繪:當(dāng)盒子的位置、大小以及其他屬性,例如顏色、字體大小等到確定下來之后,瀏覽器便把這些顏色都按照各自的特性繪制一遍,將內(nèi)容呈現(xiàn)在頁面上
觸發(fā)重繪的條件:改變元素外觀屬性。如:color,background-color等
重繪是指一個元素外觀的改變所觸發(fā)的瀏覽器行為,瀏覽器會根據(jù)元素的新屬性重新繪制,使元素呈現(xiàn)新的外觀
注意:table及其內(nèi)部元素需要多次計算才能確定好其在渲染樹中節(jié)點的屬性值,比同等元素要多發(fā)時間,要盡量避免使用table布局
重排(重構(gòu)/回流/reflow): 當(dāng)渲染書中的一部分(或全部)因為元素的規(guī)模尺寸,布局,隱藏等改變而需要重新構(gòu)建,這就是回流。
每個頁面都需要一次回流,就是頁面第一次渲染的時候
重排一定會影響重繪,但是重繪不一定會影響重排
復(fù)制代碼1.瀏覽器預(yù)先加載css后,可以不必等待HTML加載完畢就可以渲染頁面了
2.其實HTML渲染并不會等到完全加載完在渲染頁面,而是一邊解析DOM一邊渲染。
3.js寫在尾部,主要是因為js主要扮演事件處理的功能,一方面很多操作是在頁面渲染后才執(zhí)行的。另一方面可以節(jié)省加載時間,使頁面能夠更加的加載,提高用戶的良好體驗
但是隨著JS技術(shù)的發(fā)展,JS也開始承擔(dān)頁面渲染的工作。比如我們的UI其實可以分被對待,把渲染頁面的js放在前面,時間處理的js放在后面
復(fù)制代碼1.indexBD: 是h5的本地存儲庫,把一些數(shù)據(jù)存儲到瀏覽器中,沒網(wǎng)絡(luò),瀏覽器可以從這里讀取數(shù)據(jù),離線運用。5m
2.Cookie: 通過瀏覽器記錄信息確認(rèn)用戶身份,最大4kb,這也就限制了傳輸?shù)臄?shù)據(jù),請求的性能會受到影響
3.Session: 服務(wù)器端使用的一種記錄客戶狀態(tài)的機(jī)制(session_id存在set_cookie發(fā)送到客服端,保存為cookie)
4.localStroage: h5的本地存儲,數(shù)據(jù)永久保存在客服端
1、cookie,sessionStorage,localStorage是存放在客戶端,session對象數(shù)據(jù)是存放在服務(wù)器上 實際上瀏覽器和服務(wù)器之間僅需傳遞session id即可,服務(wù)器根據(jù)session-id找到對應(yīng)的用戶session對象 session存儲數(shù)據(jù)更安全一些,一般存放用戶信息,瀏覽器只適合存儲一般的數(shù)據(jù) 2、cookie數(shù)據(jù)始終在同源的http請求中攜帶,在瀏覽器和服務(wù)器來回傳遞,里面存放著session-id sessionStorage,localStorage僅在本地保存 3、大小限制區(qū)別,cookie數(shù)據(jù)不超過4kb,localStorage在谷歌瀏覽中2.6MB 4、數(shù)據(jù)有效期不同,cookie在設(shè)置的(服務(wù)器設(shè)置)有效期內(nèi)有效,不管窗口和瀏覽器關(guān)閉 sessionStorage僅在當(dāng)前瀏覽器窗口關(guān)閉前有效,關(guān)閉即銷毀(臨時存儲) localStorage始終有效
SessionStorage和localStorage區(qū)別: 1.sessionStorage用于本地存儲一個會話(session)中的數(shù)據(jù),這些數(shù)據(jù)只有在用一個會話的頁面中才能被訪問(也就是說在第一次通信過程中) 并且在會話結(jié)束后數(shù)據(jù)也隨之銷毀,不是一個持久的本地存儲,會話級別的儲存 2.localStorage用于持久化的本地存儲,除非主動刪除數(shù)據(jù),否則不會過期
復(fù)制代碼1、token就是令牌,比如你授權(quán)(登錄)一個程序時,他就是個依據(jù),判斷你是否已經(jīng)授權(quán)該軟件(最好的身份認(rèn)證,安全性好,且是唯一的)
用戶身份的驗證方式
2、cookie是寫在客戶端一個txt文件,里面包括登錄信息之類的,這樣你下次在登錄某個網(wǎng)站,就會自動調(diào)用cookie自動登錄用戶名
服務(wù)器生成,發(fā)送到瀏覽器、瀏覽器保存,下次請求再次發(fā)送給服務(wù)器(存放著登錄信息)
3、session是一類用來客戶端和服務(wù)器之間保存狀態(tài)的解決方案,會話完成被銷毀(代表的就是服務(wù)器和客戶端的一次會話過程)
cookie中存放著sessionID,請求會發(fā)送這個id。sesion因為request對象而產(chǎn)生。
復(fù)制代碼 1、用戶通過用戶名和密碼發(fā)送請求
2、服務(wù)器端驗證
3、服務(wù)器端返回一個帶簽名的token,給客戶端
4、客戶端儲存token,并且每次用于發(fā)送請求
5、服務(wù)器驗證token并且返回數(shù)據(jù)
每一次請求都需要token
復(fù)制代碼 1、cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務(wù)器上。
2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進(jìn)行COOKIE欺騙考慮到安全應(yīng)當(dāng)使用session。
3、session會在一定時間內(nèi)保存在服務(wù)器上。當(dāng)訪問增多,會比較占用你服務(wù)器的性能考慮到減輕服務(wù)器性能方面,應(yīng)當(dāng)使用COOKIE。
4、單個cookie保存的數(shù)據(jù)不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
復(fù)制代碼 1、session認(rèn)證只是把簡單的User的信息存儲Session里面,sessionID不可預(yù)測,一種認(rèn)證手段。只存在服務(wù)端,不能共享到其他的網(wǎng)站和第三方App
2、token是oAuth Token,提供的是認(rèn)證和授權(quán),認(rèn)證針對用戶,授權(quán)是針對App,目的就是讓某APP有權(quán)訪問某用戶的的信息。Token是唯一的,
token不能轉(zhuǎn)移到其他的App,也不能轉(zhuǎn)到其他用戶上。(適用于App)
3、session的狀態(tài)是存在服務(wù)器端的,客戶端只存在session id, Token狀態(tài)是存儲在客戶端的
復(fù)制代碼 1、數(shù)量和長度的限制。每個特定的域名下最多生成20個cookie(chorme和safari沒有限制)
2、安全性問題。
一、觀察者模式:juejin.cn/post/684490… juejin.cn/post/684490… 在軟件開發(fā)設(shè)計中是一個對象(subject),維護(hù)一系列依賴他的對象(observer),當(dāng)任何狀態(tài)發(fā)生改變自動通知他們。強(qiáng)依賴關(guān)系 簡單理解:數(shù)據(jù)發(fā)生改變時,對應(yīng)的處理函數(shù)就會自動執(zhí)行。一個Subjet,用來維護(hù)Observers,為某些event來通知(notify)觀察者
二、發(fā)布-訂閱者 有一個信息中介,過濾 耦合性低 它定義了一種一對多的關(guān)系,可以使多個觀察者對象對一個主題對象進(jìn)行監(jiān)聽,當(dāng)這個主題對象發(fā)生改變時,依賴的所有對象都會被通知到。
復(fù)制代碼1.冒泡排序:重復(fù)走訪過要排序的數(shù)列,一次比較兩個元素,如果他們的順序錯誤就把它們交換過來。
實現(xiàn)過程:1.比較相鄰的元素。如果第一個比第二個大,就交換他們兩個
2.對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對,這樣在最后的元素應(yīng)該會是最大的數(shù)
3.針對所有的元素重復(fù)以上的步驟,除了最后一個
4.重復(fù)步驟1-3,直到排序完成。
2.選擇排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,然后,在從剩下未排序元素中繼續(xù)尋找最小值,然后放在與排序序列的末尾
實現(xiàn)過程:
3.插入排序:構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中沖后向前掃描,找到相應(yīng)位置并插入
實現(xiàn)過程:1.從第一個元素開始,該元素可以認(rèn)為已經(jīng)被排序
2.取出下一個元素,在已排序的元素序列中沖后向前掃描
3.如果該元素(以排序)大于新元素,將元素向后移一位
4.在取出一個元素,比較之前的,直到找到自己合適的位置
4.桶排序:將數(shù)據(jù)分布到有限數(shù)量的桶里,每個桶在分別排序
1.快速排序:快速排序使用分治法把一個串(list)分為兩個子串(sub-lists).具體算法實現(xiàn)
實現(xiàn)過程:1.從數(shù)組中挑出一個元素,成為一個基準(zhǔn)
2.重新排列數(shù)組,所有元素比基準(zhǔn)小的擺在基準(zhǔn)前面,所有元素比基準(zhǔn)大的擺在基準(zhǔn)后面(相同的可以擺在一邊)
這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。成為分區(qū)操作。
3.遞歸的把小于基準(zhǔn)值的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序
算法實現(xiàn): 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.堆排序:利用對這種數(shù)據(jù)結(jié)構(gòu)所涉及的一種排序算法,堆積是一個近乎完全二叉樹的結(jié)構(gòu),并同時滿足堆積的性質(zhì):即子節(jié)點的鍵值或索引總是小于(或大于)它的父節(jié)點。
實現(xiàn)過程:1.
復(fù)制代碼1.雙重循環(huán)
2.indexOf
3.數(shù)組排序去重 最快你Olong
復(fù)制代碼判斷回文字符串:(遞歸的思想)
1.字符串分隔,倒轉(zhuǎn),聚合[...obj].reverse().join('')
2.字符串頭部和尾部,逐次向中間檢測
實現(xiàn):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.遞歸
復(fù)制代碼 二分查找可以解決已排序數(shù)組的查找問題,即只要數(shù)組中包含T(要查找的值),那么通過不斷的縮小包含T的數(shù)據(jù)范圍,就可以最終要找到的數(shù)
(1) 一開始,數(shù)據(jù)范圍覆蓋整個數(shù)組。
(2) 將數(shù)組的中間項與T進(jìn)行比較,如果T比數(shù)組的中間項小,則到數(shù)組的前半部分繼續(xù)查找,反之,則到數(shù)組的后半部分繼續(xù)查找。
(3) 就這樣,每次查找都可以排除一半元素,相當(dāng)于范圍縮小一半。這樣反復(fù)比較,反復(fù)縮小范圍,最終會在數(shù)組中找到T
代碼實現(xiàn):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
復(fù)制代碼一句話概括:1.bind()返回一個新函數(shù),并不會立即執(zhí)行。
2.bind的第一個參數(shù)將作為他運行時的this,之后的一系列參數(shù)將會在傳遞的實參前傳入作為他的參數(shù)
3.bind返回函數(shù)作為構(gòu)造函數(shù),就是可以new的,bind時指定的this值就會消失,但傳入的參數(shù)依然生效
復(fù)制代碼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會生成新函數(shù),必須的條件就是要繼承原函數(shù)的原型,因此用到寄生繼承來完成我們的過程
F.prototype = context.prototype;
bound.prototype = new F();
return bound;
}
復(fù)制代碼ajax的原理:相當(dāng)于在用戶和服務(wù)器之間加一個中間層(ajax引擎),使用戶操作與服務(wù)器響應(yīng)異步化。
優(yōu)點:在不刷新整個頁面的前提下與服務(wù)器通信維護(hù)數(shù)據(jù)。不會導(dǎo)致頁面的重載
可以把前端服務(wù)器的任務(wù)轉(zhuǎn)嫁到客服端來處理,減輕服務(wù)器負(fù)擔(dān),節(jié)省寬帶
劣勢:不支持back。對搜索引擎的支持比較弱;不容易調(diào)試
怎么解決呢?通過location.hash值來解決Ajax過程中導(dǎo)致的瀏覽器前進(jìn)后退按鍵失效,
解決以前被人常遇到的重復(fù)加載的問題。主要比較前后的hash值,看其是否相等,在判斷是否觸發(fā)ajax
復(fù)制代碼function getData(url) {
var xhr = new XMLHttpRequest(); // 創(chuàng)建一個對象,創(chuàng)建一個異步調(diào)用的對象
xhr.open('get', url, true) // 設(shè)置一個http請求,設(shè)置請求的方式,url以及驗證身份
xhr.send() //發(fā)送一個http請求
xhr.onreadystatechange = function () { //設(shè)置一個http請求狀態(tài)的函數(shù)
if (xhr.readyState == 4 && xhr.status ==200) {
console.log(xhr.responseText) // 獲取異步調(diào)用返回的數(shù)據(jù)
}
}
}
Promise(getData(url)).resolve(data => data)
AJAX狀態(tài)碼:0 - (未初始化)還沒有調(diào)用send()方法
1 - (載入)已調(diào)用send方法,正在發(fā)送請求
2 - (載入完成呢)send()方法執(zhí)行完成
3 - (交互)正在解析相應(yīng)內(nèi)容
4 - (完成)響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了
```
#### 三、函數(shù)節(jié)流(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);
}
}
}
}
```
#### 四、函數(shù)防抖(dobounce)
```
function debounce (func, wait) {
var timeout;
return function() {
var context = this;
var args = arguments;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context,args)
}, wait);
}
}
```
#### 五、實現(xiàn)一個函數(shù)clone,可以對JavaScript中的5種主要的數(shù)據(jù)類型(包括Number、String、Object、Array、Boolean)進(jìn)行值復(fù)制
```
Object.prototype.clone = function() {
var newObject = this.constructor === Array ? [] : {} //對象的深拷貝 獲取對應(yīng)的構(gòu)造函數(shù) [] 或者 {}
for (let e in this) { //遍歷對象的屬性 in this[e]
newObject[e] = typeof this[e] === 'object' ? this[e].clone() : this[e] //對象中的屬性如果還是對象 那就繼續(xù)遞歸 否則就返回基本的數(shù)據(jù)類型
}
return newObject
}
```
#### 六、實現(xiàn)一個簡單的Promise https://juejin.cn/post/6844903625769091079
```
class Promise {
constructor (executor) { // executor里面有兩個參數(shù),一個叫resolve(成功),一個叫reject(失敗)。
this.status = 'pending',
this.value = undefined;
this.reason = undefined;
// 成功存放的數(shù)組
this.onResolvedCallbacks = [];
// 失敗存放法數(shù)組
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);
})
```
#### 七、發(fā)布訂閱者模式(觀察者模式)
```
var event = {}; // 發(fā)布者
event.clientList = [] //發(fā)布者的緩存列表
event.listen = function (fn) { // 增加訂閱者函數(shù)
this.clientList.push(fn)
}
event.trigger = function () { // 發(fā)布信息
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服務(wù)器
```
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)
```
如果本文對你有幫助,就留個關(guān)注點個贊支持下吧,你的「關(guān)注」和「贊」是我創(chuàng)作的動力。
原文鏈接:https://juejin.cn/post/6844903976693940231
處 | 前端之巔
在過去的幾年里,我在亞馬遜和雅虎面試過很多專注于前端開發(fā)的 Web 開發(fā)者和軟件工程師,在這篇文章中,我想分享一些面試技巧,幫助候選人為面試做好準(zhǔn)備。
免責(zé)聲明——本文并非旨在列出在前端面試中可能會被問到的所有問題,但可以將其視為知識的基線。
通過面試不是件容易的事,作為候選人,通常需要在 45 分鐘的時間內(nèi)展示自己能做些什么。作為一名面試官,同樣難以在這么短的時間內(nèi)評估候選人是否適合。對于面試來說,并不存在一刀切的方法,面試官問的問題通常會有一個范圍,但除此之外,他們可以自行決定要問哪些其他問題。
作為曾經(jīng)的候選人和面試官,我試圖在這篇文章中涵蓋你可能會在面試中被問到的最重要的前端開發(fā)知識。
我見過候選人犯的最大錯誤之一就是準(zhǔn)備了一些瑣碎的問題,例如“什么是盒子模型”或者“JavaScript 中的 == 和 === 之間的區(qū)別是什么”。知道這些問題的答案固然是好,但這并不會告訴面試官來太多有用的信息。
相反,在實際的面試中,你可能需要使用 JavaScript、CSS 和 HTML 來編寫代碼。在你的面試期間,你可能需要實現(xiàn) UI、構(gòu)建窗口小部件或使用 Lodash 和 Underscore.js 這樣的庫編寫常用的實用程序函數(shù)。例如:
說到庫,我看到候選人經(jīng)常犯的另一個錯誤是他們需要完全依賴最新的框架來解決面試問題。你可能會想,如果我可以在生產(chǎn)環(huán)境中使用 jQuery、React、Angular 等,那為什么就不能在面試中使用它們呢?技術(shù)、框架和庫會隨著時間的推移而發(fā)生變化——我更感興趣的是你是否了解前端開發(fā)的底層原理,而不是依賴更高層次的抽象。如果你不能在沒有它們的情況下回答面試問題,我希望你至少可以徹底解釋和推測這些庫背后的原理。
總的來說,大部分的面試都涉及實際的編碼。
你需要了解 JavaScript,而且是徹底地了解。你面試的職位越高,對語言知識的要求就越高。以下是你應(yīng)該熟悉的 JavaScript 知識點:
知道如何遍歷和操作 DOM 非常重要,對于重度依賴 jQuery 或者開發(fā)了很多 React & Angular 類型應(yīng)用程序的候選人來說,他們可能會在這個問題上栽跟斗。你可能不會每天都直接接觸 DOM,因為我們大多數(shù)人都在使用各種抽象。在不使用第三方庫的情況下,你需要知道如何執(zhí)行以下這些操作:
至少,你應(yīng)該知道如何在頁面上布局元素,如何使用子元素或直接后代選擇器來定位元素,以及什么時候該用類、什么時候該用 ID。
知道哪些 HTML 標(biāo)簽最能代表你正在顯示的內(nèi)容以及相關(guān)屬性,應(yīng)該掌握手工知識。
在系統(tǒng)設(shè)計方面,通常涉及 MapReduce、分布式鍵值存儲系統(tǒng)或 CAP 定理等知識。雖然前端工程師日常不需要深入了解如何設(shè)計這類系統(tǒng),但在被要求設(shè)計出常見應(yīng)用程序的前端架構(gòu)時,你也不應(yīng)該感到驚訝。這些問題通常含糊不清,比如“設(shè)計一個像 Pinterest 這樣的網(wǎng)站”或者“如何構(gòu)建購物結(jié)賬服務(wù)?”。以下是需要考慮的知識點:
除了通用編程最佳實踐之外,你應(yīng)該期望訪問者查看你的代碼或設(shè)計及其性能影響。它曾經(jīng)足以將 CSS 置于文檔的頂部,而 JS 腳本位于頁面底部,但 Web 正在快速移動,你應(yīng)該熟悉這個領(lǐng)域的復(fù)雜性。
這個可能有點爭議,但對 Big-O 時間復(fù)雜性和常見運行時間(如 O(N) 和 O(N Log N))有一個基本的了解對你來說不會是壞事。單頁應(yīng)用程序現(xiàn)在非常常見,所以了解內(nèi)存管理等方面的知識是有幫助的。例如,如果你被要求構(gòu)建客戶端拼寫檢查程序,那么了解常見的數(shù)據(jù)結(jié)構(gòu)和算法將會讓你的任務(wù)變得輕松許多。
我不是說你一定需要念一個計算機(jī)學(xué)位,但這個行業(yè)已經(jīng)從構(gòu)建簡單的網(wǎng)頁轉(zhuǎn)移到了計算機(jī)科學(xué)。網(wǎng)上有很多資源可以讓那個你快速掌握基礎(chǔ)知識。
你需要掌握一些構(gòu)成 Web 的技術(shù)和范式。
對 Web 開發(fā)人員或工程師來說,構(gòu)建 Web 應(yīng)用程序需要掌握大量的知識。不要被知識的深度所限制,而是要保持開放的心態(tài)去學(xué)習(xí)所有復(fù)雜的部分。
除了這里涉及的技術(shù)主題之外,你還需要討論過去參與的項目,描述發(fā)生了哪些有趣的事情以及做出了哪些權(quán)衡。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。