论坛首页 Web前端技术论坛

Javascript 两种 function 定义的区别

浏览 3330 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-12-29  
大家都知道Javascript 有两个种定义Function的方法非常常用。例如

function a(){alert("a")}
var a = function(){alert("a")}

虽然两个种方式定义出来的 function 调用的时候结果一样,但是中间还是有区别的。举个简单的例子,假如我们要重定义 a() ,而且新的方法要继承 a() 里面所有方法并且进行其他扩展的话。就可以明显看到这两个方式的区别了。

1. 首先,我们先建立一个临时的变量来存储 a()
   var b = a;

然后,重新定义a()
第一种方式:
function a(){
    b();
    alert("ok");
}

第二种方式:
a = function(){
    b();
    alert("ok");
}

这是大家可以尝试发现。第一种方式重新定义的 a() 会出现堆栈溢出的错误。而第二种方式却成功保留了原来 a() 所执行的脚本,成功 alert 出了 "a" "ok" 的字样,说明 a() 的方法被重定义了。

这里就可以很明显区分两个方式的区别了。定义的顺序不同。
第一种,刚开始其实没有重新定义 a 这个function 而在里面执行了其本身。
第二种方式, a = function () 这里没有执行到 function 里面的代码 a 已经被重新定义了。所以这里的重定义是有效的。



文章来自: 本站原创
引用通告地址: http://www.pjhome.net/trackback.asp?tbID=625
Tags: functionfunction
评论: 15 | 引用: 0 | 查看次数: 3064 1 | 2 | >
ScriptBaby [2006-11-04 01:05 AM]
引用来自 ScriptBaby
关于function a(){}和var a = function(){}的区别的另一些细节...

我在做javascript的oo风格扩展的时候写了一个在一个函数原本功能的基础上稍加修改的功能, 在调试中发现某些浏览器中不包含函数名的描述方式不可以使用eval进行定义, 必须通过new Function进行定义

比方说
function example(){alert(0)}
toString得到的结果就是
function example(){alert(0)}
将它作为字符串传入eval可以得到这个函数的引用(需要注意作用域, 在“全局”范围内如此可能会导致同名的函数定义被修改)... 如 eval("function example(){alert(0)}")


var example = function(){alert(0)};
这种方式, toString得到的是
function(){alert(0)}
如果传入eval, 像这样eval("function(){alert(0)}")的话, 可能会出错... 此时用new Function("alert(0)")就可以正常工作...


关于eval的作用域... 有些细节不记得了, ms jscript中关于eval的部分应该有写到, ff之类的web开发文档中应该也有

修正:
  “可以得到这个函数的引用”处应该为“可以构造出一个这样的函数并且返回对这个函数的引用”... 实际上我不太肯定如果函数体相同的话, 返回的引用还会不会是原来的那个函数的引用(我猜不是)
ScriptBaby [2006-11-04 01:00 AM]
关于function a(){}和var a = function(){}的区别的另一些细节...

我在做javascript的oo风格扩展的时候写了一个在一个函数原本功能的基础上稍加修改的功能, 在调试中发现某些浏览器中不包含函数名的描述方式不可以使用eval进行定义, 必须通过new Function进行定义

比方说
function example(){alert(0)}
toString得到的结果就是
function example(){alert(0)}
将它作为字符串传入eval可以得到这个函数的引用(需要注意作用域, 在“全局”范围内如此可能会导致同名的函数定义被修改)... 如 eval("function example(){alert(0)}")


var example = function(){alert(0)};
这种方式, toString得到的是
function(){alert(0)}
如果传入eval, 像这样eval("function(){alert(0)}")的话, 可能会出错... 此时用new Function("alert(0)")就可以正常工作...


关于eval的作用域... 有些细节不记得了, ms jscript中关于eval的部分应该有写到, ff之类的web开发文档中应该也有
ScriptBaby [2006-11-04 00:42 AM]
引用来自 norman
引用来自 ScriptBaby
我怀疑你是不是理解错PJ的意思了
PJ说的是
...
不会出错.

一点一点来:
function a(){alert("a")}
b=a;
function a(){
    b();
    alert("ok");
}

编译时: 首先a被定义为alert("a"), 接着又被定义成b();alert("ok");
运行时: b = function a(){b();alert("ok");}, 此时b和a一样, 函数体中直接调用b, 无论从a调用还是从b调用结果都一样, 产生堆栈溢出

