iT邦幫忙

2021 iThome 鐵人賽

DAY 5
0
自我挑戰組

每日一杯 JavaScript 特調系列 第 5

JS 題:將變數宣告在全域環境是否為好習慣?

  • 分享至 

  • xImage
  •  

今天分享一個對經典 JS 面試題的探討。

原本完整的問題:
Why is it, in general, a good idea to leave the global scope of a website as-is and never touch it?
將變數宣告在全域中,為什麼不是個好習慣?


作用域的概念

區域變數:在函式內宣告的變數為區域變數,此變數只能在其所處的函式內被使用。
全域變數:在最外圍宣告的的變數,不在任何函式內,則為全域變數,任何人都可以使用。

為什麼要避免宣告成全域?

  • 即便是在一個 HTML 內引入不同的 js 檔,他們仍使用同個全域的命名空間
  • 不同於區域變數,任何地方都有權利修改全域變數,所以出問題時很難去找出是因為哪個環節修改到
  • 容易遇到命名衝突,會覆蓋或者報錯
  • 在函式內未宣告的變數,會直接成為全域變數
function badlyScoped() {
   globalVariable = "I'm a global variable";
}

badlyScoped();
console.log(globalVariable); // "I'm a global variable"

怎麼調整?

我們最初學習JS時,通常都是寫在 global

var current = null;
function init(){...}
function change(){...}
function verify(){...}

可以包裝起來

var myNameSpace = {
  current:null,
  init:function(){...},
  change:function(){...},
  verify:function(){...}
}

如果懂 MVC 觀念的話,其實也是一種 MVC 設計應用

最初寫法

let data = null;

// model 詳細作法
function getProductData(){
  fetch....
  data=result;
}

function removeProductData(name){
}

// views 最後會呈現的內容
function renderData(){

}

調整過後,包進 model、view、controller 裡

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();
	}
};

結合立即函式以及閉包的概念處理

一導入就會直接執行

(function(){
  var current = 'current';
  function init(){
	console.log('初始化')
  }
  init()
})()
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
        }
    };

})();

可以用 FOO.a_func 或者 FOO.b_func 來呼叫

但如果想作為全域變數,可以重新放進 window 裡

(function(){
  var current = 'current';
  function init(){
	console.log('初始化')
  }
  init()
  
  window.current = current  // *** 放進window裡
})()

console.log(current)

參考文章
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


上一篇
undefined 、 undeclared 、 null 的區別
下一篇
作用域 Scope、作用域鏈 Scope Chain
系列文
每日一杯 JavaScript 特調7
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言