前言
分享一下最近面試碰到的一些題目召夹,有些題目特別基礎的題目,比如箭頭函數(shù)什么作用這里就不寫了。
vue實現(xiàn)原理
最核心的方法便是通過Object.defineProperty()來實現(xiàn)對屬性的劫持,達到監(jiān)聽數(shù)據(jù)變動的目的.
- 實現(xiàn)一個數(shù)據(jù)監(jiān)聽器Observer,能夠對數(shù)據(jù)對象的所有屬性進行監(jiān)聽旷太,如有變動可拿到最新值并通知訂閱者
- 實現(xiàn)一個指令解析器Compile,對每個元素節(jié)點的指令進行掃描和解析销睁,根據(jù)指令模板替換數(shù)據(jù)供璧,以及綁定相應的更新函數(shù)
- 實現(xiàn)一個Watcher,作為連接Observer和Compile的橋梁冻记,能夠訂閱并收到每個屬性變動的通知睡毒,執(zhí)行指令綁定的相應回調(diào)函數(shù),從而更新視圖.
- mvvm入口函數(shù)冗栗,整合以上三者
defineProperty有一個缺點就是你無法繞過定義屬性這一行為演顾,es6有一個解決方法參考學習es6的proxy 和 reflect。 再分享一個Github上一個mvvm實現(xiàn):vue實現(xiàn)原理
vuex 和 redux 差異
Vuex 其實是一個針對 Vue 特化的 Flux隅居,主要是為了配合 Vue 本身的響應式機制钠至。當然吸取了一些 Redux 的特點,比如單狀態(tài)樹和便于測試和熱重載的 API胎源,但是也選擇性的放棄了一些在 Vue 的場景下并不契合的特性棉钧,比如強制的 immutability(在保證了每一次狀態(tài)變化都能追蹤的情況下強制的 immutability 帶來的收益就很有限了)、為了同構而設計得較為繁瑣的 API涕蚤、必須依賴第三方庫才能相對高效率地獲得狀態(tài)樹的局部狀態(tài)等等(相比之下 Vuex 直接用 Vue 本身的計算屬性就可以)所以 Vue + Vuex 會更簡潔宪卿,也不需要考慮性能問題,代價就是 Vuex 只能和 Vue 配合万栅。Vue + Redux 也不是不可以佑钾,但是 Redux 作為一個泛用的實現(xiàn)和 Vue 的契合度肯定不如 Vuex。
作者:尤雨溪
鏈接:https://www.zhihu.com/question/38546875/answer/76970954
來源:知乎
著作權歸作者所有烦粒。商業(yè)轉載請聯(lián)系作者獲得授權次绘,非商業(yè)轉載請注明出處。
通過proxy實現(xiàn)數(shù)據(jù)劫持
const OBSERVERS = new Set(); //定義一個集合存放監(jiān)聽函數(shù)
const observeFn = fn => OBSERVERS.add(fn); //定義一個監(jiān)聽器函數(shù)
const observeObj = obj => new Proxy(obj, {set});
function set(target, key, value, receiver) { //劫持set
const result = Reflect.set(target, key, value,receiver);
OBSERVERS.forEach(observeFn => observeFn());
return result;
}
var person = observeObj({
name: '張三',
age: 20
});
function print() {
console.log(`${person.name}, ${person.age}`)
}
function warn() {
alert(person.name)
}
observeFn(warn);
observeFn(print);
person.name = '李四';
react生命周期 & setState
組件掛載中執(zhí)行的函數(shù):
- constructor():ES6類的構造函數(shù)(為了初始化state或綁定this)
- getInitialState():ES5中初始化state。(現(xiàn)在只需要在寫在1中)
- getDefaultProps():ES5中初始化props邮偎。在ES6中使用defaultProps()方法。(可以寫在1中义黎,通過props)
- componentWillMount:組件掛載前調(diào)用禾进,只執(zhí)行一次。
- render():渲染組件廉涕,必須實現(xiàn)該方法泻云。
- componentDidMount: 組件掛載后調(diào)用,只執(zhí)行一次
組件的props或者state改變時更新函數(shù):
- componentWillReceiveProps(nextProps): 當父組件的render()方法執(zhí)行后就會觸發(fā)該方法狐蜕。初始化時不調(diào)用宠纯。
- shouldComponentUpdate(nextProps,nextState):當props改變或state改變時調(diào)用,初始化時不調(diào)用层释,返回boolean婆瓜。true表示繼續(xù)執(zhí)行render方法,fasle表示放棄本次渲染贡羔。
- render():渲染組件廉白。
組件卸載函數(shù):
- componentWillUnmount():將組件從DOM樹移出,防止內(nèi)存溢出乖寒。
setState() 用于安排一個組件的 state 對象的一次更新猴蹂。當狀態(tài)改變時,組件通過重新渲染來響應楣嘁。簡單說一下原理磅轻,調(diào)用函數(shù),react內(nèi)部會執(zhí)行一個任務逐虚,獲取當前state聋溜,執(zhí)行state更新,如果一個任務還未完成痊班,并發(fā)了很多個setstate勤婚,react會將這些set 統(tǒng)一成一個更新任務,執(zhí)行后只會進行一次dom更新涤伐。
虛擬dom原理
利用js解析html生成虛擬dom樹馒胆,大致結構如下代碼,然后利用這個虛擬dom樹生成一個真的dom樹渲染到頁面。
diff算法:在改變dom的時候凝果,會重新構造一個dom樹祝迂,用來和舊的樹相比,提取差異的部分應用到真實的dom樹上器净。
采用虛擬dom最根本的原因就是dom操作性能消耗極大型雳,缺點就是要寫一大堆構件虛擬dom的js代碼。根據(jù)項目dom操作多不多,權衡利弊合理使用虛擬dom纠俭。
var element = {
tagName: 'ul', // 節(jié)點標簽名
props: { // DOM的屬性沿量,用一個對象存儲鍵值對
id: 'list'
},
children: [ // 該節(jié)點的子節(jié)點
{tagName: 'li', props: {class: 'item'}, children: ["Item 1"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 2"]},
{tagName: 'li', props: {class: 'item'}, children: ["Item 3"]},
]
}
上面對應的HTML寫法是:
<ul id='list'>
<li class='item'>Item 1</li>
<li class='item'>Item 2</li>
<li class='item'>Item 3</li>
</ul>
移動端屏幕適配 & 觸碰事件
- 采用flexable等插件,需要了解其原理(比如動態(tài)改寫meta冤荆,html的font-size朴则,設備dpr值等)
- 使用css3 嗅探改變font-size ,適配不同dpr的font-size
觸摸屏幕發(fā)生的事件
- click: 類似pc的click钓简,但連續(xù)觸發(fā)有200ms左右的延遲
- touchstart:手指觸摸到屏幕會觸發(fā)
- touchmove:當手指在屏幕上移動時乌妒,會觸發(fā)
- touchend:當手指離開屏幕時,會觸發(fā)
- touchcancel:可由系統(tǒng)進行的觸發(fā)外邓,比如手指觸摸屏幕的時候撤蚊,突然alert了一下,或者系統(tǒng)中其他打斷了touch的行為损话,則可以 觸發(fā)該事件
express 和 koa 差異
- express采用es5的callback模式侦啸,而koa采用co框架實現(xiàn)promise回調(diào)
- koa只保留基本語法,拋棄了express內(nèi)置route席镀,static等中間件
webpack原理及優(yōu)化
原理
- 初始化參數(shù):從配置文件和 Shell 語句中讀取與合并參數(shù)匹中,得出最終的參數(shù)
- 開始編譯:用上一步得到的參數(shù)初始化 Compiler 對象,加載所有配置的插件豪诲,執(zhí)行對象的 run 方法開始執(zhí)行編譯顶捷;
- 確定入口:根據(jù)配置中的 entry 找出所有的入口文件;
- 編譯模塊:從入口文件出發(fā)屎篱,調(diào)用所有配置的 Loader 對模塊進行翻譯服赎,再找出該模塊依賴的模塊,再遞歸本步驟直到所有入口依賴的文件都經(jīng)過了本步驟的處理交播;
- 完成模塊編譯:在經(jīng)過第4步使用 Loader 翻譯完所有模塊后重虑,得到了每個模塊被翻譯后的最終內(nèi)容以及它們之間的依賴關系;
- 輸出資源:根據(jù)入口和模塊之間的依賴關系秦士,組裝成一個個包含多個模塊的 Chunk缺厉,再把每個 Chunk 轉換成一個單獨的文件加入到輸出列表,這步是可以修改輸出內(nèi)容的最后機會隧土;
- 輸出完成:在確定好輸出內(nèi)容后提针,根據(jù)配置確定輸出的路徑和文件名,把文件內(nèi)容寫入到文件系統(tǒng)曹傀。
優(yōu)化
- 利用UglifyPlugin刪除引用未使用的無用代碼辐脖,壓縮js代碼,css添加minimize參數(shù)壓縮css
- 通過commonsChunkPlugin提取公共代碼
- 通過ParallelUglifyPlugin多線程壓縮js代碼
- 縮小文件范圍皆愉,通過exclude 嗜价,inclue等配置路徑艇抠,優(yōu)化打包效率
- 通過happypack插件多線程處理loader
- 通過dllplugin接入動態(tài)鏈接庫
。久锥。家淤。webpack優(yōu)化的方法還有很多,有興趣的可以自行查閱
gulp基本原理
gulp可以認為是grunt的升級版奴拦,運用了node的流來處理文件媒鼓,大大強化了性能。通過各種 Transform Stream 來實現(xiàn)文件的處理错妖,然后再進行輸出。Transform Streams 是 NodeJS Stream 的一種疚沐,是可讀又可寫的.
babel實現(xiàn)
- babel-core:babel轉譯器本身暂氯,提供了babel的轉譯API,如babel.transform等亮蛔,用于對代碼進行轉譯痴施。像webpack的babel-loader就是調(diào)用這些API來完成轉譯過程的。
- babylon:js的詞法解析器
- babel-traverse:用于對AST(抽象語法樹究流,想了解的請自行查詢編譯原理)的遍歷辣吃,主要給plugin用
- babel-generator:根據(jù)AST生成代碼
babel的polyfill和runtime的區(qū)別:
Babel默認只轉換新的JavaScript句法(syntax),而不轉換新的API芬探,比如Set神得、Proxy、Reflect偷仿、Symbol哩簿、Promise等全局對象,以及一些定義在全局對象上的方法(比如Object.assign)都不會轉碼酝静。
舉例來說节榜,ES6在Array對象上新增了Array.from方法。Babel就不會轉碼這個方法别智。如果想讓這個方法運行宗苍,必須使用babel-polyfill,為當前環(huán)境提供一個墊片薄榛。
ssr和客戶端渲染的區(qū)別
* ssr 在服務器就把數(shù)據(jù)填充到html讳窟,返回的是完整的頁面,利于所搜索引擎seo
* 更快的內(nèi)容到達時間蛇数,特別是網(wǎng)絡較差的時候
* 服務端代碼沒有客戶端那么靈活組合
* 相比客戶端渲染挪钓,ssr有更高的服務器負載,成本增加耳舅。
垂直居中實現(xiàn)
///不知道父容器和自身高度
parentElement{
position:relative;
}
childElement{
position: absolute;
top: 50%;
transform: translateY(-50%);
}
///使用flex
parentElement{
display: flex;
align-items: center;
}
web安全
xss攻擊防御
- 對輸出的html標簽進行轉義(htmlEncode)
- 對用戶提交的數(shù)據(jù)進行驗證碌上,限制長度倚评,特殊字符過濾等
sql注入防御
- 層級化數(shù)據(jù)庫權限,不要使用管理員權限
- 對用戶輸入的信息進行數(shù)據(jù)庫查詢敏感詞的過濾馏予,限制長度等
后記
差不多就到這里了天梧。這篇文章過年前po主將會持續(xù)更新,通過面試來找自己的不足是非常高效霞丧,面試官會針對你的簡歷呢岗,你的所學,針對性的考察你蛹尝。前端路漫漫后豫,其修遠兮,慢慢走吧突那。
如果覺得本文對你有所幫助挫酿,就star一下吧~大傳送之術! 我的博客Github