另一方面
function a(){alert("a")}
b=a;
a = function(){
    b();
    alert("ok");
}
编译时: a被定义为alert("a")
运行时: b=function a(){alert("a")}; a=function(){b();alert("ok")}; 此时b的函数体中不包括ab中任何一个, a只调用b... 无论怎样都不会产生堆栈溢出...


反倒是你没有明白我的意思
ScriptBaby [2006-11-04 00:31 AM]
引用来自 norman
引用来自 ScriptBaby
引用来自 norman
小弟比较愚笨,不太明白你的意思,请问你的意思是说用function a是会被"预先"编译好,而使用 a = function(){}不是预先编译的所以不会导致stack overflow么?
那么
<script>
function a(){
    a();
    alert(1);

}
a();
</script>

<script>
a =function(){
    a();
    alert(1);

}
a();
</script>
为什么会有相同的错误呢?

我发现只要在JS做一个死循环的递归,就会导致stack overflow的问题.

以上任何一种方式都是已经“编译”后的, 区别在于使用function a的形式会在编译时就为a赋值(函数体), 而var a = function的形式只有当脚本开始运行..并且运行到那行之后才会赋值... 不管是ms jscript引擎, 还是ms vbscript引擎, 亦或是ff之流的javascript引擎, 都是如此的

至于你的程序例子, 无论用哪种方式都是没有区别的... 当然如果你用toString valueOf或者toSource方法(FF支持)的话, 还是能看出去别的(具体意义似乎不大)
norman [2006-09-21 02:34 PM]
引用来自 ScriptBaby
引用来自 norman
我觉得貌似应该是使用a=function()时.a获得了一个新的地址.而之前b=a所指向的是funtion a的老地址,所以在后来的a中其实相当与调用了另外一个函数而不是自己本身.

a=function 和 function a的区别就在于a = function会给a一个新的地址而function a不会

對於腳本引擎你可能並不知道其中的某些細節
實際上腳本語言在被正式執行之前已經經過“偽編譯”, 而像function a這種格式聲明出來的函數在這個過程中就已經生效了, 所以就算是這樣寫
a();

function a(){
  //something
};
也不會有錯

我怀疑你是不是理解错PJ的意思了
PJ说的是
function a(){alert("a")}
b=a;
function a(){
    b();
    alert("ok");
}
会出错,而
function a(){alert("a")}
b=a;
a = function(){
    b();
    alert("ok");
}
不会出错.

norman [2006-09-21 02:33 PM]
引用来自 ScriptBaby
引用来自 norman
我觉得貌似应该是使用a=function()时.a获得了一个新的地址.而之前b=a所指向的是funtion a的老地址,所以在后来的a中其实相当与调用了另外一个函数而不是自己本身.

a=function 和 function a的区别就在于a = function会给a一个新的地址而function a不会

對於腳本引擎你可能並不知道其中的某些細節
實際上腳本語言在被正式執行之前已經經過“偽編譯”, 而像function a這種格式聲明出來的函數在這個過程中就已經生效了, 所以就算是這樣寫
a();

function a(){
  //something
};
也不會有錯

小弟比较愚笨,不太明白你的意思,请问你的意思是说用function a是会被"预先"编译好,而使用 a = function(){}不是预先编译的所以不会导致stack overflow么?
那么
<script>
function a(){
    a();
    alert(1);

}
a();
</script>

<script>
a =function(){
    a();
    alert(1);

}
a();
</script>
为什么会有相同的错误呢?

我发现只要在JS做一个死循环的递归,就会导致stack overflow的问题.

ScriptBaby [2006-09-19 10:09 PM]
引用来自 norman
我觉得貌似应该是使用a=function()时.a获得了一个新的地址.而之前b=a所指向的是funtion a的老地址,所以在后来的a中其实相当与调用了另外一个函数而不是自己本身.

a=function 和 function a的区别就在于a = function会给a一个新的地址而function a不会

對於腳本引擎你可能並不知道其中的某些細節
實際上腳本語言在被正式執行之前已經經過“偽編譯”, 而像function a這種格式聲明出來的函數在這個過程中就已經生效了, 所以就算是這樣寫
a();

function a(){
  //something
};
也不會有錯
Victor [2006-09-19 05:34 PM]
我一般用prototype为函数扩展

载自:http://www.pjhome.net/article.asp?id=625&page=1#comm_top
   发表时间:2006-12-29  
好长
还可以这样:
var a = new Function("alert('a')");
0 请登录后投票
论坛首页 Web前端技术版

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