作用域与命名空间

作用域

无论如何,函数是唯一拥有自身作用域的结构,其它任何形式的结构都不支持作用域。代码如下所示

var demo = function ()
{
	...
};

function demo ()
{
	...
};

JavaScript语言中没有显式命名空间定义,这意味着所有对象都定义在一个全局共享的命名空间下

引用变量时,向上依次遍历当前作用域、全局作用域,直到发现该变量

隐式全局变量与局部变量

在函数的自身作用域内,如变量声明不使用var表达式,就会导致隐式全局变量产生。先看如下代码所示

var demo = function ()
{
	number = 1;
};
demo();

var demo = function ()
{
	for (number = 0; number < 5; number ++)
	{
		...
	};
};
demo();

运行结果都为声明了一个全局变量number;如不想声明或者覆盖一个全局作用域内的同名变量,就必须使用var表达式。代码如下所示

var demo = function ()
{
	var number = 1;
};
demo();

var demo = function ()
{
	for (var number = 0; number < 5; number ++)
	{
		...
	};
};
demo();

运行结果都为声明了一个仅在当前作用域内才有效的局部变量number

变量声明提升(Hoisting)

变量声明在JavaScript语言中会被提升,这意味着var表达式、function声明会被提升至当前作用域顶部。先看如下代码所示

demo();
var demo = function ()
{
	...
};

demo();
function demo ()
{
	...
};

代码执行之前被转化为

var demo;
demo();
demo = function ()
{
	...
};

function demo ()
{
	...
};
demo();

运行结果为第一段代码执行失败,第二段代码执行成功;因为第一段代码执行时demo仅仅是声明了,但是依然缺省值为undefined

非常有意思的是局部变量声明的提升。再看如下代码所示

var number = 0;
var demo = function ()
{
	if (true)
	{
		number = 1;
	}
	else
	{
		var number = 2;
	};
	console.log(number);
};
demo();
console.log(number);

代码执行之前被转化为

var number, demo;
number = 0;
demo = function ()
{
	var number;
	if (true)
	{
		number = 1;
	}
	else
	{
		number = 2;
	};
	console.log(number);
};
demo();
console.log(number);

输出结果为1、0;本该覆盖全局变量number的代码转为声明了一个局部变量number,如想覆盖全局变量number,就必须取消所有的var表达式。代码如下所示

var number = 0;
var demo = function ()
{
	if (true)
	{
		number = 1;
	}
	else
	{
		number = 2;
	};
	console.log(number);
};
demo();
console.log(number);

输出结果为1、1

命名空间

只有一个全局作用域会导致命名冲突,解决方案是匿名包装器,作用是通过匿名函数创建一个新的命名空间。先看如下代码所示

(function (){
	...
})();

由于匿名函数被认为是表达式,为了可调用性,需要先行执行,我们可以把自执行的匿名函数理解为匿名包装器。再看如下代码所示

( //小括号内函数先行执行
function ()
{
	...
}
) //返回函数对象
(); //立即执行匿名函数,并调用以上执行结果即函数对象

通过匿名包装器创建命名空间,不仅可以防止命名冲突,而且有利于程序的模块化

还有一些其他的函数表达式调用方法。代码如下所示

+function (){
	...
}();

!function (){
	...
}();

(function (){
	...
}());

有意思的思考题

var number = 0;
(function (){
	console.log(number); //猜猜输出是什么
	var number = 1;
})();
原文地址:https://www.cnblogs.com/johnl/p/4849826.html