你的位置:首页 > Java教程

[Java教程]作用域与命名空间


作用域

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

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