在牛客網上總是看到用友的題目,因而就投遞了簡歷... 於8.27投遞簡歷,8.31參加了線上的筆試,9.18上午10點收到電話面試,9.19下午14:00視頻面試。css
9.19.14:40 更新:剛剛視頻面試完,原來是個HR面,感受仍是挺nice的HR姐(da)姐(ma),聊了十幾分鍾,問了我做爲一個廣州人對南北方生活差別有什麼見解...html
據瞭解,該面試官的部門使用React框架開發,因此問的問題也圍繞React展開的比較多,如下是面試官問的問題。前端
Vue的數據綁定依賴數據劫持Object.defineProperty()
中的getter
和setter
以及發佈訂閱模式(eventEmitter)
來監聽值的變化,從而讓virtual DOM
驅動Model層
和View層
的更新,利用v-model
這一語法糖可以輕易地實現雙向的數據綁定。這種模式被稱爲MVVM: M <=> VM <=> V
。但其實質仍是State->View->Actions
的單向數據流,只是使用了v-model
就不須要顯式地編寫從視圖層
到Model
層更新罷了。node
React則須要依賴onChange()/setState()
模式來實現數據的雙向綁定,由於它在誕生之初就是被設計成單向的數據流react
父子之間 二者均可以經過props
綁定data
或state
來進行傳值,又或者經過綁定回調函數來傳值。git
兄弟組件之間 均可以經過使用發佈訂閱模式
寫一個EventBus
來監聽值的變化。es6
跨層級:React中可使用React.context
來進行跨層級的通訊。Vue中可使用V2.2.0新增的provide/inject來實現跨層級注入數據。github
React在JSX中使用原生的JS語法來實現插值,條件渲染,循環渲染等等。web
而Vue則須要依賴指令來進行,更加容易上手可是封裝的程度更高,調試成本更大,難以定位Bug。面試
在React中組件的更新渲染是從數據發生變化的根組件開始往子組件逐層從新渲染,而組件的生命週期有shouldComponentUpdate()
函數供給開發者優化組件在不須要更新的時候返回false
而在Vue中是經過watcher
監聽到數據的變化以後經過本身的diff
算法,在virtualDom
中直接找到以最低成本更新視圖的方式。
優勢:全部狀態更新更易追蹤,源頭易追溯,更利於維護。
缺點:只能手動地編寫視圖層到數據層的更新,代碼量增多。
優勢:由框架隱式地幫我實現視圖層和數據層互相驅動更新,代碼更加簡潔。
缺點:高度封裝的「暗箱操做」增長了debug的難度,內在的數據流方向變得難以掌握。
這時我說到了在公司實習的項目中用到的redux,還說了當時爲項目引入redux的理由,而且以爲太過臃腫,好比僅僅爲了給當前頁面保存當前查看的頁碼的這一功能,使用組件之間的值傳遞就能夠替代臃腫的redux在項目裏的功能。因而便引出了面試官問了如下的問題。
能夠用 React.context 來代替redux的功能。
- 父向子傳值:使用props,父組件行爲觸發相應的function使得state的改變,props依賴當前父組件的state,子組件的props也相應的接收到傳遞來的值。
- 子向父傳值:子組件的props指向一個回調函數,子組件行爲觸發指定的props的函數,利用函數傳參傳到父組件的回調函數接收參數以接收傳值。
- 兄弟傳值:找到一個共同的子組件或者共同的父組件來藉助傳值;使用React.context來傳值;使用Redux
mount
->update
->unmount
根據生命週期順序調用的生命週期函數:
constructor()
componentWillMount()
首次渲染前調用
render()
componentDidMount()
渲染後調用
shouldComponentUpdate()
返回布爾值,接收到新的props或state的時候被調用
componentWillUpdate()
渲染前調用
render()
componentDidUpdate()
組件完成更新後調用,初始化時不調用
componentWillUnmount()
組件在DOM中被移除的時候調用
我直接從優化web前端性能的各個方法講了,包括:使用緩存,減小http請求,使用雪碧圖,減小沒必要要的DOM操做,css和js的文件壓縮... 感受都沒有回答到點子上,實際上針對react的組件有一套性能優化的方法
shouldComponentUpdate()
控制組件在沒必要要從新渲染的時候將該函數返回false
React.pureComponent
代替React.Component
此時更新渲染依賴的是淺比較,也就是檢查數據的引用地址是否發生變化。new
。arguments
,因此用擴展運算符解決。js的變量做用域有全局變量和局部變量
函數內部能夠直接讀取全局變量
函數外部沒法讀取到函數內部的局部變量,由於函數在執行完以後,函數內部的環境就被銷燬了。
若是函數內部沒有使用var
聲明一個變量則其實是聲明爲全局變量
而閉包就是可以讀取外部函數內部變量的函數,而且最終外部函數return
這個內部函數,這時就生成了閉包。
js的垃圾回收機制是根據引用計數來實現的。會自動把一個函數運行以後內部的變量給銷燬掉,而產生閉包以後其外部函數中的局部變量的引用就變成了循環引用,則不會被垃圾回收機制捕獲並銷燬,因此這就形成了內存泄漏,除非人工把該閉包函數=null
將其引用解除並內存釋放,此部分將一直留存在runtime
的內存中。
訪問一個對象的屬性,若是對象的內部不存在這個屬性則會訪問其__proto__
的屬性,若是仍是找不到就再繼續訪問它的__proto__
的屬性,知道null
爲止。
String.prototype.substr()
參數1:startIndex 參數2:length
String.prototype.substring()
參數1:startIndex 參數2:endIndex
String.prototype.slice()
參數1:startIndex 參數2:endIndex
均不改變原字符串,均返回修改後的字符串 詳情見MDN
for循環
Array.prototype.forEach((element)=>{...})
不改變原數組,無返回值
Array.prototype.map((element)=>{...})
不改變原數組,返回新數組
Array.prototype.filter((element)=>{condition})
不改變原數組,返回新數組
Array.prototype.reduce((previousValue,currentValue,currentIndex))
不改變原數組,返回最後一次執行回調函數的返回值
!important > 行內樣式 > ID > 類、僞類、屬性 > 標籤名 > 繼承 > 通配符
.catch()
來處理錯誤git diff
查看兩個分支之間的差別merge conflict
產生後經過手動比較文件中衝突的部分選擇刪除或保留衝突的代碼再從新merge並commitrebase
會更變當前分支的基線,先找到合併目標的分支與當前開發者分支的最近公共節點,而後把當前分支的新commit撤銷,並把改動保存到.git/rebase
中,並從當前分支更新到目標分支,以後再把新的commit改動內容應用到當前的分支上。merge
則會產生一個新的merge commit
。