# Is it bad to use global variables in JavaScript? 原問題: Why is it, in general, a good idea to leave the global scope of a website as-is and never touch it? 將變數宣告在全域中,為什麼不是個好習慣? --- #### 作用域的概念 區域變數:在函式內宣告的變數為區域變數,此變數只能在其所處的函式內被使用。 全域變數:在最外圍宣告的的變數,不在任何函式內,則為全域變數,任何人都可以使用。 ### 為什麼要避免宣告成全域? - 即便是在一個html內引入不同的 js 檔,他們仍使用同個全域的命名空間 - 不同於區域變數,任何地方都有權利修改全域變數,所以出問題時很難去找出是因為哪個環節修改到。 - 容易遇到命名衝突,會覆蓋或者報錯 - 在函式內未宣告的變數,會直接成為全域變數 ```javascript= function badlyScoped() { globalVariable = "I'm a global variable"; } badlyScoped(); console.log(globalVariable); // "I'm a global variable" ``` ### 怎麼調整? 我們最初學習JS時,通常都是寫在 global ```javascript= var current = null; function init(){...} function change(){...} function verify(){...} ``` 可以包裝起來 ```javascript= var myNameSpace = { current:null, init:function(){...}, change:function(){...}, verify:function(){...} } ``` #### 其實這就能應用在當初老師帶過的 MVC 觀念 最初寫法 ```javascript= let data = null; // model 詳細作法 function getProductData(){ fetch.... data=result; } function removeProductData(name){ } // views 最後會呈現的內容 function renderData(){ } ``` 調整過後 ```javascript= let models = { getProductData:function(){ fetch... data=result; }, removeProductData:function(name){ } } let controllers={ removeProduct:function(e){ models.removeProductData(e.currentTarget.textContent); views.renderData(); }, init:function(){ getProductData().then(()=>{ views.renderData(); } }; ``` --- #### 結合立即函式以及閉包的概念處理 一導入就會直接執行 ```javascript= (function(){ var current = 'current'; function init(){ console.log('初始化') } init() })() ``` ```javascript= var FOO = (function() { var my_var = 10; //shared variable available only inside your module function bar() { // this function not available outside your module console.log(my_var); // this function can access my_var } return { a_func: function() { console.log(my_var); // this function can access my_var }, b_func: function() { console.log(my_var); // this function can also access my_var } }; })(); ``` 如果想作為全域,可以這麼做 ```javascript= (function(){ var current = 'current'; function init(){ console.log('初始化') } init() window.current = current // *** 放進window裡 })() console.log(current) ``` 延伸問題思考: 在React中,我們可以在不同組件中取相同名字的變數,都可以成功吃到 編譯的幫助還是React本身的機制? 參考文章 https://www.w3.org/wiki/JavaScript_best_practices#Avoid_globals https://lucybain.com/blog/2014/js-dont-touch-global-scope/ https://medium.com/@nupoor_neha/javascript-front-end-interview-questions-1cbc5e32792b https://stackoverflow.com/questions/1841916/how-to-avoid-global-variables-in-javascript https://stackoverflow.com/questions/2613310/ive-heard-global-variables-are-bad-what-alternative-solution-should-i-use http://wiki.c2.com/?GlobalVariablesAreBad (深潛探討)