话不多说,我们先看代码:

	function f (){
		fff = 999;
	}
	f();
	console.log(fff);

我们定义了一个名为 f 的函数,函数内没有对变量进行声明,直接给 fff 变量进行了赋值,并且在外部调用了 f 函数,我们输出一下 fff 的变量,大家猜一下代码效果如何:
JS之变量声明与window对象的关系_编程语言
它可以正常输出。。。
我们再看另一段代码:

	function f (){
		var fff = 999;
	}
	f();
	console.log(fff);

这段代码不同的地方是,在函数体内我们按规定对变量进行了声明。那么这段代码的效果是:
JS之变量声明与window对象的关系_javascript_02
fff is not defined
奇了怪了是吧,我规规矩矩的声明变量倒不行,不声明直接赋值,竟然可以在函数外使用函数内的变量,这似乎不符合我们的认知,那么问题出在了哪里?
首先我们知道JavaScript中有一个内置对象是window,所有在脚本中(没有在函数的范围内)通过var定义的变量,都挂在window对象上,在任意位置,一个变量的赋值都可以看做是在window上寻找这个变量。
我们实测一下:

	var aaa = 777;
	console.log(window)

JS之变量声明与window对象的关系_前端_03
果不其然,我们在window对象中找到了这个变量。

	function f (){
		fff = 999;
	}

这段代码在解析的时候,它会把 fff = 999,当做是window.fff = 999。
所以这个函数通过外部调用之后,可以在函数外使用函数内的变量,因为这个变量已经挂在了window对象上。

	function f (){
		fff = 999;
	}
	f();
	console.log(window)

JS之变量声明与window对象的关系_前端_04

function f (){
	window.fff = 999;
}
f();
console.log(window)

JS之变量声明与window对象的关系_编程语言_05
经过我们的测试,实际效果和预期一样。
这个问题之前当过面试题,这是一种很危险的做法,很容易导致程序出现问题,所以我们在定义变量时一定不要忘记写var,尤其是函数内,不然会制造出一些意想不到的bug。我们要尽量避免这种情况的发生,并且如何面试时被问到,要知道这个问题是什么情况。


JS之变量声明与window对象的关系_js_06