锁定老帖子 主题:函数申明和变量申明的微妙区别
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-09
按dlee的说法,外部代码执行完后其它函数才会创建,那我还是以
<script> var test1 = 1; alert(test1); function test1(){}; </script> 这段代码为例子吧 alert(test1)执行完后才创建test1函数,可是我在页面上创建一个按钮,在window.onload完毕后 (估计页面JS初始化完成了)手动触发按钮的onclick="alert(test1);"事件,这个时候test1还是1,并不是 function ,函数并没有被创建... 这个如何解释? |
|
返回顶楼 | |
发表时间:2007-05-09
to BaSaRa:
确实又是一个不能自圆其说的情况,呵呵。 不过有一个通用的方法可以绕过这个问题,那就是采用匿名函数赋值的方法来做。最初的代码要改成这样: <script> var test1 = 1; test1 = function() {}; alert(test1); </script> 具体的原因,我们可以继续再探讨。 |
|
返回顶楼 | |
发表时间:2007-05-09
onclick事件监听的匿名函数注册在function test1(){};函数创建之前,如果是这样的话,就可以解析了。不过还有一点说不过去,就是最后只要函数function test1(){};被创建了,那么test1这个reference就会改变,那么点下按钮之后就应该是function。除非这个函数就没有被创建过。
|
|
返回顶楼 | |
发表时间:2007-05-09
这个问题太奇怪了,偶下断点debug了一下,发现这个执行顺序完全可以用诡异来形容...外行看热闹,期待内行来讲讲门道了。
|
|
返回顶楼 | |
发表时间:2007-05-09
如果存在函数不调用则不创建的原则呢?是不是就说过去了?
|
|
返回顶楼 | |
发表时间:2007-05-09
to Readonly:
与执行顺序无关。 症状是:只要创建了一个名称为xxx的普通变量,再以最初一楼代码中的那种方式创建名称为xxx的函数就是无效的(并没有创建这个函数),无论将这个函数声明放在哪里。只能通过用匿名函数明确地为xxx变量赋值,才可能绕过这个问题。 这个症状在IE和Firefox中是一致的。 |
|
返回顶楼 | |
发表时间:2007-05-09
可能就是因为这个原因,在很多的Ajax组件库中都采用了使用匿名函数赋值的方法,因为这样做不容易被覆盖。
另外像Dojo这样的库都将全部的函数都放在某个名字空间变量中,例如: dojo.byId或者dojo.io.bind, 虽然有很多Prototype Fans认为$函数才是最方便优雅的写法,但是dojo.byId用起来会更安全一些,因为开发者定义一个变量名称为dojo.byId是不可能的(变量名中不能出现“.”)。 |
|
返回顶楼 | |
发表时间:2007-05-09
http://www.iteye.com/topic/19506
首先:以下代码让我相信javascript有个预编译过程,不是完全按照顺序解释执行的。 代码 1. <SCRIPT LANGUAGE="JavaScript"> 2. a(); 3. function a(){ 4. alert(); 5. } 6. </SCRIPT> 个人理解这个预编译过程不会象java/c#那样把代码编译成虚拟机认识的语言,更不会象vb,vc那样编译成更底层的语言。猜想只是把这个函数预装载到这段函数执行的全局环境中,在这个执行环境中,该函数被标识定义过,可以直接使用了。(看到网上很多人写的AOP的javascript实现,其实这个预编译过程才是翻译元数据最佳时候,可惜就javascript语言来讲,是有些落伍了) 这个文章主要讲变量的一些问题。变量说了,为什么函数可以,我变量就不可以呢。 代码 1. <SCRIPT LANGUAGE="JavaScript"> 2. document.writeln(a); 3. var a=0; 4. </SCRIPT> 为什么我要输出undefined呢?为什么我a就不可以预编译一把呢? 大家看看以下两段代码会输出什么呢啊??? 代码 1. <SCRIPT LANGUAGE="JavaScript"> 2. document.writeln(a); 3. a=0; 4. </SCRIPT> 代码 1. <SCRIPT LANGUAGE="JavaScript"> 2. document.writeln(a); 3. </SCRIPT> 可能你运行试了,可能你本来就知道,a未定义。哈哈哈,好了。 现在我确信var a=0;被javascript解释器“预编译过”,至少是记录下来了。甚至把它的值设置为 undefined。“undefined”这个词名字取的很是让人误解,怎么能叫未定义呢,分明是javascript中所有变量的初始化值。关于 null与undefined的比较我实在不愿提了。 注意上面两段代码还反映一个现象。隐式声明的变量是在解释的时候才把自己定义为全局变量的。 关于函数与变量javascript预编译的不同处理,大家可以与java class的加载过程比较下。java也是对基本类型设出值,对象为null的。(不往远扯了) |
|
返回顶楼 | |
发表时间:2007-05-09
<script>
alert(test1); var test1 = 1; function test1(){};//函数申明不能覆盖变量申明? alert(test1); </script> 看看这段代码怎么输出。 在看看 <script> alert(test2); var test2 = 1; eval('function test2(){};'); alert(test2);//函数申明怎么又覆盖了变量申明? </script> 再看看 <script> alert(x) alert(a) alert(b) alert(c)//根本没反映 var x=1; function a(){} var b=function(){}; eval('function c(){};'); </script> eval在犀牛书中建议不要乱用,具体什么原因并没说。 可能这是原因之一。 |
|
返回顶楼 | |
发表时间:2007-05-10
函数定义是在变量赋值之前完成的,所以函数定义会被变量赋值覆盖,而变量赋值不会被函数定义覆盖。将匿名函数赋值给变量是一个赋值的过程,所以这个会覆盖前面赋值的变量。道理就是这么简单的。
|
|
返回顶楼 | |