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;
// 如果滾動超過一屏,返回頂部按鈕出現,反之隱藏
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;
// 判斷是否到達頂部,到達頂部停止滾動,沒到達頂部繼續滾動
if(toTop == 0){
clearInterval(timer);
}else {
// 設置滾動速度
var speed = Math.ceil(toTop/5);
// 頁面向上滾動
document.documentElement.scrollTop=document.body.scrollTop=toTop-speed;
}
},50);
}
言
金九銀十跳槽季,offer快到碗里來,前端面試考點眾多,而網上各個知識點的博客文章又太多,看的眼花繚亂...所以我整理了一下常見知識點的精華文章,每個知識點的文章控制在3篇以內,盡量覆蓋該知識點的下容易被面試到的所有內容,文章都是之前自己讀過的,確定是精華干貨。文章會一直更新,也歡迎大家推薦精華文章,大家共同學習進步呀!
display:flex; 在父元素設置,子元素受彈性盒影響,默認排成一行,如果超出一行,按比例壓縮 flex:1; 子元素設置,設置子元素如何分配父元素的空間,flex:1,子元素寬度占滿整個父元素align-items:center 定義子元素在父容器中的對齊方式,center 垂直居中justify-content:center 設置子元素在父元素中居中,前提是子元素沒有把父元素占滿,讓子元素水平居中。
transtion transition-property 規定設置過渡效果的 CSS 屬性的名稱。
transition-duration 規定完成過渡效果需要多少秒或毫秒。
transition-timing-function 規定速度效果的速度曲線。
transition-delay 定義過渡效果何時開始。
animation屬性可以像Flash制作動畫一樣,通過控制關鍵幀來控制動畫的每一步,實現更為復雜的動畫效果。
ainimation實現動畫效果主要由兩部分組成:
通過類似Flash動畫中的幀來聲明一個動畫;
在animation屬性中調用關鍵幀聲明的動畫。
translate 3D建模效果
圖片中的 alt屬性是在圖片不能正常顯示時出現的文本提示。alt有利于SEO優化
圖片中的 title屬性是在鼠標在移動到元素上的文本提示。
復制代碼 <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>
標準盒子模型:寬度=內容的寬度(content)+ border + padding
低版本IE盒子模型:寬度=內容寬度(content+border+padding)
已知寬度,block元素 ,添加添加margin:0 auto屬性。
已知寬度,絕對定位的居中 ,上下左右都為0,margin:auto
復制代碼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;}
給浮動元素父級設置高度
父級同時浮動(需要給父級同級元素添加浮動)
父級設置成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
}
圣杯布局/雙飛翼布局
復制代碼 <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 隱藏對應的元素,在文檔布局中不再給它分配空間,它各邊的元素會合攏,就當他從來不存在。
visibility:hidden 隱藏對應的元素,但是在文檔布局中仍保留原來的空間。
link屬于HTML標簽,而@import是CSS提供的頁面被加載的時,link會同時被加載,而@import引用的CSS會等到頁面被加載完再加載
import只在IE5以上才能識別,而link是HTML標簽,無兼容問題
link方式的樣式的權重 高于@import的權重.
共同點: 改變行內元素的呈現方式,display被置為block 讓元素脫離普通流,不占據空間 默認會覆蓋到非定位元素上
不同點: absolute的”根元素“是可以設置的 fixed的”根元素“固定為瀏覽器窗口。當你滾動網頁,fixed元素與瀏覽器窗口之間的距離是不變的。
Animation和transition大部分屬性是相同的,他們都是隨時間改變元素的屬性值,他們的主要區別是transition需要觸發一個事件才能改變屬性, 而animation不需要觸發任何事件的情況下才會隨時間改變屬性值,并且transition為2幀,從from .... to,而animation可以一幀一幀的。
transition 規定動畫的名字 規定完成過渡效果需要多少秒或毫秒 規定速度效果 定義過渡效果何時開始 animation 指定要綁定到選擇器的關鍵幀的名稱
復制代碼不同級別:總結排序:!important > 行內樣式>ID選擇器 > 類選擇器 > 標簽 > 通配符 > 繼承 > 瀏覽器默認屬性
1.屬性后面加!import 會覆蓋頁面內任何位置定義的元素樣式
2.作為style屬性寫在元素內的樣式
3.id選擇器
4.類選擇器
5.標簽選擇器
6.通配符選擇器(*)
7.瀏覽器自定義或繼承
**同一級別:后寫的會覆蓋先寫的**
css選擇器的解析原則:選擇器定位DOM元素是從右往左的方向,這樣可以盡早的過濾掉一些不必要的樣式規則和元素
復制代碼 多個圖片集成在一個圖片中的圖
使用雪碧圖可以減少網絡請求的次數,加快允許的速度
通過background-position,去定位圖片在屏幕的哪個位置
相同點: 都常用來判斷一個變量是否為空,或者是什么類型的。
不同點: typeof 返回值是一個字符串,用來說明變量的數據類型 instanceof 用于判斷一個變量是否屬于某個對象的實例.
復制代碼visibility:hidden、display:none、z-index=-1、opacity:0
1.opacity:0,該元素隱藏起來了,但不會改變頁面布局,并且,如果該元素已經綁定了一些事件,如click事件也能觸發
2.visibility:hidden,該元素隱藏起來了,但不會改變頁面布局,但是不會觸發該元素已經綁定的事件
3.display:node, 把元素隱藏起來,并且會改變頁面布局,可以理解成在頁面中把該元素刪掉
淺克隆: 只是拷貝了基本類型的數據,而引用類型數據,復制后也是會發生引用,我們把這種拷貝叫做“(淺復制)淺拷貝”,換句話說,淺復制僅僅是指向被復制的內存地址,如果原地址中對象被改變了,那么淺復制出來的對象也會相應改變。
深克?。?創建一個新對象,屬性中引用的其他對象也會被克隆,不再指向原有對象地址。 JSON.parse、JSON.stringify()
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數據結構,數組去重
=賦值
==返回一個布爾值;相等返回true,不相等返回false; 允許不同數據類型之間的比較; 如果是不同類型的數據進行,會默認進行數據類型之間的轉換; 如果是對象數據類型的比較,比較的是空間地址
=== 只要數據類型不一樣,就返回false;
復制代碼1、js工廠模式
2、js構造函數模式
3、js原型模式
4、構造函數+原型的js混合模式
5、構造函數+原型的動態原型模式
6、觀察者模式
7、發布訂閱模式
call() 和apply()的第一個參數相同,就是指定的對象。這個對象就是該函數的執行上下文。
call()和apply()的區別就在于,兩者之間的參數。
call()在第一個參數之后的 后續所有參數就是傳入該函數的值。
apply() 只有兩個參數,第一個是對象,第二個是數組,這個數組就是該函數的參數。 bind() 方法和前兩者不同在于: bind() 方法會返回執行上下文被改變的函數而不會立即執行,而前兩者是 直接執行該函數。他的參數和call()相同。
原型鏈繼承 核心: 將父類的實例作為子類的原型
構造繼承 核心:使用父類的構造函數來增強子類實例,等于是復制父類的實例屬性給子類
實例繼承 核心:為父類實例添加新特性,作為子類實例返回
拷貝繼承
組合繼承 核心:通過調用父類構造,繼承父類的屬性并保留傳參的優點,然后通過將父類實例作為子類原型,實現 函數復用
寄生組合繼承 核心:通過寄生方式,砍掉父類的實例屬性,這樣,在調用兩次父類的構造的時候,就不會初始化兩次實 例方法/屬性,避免的組合繼承的缺點
個人感覺,簡單來說閉包就是在函數里面聲明函數,本質上說就是在函數內部和函數外部搭建起一座橋梁,使得子函數可以訪問父函數中所有的局部變量,但是反之不可以,這只是閉包的作用之一,另一個作用,則是保護變量不受外界污染,使其一直存在內存中,在工作中我們還是少使用閉包的好,因為閉包太消耗內存,不到萬不得已的時候盡量不使用。
把所有的對象共用的屬性全部放在堆內存的一個對象(共用屬性組成的對象),然后讓每一個對象的 __proto__存儲這個「共用屬性組成的對象」的地址。而這個共用屬性就是原型,原型出現的目的就是為了減少不必要的內存消耗。而原型鏈就是對象通過__proto__向當前實例所屬類的原型上查找屬性或方法的機制,如果找到Object的原型上還是沒有找到想要的屬性或者是方法則查找結束,最終會返回undefined
將html代碼按照深度優先遍歷來生成DOM樹。 css文件下載完后也會進行渲染,生成相應的CSSOM。 當所有的css文件下載完且所有的CSSOM構建結束后,就會和DOM一起生成Render Tree。 接下來,瀏覽器就會進入Layout環節,將所有的節點位置計算出來。 最后,通過Painting環節將所有的節點內容呈現到屏幕上。
復制代碼1、瀏覽器的地址欄輸入URL并按下回車。
2、瀏覽器查找當前URL是否存在緩存,并比較緩存是否過期。3、DNS解析URL對應的IP。
4、根據IP建立TCP連接(三次握手)。
5、HTTP發起請求。
6、服務器處理請求,瀏覽器接收HTTP響應。
7、渲染頁面,構建DOM樹。
8、關閉TCP連接(四次揮手)
相同點 都是保存在瀏覽器端,且同源的。
不同點
同源策略(協議+端口號+域名要相同)
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()
1.創建ajax實例
2.執行open 確定要訪問的鏈接 以及同步異步
3.監聽請求狀態
4.發送請求
ES6的set對象 先將原數組排序,在與相鄰的進行比較,如果不同則存入新數組
復制代碼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;
}
利用下標查詢
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開頭都是服務端的問題
同步:在同一時間內做一件事情
異步:在同一時間內做多個事情 JS是單線程的,每次只能做一件事情,JS運行在瀏覽器中,瀏覽器是多線程的,可以在同一時間執行多個任務。
定時器、ajax、事件綁定、回調函數、async await、promise
三次握手
四次揮手
建立連接的時候, 服務器在LISTEN狀態下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發送給客戶端。 而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,而自己也未必全部數據都發送給對方了,所以己方可以立即關閉,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送,從而導致多了一次。
如果元素類型發生變化,直接替換 如果是文本,則比較文本里面的內容,是否有差異,如果是元素就需要比較當前元素的屬性是否相等,會先比較key, 在比較類型 為什么 react中循環 建議不要使用索引 ,如果純為了展示 那可以使用索引
全局作用域
私有作用域
塊級作用域
上級作用域
他是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徹底完成
相同點
不同點
注意:forEach對于空數組是不會調用回調函數的。
async/await函數是異步代碼的新方式
async/await是基于promise實現的
async/await使異步代碼更像同步代碼
await 只能在async函數中使用,不能再普通函數中使用,要成對出現
默認返回一個promise實例,不能被改變
await下面的代碼是異步,后面的代碼是同步的
全局作用域下的this指向window 如果給元素的事件行為綁定函數,那么函數中的this指向當前被綁定的那個元素 函數中的this,要看函數執行前有沒有 . , 有 . 的話,點前面是誰,this就指向誰,如果沒有點,指向window 自執行函數中的this永遠指向window 定時器中函數的this指向window 構造函數中的this指向當前的實例 call、apply、bind可以改變函數的this指向 箭頭函數中沒有this,如果輸出this,就會輸出箭頭函數定義時所在的作用域中的this
所有的函數數據類型都天生自帶一個prototype屬性,該屬性的屬性值是一個對象 prototype的屬性值中天生自帶一個constructor屬性,其constructor屬性值指向當前原型所屬的類 所有的對象數據類型,都天生自帶一個_proto_屬性,該屬性的屬性值指向當前實例所屬類的原型
復制代碼promise、generator、async/await
promise: 1.是一個對象,用來傳遞異步操作的信息。代表著某個未來才會知道結果的時間,并未這個事件提供統一的api,供進異步處理
2.有了這個對象,就可以讓異步操作以同步的操作的流程來表達出來,避免層層嵌套的回調地獄
3.promise代表一個異步狀態,有三個狀態pending(進行中),Resolve(以完成),Reject(失敗)
4.一旦狀態改變,就不會在變。任何時候都可以得到結果。從進行中變為以完成或者失敗
promise.all() 里面狀態都改變,那就會輸出,得到一個數組
promise.race() 里面只有一個狀態變為rejected或者fulfilled即輸出
promis.finally()不管指定不管Promise對象最后狀態如何,都會執行的操作(本質上還是then方法的特例)
復制代碼事件流描述的是從頁面中接受事件的順序,事件 捕獲階段 處于目標階段 事件冒泡階段 addeventListener 最后這個布爾值參數如果是true,表示在捕獲階段調用事件處理程序;如果是false,表示在冒泡階段調用事件處理程序。
1、事件捕獲階段:實際目標div在捕獲階段不會接受事件,也就是在捕獲階段,事件從document到<html>再到<body>就停止了。
2、處于目標階段:事件在div發生并處理,但是事件處理會被看成是冒泡階段的一部分。
3、冒泡階段:事件又傳播回文檔
阻止冒泡事件event.stopPropagation()
function stopBubble(e) {
if (e && e.stopPropagation) { // 如果提供了事件對象event 這說明不是IE瀏覽器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
}
阻止默認行為event.preventDefault()
function stopDefault(e) {
if (e && e.preventDefault) {
e.preventDefault()
} else {
// IE瀏覽器阻止函數器默認動作的行為
window.event.returnValue = false
}
}
在DOM標準事件模型中,是先捕獲后冒泡。但是如果要實現先冒泡后捕獲的效果, 對于同一個事件,監聽捕獲和冒泡,分別對應相應的處理函數,監聽到捕獲事件,先暫緩執行,直到冒泡事件被捕獲后再執行捕獲事件。
復制代碼千萬不要使用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()方法測試一個對象是否存在另一個對象的原型鏈上。
復制代碼因為js是單線程的。瀏覽器遇到etTimeout 和 setInterval會先執行完當前的代碼塊,在此之前會把定時器推入瀏覽器的
待執行時間隊列里面,等到瀏覽器執行完當前代碼之后會看下事件隊列里有沒有任務,有的話才執行定時器里的代碼
復制代碼 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是一個漸進式的JS框架。他易用,靈活,高效; 可以把一個頁面分隔成多個組件;當其他頁面有類似功能時,直接讓封裝的組件進行復用; 他是構建用戶界面的聲明式框架,只關心圖層;不關心具體是如何實現的
Vue的雙向數據綁定是由數據劫持結合發布者訂閱者實現的。 數據劫持是通過Object.defineProperty()來劫持對象數據的setter和getter操作。 在數據變動時作你想做的事
原理 通過Observer來監聽自己的model數據變化,通過Compile來解析編譯模板指令,最終利用Watcher搭起Observer和Compile之間的通信橋梁,達到數據變化->視圖更新 在初始化vue實例時,遍歷data這個對象,給每一個鍵值對利用Object.definedProperty對data的鍵值對新增get和set方法,利用了事件監聽DOM的機制,讓視圖去改變數據
react整體是函數式的思想,把組件設計成純組件,狀態和邏輯通過參數傳入,所以在react中,是單向數據流;
vue的思想是響應式的,也就是基于是數據可變的,通過對每一個屬性建立Watcher來監聽,當屬性變化的時候,響應式的更新對應的虛擬dom。
復制代碼頁面通過mapAction異步提交事件到action。action通過commit把對應參數同步提交到mutation。
mutation會修改state中對于的值。 最后通過getter把對應值跑出去,在頁面的計算屬性中
通過mapGetter來動態獲取state中的值
state中保存著共有數據,數據是響應式的 getter可以對state進行計算操作,主要用來過濾一些數據,可以在多組件之間復用 mutations定義的方法動態修改state中的數據,通過commit提交方法,方法必須是同步的 actions將mutations里面處理數據的方法變成異步的,就是異步操作數據,通store.dispatch來分發actions,把異步的方法寫在actions中,通過commit提交mutations,進行修改數據。 modules:模塊化vuex
hash ——即地址欄URL中的#符號(此hsah 不是密碼學里的散列運算) hash 雖然出現URL中,但不會被包含在HTTP請求中,對后端完全沒有影響,因此改變hash不會重新加載頁面。 history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法
這兩個方法應用于瀏覽器的歷史記錄站,在當前已有的back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改是,雖然改變了當前的URL,但你瀏覽器不會立即向后端發送請求。
當 Vue.js 用v-for正在更新已渲染過的元素列表時,它默認用“就地復用”策略。 如果數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序,而是簡單復用此處每個元素,并且確保它在特定索引下顯示已被渲染過的每個元素。
key的作用主要是為了高效的更新虛擬DOM。
$route是“路由信息對象”,包括path,params,hash,query,fullPath,matched,name等路由信息參數。 $router是“路由實例”對象包括了路由的跳轉方法,鉤子函數等。
導航守衛 router.beforeEach 全局前置守衛
復制代碼// 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 全局后置鉤子');
});
路由獨享的守衛 你可以在路由配置上直接定義 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銷毀,防止離開之后,定時器還在調用。
}
}
請求后臺資源的模塊。
復制代碼$ npm install axios -S裝好
然后發送的是跨域,需在配置文件中config/index.js進行設置。后臺如果是Tp5則定義一個資源路由。 js中使用import進來,然后.get或.post。返回在.then函數中如果成功,失敗則是在.catch函數中
1.不要在模板里面寫過多表達式
2.循環調用子組件時添加key
3.頻繁切換的使用v-show,不頻繁切換的使用v-if
4.盡量少用float,可以用flex
5.按需加載,可以用require或者import()按需加載需要的組件
6.路由懶加載
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;}
復制代碼 => 相同點:
1.數據驅動頁面,提供響應式的試圖組件
2.都有virtual DOM,組件化的開發,通過props參數進行父子之間組件傳遞數據,都實現了webComponents規范
3.數據流動單向,都支持服務器的渲染SSR
4.都有支持native的方法,react有React native, vue有wexx
=> 不同點:
1.數據綁定:Vue實現了雙向的數據綁定,react數據流動是單向的
2.數據渲染:大規模的數據渲染,react更快
3.使用場景:React配合Redux架構適合大規模多人協作復雜項目,Vue適合小快的項目
4.開發風格:react推薦做法jsx + inline style把html和css都寫在js了
vue是采用webpack + vue-loader單文件組件格式,html, js, css同一個文件
復制代碼Redux數據流里,reduces其實是根據之前的狀態(previous state)和現有的action(current action)
更新state(這個state可以理解為上下累加器的結果)
每次redux reducer被執行時,state和action被傳入,這個state根據action進行累加或者是'自身消減'(reduce),
進而返回最新的state,這也就是典型reduce函數的用法:state -> action -> state
復制代碼refs就想一個逃生窗,允許我們之間訪問dom元素或者組件實例,可以向組件添加一個ref屬性的值是一個回調函數,
它將接受地城dom元素或組件的已掛在實例,作為第一個參數
復制代碼幫組我們跟蹤哪些項目已更改、添加、從列表中刪除,key是獨一無二的,可以讓我們高效的去定位元素,并且操作它
復制代碼三個狀態:Mounting(已插入真實的DOM)
Updating(正在被重新渲染)
Unmounting(已移除真實的DOM)
componentDIdMount 在第一次渲染后調用,只在客服端。之后組件已經生成對應的DOM結構,
componentDidUpdate 在組件完成更新后立即調用,在出初始化是不會調用
復制代碼父組件通過props 給子組件傳遞數據,子組件則是通過調用父組件傳給它的函數給父組件傳遞數據。
復制代碼虛擬DOM相當于在js和真實dom中間加了一個緩存,利用dom diff算法避免了沒有必要的doom操作,從而提高性能
具體實現步驟:
·用JavaScript對象結構表示DOM樹的結構;然后用這個樹構建一個真正的DOM樹,插到文檔中
·當狀態變更的時候,重新構造一棵樹的對象樹,然后用新的樹和舊的樹進行對比,記錄兩棵樹差異
·把2所記錄的差異應用到步驟1所構建的真正的DOM樹上,試圖就更新了。
復制代碼1.把樹形結構按照層級分解,只比較同級元素
2.給列表結構的每個單元添加key屬性,方便比較。在實際代碼中,會對新舊兩棵樹進行一個深度優先的遍歷,這樣每個節點都會有一個標記
3.在深度優先遍歷的時候,每遍歷到一個節點就把該節點和新的樹進行對比。如果有差異的話就記錄到一個對象里面
Vritual DOM 算法主要實現上面步驟的三個函數:element, diff, patch。然后就可以實際的進行使用
react只會匹配相同的class的component(這里的class指的是組件的名字)
合并操作,條用component的setState方法的時候,React將其標記為dirty.到每一個時間循環借宿,React檢查所有標記dirty的component重新繪制
4.選擇性子樹渲染??梢灾貙憇houldComponentUpdate提高diff的性能
復制代碼flux的最大特點,就是數據的‘單向流動’
1.用戶訪問View
2.View發出用戶的Action
3.Dispatcher收到Action,要求state進行相應的更新
4.store更新后,發出一個‘change’事件后,更新頁面
復制代碼shouldComponentUpdate 這個方法用來判斷是否需要調用render方法重新描繪dom.因為dom的描繪非常消耗性能,
如果我們在shouldComponentUpdate方法中能夠寫出更優化的dom diff算法,可以極大的提高性能
復制代碼根據組件的職責通常把組件分為UI組件和容器組件
UI組件負責UI的呈現,容器組件負責管理數據和邏輯
兩者通過React-redux提供connect方法聯系起來
復制代碼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.異步加載模塊
2.提取第三庫
3.代碼壓縮
4.去除不必要的插件
復制代碼一、減少代碼體積 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、盡量使用事件代理,避免直接事件綁定
復制代碼1.減少入口文件體積
2.靜態資源本地緩存
3.開啟Gzip壓縮
4.使用SSR,nuxt.js
復制代碼由來:
300毫米延遲解決的是雙擊縮放。雙擊縮放,手指在屏幕快速點擊兩次。safari瀏覽器就會將網頁縮放值原始比例。由于用戶可以雙擊縮放或者是滾動的操作,
當用戶點擊屏幕一次之后,瀏覽器并不會判斷用戶確實要打開至這個鏈接,還是想要進行雙擊操作
因此,safair瀏覽器就會等待300ms,用來判斷用戶是否在次點擊了屏幕
解決方案:1.禁用縮放,設置meta標簽 user-scalable=no
2.fastclick.js
原理:FastClick的實現原理是在檢查到touchend事件的時候,會通過dom自定義事件立即
發出click事件,并把瀏覽器在300ms之后真正的click事件阻止掉
fastclick.js還可以解決穿透問題
在不改變外部行為的前提下,簡化結構、添加可讀性
復制代碼 2XX(成功處理了請求狀態)
200 服務器已經成功處理請求,并提供了請求的網頁
201 用戶新建或修改數據成功
202 一個請求已經進入后臺
204 用戶刪除成功
3XX(每次請求使用的重定向不要超過5次)
304 網頁上次請求沒有更新,節省帶寬和開銷
4XX(表示請求可能出錯,妨礙了服務器的處理)
400 服務器不理解請求的語法
401 用戶沒有權限(用戶名,密碼輸入錯誤)
403 用戶得到授權(401相反),但是訪問被禁止
404 服務器找不到請求的網頁,
5XX(表示服務器在處理請求的時候發生內部錯誤)
500 服務器遇到錯誤,無法完成請求
503 服務器目前無法使用(超載或停機維護)
復制代碼1.服務器首先產生Etag,服務器可在稍后使用它來判斷頁面是否被修改。本質上,客戶端通過該記號傳回服務器要求服務器驗證(客戶端)緩存)
2.304是 HTTP的狀態碼,服務器用來標識這個文件沒有被修改,不返回內容,瀏覽器接受到這個狀態碼會去去找瀏覽器緩存的文件
3.流程:客戶端請求一個頁面A。服務器返回頁面A,并在A上加一個Tage客服端渲染該頁面,并把Tage也存儲在緩存中??蛻舳嗽俅握埱箜撁鍭
并將上次請求的資源和ETage一起傳遞給服務器。服務器檢查Tage.并且判斷出該頁面自上次客戶端請求之后未被修改。直接返回304
last-modified: 客服端請求資源,同時有一個last-modified的屬性標記此文件在服務器最后修改的時間
客服端第二次請求此url時,根據http協議。瀏覽器會向服務器發送一個If-Modified-Since報頭,
詢問該事件之后文件是否被修改,沒修改返回304
有了Last-Modified,為什么還要用ETag?
1、因為如果在一秒鐘之內對一個文件進行兩次更改,Last-Modified就會不正確(Last—Modified不能識別秒單位的修改)
2、某些服務器不能精確的得到文件的最后修改時間
3、一些文件也行會周期新的更改,但是他的內容并不改變(僅僅改變修改的事件),這個時候我們并不希望客戶端認為文件被修改,而重新Get
ETag,為什么還要用Last-Modified?
1、兩者互補,ETag的判斷的缺陷,比如一些圖片等靜態文件的修改
2、如果每次掃描內容都生成ETag比較,顯然要比直接比較修改時間慢的多。
ETag是被請求變量的實體值(文件的索引節,大小和最后修改的時間的Hash值)
1、ETag的值服務器端對文件的索引節,大小和最后的修改的事件進行Hash后得到的。
復制代碼1.get數據是存放在url之后,以?分割url和傳輸數據,參數之間以&相連; post方法是把提交的數據放在http包的Body中
2.get提交的數據大小有限制,(因為瀏覽器對url的長度有限制),post的方法提交的數據沒有限制
3.get需要request.queryString來獲取變量的值,而post方式通過request.from來獲取變量的值
4.get的方法提交數據,會帶來安全問題,比如登錄一個頁面,通過get的方式提交數據,用戶名和密碼就會出現在url上
復制代碼1.超文本的傳輸協議,是用于從萬維網服務器超文本傳輸到本地資源的傳輸協議
2.基于TCP/IP通信協議來傳遞數據(HTML,圖片資源)
3.基于運用層的面向對象的協議,由于其簡潔、快速的方法、適用于分布式超媒體信息系統
4.http請求信息request:
請求行(request line)、請求頭部(header),空行和請求數據四部分構成
請求行,用來說明請求類型,要訪問的資源以及所使用的HTTP版本.
請求頭部,用來說明服務器要使用的附加信息
空行,請求頭部后面的空行是必須的
請求數據也叫主體,可以添加任意的其他數據。
5.http相應信息Response
狀態行、消息報頭、空行和響應正文
狀態行,由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成
消息報頭,用來說明客戶端要使用的一些附加信息
空行,消息報頭后面的空行是必須的
響應正文,服務器返回給客戶端的文本信息。
復制代碼https:是以安全為目標的HTTP通道,簡單講是HTTP的安全版本,通過SSL加密
http:超文本傳輸協議。是一個客服端和服務器端請求和應答的標準(tcp),使瀏覽器更加高效,使網絡傳輸減少
復制代碼長連接: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請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器端獲取。這種方式非常合適加載靜態資源
復制代碼1.web緩存就是存在于客戶端與服務器之間的一個副本、當你第一個發出請求后,緩存根據請求保存輸出內容的副本
2.緩存的好處
(1)減少不必要的請求
(2)降低服務器的壓力,減少服務器的消耗
(3)降低網絡延遲,加快頁面打開速度(直接讀取瀏覽器的數據)
復制代碼1.sql注入原理:是將sql代碼偽裝到輸入參數中,傳遞到服務器解析并執行的一種攻擊手法。也就是說,
在一些對server端發起的請求參數中植入一些sql代碼,server端在執行sql操作時,會拼接對應參數,
同時也將一些sql注入攻擊的“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代替用戶完成指定的動作,需要知道其他頁面的代碼和數據包
復制代碼1.盡可能的避開互聯網有可能影響數據傳輸速度和穩定性的瓶頸和環節。使內容傳輸的更快更穩定。
2.關鍵技術:內容存儲和分發技術中
3.基本原理:廣泛采用各種緩存服務器,將這些緩存服務器分布到用戶訪問相對的地區或者網絡中。當用戶訪問網絡時利用全局負載技術
將用戶的訪問指向距離最近的緩存服務器,由緩存服務器直接相應用戶的請求(全局負載技術)
復制代碼客服端發c起請求連接服務器端s確認,服務器端也發起連接確認客服端確認。
第一次握手:客服端發送一個請求連接,服務器端只能確認自己可以接受客服端發送的報文段
第二次握手: 服務端向客服端發送一個鏈接,確認客服端收到自己發送的報文段
第三次握手: 服務器端確認客服端收到了自己發送的報文段
復制代碼1.查詢NDS(域名解析),獲取域名對應的IP地址 查詢瀏覽器緩存
2.瀏覽器與服務器建立tcp鏈接(三次握手)
3.瀏覽器向服務器發送http請求(請求和傳輸數據)
4.服務器接受到這個請求后,根據路經參數,經過后端的一些處理生成html代碼返回給瀏覽器
5.瀏覽器拿到完整的html頁面代碼開始解析和渲染,如果遇到外部的css或者js,圖片一樣的步驟
6.瀏覽器根據拿到的資源對頁面進行渲染,把一個完整的頁面呈現出來
復制代碼流程:解析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): 當渲染書中的一部分(或全部)因為元素的規模尺寸,布局,隱藏等改變而需要重新構建,這就是回流。
每個頁面都需要一次回流,就是頁面第一次渲染的時候
重排一定會影響重繪,但是重繪不一定會影響重排
復制代碼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的本地存儲,數據永久保存在客服端
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用于持久化的本地存儲,除非主動刪除數據,否則不會過期
復制代碼1、token就是令牌,比如你授權(登錄)一個程序時,他就是個依據,判斷你是否已經授權該軟件(最好的身份認證,安全性好,且是唯一的)
用戶身份的驗證方式
2、cookie是寫在客戶端一個txt文件,里面包括登錄信息之類的,這樣你下次在登錄某個網站,就會自動調用cookie自動登錄用戶名
服務器生成,發送到瀏覽器、瀏覽器保存,下次請求再次發送給服務器(存放著登錄信息)
3、session是一類用來客戶端和服務器之間保存狀態的解決方案,會話完成被銷毀(代表的就是服務器和客戶端的一次會話過程)
cookie中存放著sessionID,請求會發送這個id。sesion因為request對象而產生。
復制代碼 1、用戶通過用戶名和密碼發送請求
2、服務器端驗證
3、服務器端返回一個帶簽名的token,給客戶端
4、客戶端儲存token,并且每次用于發送請求
5、服務器驗證token并且返回數據
每一次請求都需要token
復制代碼 1、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。
2、cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙考慮到安全應當使用session。
3、session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能考慮到減輕服務器性能方面,應當使用COOKIE。
4、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。
復制代碼 1、session認證只是把簡單的User的信息存儲Session里面,sessionID不可預測,一種認證手段。只存在服務端,不能共享到其他的網站和第三方App
2、token是oAuth Token,提供的是認證和授權,認證針對用戶,授權是針對App,目的就是讓某APP有權訪問某用戶的的信息。Token是唯一的,
token不能轉移到其他的App,也不能轉到其他用戶上。(適用于App)
3、session的狀態是存在服務器端的,客戶端只存在session id, Token狀態是存儲在客戶端的
復制代碼 1、數量和長度的限制。每個特定的域名下最多生成20個cookie(chorme和safari沒有限制)
2、安全性問題。
一、觀察者模式:juejin.cn/post/684490… juejin.cn/post/684490… 在軟件開發設計中是一個對象(subject),維護一系列依賴他的對象(observer),當任何狀態發生改變自動通知他們。強依賴關系 簡單理解:數據發生改變時,對應的處理函數就會自動執行。一個Subjet,用來維護Observers,為某些event來通知(notify)觀察者
二、發布-訂閱者 有一個信息中介,過濾 耦合性低 它定義了一種一對多的關系,可以使多個觀察者對象對一個主題對象進行監聽,當這個主題對象發生改變時,依賴的所有對象都會被通知到。
復制代碼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.
復制代碼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
復制代碼一句話概括: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的原理:相當于在用戶和服務器之間加一個中間層(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.cn/post/6844903625769091079
```
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)
```
如果本文對你有幫助,就留個關注點個贊支持下吧,你的「關注」和「贊」是我創作的動力。
原文鏈接:https://juejin.cn/post/6844903976693940231
處 | 前端之巔
在過去的幾年里,我在亞馬遜和雅虎面試過很多專注于前端開發的 Web 開發者和軟件工程師,在這篇文章中,我想分享一些面試技巧,幫助候選人為面試做好準備。
免責聲明——本文并非旨在列出在前端面試中可能會被問到的所有問題,但可以將其視為知識的基線。
通過面試不是件容易的事,作為候選人,通常需要在 45 分鐘的時間內展示自己能做些什么。作為一名面試官,同樣難以在這么短的時間內評估候選人是否適合。對于面試來說,并不存在一刀切的方法,面試官問的問題通常會有一個范圍,但除此之外,他們可以自行決定要問哪些其他問題。
作為曾經的候選人和面試官,我試圖在這篇文章中涵蓋你可能會在面試中被問到的最重要的前端開發知識。
我見過候選人犯的最大錯誤之一就是準備了一些瑣碎的問題,例如“什么是盒子模型”或者“JavaScript 中的 == 和 === 之間的區別是什么”。知道這些問題的答案固然是好,但這并不會告訴面試官來太多有用的信息。
相反,在實際的面試中,你可能需要使用 JavaScript、CSS 和 HTML 來編寫代碼。在你的面試期間,你可能需要實現 UI、構建窗口小部件或使用 Lodash 和 Underscore.js 這樣的庫編寫常用的實用程序函數。例如:
說到庫,我看到候選人經常犯的另一個錯誤是他們需要完全依賴最新的框架來解決面試問題。你可能會想,如果我可以在生產環境中使用 jQuery、React、Angular 等,那為什么就不能在面試中使用它們呢?技術、框架和庫會隨著時間的推移而發生變化——我更感興趣的是你是否了解前端開發的底層原理,而不是依賴更高層次的抽象。如果你不能在沒有它們的情況下回答面試問題,我希望你至少可以徹底解釋和推測這些庫背后的原理。
總的來說,大部分的面試都涉及實際的編碼。
你需要了解 JavaScript,而且是徹底地了解。你面試的職位越高,對語言知識的要求就越高。以下是你應該熟悉的 JavaScript 知識點:
知道如何遍歷和操作 DOM 非常重要,對于重度依賴 jQuery 或者開發了很多 React & Angular 類型應用程序的候選人來說,他們可能會在這個問題上栽跟斗。你可能不會每天都直接接觸 DOM,因為我們大多數人都在使用各種抽象。在不使用第三方庫的情況下,你需要知道如何執行以下這些操作:
至少,你應該知道如何在頁面上布局元素,如何使用子元素或直接后代選擇器來定位元素,以及什么時候該用類、什么時候該用 ID。
知道哪些 HTML 標簽最能代表你正在顯示的內容以及相關屬性,應該掌握手工知識。
在系統設計方面,通常涉及 MapReduce、分布式鍵值存儲系統或 CAP 定理等知識。雖然前端工程師日常不需要深入了解如何設計這類系統,但在被要求設計出常見應用程序的前端架構時,你也不應該感到驚訝。這些問題通常含糊不清,比如“設計一個像 Pinterest 這樣的網站”或者“如何構建購物結賬服務?”。以下是需要考慮的知識點:
除了通用編程最佳實踐之外,你應該期望訪問者查看你的代碼或設計及其性能影響。它曾經足以將 CSS 置于文檔的頂部,而 JS 腳本位于頁面底部,但 Web 正在快速移動,你應該熟悉這個領域的復雜性。
這個可能有點爭議,但對 Big-O 時間復雜性和常見運行時間(如 O(N) 和 O(N Log N))有一個基本的了解對你來說不會是壞事。單頁應用程序現在非常常見,所以了解內存管理等方面的知識是有幫助的。例如,如果你被要求構建客戶端拼寫檢查程序,那么了解常見的數據結構和算法將會讓你的任務變得輕松許多。
我不是說你一定需要念一個計算機學位,但這個行業已經從構建簡單的網頁轉移到了計算機科學。網上有很多資源可以讓那個你快速掌握基礎知識。
你需要掌握一些構成 Web 的技術和范式。
對 Web 開發人員或工程師來說,構建 Web 應用程序需要掌握大量的知識。不要被知識的深度所限制,而是要保持開放的心態去學習所有復雜的部分。
除了這里涉及的技術主題之外,你還需要討論過去參與的項目,描述發生了哪些有趣的事情以及做出了哪些權衡。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。