论坛首页 Web前端技术论坛

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

浏览 17182 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-09  
<script>
var test1 = 1;
function test1(){};//函数申明不能覆盖变量申明?
alert(test1);
</script>
<script>
var test2 = 1;
eval('function test2(){};');
alert(test2);//函数申明怎么又覆盖了变量申明?
</script>
   发表时间:2007-05-09  
估计是eval()内部apply()了一下,把这个function挂到window上了
0 请登录后投票
   发表时间:2007-05-09  
var test2 = 1;
eval('test2=new Function();')
alert(test2);
如果这样就可以覆盖掉了(指向一个匿名函数)
0 请登录后投票
   发表时间:2007-05-09  
不是这个意思,出现这个情况的原因是这样:对于页面中的脚本,JavaScript引擎一般是先执行完所有外部的代码之后,才会创建声明的函数的。
所以jindw上面的第一段代码,其实相当于是:
<script>
var test1 = 1;
alert(test1);
function test1(){};//函数申明不能覆盖变量申明?
</script>

而第二段代码呢,
<script>
var test2 = 1;
eval('function test2(){};');
alert(test2);//函数申明怎么又覆盖了变量申明?
</script>

因为eval这条语句属于外部代码,所以执行的顺序与jindw写的顺序是相同的。

当然,如果在外部的代码中包含有函数调用,其调用的这个函数是会在调用之前创建的。
0 请登录后投票
   发表时间:2007-05-09  
呵呵,还有更奇怪的。

<script> 
alert(test1());//这样也行???? 
var test1 = 1; 
function test1(){return 'xxx'};
</script> 
0 请登录后投票
   发表时间:2007-05-09  
是的,这就是上面我最后补充的一句话的情况:
引用
当然,如果在外部的代码中包含有函数调用,其调用的这个函数是会在调用之前创建的。
0 请登录后投票
   发表时间:2007-05-09  
2007-05-09 18:49 
2007-05-09 18:52 
又一次把java eye当QQ用了

to dlee:
这些东西在ECMA262-3里面有描述吗?
我初看一下,没找到呢。
0 请登录后投票
   发表时间:2007-05-09  
12.2 Variable statement Description
If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local
scope in that function, as described in s10.1.3. Otherwise, they are defined with global scope (that is, they
are created as members of the global object, as described in 10.1.3) using property attributes { DontDelete
}. Variables are created when the execution scope is entered. A Block does not define a new execution
scope. Only Program and FunctionDeclaration produce a new scope. Variables are initialised to undefined
when created. A variable with an Initialiser is assigned the value of its AssignmentExpression when the
VariableStatement is executed, not when the variable is created.


函数申明:
Semantics
The production FunctionDeclaration : function Identifier ( FormalParameterListopt ) { FunctionBody }
is processed for function declarations as follows:
1. Create a new Function object as specified in 13.2 with parameters specified by FormalParameterList, and
body specified by FunctionBody. Pass in the scope chain of the running execution context as the Scope.
2. Create a property of the current variable object (as specified in 10.1.3) with name Identifier and value
Result(1).
0 请登录后投票
   发表时间:2007-05-09  
没找到合适的解释
0 请登录后投票
   发表时间:2007-05-09  
以前有个人曾经问过我,我在IE和Firefox上试过,行为都是这样的。

我猜想应该是考虑到执行效率的原因。这样做将创建声明函数(通过eval类似的机制)的工作放在最后,这部分工作可以以异步的方式来做,而不会影响到页面的render,而外部的代码在统一eval之后也可以尽快执行。

所以做JavaScript开发,不应该对函数创建的时机作出假设。而且函数创建的行为可能是异步的,执行到函数声明之后的这条语句时,函数尚未创建是完全有可能的。
0 请登录后投票
论坛首页 Web前端技术版

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