JS全局变量与顶层对象浅析

"全局变量与顶层对象"

Posted by Mzx on February 6, 2017

全局变量和顶层对象

什么是全局变量

JS中全局变量就是指在函数外部通过var声明的变量。如果是在nodeJS环境中则需通过global.variable显示的声明。全局变量在程序启动时便加载到内存中,直到程序结束。

问题

  • 为什么在node中通过var定义的变量不是全局变量?

    答: 因为在node中所有的代码都在当前module中。而module不是全局的。所以需要通过global声明。

	//demo1 在chrome浏览器中
	var name = 'Tom'
	console.log(window.name) // Tom
	
	//demo2 在node中
	global.name = 'Tom'
	console.log(name) // Tom

什么是顶层对象

顶层对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用顶层对象,可以访问所有其他所有预定义的对象、函数和属性。顶层对象不是任何对象的属性,所以它没有名称。顶层对象在浏览器环境中是指window,在node环境中是指global

ES5中顶层对象是全局变量的宿主。即在浏览器环境中在函数外部通过var声明的变量都是全局变量都被绑定到window上。因为全局变量的生命周期是跟随程序的。而且变量的值可以在程序的任何地方做任意修改。所以很容易造成问题。但是在ES6中变将全局变量和顶层对象解耦了。不过为了兼容之前的程序。通过var声明的全局变量还是属于顶层对象的。但是通过let、const声明的全局变量不再属于顶层对象。

	//demo3 在chrome浏览器中
	var age = 18
	console.log(window.age) //18
	let sex = '男'
	console.log(window.sex) //undefined

关于this

  • 浏览器环境中:
    • 函数外部: this === window
    • 函数内部(单纯的函数即不是对象的方法):
      • 严格模式: this === undefined
      • 非严格模式:this === window
  • node环境中:
    • 函数外部: this === 当前的module
    • 函数内部:同浏览器环境
	//demo4 在浏览器环境中
	var age = 18
	console.log(this.age) //18
	
	//demo5 在node环境中
	var age = 18
	global.name = 'Tom'
	console.log(this.age) //undefined
	console.log(this.name) //undefined

如果在顶层对象中绑定一个不可变的变量

如使用node做项目时,经常需要加载很多常量。一种方法是使用const然后不停地require。这种方式的缺点就是每次在新的module中使用时都要require常量对应的module。另一中方法是将常量绑定到global。使用Object.defineProperty设置其为不可修改的。

	//demo6 在node环境中
	Object.defineProperty(global, 'finalValue', {
  		value: function (key, value) {
    				Object.defineProperty(global, key, {
      					value: value
    			});
 		}
	})
	
	finalValue('appName', 'app')
	console.log(appName) //app
	appName = 'newApp' //throw err