寫文章不容易,點個讚唄兄弟
專一 Vue 源碼分享,文章分爲白話版和 源碼版,白話版助於理解工做原理,源碼版助於瞭解內部詳情,讓咱們一塊兒學習吧
研究基於 Vue版本 【2.5.17】
若是你以爲排版難看,請點擊 下面連接 或者 拉到 下面關注公衆號也能夠吧javascript
今天咱們解讀 methods 的源碼,其實 methods 挺簡單的,因此就不打算出白話版了,可是 methods 裏面讓我從新認識到這一個重要的知識點,是我是我,可能大家已經掌握了哈哈瀏覽器
methods 簡單到什麼程度呢,估計你用腳都能想獲得閉包
那麼如今的問題怎麼解答app
"遍歷 methods 這個對象,而後逐個複製到 實例上?"函數
沒錯,你猜對了,的確是逐個複製,簡化源碼是這麼寫的oop
function initMethods(vm, methods) { for (var key in methods) { vm[key] = methods[key] == null ? noop : bind(methods[key], vm); } }
其實 methods 的固定做用域的惟一重點就是 bind 了,bind 相信你們也都用過學習
bind 是固定函數做用域的,說實在的,以前我還真不太用 bind 這個東西,就知道能夠綁定做用域,我以爲我會 call 和 apply 就好了,如今後悔了,發現用處太大了優化
調用 bind 會 返回 綁定做用域的函數,而這個函數直接執行時,做用域就已是固定了的this
不像 call 和 apply 這種一次性綁定做用域的 妖豔賤貨不一樣,這個貨一次綁定,終身受益啊
Vue 使用了 bind 去綁定 methods 方法,顯然是爲了不有些刁民會錯誤調用而報錯,索性直接固定做用域,並且考慮到 bind 有的瀏覽器不支持
因而寫了一個兼容方法,意思大概是這樣
一、bind 函數須要傳入做用域 context 和 函數 A
二、而後 閉包保存 這個 context,返回一個新函數 B
三、B 執行的時候,使用 call 方法 直接綁定 函數A 的做用域爲 閉包保存的 context
下面是 Vue bind 兼容的源碼,我建議你們把這個方法保存下來,尤大的東西,還不瞬間保存??
function polyfillBind(fn, ctx) { function boundFn(a) { var l = arguments.length; return l ? ( l > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a) ): fn.call(ctx) } boundFn._length = fn.length; return boundFn } function nativeBind(fn, ctx) { return fn.bind(ctx) } var bind = Function.prototype.bind ? nativeBind : polyfillBind;
Vue 使用 bind 以後,對咱們有什麼好處?
咱們調用 實例的方法,再也不每次都使用 實例去調用了
這樣子,有什麼好處呢,當屢次調用方法的話,使用局部變量保存以後,直接訪問局部變量能夠減小做用域鏈的檢索
methods:{ test(){}, getName(){ // 原本是這樣,屢次使用實例調用 this.test() this.test() // 如今局部變量保存,這是優化點 var test = this.test test() test() } }
bind 綁定做用域強到沒法改變
舉栗子
function a(){ console.log(this) } var b={ name:1 } var c = a.bind(b) var d={ c:c, woqu:3434333 } c() d.c()
c 和 d.c 執行打印下面的結果
儘管使用 d 調用,做用域仍然是 b,簡直不要太強啊
講到這裏,methods 的精髓,就是 bind 了,頗有用哦,這個東西,你們務必要記住
一、methods 會逐個複製到 實例上
二、methods 方法會使用 bind 綁定實例做用域,確保做用域不被修改