2019年6月6號,爲了愛情,我離開工做了一年多的廣州來到了杭州這個互聯網城市。開始個人前端面試之旅...javascript
放下擰螺絲的扳手,開始造起了飛機...前端
一臉矇蔽,以前看過源碼,可是沒有深刻研究,只回答出了使用 Object.definePropertyvue
Object.defineProperty(obj, prop, {
// ...
get: function() {}
set: function() { // ... }
})複製代碼
要是再給我一次機會我會這樣回答java
Vue 雙向綁定,使用數據劫持和發佈訂閱模式實現的
面試
而後我再畫一個圖來描述整個實現過程是怎樣的api
vue2.0 採用的是Object.defineProperty進行數據劫持的數組
主要實現原理是使用描述對象中的set方法進行攔截,併發送訂閱器信號bash
// ...
let dep = new Dep()
return Object.defineProperty(obj, prop, {
// ...
get: function(key) {
dep.target = this
dep.addSub()
// ...
}
set: function(newVal) {
val = newVue;
// 發送一個dep信號
dep.notify()
// ...
}
})複製代碼
而vue3.0中可能會採用Proxy來實現數據劫持架構
let target = {}
let p = new Proxy(target, {
set: function() {
//...
},
get: function() {
//...
}
})
複製代碼
爲啥呢?併發
咱們知道 Object.defineProperty 是有侷限性的,他的攔截的 target 就是單純的對象的key的值
因此呢,對象屬性的刪減,數組,數組長度的改變,它就無法進行劫持了
而 ES6 的新特性,Proxy,它能夠攔截對象,數組幾乎一切對象包裝類型
可是 Proxy 無法兼容 IE,因此 Vue3.0 底層仍是採用 Object.defineProperty
而 使用 Proxy 做爲一個 api ,也就是說:
咱們不兼容IE, 就大膽用 Proxy 雙向綁定並且不會有屬性刪減和數組劫持不到的問題
咱們要兼容IE,就用原來的雙向綁定,可是要注意它的不能劫持部分變化的缺陷
從上圖咱們能夠看到,Observer 觀察了 object 值的變化,這是一種觀察者模式
而 Observer 將觀察的信號發佈給訂閱器這是一種 發佈訂閱模式
咱們先談觀察者模式
什麼是觀察者模式,首先有一個觀察者,一個被觀察者,被觀察者這裏是數據,而觀察者是Observer,被觀察者發生變化時,主動發生信號給被觀察者
按照這個思路來講,咱們也能想象尤大,當時設計雙向綁定時候,思考怎樣去監聽這個數據的變化,也就是如何使用觀察者模式來實現,而剛好對一個對象的處理中有個對象方法咱們可使用,就是 Object.defineProperty
假如沒有這個方法咱們怎麼實現呢?
這就是 angular 的另一種實現方式髒檢測,也就是不停的輪詢數據的變化狀況,顯然髒檢測對性能消耗比較大
在軟件架構中,發佈訂閱是一種消息範式,消息的發送者(稱爲發佈者)不會將消息直接發送給特定的接收者(稱爲訂閱者)。而是將發佈的消息分爲不一樣的類別,無需瞭解哪些訂閱者(若是有的話)可能存在。一樣的,訂閱者能夠表達對一個或多個類別的興趣,只接收感興趣的消息,無需瞭解哪些發佈者(若是有的話)存在。
這裏很明顯了,區別就在於,不一樣於觀察者和被觀察者,發佈者和訂閱者是互相不知道對方的存在的,發佈者只須要把消息發送到訂閱器裏面,訂閱者只管接受本身須要訂閱的內容
由此發佈訂閱模式是一種鬆耦合的關係,watcher 和 Observer 之間是互相不受影響
感謝觀看,第一次寫公開博客文筆很差,慚愧慚愧!