论坛首页 Web前端技术论坛

关于var的问题

浏览 5338 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-10-14  
var到底有没有预处理
>>> function a(){var a=123; return function (){alert(b)};var b=234;}
>>> a()()
比如这样是会报告b不存在的,如果var有预处理的话就算在return后面也可以的吧,当然这样
>>> function a(){var a=123;var b=234; return function (){alert(b)};}
>>> a()()
是没有问题的,这是不是说明两个问题:
1.闭包不能闭return后面的东西
2.var没有优先级别,其实也不是什么声明,和function没有可比性,只是强制确定一些scope范围

关于var没有向function一样优先级问题例子:
function a(){var a=123;var b=234; return function (){alert(c)}; function c(){}}
a()()
   发表时间:2007-10-14  
不是这样的。

你第一个代码中,alert(b)的时候,是有b的,但是还没有执行赋值。你的代码等价于:
function a(){var a=123; var b; return function (){alert(b)};b=234;} 

之所以alert不出来,只是因为赋值语句在return之后根本执行不到。

测试例子:
D:\js\rhino1_6R7>java -jar js.jar
Rhino 1.6 release 7 2007 08 19
js> function a(){var a=123; return function (){print(b)};var b=234;}
js> a()()
undefined
js> function a(){var a=123; return function (){print(b)};}
js> a()()
js: "<stdin>", line 7: uncaught JavaScript runtime exception: ReferenceError: "b
" is not defined.

看到差别了没有?

function声明的差别在于function声明整个会提前,而var声明,只有声明提前,赋值并不会提前。
0 请登录后投票
   发表时间:2007-10-14  
果然,非常感谢,也就是说var和function一样被预处理,但是紧随var后面的副值语句却要按顺序执行,甚至
>>> function a(){var a=123; return function (){alert(b)};if(false){var b=234}}
>>> a()()

这个根本不会执行的var语句也被初始化了,就是说只要在一个scope里面,上来就会处理所有的function声明和var预处理,非常感谢,不过这个有什么用呢,并且非常容易在closure里面产生大量无用变量,比如哪个lazy function本来我觉得在中途return后面的变量就都无效了,看来不是这样,后面的function不仅会被保存,而且var的变量也会被保存下来
0 请登录后投票
   发表时间:2007-10-14  
你问var这样有什么用?实际是没有用。而且容易造成bug。可以说这是JS设计的一个失误。JS1.7(还是1.8或1.9?忘记了)以后引入了let关键字。
void function () {
	for (let i = 0; i < 3; i++) {
		print(i);
	}
	try { print(i); } catch(e) { print(e); }
	let(i = 10) {
		print(i)
	}
	try { print(i); } catch(e) { print(e); }
	{
		let i = 20;
		print(i);
	}
	try { print(i); } catch(e) { print(e); }
	if (false) {
		let i = 30;
		print(i);
	}
	try { print(i); } catch(e) { print(e); }
	if (true) {
		let i = 40;
		print(i);
	}
	try { print(i); } catch(e) { print(e); }
}();


结果:
D:\js\test>jshost test-let.js
0
1
2
ReferenceError: i is not defined
10
ReferenceError: i is not defined
20
ReferenceError: i is not defined
ReferenceError: i is not defined
40
ReferenceError: i is not defined
0 请登录后投票
   发表时间:2007-10-14  
可以看看  JavaScript: The Definitive Guide, 5th Edition
4.6. Variables as Properties
4.7. Variable Scope Revisited
讲的比较清楚
0 请登录后投票
   发表时间:2007-10-14  
let就是修补了var只能保持global和function这两种scope缺陷的吧,就是let可以保存所有只要出现{}的scope(相当于scope了),let也应该算预处理吧
0 请登录后投票
   发表时间:2007-10-14  
非常感谢提示,拿出买了半个多月没看的第五版权威指南,仔细看了下第四章,和第四版不一样,4.31最后一个例子说明了var的scope效应,开头结尾都生效,不管在哪里var,第四版里没有,4.2最后一句很精彩,我测试了下
var test=123
delete(window.test)
alert(test)

ff下面delete会返回false删不了,ie下面会抛异常,去掉var
test=123
delete(window.test)
alert(test)

ff下面delete返回true了,test不存在了,ie还是抛异常,另外测试safari opera结果和ff完全一样
总结var会预处理,var声明不能delete,ie处理delete有问题,不返回false,并且不使用var声明变量也不可以删,比较怪异,另外4.62介绍的调用对象是不是就是hax大哥说的rhino里面的__parent__呀
0 请登录后投票
   发表时间:2007-10-14  
手头没有该书,不清楚。

注意var在function里面和在global上的意义有一点差别。可以说这也是一个设计失误。function内的比较清楚。
你的代码2,在许多引擎中会出warning,也就是这样的test赋值其实是不太建议采用的做法。如果明确要在global上赋值,最好写成window.test = 123。这有一个好处,就是写语句之前让你想一想,到底这个变量应该放在哪个scope中。
JScript还有更奇怪的行为,例如delete(window.test)会异常,实际上所有在DOM上的delete都会异常,区别在于DOM元素上可以用removeAttribute移除,而window上没有办法。如果是直接test=123直接delete(test)就ok,但是会有潜在的奇怪问题。如果是var test=123的话,delete(test)返回false。
0 请登录后投票
   发表时间:2007-10-14  
不看不知道,原来认为ie ff在语言核心应该差不多,今天看来ie实现的问题还是挺大的...万恶的JScript
0 请登录后投票
   发表时间:2008-03-14  
hax 写道
如果明确要在global上赋值,最好写成window.test = 123。JScript还有更奇怪的行为,例如delete(window.test)会异常,实际上所有在DOM上的delete都会异常,区别在于DOM元素上可以用removeAttribute移除,而window上没有办法。如果是直接test=123直接delete(test)就ok,但是会有潜在的奇怪问题。如果是var test=123的话,delete(test)返回false。


补充,今天发现奇怪的现象。貌似window.x和直接写x有差异。
x = 1
delete x
这个可以成功。
但是
x = 1
window.x
delete x
就失败。

注意第二个只是从window访问了一次x,甚至 'x' in window 也一样。

更无厘头的是,x实际是被delete了。但是typeof x返回unknown。。。


貌似IE在这里的处理十分奇特。我猜测,x = 1,是由JScript引擎处理的,而window.x则存在一个Global到window的绑定,即有其他COM的映射了,这个绑定会发生在第一次从window来访问x的时候。一旦绑定建立之后,对x的读写也会同步到window.x上。所以x被delete之后,window.x上剩下了一个映射的空壳(unknown)。
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics