記一次懺悔的前端面試經驗(Vue 雙向綁定原理)

 2019年6月6號,爲了愛情,我離開工做了一年多的廣州來到了杭州這個互聯網城市。開始個人前端面試之旅...javascript

放下擰螺絲的扳手,開始造起了飛機...前端


面試的第一家,一開始就問 Vue 雙向綁定怎麼實現

一臉矇蔽,以前看過源碼,可是沒有深刻研究,只回答出了使用 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 之間是互相不受影響


後記

感謝觀看,第一次寫公開博客文筆很差,慚愧慚愧!

相關文章
相關標籤/搜索