导航栏: 首页 评论列表

JavaScript声明全局变量三种方式的异同

默认分类 2011-04-27 01:22:25

转载:http://www.cnblogs.com/snandy/archive/2011/03/19/1988284.html

JavaScript声明全局变量三种方式的异同

变量变量声明是一门语言最基本的概念,初学者都会很快掌握。JavaScript中声明变量也是如此,很简单var(关键字)+变量名(标识符)。

方式1

1var test;
2var test = 5;<br>

需注意的是该句不能包含在function内,否则是局部变量。这是第一种方式声明全局变量。

方式2

1test = 5;

没有使用var,直接给标识符test赋值,这样会隐式的声明了全局变量test。即使该语句是在一个function内,当该function被执行后test变成了全局变量。

方式3

1window.test;
2window.test = 5;

这种方式经常被用到一个匿名函数执行后将一些函数公开到全局。 如JQuery1.5中最末一句

1window.jQuery = window.$ = jQuery;

如果只是使用变量test,那么三种方式将没有什么区别。比如:alert(test) 都将显示5。但三种方式在某些情况下还是有区别的。分别按以上三种方式声明三个变量a1,a2,a3。

1a1 = 11;
2var a2 = 22;
3window.a3 = 33;

1,for in window

1for(ainwindow){
2    if(a=='a1'||a=='a2'||a=='a3'){
3       alert(a)
4    }
5}

IE6/7/8/9:只弹出了a3,说明通过第一,二种方式声明的全局变量通过for in window时将获取不到。
Firefox/Chrome/Safari/Opera :a1,a2,a3都弹出了,说明三种方式声明的全局变量,通过for in window时都能获取到。

2,delete

01try {
02    alert(deletea1);
03}catch(e){alert('无法delete a1')}
04 
05try{
06    alert(deletea2);
07}catch(e){alert('无法delete a2')}
08 
09try{
10    alert(deletea3);
11}catch(e){alert('无法delete a3')}

结果如下

可以看到,
1,delete a2所有浏览器都是false。即通过var声明的变量无法删除,所有浏览器表现一致。这在犀牛书上也有提到。
2,通过window.a3方式声明的全局变量在IE6/7/8中均无法删除,IE9/Firefox/Chrome/Safari/Opera中却可以。


虽然有以上两点不同,但当用in运算时,都返回true。

1alert('a1'in window);//true
2alert('a2'in window);//true
3alert('a3'in window);//true

用with打开对象window闭包时,所有浏览器也表现一致,如下

01with(window){
02    if(a1){
03       alert(a1);//11
04    }
05    if(a2){
06       alert(a2);//22
07    }
08    if(a3){
09       alert(a3);//33
10   
11}

相关:

JavaScript中两种类型的全局对象/函数

分类: javascript

posted on 2011-03-19 16:48 snandy 阅读(1189)评论(10) 编辑 收藏

评论

#1楼 2011-03-19 18:50yzx226    

学习了  回复 引用 查看  

#2楼 2011-03-19 22:54Gray Zhang    

var test = 3; // 这种其实创建的是一个variable
test = 3; // 这种其实是在global下创建一个property
window.test = 3; // 同上一种,但通用性不好,不在浏览器环境下会出问题
所以比较正统的符合ECMA的应该是Global.test = 3;
但是一般来说Global是访问不到的,那么就得想办法弄出来
按ECMAv3的标准来说,正常调用一个函数的话,其内部的this就是Global,所以这么写
var global = (function() { return this; }());
但是ECMAv5又出了一个strict模式,在该模式下,如果正常调用一个函数,其内部的this是undefined
好在ECMAv5里又有indirect eval call,这在你的另一篇中有提到过,indirect eval call永远在global下执行,所以那个时候的this就是Global了
var global = (1,eval)('(this)');
所以综合一下,获取global的方法是:
var global = (function() { return this || (1,eval)('(this)'); }());
再随后global.tes = 3;就安全了
 回复 引用 查看  

#3楼 2011-03-19 22:55Gray Zhang    

相关的一些资料:http://perfectionkills.com/unnecessarily-comprehensive-look-into-a-rather-insignificant-issue-of-global-objects-creation/ 回复 引用 查看  

#4楼 2011-03-19 23:37Franky    

引用var test = 3; // 这种其实创建的是一个variable
test = 3; // 这种其实是在global下创建一个property


这两种都是在VariableObject上添加一个属性.区别是一个具备可删除特性,一个不具备这个特性.

不过早期的firefox,大概是2之前的版本,有一个实现上的bug.多某个标识符赋值,可能会发生特性上的修改,比如本来具备不可删除特性的,变量,会因为赋值运算,导致该属性的 不可删除特性被去掉.

对于获取global这个事, Gray Zhang,已经开始考虑严格模式了?

另外楼主提到的 ie下 in 和 for in 的区别,确实是ie实现上的bug.

引用用with打开对象window闭包时,所有浏览器也表现一致,如下

我个人对这个with打开闭包的说法,持反对态度. 我认为爱民大哥,之所以在其语言精髓与编程实践中有这一说发,源自于当时他对闭包概念的错误理解. 所以这一说法是不恰当的.
 回复 引用 查看  

#5楼 2011-03-19 23:54Gray Zhang    

@Franky
strict模式其实很多思想蛮合理的,比如不要不使用var来定义全局变量,以及不要随意删除属性等
而且使用Firefox 4.0的话,其Console在strict模式下会报出不少的warning可以便于检查代码
所以我现在写js一般是先加上'use strict',到上线的时候再去掉的
 回复 引用 查看  


>> 留言评论