锁定老帖子 主题:关于var的问题
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-10-14
>>> 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()() 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间: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声明,只有声明提前,赋值并不会提前。 |
|
返回顶楼 | |
发表时间: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的变量也会被保存下来 |
|
返回顶楼 | |
发表时间: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 |
|
返回顶楼 | |
发表时间:2007-10-14
可以看看 JavaScript: The Definitive Guide, 5th Edition
4.6. Variables as Properties 4.7. Variable Scope Revisited 讲的比较清楚 |
|
返回顶楼 | |
发表时间:2007-10-14
let就是修补了var只能保持global和function这两种scope缺陷的吧,就是let可以保存所有只要出现{}的scope(相当于scope了),let也应该算预处理吧
|
|
返回顶楼 | |
发表时间: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__呀 |
|
返回顶楼 | |
发表时间: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。 |
|
返回顶楼 | |
发表时间:2007-10-14
不看不知道,原来认为ie ff在语言核心应该差不多,今天看来ie实现的问题还是挺大的...万恶的JScript
|
|
返回顶楼 | |
发表时间: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)。 |
|
返回顶楼 | |