论坛首页 Web前端技术论坛

函数申明和变量申明的微妙区别

浏览 17179 次
精华帖 (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 ,函数并没有被创建...

这个如何解释?

0 请登录后投票
   发表时间:2007-05-09  
to BaSaRa:
确实又是一个不能自圆其说的情况,呵呵。
不过有一个通用的方法可以绕过这个问题,那就是采用匿名函数赋值的方法来做。最初的代码要改成这样:
<script>
var test1 = 1;
test1 = function() {};
alert(test1);
</script>

具体的原因,我们可以继续再探讨。
0 请登录后投票
   发表时间:2007-05-09  
onclick事件监听的匿名函数注册在function test1(){};函数创建之前,如果是这样的话,就可以解析了。不过还有一点说不过去,就是最后只要函数function test1(){};被创建了,那么test1这个reference就会改变,那么点下按钮之后就应该是function。除非这个函数就没有被创建过。
0 请登录后投票
   发表时间:2007-05-09  
这个问题太奇怪了,偶下断点debug了一下,发现这个执行顺序完全可以用诡异来形容...外行看热闹,期待内行来讲讲门道了。

  • 大小: 70.4 KB
0 请登录后投票
   发表时间:2007-05-09  
如果存在函数不调用则不创建的原则呢?是不是就说过去了?
0 请登录后投票
   发表时间:2007-05-09  
to Readonly:
与执行顺序无关。
症状是:只要创建了一个名称为xxx的普通变量,再以最初一楼代码中的那种方式创建名称为xxx的函数就是无效的(并没有创建这个函数),无论将这个函数声明放在哪里。只能通过用匿名函数明确地为xxx变量赋值,才可能绕过这个问题。

这个症状在IE和Firefox中是一致的。
0 请登录后投票
   发表时间:2007-05-09  
可能就是因为这个原因,在很多的Ajax组件库中都采用了使用匿名函数赋值的方法,因为这样做不容易被覆盖。

另外像Dojo这样的库都将全部的函数都放在某个名字空间变量中,例如:
dojo.byId或者dojo.io.bind,
虽然有很多Prototype Fans认为$函数才是最方便优雅的写法,但是dojo.byId用起来会更安全一些,因为开发者定义一个变量名称为dojo.byId是不可能的(变量名中不能出现“.”)。
0 请登录后投票
   发表时间: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的。(不往远扯了)
0 请登录后投票
   发表时间: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在犀牛书中建议不要乱用,具体什么原因并没说。 可能这是原因之一。
0 请登录后投票
   发表时间:2007-05-10  
函数定义是在变量赋值之前完成的,所以函数定义会被变量赋值覆盖,而变量赋值不会被函数定义覆盖。将匿名函数赋值给变量是一个赋值的过程,所以这个会覆盖前面赋值的变量。道理就是这么简单的。
0 请登录后投票
论坛首页 Web前端技术版

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