JS 题:将变数宣告在全域环境是否为好习惯?

今天分享一个对经典 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


<<:  17.unity显示/隐藏物件(SetActive)

>>:  【Day2】想要在铁人赛完毕前做好的简单 App

JS 物件属性:属性的特徵 DAY68

Object.defineProperty 定义物件属性,调整属性特徵(请牢记!!) // 定义物件...

Day 25 - Rancher Fleet.yaml 档案探讨

本文将於赛後同步刊登於笔者部落格 有兴趣学习更多 Kubernetes/DevOps/Linux 相...

Day8 Function and Interface

Function func (basedMethod) funcName(parameters)(r...

[Day 9] SRE - 自动化

自动化 什麽东西可以自动化?对我而言只要可以列出SOP的事情,都可以实现自动化。 价值 一致性 当不...

NIST SP 800-88 R1媒体消毒准则(Guidelines for Media Sanitization)

NIST SP 800-88 R1引入了三种消毒方法:清除(clear),清除(Purge)和销毁(...