js中不容小覷的var宣告
阿新 • • 發佈:2018-11-10
在學習vue相關課程中,有一次跟著老師敲程式碼,寫出瞭如下程式碼:
var Child = { template:`<div @click='handleClick'><slot></slot></div>`, methods:{ handleClick(){ this.$bus.$emit( 'change' ); }, }, mounted(){var self = this; counter = 0; this.$bus.$on( 'change',function(){ counter++; console.log( "you clicked "+counter+" times" ); } ); } };
將元件註冊到app例項後,例項化3個子元件,在點選觸發'click'的時候,列印效果如下:
點選一次執行3次可以理解,因為每個子元件都給prototype裡的$bus匯流排push了自己的事件處理函式,但理論上來講,每個元件例項化的過程中,都會呼叫自己的mounted鉤子,在鉤子裡因為閉包的存在,形成可儲存的作用域,所以,每個例項都有自己獨立的的context( 如counter ),即:應該執行3次,但counter不應該累加,應該出現3個'you clicked 1 times' 。
覺得迷糊,我自己又按照自己的理解寫了一遍程式碼,執行,結果好好的,就是上述期待效果,問題在哪呢?
將兩個檔案逐行對比後,定位到了問題:
正確的版本
出問題的版本
兩個版本之間唯一的差別是,counter變數一個用var聲明瞭,一個沒有,於是趕緊搜起...看到這麼一篇文章,其中與我的問題相關的核心描述在此:
看到此處,豁然開朗,所以不加var的變數都綁在了全域性window物件上,不會再根據mounted鉤子函式的執行單獨建立作用域了,所有child例項push到$bus裡的事件處理函式訪問的都是window.counter,所以數值累加就是正常表現了。
看來js程式碼中var的使用不容小覷,對於宣告的任何一個變數都要做到胸有成竹,是不是要綁在window上做全域性用?如果不是,一定要加var,使其在自身作用域內執行,防止汙染全域性。