推薦:兩年前端程式媛從0到18k的逆襲之路 | 2021年中總結
image.png
求點贊+求分享+求評論,哦耶!!!(基本工資有一部分花在付費學習上)
(文末有彩蛋。。。)。一個朋友,面試的小哥,每天早晨六點起床學習,三本兩年多經驗拿了年包
50w
的
offer
。某大佬:
- 你看很多,校招
白菜價,誰又拿了大廠的offer。你會發現,他們不但學曆高,而且都十分的努力。我個人挺佩服的。24k
- 學曆低的想拿大的
,除了努力提升自己的技術,你别無選擇。捷徑有人能走,但是你想一想這個人是不是你。offer
1. Dear developers
Dear developers
6月徐來,年中總結,認識某人三本兩年多經驗拿了年包 50w 的
offer
,通過相識,清晰了職業規劃,發展方向。
2021
年的時間進度條也已過半,我們彼此或多或少經曆了很多很多不平凡的事發生。下面面試了一些大廠,中廠,小廠的經驗。
每個人都需要 有目标,有職業規劃,有夢想,有向上的心。(當然,如果你沒有,誰也不強求你)
image.png
在這裡感謝一下:冴羽大佬,位元組強哥,浩月等大佬。
履歷發給他們後,隻修改一次到達他們的認同(不過我卡學曆,除非某些方面非常優秀),我也發現了很多差距,是以接下來準備繼續學習(卷)。
2.履歷總結
淘系:履歷上,如有學曆硬傷,過不了履歷評估;履歷上不能廢話太多,你要是面試官你希望面試官問你哪些地方,你就往哪些地方寫;項目上也隻是寫你做過的哪些事情,技術深度,實際的提升等;如果你有部落格,文章網站等都可以寫一寫。
位元組:履歷上,項目經驗不要大量寫業務描述,需要的是一些技術方面的亮點;區分與其他人的優勢,找個好的履歷模闆(這裡推薦 木及履歷 百度一下就有),如果你是5年以下經驗的,如果一頁寫不完,要麼是大牛,要麼就是提煉不足,是以不管怎樣,提煉到一頁以内寫完。
一些普通的,你隻需要在技能欄裡寫如:精通
Vue
技術棧即可,(面試官或hr就了解關于Vue項目你基本能掌握即可)。
image.png
image.png
履歷:簡潔,主題鮮明。
履歷細節:
- 性名,年齡,工作經驗,聯系方式,學曆。
- 崗位,薪資面議,技能,工作經曆(倒叙書寫)。
- 技能就别寫普通的了,到一定技能可寫如下(隻是個示例):
1. 熟練掌握JavaScript,TypeScript,Node,CSS以及ES6的新特性
2. 擅長Vue技術棧,以及其生态,某架構及其實作原理,源碼
3. 有良好的資料結構與算法,能熟練在項目中運用設計模式
4. 熟悉HTTP協定,網絡原理,webpack,babel等等
- 項目描述,如技術棧
開發Vue+Vuex+axios+element ui+echarts+es6
- (項目描述,時間點,遇到什麼問題,用什麼技術解決,取得了什麼效果)
- (在項目中扮演的角色等,開源能力,知識筆記,部落格)
3.細聊
- 聊聊小程式,小遊戲,
端(我做過)H5,app端,PC
- 多端開發能力如何
- 網站性能優化,了解浏覽器實作原理
- 浏覽器緩存,計算機基礎知識,資料結構與算法
- 浏覽器事件循環
- 前端工程化的:子產品化,元件化,規範化(
配置,檔案,元件,函數,變量命,eslint
等),自動化commit
- 項目目錄,規範,開發流程
- HTTP:伺服器的認識,三次握手/四次揮手,一個url輸入到浏覽器産生界面發現了等
- 單例模式
- 閉包是什麼
- 原型鍊是什麼
-
-promise
等,api all,race,any
async/await
- 程式設計能力解決單點難題
- 架構能力解決複雜,大項目的頂層設計
- 工程能力解決大規模人員參與的項目協作問題
- 領域知識解決特殊業務的系列問題
- 問道:
的es6
fill,includes,find,Object.keys()
- 問道:防抖,節流
- 問道:
,promise
,let/const
,axios
,git flow
分支等branch
- 問道:
的繼承es5,es6
- 問道:自動化包含:單元測試,
測試,ui
,容器化,CI/CD
,容器編排DockerFile
監控k8s
sentry
HTML5的新标簽:header,sction,footer,aside,nav,main,article,figure,localStorage和sessionStorage,audio/video/svg等。
CSS3的:定位,static,relative,find,absoulte,sticky。
4.工資隻是個大概估算(大概而已,别杠)
中小廠:
- 初級:一線:7-20K;二線:5-15k
- 中級:一線:15-25k;二線:12-23k
- 進階:一線:20-40k;二線:15-35k
大廠:
- 25-50k都有,看能力
image.png
水準(也隻是個大概)
初級要:
- 負責業務系統前端子產品的設計與開發;
- 負責産品的需求分析,開發,測試,維護等各項工作;
- 承擔PC端和移動端的前端HTML5的開發任務;
- 整體頁面結構以及css樣式層的設計,優化;
- 完成頁面腳本程式編寫,實作各類頁面動态,互動效果;
- 能夠了解後端架構,與後端工程師配合為項目提供最優化的技術解決方案。
中級要:
- 負責所在項目需求實作與開發;
- 完成系統細節技術設計,完成核心代碼的編寫;
- 確定需求實作,滿足項目設計規範,軟體編碼規範以及性能要求;
- 測試,系統測試等;
- 積極溝通,以確定功能實作按時,按質傳遞;
- 積極參與階段評審,滿足項目過程品質需求,稽核和指導開發人員。
已滿足,走向進階開發(個人帶領過小團隊):
- 負責大型系統的web前端開發
- 參與技術選型,推進應用和開發工作,支撐平台架構設計與開發功能
- 提升系統的整體使用者體驗,推動前端技術的發展
- 為提升團隊開發效率,提煉公共元件,創造實用工具
- 優化現有業務,開發流程
- 關注前端發展,應用行業新技術
- 團隊管理
筆記
子產品一:
ES6 Module和Commonjs差別:
-
靜态引入,編譯時引入ES6 Module
-
動态引入,執行時引入Commonjs
- 隻有
才能靜态分析,實作ES6 Module
Tree-Shaking
let apiList = require('../config/api.js')
if(isDev) {
// 動态也引入執行時引入
apiList = require('../config/api.js')
}
import apiList form '../config/api.js'
if(isDev) {
// 編譯時報錯,隻能靜态引入
import apiList from '../config/api_dev.js'
}
Scope Hosting
:
// hello.js
export default 'hello'
// main.js
import str from './hello.js'
console.log(str)
-
性能優化-産出代碼webpack
- 小圖檔
編碼base64
-
加bundle
hash
- 懶加載
- 提供公共代碼
- 使用
加速CDN
- 使用
production
-
Scope Hosting
- 代碼體積更小
- 建立函數作用域更小
- 代碼可讀性更好
babel
:前端開發環境必備工具,同
webpack
,需要了解基本的配置和使用
環境搭建和基本配置:
babel-polyfill,babel-runtime
環境搭建:
.babelrc
配置:
presets
和
plugins
core-js
,
regenerator
結合,如何按需引入
babel-polyfill
,
Babel 7.4
之後棄用
babel-polyfill
,推薦直接使用
core-js
和
regenerator
。
babel-polyfill
按需引入:檔案較大,隻有一部分功能,無需全部引入,配置按需引入。
babel-polyfill
的問題?
- 會污染全局環境;
- 如果做一個獨立的
系統,則無礙;web
- 如果做一個第三方
,則會有問題;Lib
babel-runtime
不會污染全局環境:
- 基本配置
- 進階配置
- 優化打包效率
- 優化産生代碼
- 建構流程概述
-
babel
細分:
拆配置設定置和
merge
;啟動本地服務;處理
ES6
;處理樣式;處理圖檔;多入口;抽離css檔案;抽離公共代碼;懶加載;處理JSX;處理Vue;webpack優化建構速度:優化
babel-loader
,
IgnorePlugin
,
noParse
,
happyPacK
,
ParalleIUglifyPlugin
。
前端為何打包建構,好處?
- 體積更小(
,壓縮,合并),加載更快Tree-Shaking
- 編譯進階語言或文法(
)TS,ES6+,子產品化,SCSS
- 相容性和錯誤檢查(
)Polyfill,postcss,eslint
通過打包和建構,可以統一,高效的開發環境;統一的建構流程和産出标準,內建公司建構規範(提測,上線等)。
子產品二:
module, chunk, bundle的差別?
-
各個源碼檔案,module
中一切皆子產品webpack
-
多子產品合并成的,如chunk
,entry
,import()
splitChunk
-
最終的輸出檔案bundle
loader
和
plugin
的差別:
loader
子產品轉換器,如
less-css
;
plugin
擴充插件,如:
HtmlWebpackPlugin
。
babel
和
webpack
的差別?
-
-babel
新文法編譯工具,不關心子產品化。js
-
-打包建構工具,是多個webpack
,loader
的集合plugin
如何産生一個
lib
?參考
webpack.dll.js ouput library.
output: {
// lib的檔案名
filename: 'lodash.js',
// 輸出lib到dist目錄下
path: disPath,
library: 'lodash',
},
為何
Proxy
不能被
Polyfill
?
- 如
可以用Class
模拟function
- 如
可以用Promise
來模拟callback
- 但
的功能用Proxy
無法模拟Object.defineProperty
和
babel-polyfill
的差別
babel-runtime
-
會污染全局babel-polyfill
-
不會污染全局babel-runtime
- 産生第三方
要用lib
babel-runtime
webpack
如何實作懶加載
-
import()
- 結合
異步元件Vue React
- 結合
異步加載路由Vue-router``React-router
webpack優化建構速度(可用于生産環境)
- 優化
babel-loader
-
IgnorePlugin
-
noParse
-
happyPack
-
ParalleIUglifyPlugin
webpack
優化建構速度(不用于生産環境)
- 自動重新整理
- 熱更新
- DIIPlugin
項目流程
- 項目分多人,多角色參與
- 項目分多階段
- 項目需要計劃和執行
需求分析:了解背景,質疑需求是否合理,需求是否閉環,開發難度如何,是否需要其他支援,不要急于給排期。技術方案設計:1,求簡,不過渡設計;2,産出文檔,複盤;3,找準設計重點,元件怎麼設計;4,組内評審;5,和
RD,CRD
溝通;6,發出會議結論。
完整項目流程:各個角色(需求分析),技術方案設計,開發,聯調,測試,上線。
如何保證代碼品質,開發,項目品質?
- 如何回報排期
- 符合開發規範
- 寫出開發文檔
- 及時寫單元測試
-
Mock API
-
Code Review
聯調:1,和RD,CRD技術聯調;2,讓UE确定視覺效果;3,讓PM确定産品功能。
加需求:走需求變更流程,按規定走,發起項目組和leader的評審,重新評估排期。
測試:提測發郵件,抄送項目組,測試問題要詳細記錄。
有問題及時溝通,QA和FE天生資訊不對稱,當面讨論,讓QA幫你複現,需要特定裝置才能複現。溝通,及時識别風險,及時彙報。
子產品三:
了解:
CSS
盒模型,
DOM
事件類,
HTTP
協定類,原型鍊類,面向對象類,通信類,前端安全類,前端算法類;渲染機制類,JS運作機制,頁面性能,錯誤監控,業務能力,團隊協作能力,帶人能力。
布局
浮動,絕對定位,
flex-box
,表格布局,網格布局。
浮動解決方案:
<div class="left"></div>
<div class="right"></div>
<div class="center"></div>
div {min-height: 100px;}
.left {float: left; width: 300px; background: red;}
.right {float: right;..}
.center { background: yellow; }
絕對定位:absolute
flex box
表格布局
網格布局
基本模型,
content,padding, border, margin
height-content height, width-content width
标準模型,IE模型的差別:
- 計算的寬度和高度不同
IE模型:它的寬和高是計算:
padding+border
。
CSS3的屬性,CSS如何設定這兩種模型,
box-sizing
:
content-box
;(标準模型)
box-sizing:border-box
(
IE
模型)
JS如何設定擷取盒模型的寬和高:
dom.style.width/height,dom.currentStyle.width/height
相容性更好一些:
window.getComputeStyle(dom).width/height
;
dom.getBoundingClientRect().width/height
BFC(邊距重疊解決方案)塊級格式化上下文:BFC的原理,BFC的渲染規則:
- BFC這個元素的垂直方向的邊距會發生重疊
- BFC的區域不會與浮動元素的boxs重疊,清除浮動布局
- BFC在頁面上是獨立的容器,外面的元素不會影響裡面的元素,裡面的元素也不會影響外面的元素
- 計算BFC高度的時候,浮動元素也會參與計算
如何建立BFC,給父元素添加:
overflow: hidden;
,
overflow:auto;
,
flow
不為
none
,設定浮動
BFC
,
position
:不是
static/relative
使用BFC的場景:解決邊距重疊問題,解決清除浮動。BFC的元素不會與float元素互相重疊。
DOM事件:
1.DOM事件的級别;2.DOM事件模型;3.DOM事件流;4.描述DOM事件捕獲的具體流程;5.Event對象的常用應用;6.自定義事件。
DOM事件類,事件級别:
DOM0 element.onclick = function(){}
DOM2 element.addEventListener('click',function(){}, false)
DOM3 element.addEventListener('keyup',function(){}, false)
DOM
事件模型:捕獲,冒泡
事件流:浏覽器在為這個目前頁面與使用者做互動的過程中,點選屬标,傳到頁面上。
事件流:
window
對象,捕獲,目标元素(目标階段)-》冒泡,window對象。
描述DOM事件捕獲的具體流程:
window-document-html-body-目标元素
。(
document.documentElement
)
Event
對象的常用:
event.preventDefault()
阻止預設行為;
event.stopPropagation()
阻止冒泡行為;
event.stopImmediatePropagation()
;
event.currentTarget
,目前所綁定的事件;
event.target
。
自定義事件:
var eve = new Event('custome');
ev.addEventListener('custome',function(){
console.log('custome');
});
ev.dispatchEvent(eve);
window.addEvenListener('click', function(){}, true);// 捕獲階段觸發
子產品四:
HTTP協定:
- HTTP協定的主要特點
- HTTP封包的組成部分
- HTTP方法
- POST和GET的差別
- HTTP狀态碼
- 什麼是持久連接配接
- 什麼是管線化
HTTP封包的組成部分
請求封包:請求行,請求頭,空行,請求體;響應封包:狀态行,響應頭,空行,響應體。請求行包含:http方法,頁面位址,http協定以及版本;請求頭包含:key-value值,告訴伺服器端我要什麼内容。
HTTP協定類的主要特點:簡單快速,靈活,無連接配接,無狀态。
HTTP協定類,HTTP方法:GET,擷取資源,POST,傳輸資源,PUT,更新資源,DELETE,删除資源,HEAD,獲得封包首部。
HTTP協定類:POST和GET的差別:1.GET在浏覽器回退時是無害的,而POST會再次送出請求;2.GET産生的URL位址可以被收藏,而POST不可以;3.GET請求會被浏覽器主動緩存,而POST不會,除非手動設定;4.GET請求隻能進行url編碼,而POST支援多種編碼方式;5.GET請求參數會被完整保留在浏覽器曆史記錄裡,而POST中的參數不會保留;6.GET請求在URL中傳送的參數是有長度限制的,而POST是沒有限制的;7.對參數的資料類型,GET隻接受ASCII字元,而POST沒有限制;8.GET比POST更不安全,因為參數直接暴露在URL中,是以不是用來傳遞敏感資訊的;9.GET參數通過URL傳遞的,POST放在Request body中。
HTTP
狀态碼:
-
:訓示資訊,表示請求已接收,繼續處理;1xx
-
:成功,表示請求已被成功接收;2xx
-
:重定向,要完成請求必須進行更進一步的操作;3xx
-
:用戶端錯誤,請求有文法錯誤或請求無法實作;4xx
-
:伺服器錯誤,伺服器未能實作合法的請求。5xx
-
ok: 用戶端請求成功200
-
: 客戶發送了一個帶有Range頭的GET請求,伺服器完成了它206 Partial Content
-
: 所請求的頁面已經轉移至新的url301 Moved Permanently
-
: 所有請求的頁面已經臨時轉移至新的url302 Found
-
:用戶端有緩沖的文檔并發出了一個條件性的請求 伺服器告訴客戶,原來緩沖的文檔還可以繼續使用304 Not Modified
-
用戶端請求有文法錯誤,不能被伺服器所了解400
-
請求未經授權,這個狀态碼必須和401
報頭域一起使用www-Authenticate
-
對被請求頁面的通路被禁止403
-
請求資源不存在404
-
伺服器發送不可預期的錯誤,原來緩沖的文檔還可以繼續使用505
-
請求未完成,伺服器臨時過載或當機,一段時間後可能恢複正常503
持久連接配接:HTTP1.1版本 1.0不支援
HTTP協定采用“請求-應答”模式,當使用普通模式,即非
keep-alive
模式時,每個請求/應答 客戶和伺服器都要新鍵一個連接配接,完成之後立即斷開連接配接(HTTP協定為無連接配接的協定)。
當使用
keep-alive
模式(又稱為持久連接配接,連接配接重用)時,
keep-alive
功能使用戶端到伺服器端的連接配接有效,當出現對伺服器的後繼請求時,
keep-alive
功能避免了建立或重建立立連接配接。
管線化:
- 在使用非持久連接配接的情況下,某個連接配接上消息的傳遞類似于請求1-響應1
- 使用持久連接配接情況下:請求1-請求2-響應1-響應2
管線化:
- 管線化機制通過持久連接配接完成,僅僅HTTP1.1支援此技術
- 隻有GET和HEAD請求可以進行管線化,而post則有限制
- 初次建立連接配接時不應啟動管線機制,因為對方(伺服器)不一定支援HTTP/1.1 版本的協定
- 管線化不影響響應到來的順序,響應傳回的順序并未改變
- HTTP/1.1要求伺服器支援管線化,但并不要求服務端也對響應進行管理化處理,隻要求對于管線化的請求不失敗即可
- 由于上面提到的伺服器端問題,開啟管線化很可能并不會帶來大幅度的性能提升,而且很多伺服器端和代理程式對管線化的支援并不好,是以現代浏覽器如Chrome和FireFox預設并未開啟管線化支援
原型鍊類:建立對象幾種方法,原型,構造函數,執行個體,原型鍊,instanceof的原理。
建立對象的幾種方法:
// 字面量
var o1 = {name:'o1'};
var o2 = new Object({name:'01'});
// 通過構造函數
var m = function(){this.name='01'}
var m1 = new m();
// Object.create
var p = {name:'o3'};
var o3 = Object.create(p);
原型鍊:
構造函數,new,執行個體,構造函數-prototype-原型對象-
__proto__
原型對象,原型對象
constructor
構造函數,執行個體
__proto__
到原型對象。
原型鍊類:執行個體對象
proto
-
instanceof - prototype
- 原型,執行個體對象 -
constructor
- 構造函數。
子產品四:
new 運算符:
- 一個新對象被建立,它繼承自
。foo.protoype
- 構造函數foo被執行,執行的時候,相應的傳參會被傳入,同時上下文(
)會被指定為這個新執行個體,this
,隻能用在不傳遞任何參數的情況。new foo等同于new.foo()
- 如果構造函數傳回了一個“對象”,那麼這個對象會取代整個new出來的結果。如果構造函數沒有傳回對象,那麼new出來的結果為步驟1建立的對象。
類與執行個體:類的聲明;生成執行個體。
類與繼承:如何實作繼承;繼承的幾種方式。
類的聲明:
function Animal() {
this.name = 'name';
}
// es6 class
class Animal2 {
constructor() {
this.name = name;
}
}
繼承的本質原型鍊:
- 借助構造函數實作繼承
function Parent1() {
this.name = 'parent';
}
function Child() {
Parent.call(this);
this.type = 'child';
}
缺點是擷取不到父類構造函數prototype上的方法。
- 借助原型鍊實作繼承
function Parent2() {
this.name = 'parent2';
}
function Child2() {
this.type = 'child2';
}
child2.prototype=new Parent2();
原型鍊繼承方式的缺點:原型鍊中的原型對象,引用同一個對象,就是父類的執行個體對象。
第三種繼承方式:組合方式
function Parent3() {
this.name = 'parent3';
this.play = [1,2,3];
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child4();
s3.play.push(4);
解決1,2不足,缺點就是父級的構造函數執行了兩次。
第四種方式:結合繼承的優化,繼承父類的原型對象(原型式)
function Parent4() {
this.name = 'parent4';
this.play = [1,2,3];
}
function Child4() {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype
// 資料類型:應用類型和值類型
// constructor指向
第5,組合繼承方式
function Parent5() {
this.name = 'parent5';
this.play = [1,2,3];
}
function Child5() {
Parent5.call(this);
this.play = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype); // __proto__
Child5.prototype.constructor = Child5;
// 構造函數指向Child5
- DNS:
。根DNS,頂級DNS,權威DNS,本地DNS,負載均衡
- 下層協定:可靠資料傳輸,四層與七層,
。TCP/IP,UNIX Domain Socket
- 代理:正向代理,反向代理,Proxy協定。
-
:協定名,查詢參數,編碼。URI/URL
-
:全雙工,二進制幀,有狀态。webSocket
- 編碼:
Base64,chunked,壓縮(gzip,deflate)
- 抓包工具:
Wireshark,tcpdump
- HTTP/3:基于
UDP,QUIC,gRPC
- HTTP/2:
HPACK,Server Push,SPDY
- HTTPS:對稱加密(
),非對稱加密(AES,ChaCha
),摘要算法(RSA,DH
),證書(SHA-2
),X509,CA
(SNI,OCSP,連接配接優化)。SSL/TLS
-
(負載均衡,就近通路,CDN
Squid/Varaish/ATS
-
:應用層防護,通路控制,審計WAF
TCP
三次握手,
SYN,SYN.ACK,ACK
;
TCP
四次握手關閉連接配接:
FIN,ACK/FIN,ACK
子產品五:
- 什麼是同源政策以及限制
- 前後端如何通信
- 如何建立Ajax
- 跨域通信的幾種方式
什麼是同源政策以及限制
同源政策限制從一個源加載的文檔或腳本如何與另一個源的資源進行互動。這是一個用于隔離潛在惡意檔案的關鍵的安全機制。
- Cookie, LocalStorage, IndexDB無法讀取
- DOM無法擷取
- AJAX請求不能發送
AJAX是同源下面的通信方式,WebSocket不限制同源政策,CORS支援跨源通信,也支援同源通信。
如何建立Ajax
-
對象的工作流程XMLHttpRequest
- 相容性處理
- 事件的觸發條件
- 事件的觸發順序
-
Object.prototype.toString.call()
var util = {};
util.indexOf = function(array, item) {
for(var i=0; i<array.length; i++) {
if(array[i] === item) {
return i;
}
}
return -1;
};
// 判斷是否為函數
util.isFunction = function(source) {
return '[Object Function]` === Object.prototype.toString.call(source)
}
// 判斷是不是ie
util.isIE = function() {
var myNav = navigator.userAgent.toLowerCase();
return (myNav.indexOf('msie') !== -1) ? parseInt(myNav.split('mise')[1]) : false;
};
模拟
ajax
的功能:
util.json = function(options) {
var opt = {
utl: '',
type: 'get',
data: {},
success: function() {}
error: function() {}
};
util.extend(opt, options);
if(opt.url) {
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
var data = opt.data, url = opt.url,
type = opt.type.toUpperCase(), dataArr=[];
for(var k in data) {
dataArr.push(K+'='+data[k]);
}
if(type === 'GET') {
url = url + '?' + dataArr.join('&');
xhr.open(type, url.replace(/\?$/g, ''), true);
xhr.send();
}
if(type === 'POST'){
xhr.open(type, url, true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(dataArr.join('&'));
}
xhr.onload = function() {
if(xhr.status === 200 || xhr.status === 304) {
var res;
if(opt.success && opt.success instanceof Function) {
res = xhr.responseText;
if(typeof res === 'string') {
res = JSON.parse(res);
opt.success.call(xhr.res);
}
}
}else{
if(opt.error && opt.error instanceof Function) {
opt.error.call(xhr.res);
}
}
跨域通信的幾種方式:
-
JSONP
-
Hash
-
PostMessage
-
WebSocket
-
CORS
jsonp
的原理:
util.jsonp = function(url, onsuccess, onerror, charset) {
var callbackName = util.getName('tt_player');
window[callbackName] = function() {
if(onSuccess && utils.isFunction(onSuccess)) {
onSuccess(arguments[0]);
}
};
var script = util.creatScript(url+'&callback='+callbaseName,charset);
script.onload = script.onreadystatechange = function() {
if(!script.readyState || /loader|complete/.test(script.readyState)){
script.onload = script.onreadystatechange = null;
// 移除該script的DOM對象
if(script.parentNode){
script.parentNode.removeChild(script);
}
// 删除函數或變量
window[callbackName] = null;
}
};
script.onerror = function() {
if(onerror && util.isFunction(onerror)) {
onerror();
}
};
// script标簽的異步加載來實作的
<script src="http://xxx.com/?data = name & callback = 'jsonp'charset = 'utf-8'></script>
<script>
jsonp({data:{}})
</script>
使用
webSocket
不受同源政策限制:
var ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = function(evt) {
console.log('');
ws.send('');
};
ws.onmessage = function(evt) {
console.log('');
ws.close();
};
ws.onclose = function(evt) {
console.log('');
};
子產品五:
csrf, xss
-CSRF:通常稱為跨站請求僞造
Cross-site-request forgery
縮寫CSRF,攻擊原理,防禦措施。
CSRF
防禦措施:1.
token
驗證;2.
Referer
驗證;3.隐藏令牌
CSRF
攻擊原理:依賴使用者點選登入,下發cookie,引誘點選,通路,指向的是網站A的api接口,特别是get類型。加token驗證,注冊成功以後,沒有手動上傳token,沒有帶token就避免了攻擊;
Referer
驗證,指頁面來源,是否來自我這個站點下的頁面,是的話執行動作,不是就攔截。
XSS
-
Cross-site scripting
跨域腳本攻擊:
XSS
原理,向頁面注入腳本,防禦措施,讓腳本不能執行
XSS和CSRF差別
-
是向你頁面注入XSS
去執行,然後JS函數體裡做它想做的事情JS
-
是利用你本身的漏洞去幫助你主動執行那些接口,CSRF依賴于你這個使用者要登入網站CSRF
算法:堆,棧,隊列,連結清單;JS的數組本身就具備堆,棧,隊列的特性,
push, pop, shift, unshift
堆棧:先進後出,先進先出,
unshift進,pop出.
渲染機制
- 什麼是
及作用DOCTYPE
- 浏覽器渲染過程
- 重排
Reflow
- 重繪
Repaint
- 布局
Layout
DTD
(
document type definition
,文檔類型定義)是一系列的文法規則,用來定義XML或(X)HTML的檔案類型。浏覽器會使用它來判斷文檔類型,決定使用何種協定來解析,以及切換浏覽模式。
DOCTYPE
是用來聲明文檔類型和DTD規範的,一個主要的用途便是檔案的合法性驗證,如果檔案代碼不合法,那麼浏覽器解析時便會出一些差錯。
浏覽器的渲染過程
HTML,HTML Parser,DOM Tree(DOM) (Style sheets-> CSS Parser-> Style Rules)->Attachment->Render Tree(Layout)->Painting->Display
Reflow
重排
定義:DOM結構種的各個元素都有自己的盒子(模型),這些都需要浏覽器根據各種樣式來計算并根據計算結果将元素放到它該出現的位置,這個過程稱為reflow。
觸發reflow:
- 當你增加,删除,修改DOM節點時,會導緻Reflow或Repaint。
- 當你移動DOM的位置,或是搞個動畫的時候
- 當你修改css樣式的時候
- 當你Resize視窗的時候(移動端沒有這個問題),或是滾動的時候
- 當你修改網頁的預設字型時
重繪Repaint
當各種盒子的位置,大小以及其他屬性,例如顔色,字型大小等會确定下來後,浏覽器于是把這些元素都各自的特性繪制了一遍,于是頁面的内容出現了,這個過程稱為repaint。
運作機制:JS的單線程,一個時間之内,JS隻能幹一件事;EventLoop事件循環。
任務隊列:同步任務,異步任務。
頁面性能
提升頁面性能的方法:
- 資源壓縮合并,減少HTTP請求
- 非核心代碼異步加載,異步加載的方式,
- 利用浏覽器緩存
- 使用CDN
- 預解析DNS
<meta http-equiv='x-dns-prefetch-control` content='on'>
<link rel = 'dns-prefetch' href="//host_name_to_prefetch.com'>
CDN-讓網絡快速達到服務端,把檔案下載下傳下來,尤其是當頁面第一次打開的時候,浏覽器緩存是起不到任何作用的,那麼使用CDN是非常明顯的。
預解析DNS,如果你的頁面使用多個域名的時候,你的DNS解析是非常明顯的。
- 頁面中的所有
标簽,在一些進階浏覽器裡面是預設打開a
預解析的,也就是說你不用加DNS
等這句話,也可以使用meta
預解析的,但是如果你的頁面是DNS
協定開頭的,很多浏覽器預設是關閉https
預解析的,需要強制打開DNS
預解析。DNS
- 非核心代碼異步加載
- 利用浏覽器緩存
異步加載的方式:動态腳本加載;
defer;async
異步加載的差別:
-
是在defer
解析完之後才會執行,如果是多個,按照加載的順序依次執行。HTML
-
是在加載完之後立即執行,如果是多個,執行順序和加載順序無關。async
子產品六:
浏覽器緩存:
緩存的分類:強緩存/協商緩存
// 強緩存
Expires thXXX
Cache-Control: max-age
// 協商緩存
Last-Modified/If-Modified-Since
Etag/If-None-Match
緩存,浏覽器緩存說的就是你個資源檔案在浏覽器中存在的這個備份,或說是副本。
強緩存就是我問都不問不直接請求,直接拿過來就用了;協商緩存就是浏覽器發現我本地有這個副本,但我又不确定用不用它,向伺服器問一下,我這個檔案要不要用,也就是協商和伺服器協商一下,我這個能不能用,它是不是過期了,這個過程叫協商緩存。
強緩存:
Expires
:過期時間,值表示絕對時間;
Cache-Control:Cache-Control:max-age=3600
相對時間。
協商緩存:
Last-Modified
上次修改的時間,
If-Modified-Since
請求的時候我給伺服器帶的,
Etag
解決:伺服器下方的資源會給你
Etag
值,
If-None-Match
。
1.0 缺點:雖然我的時間變了,但是我的内容沒有發生變化,内容沒有發生變化,我完全可以從副本中拿。
1.1 過了強緩存的時間,浏覽器再去向伺服器請求,問它,這個資源我可不可以再用的時候,它會通過
If-None-Match
,
http
中會加一個這個
If-None-Match
key值,然後會加一個
value
,這個
value
就是伺服器下方的
Etag
值。
緩存是為了提高頁面性能優化的.
了解錯誤監控類:前端錯誤的分類,錯誤的捕獲方式,上報錯誤的基本原理。前端錯誤的分類:即時運作錯誤,代碼錯誤,資源加載錯誤。即時運作錯誤的捕獲方式:
try...catch...
,
window.onerror
資源加載錯誤:
object.onerror
,
performance.getEntries()
,
Error
事件
上報錯誤的基本原理:1. 采用ajax通信的方式上報;2. 利用Image對象上報。
- 業務能力
- 思考能力
- 學習能力
- 付出
子產品七:
Vuex是一個專為Vue服務,用于管理頁面的資料狀态,提供統一資料操作的生态系統。它集中于MVC模式中的Model層,規定所有的資料操作必須通過
action-mutation-state
,change的流程來進行,再結合
Vue
的資料視圖雙向綁定特性來實作頁面的展示更新。
統一的頁面狀态管理以及操作處理,可以讓複雜的元件互動變得簡單清晰,同時可在調試模式下進行時光機般的倒退前進操作,檢視資料改變過程,使
code debug
更加友善。
Vue Components
-
Dispath
-
Actions
-
commit
-
Mutations
-
Mutate
-
State
-
Render
。
- Vue Components,Vue元件,HTML頁面上,負責接收使用者操作等互動行動,執行dispath方法觸發對應action進行回應。
- dispath,操作行為觸發方法,是唯一能執行action的方法。
- actions,操作行為處理方法,負責處理Vue Components接收到的所有互動行為,包含同步/異步操作,支援多個同名方法,按照注冊的順序依次觸發。向背景API請求的操作就在這個子產品中進行,包括觸發其他action以及送出mutation操作。該子產品提供了Promise的封裝,以支援action的鍊式觸發。
- commit,狀态改變送出操作的方法。對mutation進行送出,是唯一能執行mutation的方法。
- mutations:狀态改變操作方法,是Vuex修改state的唯一方法,其他修改方式在嚴格模式下将會報錯,該方法隻能進行同步操作,且方法名隻能全局唯一。操作之中會有一些hook暴露出來,以進行state的監控等。
- state:頁面狀态管理容器對象。集中存儲Vue Components中data對象的零散資料,全局唯一,以進行統一的狀态管理。頁面顯示所需的資料從該對象中進行讀取,利用Vue的細粒度資料響應機制來進行高效的狀态更新。
- getters:state對象讀取方法。被包含中render中,Vue Components通過該方法讀取全局state對象。
生命周期流程圖
new Vue
建立
Vue
執行個體,初始化(事件&生命周期),
beforeCreate
,初始化(注入&校驗),
created
,是否指定'el'選項?是,是否指定'template'選項,是(将template編譯到render函數中),否(将el外部的HTML作為template編譯);
beforeMount
,建立
vm.$el
,并用替換el,
mounted
,挂載完畢。(當data被修改時,
beforeUpdate
,虛拟
DOM
重新渲染并應用更新,
updated
),當調用
vm.$destory
函數時,
beforeDestory
,解除綁定銷毀子元件以及事件監聽器,
destoryed
。
生命周期建立前後,挂載前/後,更新前/後,銷毀前/後。
-
,在beforeCreate
生命周期執行時,beforeCreate
和data
中的資料還未初始化,是以此時不能使用methods
中的資料和data
中的方法。methods
-
,created
和data
初始化完畢,此時可以使用methods
中的方法和methods
中的資料。data
-
,beforeMount
模闆已經編譯好,但還未挂載到頁面,此時頁面還是上一個狀态。template
-
,此時Vue執行個體初始化完成了,DOM挂載完畢,可以直接操作dom或者使用第三方dom庫。mounted
-
,此時data已更新,但還未同步頁面。beforeUpdate
-
,updated
和頁面都已經更新完成。data
-
,Vue執行個體進入銷毀階段,但所有的data和methods,指令,過濾器等都處于可用狀态。beforeDestory
-
,此時元件已經被銷毀,data,methods等都不可用。destoryed
v-cloak主要是用來避免頁面加載時出現閃爍的問題,可以結合CSS的
[v-cloak]{display:none}
方式解決這一問題。
元件之間,父子之間的通信方案:
- 通過事件總線bus,即通過釋出訂閱方式
- vuex
- 父元件通過prop向元件傳輸資料
- 子元件綁定自定義事件,通過
來調用自定義事件this.$emit(event.params)
- 使用vue提供的
&parent children
方法來通信refs
元件的按需加載是項目優化的一個環節,也可以降低首屏渲染時間;使用
()=>import()
;使用
resolve=>require(['./componentA'], resolve)
keep-alive
是
Vue
的内置元件,能在元件切換過程中将狀态保留在記憶體中,防止重複渲染DOM。
chunk
是
webpack
打包過程中的
Modules
的集合,是打包過程中的概念。
JSONP:ajax請求受同源政策影響,不允許進行跨域請求,而script标簽src屬性中的連結卻可以通路跨域的Js腳本,利用這個特性,服務端不再傳回JSON格式的資料,而是傳回一段調用某個函數的js代碼,在src中進行進行了調用,這樣實作了跨域。
斐波那契數列:
function f(n) {
if(n===0){
return 0;
}else if(n===1){
return 1;
}else{
var fn1 = 0;
var fn2 = 1;
var fnx = 0;
for(var i = 0; i< n-1; i++) {
var newFn = fn2;
fnx = fn1+fn2;
fn1 = fn2;
fn2 = fnx;
}
return fnx;
}
}
遞歸算法:
function fib(count) {
var count = parseInt(count);
if(isNaN(count) || count<=0) {
return 0;
}
function f(count) {
if(count<=2) {
return 1;
}
return f(count-1)+f(count-2);
}
return f(count);
}
求前20個數字:
var arr = [];
arr[1] = 1;
arr[2] = 2;
for(var i = 3; i<20; i++) {
arr[i] = arr[i-1] + arr[i-2];
}
for(var i = 1; i<arr.length; i++) {
console.log(arr[i]);
}
子產品八:
Vue實作資料雙向綁定的:
實作了一個監聽器Observer,對資料對象進行周遊,包括了屬性對象,利用
Object.defineProperty()
屬性都加上
setter
和
getter
。這樣的話,給這個對象的某個值指派,就會觸發
setter
,那麼就監聽到了資料變化。
實作了一個解析器Compile,解析Vue模闆指令,将模闆中的周遊都替換成資料,然後初始化渲染頁面視圖,并将每個指令對應的節點綁定更新函數,添加監聽資料的訂閱者,一旦資料有變動,收到通知,調用更新函數進行資料更新。
實作一個訂閱者Watcher:Watch訂閱者是Observer和Compile之間通信的橋梁,主要的任務是訂閱Observer中的屬性值變化的消息,當收到屬性值變化的消息時,觸發解析器Compile中的對應的更新函數。
實作一個訂閱器Dep,訂閱器采用釋出-訂閱設計模式,用來收集訂閱者Watcher,對監聽器Observer和訂閱者watcher進行統一管理。
算法
- 棧,後進先出,
push,pop
- 隊列,先進先出,
push,shift
- 連結清單,結點,對元素的記憶體位址一無所知(每一個結點的結構都包括了兩部分的内容,資料域和指針域)
示例:
{
// 資料域
val: 1,
// 指針域,指向下一個結點
next: {
val: 2,
next:。。。
}
}
// 連結清單
function ListNode(val) {
this.val = val;
this.next = null;
}
- 二叉樹:根結點,子結點,葉子結點;葉子結點高度未1,等樹的高度;度表示一個結點開叉出去多少個子樹,被記為結點的度;度為0,表示為葉子結點。
- 二叉樹結構:1,它可以沒有根結點作為一顆空樹存在;2,如果它不是空樹,那麼必須由根結點,左子樹和右子樹組成且左右子樹度是二叉樹。3.二叉樹不能被簡單定義為每個結點的度度是2的樹。
二叉樹:在JS中,二叉樹使用對象來定義,它的結構分為三塊:
- 資料域
- 左側子結點的引用
- 右側子結點的引用
二叉樹結點的構造函數:
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
// 建立一個二叉樹結點時
const node = new TreeNode(1);
二叉樹周遊:1.先序周遊,2.中序周遊,3.後序周遊,4.層次周遊(按照順序規則不同)
按照實作方式不同:遞歸周遊;疊代周遊(先中後序周遊,層次周遊)
建立一個由資料域,左右子樹組成的結點,每一顆二叉樹度應該由這三部分組成。
遞歸函數(遞歸式,遞歸邊界)
// 先序周遊的周遊實作
// 所有周遊函數的入參都是根據結點對象
function preorder(root) {
// 遞歸邊界,root為空
if(!root) {
return
}
// 輸出目前周遊的結點值
console.log('目前周遊的結點值' + root.val);
// 遞歸周遊左子樹:
preorder(root.left);
// 遞歸周遊右子樹:
preorder(root.right);
}
// 中序周遊,左子樹,根結點,右子樹
function inorder(root) {
if(!root) {
return
}
// 遞歸周遊左子樹
inorder(root.left);
// 輸出目前周遊的結點值
console.log('目前周遊的結點是', root.val);
// 遞歸周遊右子樹
inorder(root.right);
}
// 後序周遊:左子樹,右子樹,根結點
function postorder(root) {
if(!root) {
return
}
// 遞歸周遊左子樹
postorder(root.left)
// 遞歸周遊右子樹
postorder(root.right)
// 輸出目前周遊的結點值
console.log('目前周遊的結點值是:'+root.val)
}
時間複雜度/空間複雜度
- 時間:算法對應的執行總次數的一個變化趨勢
- 空間:記憶體增長的趨勢
求兩數求和問題
const twoSum = function(nums, target) {
// 這裡我用對象來模拟map的能力
const diffs = {}
// 緩存數組的長度
const len = nums.length
// 周遊數組
for(let i = 0; i<len; i++) {
// 判斷目前對應的target內插補點是否存在
if(diffs[target-nums[i]] !== undefined) {
// 若有對應內插補點,那麼答案get
return [diffs[target-nums[i]], i]
}
// 若沒有對應內插補點,則記錄目前值
diffs[nums[i]=i
}
}
合并兩個有序數組:
const merge = function(nums1, m, nums2, n) {
// 初始化兩個指針的指向,初始化num1尾部索引k
let i = m-1, j = n-1, k = m+n-1;
// 當兩個數組都沒周遊完時,指針同步移動
while(i>=0 && j>=0) {
// 取較大的值,從末尾往前填補
if(nums1[i] >= nums2[j]){
num1[k] = nums1[i]
i--;
k--;
}else{
num1[k] = nums2[j]
j--;
k--;
}
}
// nums2留下的情況,特殊處理一下
while(j>=0){
nums1[k] = num2[j];
j--;
k--;
}
};
字元串:反轉字元串:
const str = 'huang';
// 定義反轉後的字元串
const res = str.split('').reverse().join('');
console.log(res);
回文字元串:正着讀和倒着讀都一樣
function isPalindrome(str) {
// 先反轉字元串
const reversedstr = str.split('').reverse().join('');
return reversedstr === str
}
具有對稱性:
function isPalindrome(str){
// 緩存字元串的長度
const len = str.length
// 周遊前半部分,判斷和後半部分是否對稱
for(let i = 0; i<len/2; i++) {
if(str[i] !== str[len-i-1]){
return false
}
}
return true
}
連結清單的合并:
const mergeTwoLists = function(l1,l2) {
// 定義結點,確定連結清單可以被通路到
let head = new ListNode()
let cur = head; // cur這裡就是咱們那根“針”
while(l1&&l2) {
// 如果l1的結點值較小
if(l1.val <= l2.val) {
// 先串起來l1的結點
cur.next = l1
// l1指針向前一步
l1 = l1.next
}else{
// l2較小時,串起l2的結點
cur.next = l2
// l2指針向前一步
l2 = l2.next
}
// "針"在串起一個結點後,也會往前一步
cur = cur.next
}
// 處理連結清單不等長的情況
cur.next = l1 !== null ? l1 : l2
// 傳回起始點
return head.next
}
單例模式
class SingleDog{
show() {
console.log('我是單例對象')
}
static getInstance() {
// 判斷是否已經new過這個執行個體
if(!SingleDog.instance) {
SingleDog.instance = new SingleDog()
}
return SingleDog.instance
}
}
閉包:
SingleDog.getInstance = (function() {
// 定義自有變量instance
let instance = null
return function() {
// 判斷自由變量是否為null
if(!instance) {
instance = new SingleDog()
}
return instance
}
})()
Vue原理:
- 元件化和MVVM資料驅動視圖
- 響應式原理
- vdom和diff算法
- 模闆編譯/更新
- 元件渲染過程
- 前端路由
路由模式:
hash/history;
路由配置:動态路由/懶加載
元件渲染過程:1. 初次渲染過程,2.更新過程,3.異步渲染過程。
解析模闆為render函數(或開發環境vue-loader),觸發響應式監聽data屬性,getter和setter,執行render函數生成vnode,path(elem, newNode);修改data,觸發setter,更新執行render函數生成newNode;
$nextTick
,彙總data的修改,一次性更新視圖,減少DOM操作次數,提高性能。
路由模式:hash變化會觸發網頁跳轉即浏覽器的前進後退,hash變化不會重新整理頁面,SPA必需的特點:hash永遠不會送出到server端。
history原理表現:用url規範的路由,但跳轉時,重新整理頁面,
history.pushState
,
window.onpopstate
元件化:元件化曆史,資料驅動視圖,MVVM。響應式:
Object.defineProperty
,監聽對象(深度),監聽數組,
Object.defineProperty
的缺點,
Vue.set, Vue.delete
,原生數組。
vdom和diff
:
Vnode
結構,
Snabbdom
度。模闆編譯:
with
文法,模闆編譯為
render
函數,執行
render
函數生成
vnode
。
Vue
元件如何通訊:父子元件
props
和
this.$emit
,自定義事件
event.$on/event.$off/event.$emit/Vuex
。
雙向資料綁定
v-model
的實作原理:
-
元素的input
value=this.name
- 綁定
事件:input
this.name = $event.target.value
-
更新觸發:date
re-render
computed
的特點:緩存,data不變,提高性能。何時使用異步元件:加載大元件,異步加載。何時使用
deforeDestory
,解綁自定義事件:
event.$off
,清除定時器,解綁自定義事件。
vue
優化:
- 合理使用
和v-show
v-if
- 合理使用
computed
-
時加v-for
,以避免和key
同時使用(v-if
優先級更高一些,每次v-for
都需要使用v-for
,這些性能是一種消耗。)v-if
- 自定義事件,
事件及時銷毀DOM
- 合理使用異步元件,合理使用
,keep-alive
層級不要太深data
- 使用
,在開發環境做編譯(預編譯),前端通用的性能優化,如圖檔懶加載,使用SSR。vue-loader
什麼是并發/并行
- 并發是指一個處理器同時處理多個任務。
- 并行是指多個處理器或者是多核處理器同時處理多個不同的任務。
- 并發是邏輯上的同時發生,并行是實體上的同時發生。
- 并發是一個人同時吃三個饅頭,而并行是三個人同時吃三個饅頭。
垃圾回收:1,引用計數垃圾收集;2,标記-清除。
找出資料中重複的元素:
function fun(arr) {
var a = arr.sort();
var result = [];
for(var i = 0; i < arr.length; i++) {
if(arr[i] === arr[i+1] && result.indexOf(arr[i]) == -1) {
result.push(arr[i]);
}
}
return result;
}
new
操作:
var obj = new Da();
var obj = {};
obj.__proto__ = Da.prototype;
Da.call(obj);
深入淺出防抖函數
debounce
,實作原理:
防抖函數
debounce
指的是某個函數在某段時間内,無論觸發了多少次回調,都隻執行一次。假如我們設定了一個等待時間3秒的函數,在這個3秒内如果遇到函數調用請求就重新計時3秒,直到新的3秒内沒有函數調用請求,此時執行函數,不然就以此類推重新計時。
實作原理就是利用定時器,函數第一次執行時設定一個定時器,之後調用時發現已經設定過定時器就清空之前的定時器,并重新設定一個新的定時器,如果存在沒有被清空的定時器,當定時器計時結束後觸發函數執行。
判斷:
-
instanceOf
-
Constructor
-
Object.prototype.toString.call()
繼承我總結了:有1,原型鍊繼承,2,借用構造函數繼承,3,組合繼承,4,原型式繼承,5,寄生式繼承,6,寄生組合式繼承。es6中新增的class和extends文法,用來定義類和實作繼承,底層采用了寄生組合式繼承。
this
的指向問題:
- 屬性事件的this,在标簽内調用事件函數,誰調用this所在的函數,那麼this就指向誰
- 直接在fn函數中寫this(如果直接在fn函數中寫this,那麼this為将根據其上下文來決定,一般指向window
-
事件中的thisonclick
周遊:
-
Object.keys(obj)
-
Object.values(obj)
你懂得越多,考慮的就越全面。
❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創作更好的文章