- 浏览: 304259 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
花易歌:
如果是不同的字段,2.2里面的or也会多次扫描表,这样的话un ...
mysql 实战 or、in与union all 的查询效率 -
代码有点长:
试过好多个,就楼主的实现了,
pdf2swf+flexpaper解决pdf在线阅读(类百度文库) -
z798227085:
按楼主方法实现了 给32个赞~~
pdf2swf+flexpaper解决pdf在线阅读(类百度文库) -
hhg_ch:
thanks ! Good knowledge!
pdf2swf+flexpaper解决pdf在线阅读(类百度文库) -
80197675:
songshuaiyang 写道博主在吗?请问一下,我用自己的 ...
pdf2swf+flexpaper解决pdf在线阅读(类百度文库)
[<<javascript征途>>-第四章 J存在这样的一句话【javaScript 解释器会在预编译期就把函数处理了,而对于匿名函数却视而不见,直到执行期才按表达式逐行进行解释。】
我认为该结论是错误的应该解释为
JavaScript 解释器会在预编译期就把函数处理了及变量声明处理,直到执行期才完成对变量的赋值及表达式的处理。
并不是对匿名函数视而不见
示例
<script Language="JavaScript"> test();//1 function test(){ alert( "test1" ); } test();//2 function test(){ alert( "test2" ); } test();//3 </script>
按我们以前说的JavaScript是从上到下执行,这样理解的话1的话应该是报错,2的话应该为test1,3的话应该test2。
但实际上我们看到的结果三处都为test2。
为什么会这样呢
第一:JavaScript时按<script></script>编译,并执行的。
第二:JavaScript编译时完成对变量的声明,及函数处理。
第三:JavaScript后声明的函数将会覆盖前声明的函数
从上面三条我们可以看出在编译时 第二个test函数将覆盖第一test函数。当执行test时,对于<script>中只存在第二个test的定义,所以三处消息都为test2
请看如下示例
<script Language="JavaScript"> test();//1 var test = function( ){ alert( "test1" ); } test();//2 function test(){ alert( "test2" ); } test();//3 </script>
这样结果会是什么呢。
结果可能也让你意外,1为test2,2为test1,3为test1。
这个也可以用上面的第二条解释,对应变量test解释器只会完成相应的声明,而不会完成相应的赋值。所以test 的实际为第二函数test,这也是为什么1弹出test2,当代码执行到var test时,这个时候才完成对变量test赋 值,及将匿名函数赋值给test这样函数2和3为什么会是结果test1呢。
各位看到这里也没说明<<javascript征途>>中理论的错误,不着急大家可以看如下示例
<script Language="JavaScript"> test();//1 var test1 = function test ( ){ alert( "test1" ); } test1();//2 function test(){ alert( "test2" ); } test();//3 </script>
各位想想test1()会是什么结果,按照<<javascript征途>>中的说明将有名函数test赋值给test1,并在解释阶段完成对test函数表达式的处理。
结果1为test2,2也为test2,3也为test2
但结果确与<<javascript征途>>结论的结果不一致,
真实的结果为 1为test2,2为test1,3为test2
第一个test函数并未在解释阶段完成处理,而是在执行阶段完成处理,并且不能覆盖解释阶段的test的函数定义。所以才有了如上结果。
以上是我个人的一点看法,对于JavaScript底层机制还不时挺熟悉,只能结合测试的代码说明这个问题。请各位大虾结合自己的看法发表下意见。
评论
<div class="quote_div">
<p>如果IE下能访问到非匿名函数表达式的Identifier,那表明IE对这种表达式(var a = function Fun(){})的解释执行与ECMAScript标准不符,这里找到了一篇文章非常详细地分析了这玩艺:</p>
<p><a href="http://kangax.github.com/nfe/">Named function expressions demystified</a> (JScript bugs讲述了IE的bug)</p>
<p> </p>
<p>摘选这篇分析的结果:</p>
<p>IE下,所有function xxx(){}这类表达式,都会进行预定义(与标准严重不符,包括赋值语句及其它块中的也处理了)</p>
<p>如果按ECMA标准应该算是FunctionExpression的带Identifier的函数语句,IE即当声明又当表达式,并且执行双份:</p>
<pre name="code" class="js">var a = function b(){
alert("test");
};
// 按标准,此处应出错,因为b未定义。
alert(a === b); // IE下为false... IE sucks</pre>
<p> 它可以看作类似于以下代码:</p>
<pre name="code" class="js">function b(){
alert("test");
}
var a = function(){
alert("test");
};
alert(a === b);</pre>
<p> </p>
<p>对此。。。我的看法是:这些东西太低层了,各个浏览器差异还真不小,理解就好了,不用太过于专注。</p>
<p>尽量不要用带名称的函数表达式,函数声明放在最外层。</p>
<p> </p>
<p>最后再来一句: IE sucks</p>
</div>
<p><br> clue 你也太厉害呢,全是英文材料,膜拜中!!!!!!!!!!!!!!!!!!!!!</p>
<p> 现在在整理JavaScript,发现很多的概念【很多的概念在网上解释的也不正确】及代码书写模式以前都没见过。</p>
<p> 以后有问题向clue请教。</p>
<div class="quote_div">
<p>很感谢clue的解释</p>
<p>尤其对于函数表达式及函数定义概念和对于函数表达式作用域链的解释。</p>
<p>不过一下代码在IE与Firefox存在差异,</p>
<pre name="code" class="js"><script Language="JavaScript">
var test1 = function test ( ){
alert( "test1" );
}
alert( test );
test();
window.test();
</script></pre>
<p> 这个代码在IE中并未提示错误,alert() 与test函数,window.test(),运行正常,</p>
<p>在Firefox存在错误也就是未定义。</p>
<p>我在IE下调试的这样一直以为test作用域处于widow下,所以对于</p>
<pre name="code" class="js">test(); // statement 1
var test1 = function test ( ){
alert( "test1" );
}; // statement 2
test1();//statement 3
function test(){
alert( "test2" );
} // declaration
test();//statement 4</pre>
<p>
这个的执行结果有点迷惑,尤其《JavaScript征途》那句话的更让我迷惑。</p>
<p>看到clue的解释尤其英文中关于函数表达式的作用域的说明才让我明白。</p>
<p> </p>
</div>
<p>如果IE下能访问到非匿名函数表达式的Identifier,那表明IE对这种表达式(var a = function Fun(){})的解释执行与ECMAScript标准不符,这里找到了一篇文章非常详细地分析了这玩艺:</p>
<p><a href="http://kangax.github.com/nfe/">Named function expressions demystified</a> (JScript bugs讲述了IE的bug)</p>
<p> </p>
<p>摘选这篇分析的结果:</p>
<p>IE下,所有function xxx(){}这类表达式,都会进行预定义(与标准严重不符,包括赋值语句及其它块中的也处理了)</p>
<p>如果按ECMA标准应该算是FunctionExpression的带Identifier的函数语句,IE即当声明又当表达式,并且执行双份:</p>
<pre name="code" class="js">var a = function b(){
alert("test");
};
// 按标准,此处应出错,因为b未定义。
alert(a === b); // IE下为false... IE sucks</pre>
<p> 它可以看作类似于以下代码:</p>
<pre name="code" class="js">function b(){
alert("test");
}
var a = function(){
alert("test");
};
alert(a === b);</pre>
<p> </p>
<p>对此。。。我的看法是:这些东西太低层了,各个浏览器差异还真不小,理解就好了,不用太过于专注。</p>
<p>尽量不要用带名称的函数表达式,函数声明放在最外层。</p>
<p> </p>
<p>最后再来一句: IE sucks</p>
<div class="quote_div">翻了翻ECMAScript edition3 (<img src="/images/smiles/icon_confused.gif" alt=""> 发现这玩艺越读越深,每次都有小惊喜……)<br><br><strong>函数定义有两类,函数声明与函数表达式:</strong><br>FunctionDeclaration : <br> function Identifier ( FormalParameterList<span style="font-size: xx-small;">opt</span> ) { FunctionBody } <br>FunctionExpression : <br> function Identifier<span style="font-size: xx-small;">opt</span> ( FormalParameterList<span style="font-size: xx-small;">opt</span> ) { FunctionBody } <br><br><span style="text-decoration: underline;">可以看到, function A(){} 与 var a = function A(){}是完全不同的,一个是声明,一个是表达式。</span><br>(而与var a = function(){}的区别请看附1)<br><br><strong>而JS程序的组成为:</strong><br>Program : <br> SourceElements <br>SourceElements : <br> SourceElement <br> SourceElements SourceElement <br>SourceElement : <br> Statement <br> FunctionDeclaration <br><br><strong>执行过程为:</strong><br>1. Process SourceElements for function declarations. <br>2. Evaluate SourceElements. <br>3. Return Result(2). <br><br>即:先处理函数声明,再处理代码。<br>var a = function A(){}不属于函数声明,它属于函数表达式(FunctionExpression)<br><br><span style="font-size: large;">so, 现在回到那句有争议的话,<strong>它的问题在于这两点</strong>:<br>1. "javaScript 解释器会在预编译期就把<span style="color: red;">函数</span>处理了" --> 应为"函数声明"<br>2. 漏掉了既非函数声明,也非匿名函数的表达式: var a = function A(){}</span><br><br><br>------------------------------------<br><strong>附1</strong>:<br>var a = function A(){} 这类函数表达式的解释执行过程<br>它并不是函数声明,试试这段代码就知道了:<br>var a = function Fun(){};<br>alert(Fun); // 会报错,并无Fun这个变量<br><br>ECMA中描述的解释执行过程:<br>The production FunctionExpression : function Identifier ( FormalParameterList<span style="font-size: xx-small;">opt</span> ) { FunctionBody } is evaluated as follows: <br>1. Create a new object as if by the expression new Object(). <br>2. Add Result(1) to the front of the scope chain. <br>3. Create a new Function object as specified in section 13.2 with parameters specified by FormalParameterListopt <br>and body specified by FunctionBody. Pass in the scope chain of the running execution context as the Scope. <br>4. Create a property in the object Result(1). The property's name is Identifier, value is Result(3), and attributes are <br>{ DontDelete, ReadOnly }. <br>5. Remove Result(1) from the front of the scope chain. <br>6. Return Result(3). <br>看起来头晕么?我也是到今天才突然明白过来,简单转述一下:<br>它与不带Identifier的函数表达式的区别在于,1,2,4,5步,临时将scope chain增加了一层(有点类似with语句),只不过这一层是空白对象,然后将Identifier定义在这层scope上。<br>然后,这个函数存储的[[scope]]能访问到自身的Identifier。<br>最后,创建函数完毕后,又将增加的这层scope移掉了,对外界来说,这段代码和没有Identifier一样,但对函数内部来说,它能通过Identifier访问自身。<br><br>模拟执行:<br><pre name="code" class="js">test(); // statement 1
var test1 = function test ( ){
alert( "test1" );
}; // statement 2
test1();//statement 3
function test(){
alert( "test2" );
} // declaration
test();//statement 4
</pre>
<br>1. 初始状态<br>scope chain: {global:[]}<br>2. 处理函数声明<br>scope chain: {global:[test1:undefined, test:function(){alert("test2")}]}<br>3. 执行第一句<br>scope chain: 同上<br>运行global.test // test2<br>4. 执行第二句{<br> 1. 新增对象插入到scope chain<br> scope chain: {empty_object:[]} -> {global:[test1:undefined, test:function(){alert("test2")}]}<br> 2. 创建函数,以F来称呼它<br> F.[[scope]] = {empty_object:[]} -> {global:...}<br> 3. 在4.1步中新增的对象上增加test属性<br> F.[[scope]] = {empty_object:[test:function(){alert("test1")}]} -> {global:...}<br> scope chain: 同上<br> 4. 从scope chain中移除4.1插入的对象<br> scope chain: {global: ...}<br>},并赋值给test1<br>scope chain: {global:[test1:function(){alert("test1")}, test:function(){alert("test2")}]}<br>5. 第三句<br>运行global.test1 // test1<br>6. 第四句<br>运行global.test // test2<br><br><strong>以上分析涉及到了scope chain相关知识,不懂的请自行查阅资料(google, ECMAScript)</strong>
</div>
<p> </p>
<p>很感谢clue的解释</p>
<p>尤其对于函数表达式及函数定义概念和对于函数表达式作用域链的解释。</p>
<p>不过一下代码在IE与Firefox存在差异,</p>
<pre name="code" class="js"><script Language="JavaScript">
var test1 = function test ( ){
alert( "test1" );
}
alert( test );
test();
window.test();
</script></pre>
<p> 这个代码在IE中并未提示错误,alert() 与test函数,window.test(),运行正常,</p>
<p>在Firefox存在错误也就是未定义。</p>
<p>我在IE下调试的这样一直以为test作用域处于widow下,所以对于</p>
<pre name="code" class="js">test(); // statement 1
var test1 = function test ( ){
alert( "test1" );
}; // statement 2
test1();//statement 3
function test(){
alert( "test2" );
} // declaration
test();//statement 4</pre>
<p>
这个的执行结果有点迷惑,尤其《JavaScript征途》那句话的更让我迷惑。</p>
<p>看到clue的解释尤其英文中关于函数表达式的作用域的说明才让我明白。</p>
<p> </p>
函数定义有两类,函数声明与函数表达式:
FunctionDeclaration :
function Identifier ( FormalParameterListopt ) { FunctionBody }
FunctionExpression :
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
可以看到, function A(){} 与 var a = function A(){}是完全不同的,一个是声明,一个是表达式。
(而与var a = function(){}的区别请看附1)
而JS程序的组成为:(附2有分析如何区分声明与表达式)
Program :
SourceElements
SourceElements :
SourceElement
SourceElements SourceElement
SourceElement :
Statement
FunctionDeclaration
执行过程为:
1. Process SourceElements for function declarations.
2. Evaluate SourceElements.
3. Return Result(2).
即:先处理函数声明,再处理代码。
var a = function A(){}不属于函数声明,它属于函数表达式(FunctionExpression)
so, 现在回到那句有争议的话,它的问题在于这两点:
1. "javaScript 解释器会在预编译期就把函数处理了" --> 应为"函数声明"
2. 漏掉了既非函数声明,也非匿名函数的表达式: var a = function A(){}
------------------------------------
附1:
var a = function A(){} 这类函数表达式的解释执行过程
它并不是函数声明,试试这段代码就知道了:
var a = function Fun(){};
alert(Fun); // 会报错,并无Fun这个变量
ECMA中描述的解释执行过程:
The production FunctionExpression : function Identifier ( FormalParameterListopt ) { FunctionBody } is evaluated as follows:
1. Create a new object as if by the expression new Object().
2. Add Result(1) to the front of the scope chain.
3. Create a new Function object as specified in section 13.2 with parameters specified by FormalParameterListopt
and body specified by FunctionBody. Pass in the scope chain of the running execution context as the Scope.
4. Create a property in the object Result(1). The property's name is Identifier, value is Result(3), and attributes are
{ DontDelete, ReadOnly }.
5. Remove Result(1) from the front of the scope chain.
6. Return Result(3).
看起来头晕么?我也是到今天才突然明白过来,简单转述一下:
它与不带Identifier的函数表达式的区别在于,1,2,4,5步,临时将scope chain增加了一层(有点类似with语句),只不过这一层是空白对象,然后将Identifier定义在这层scope上。(注:ECMAScript 3rd中是说new Object(),这使得它会受Object.prototype影响,会产生很多问题,很多浏览器并没按这个来做。ECMAScript 5th中已经改掉了)
然后,这个函数存储的[[scope]]能访问到自身的Identifier。
最后,创建函数完毕后,又将增加的这层scope移掉了,对外界来说,这段代码和没有Identifier一样,但对函数内部来说,它能通过Identifier访问自身。
模拟执行:
test(); // statement 1 var test1 = function test ( ){ alert( "test1" ); }; // statement 2 test1();//statement 3 function test(){ alert( "test2" ); } // declaration test();//statement 4
1. 初始状态
scope chain: {global:[]}
2. 处理函数声明
scope chain: {global:[test1:undefined, test:function(){alert("test2")}]}
3. 执行第一句
scope chain: 同上
运行global.test // test2
4. 执行第二句{
1. 新增对象插入到scope chain
scope chain: {empty_object:[]} -> {global:[test1:undefined, test:function(){alert("test2")}]}
2. 创建函数,以F来称呼它
F.[[scope]] = {empty_object:[]} -> {global:...}
3. 在4.1步中新增的对象上增加test属性
F.[[scope]] = {empty_object:[test:function(){alert("test1")}]} -> {global:...}
scope chain: 同上
4. 从scope chain中移除4.1插入的对象
scope chain: {global: ...}
},并赋值给test1
scope chain: {global:[test1:function(){alert("test1")}, test:function(){alert("test2")}]}
5. 第三句
运行global.test1 // test1
6. 第四句
运行global.test // test2
附2
由上面的文法定义得知,程序(或函数体)内容为SourceElements,内含多个并行的SourceElement。
而一个SourceElement由语句(Statement)或函数声明(FunctionDeclaration)组成
注意!再往下没有FunctionDeclaration的递归了,也就是说,只有在程序或函数体根层(因为是并列的SourceElement,没有包含)才算是FunctionDeclaration。
也就是说,如果在if块或其它块中的function xxx(){},并不算是声明,只是表达式罢了。
当然。。。IE总是出人意料,更详细资料看这里:
http://kangax.github.com/nfe/
以上分析涉及到了scope chain相关知识,不懂的请自行查阅资料(google, ECMAScript)
发表评论
-
JavaScript 申明对象及数组的几种方法
2013-03-24 18:24 1778在JavaScript中可以用下面的几种方法申明对象: ... -
JavaScript 直接使用get方式提交存在特殊字符【例如加号】的解决方法
2011-02-10 17:17 2531最近开发时碰到这样的 ... -
JavaScript this
2010-11-17 13:01 1820this是JavaScript中一个比较混乱的地方。其实理解J ... -
JavaScript匿名类整理
2010-11-02 11:06 2258以下为总结在开源的JavaScript框架中能看到很多这样语法 ... -
JavaScript作用域链
2010-10-22 13:13 1700作用域是程序开发的一 ... -
JavaScript开发中一些问题(二)
2010-06-02 17:57 1452JavaScript开发中一些问题(二) JavaScrip ... -
JavaScript开发中一些问题(一)
2010-06-01 21:08 1492JavaScript开发中一些问题(一) 作用域在方法中未采 ...
相关推荐
<!DOCTYPE html> ...<option value="">----量表四----</option> </select> <script type="text/javascript"> $(function(){ $("#table_id").comboSelect(); }); </script> </body> </html>
--------------调用javascript的类<br>Log----------------------写系统日志类<br>OperateFile--------------文件操作的类<br>SortTip------------------排序提示的类<br>Paging-------------------数据库分页的类...
<br/>//-----常规变量---<br/>//-----菜单项目---<br/>//-----插入菜单---<br/>//-----程序初试化---<br/>//-----单击超连接---<br/>//-----滑动处理---<br/>//-----滑出---<br/>//-----绝对定位---<br/>//-----关于...
DWR (Direct Web Remoting) 是一个开源的Java框架,它允许JavaScript在浏览器端直接调用服务器端的Java方法,从而实现动态Web应用中的Ajax功能,即无刷新更新页面。DWR通过在客户端和服务器之间建立一个通信层,使得...
Direct Web Remoting (DWR) 是一个开源的Java库,允许在Web应用程序中实现Ajax功能,即在客户端JavaScript和服务器端Java之间进行实时通信。DWR简化了这个过程,使得开发者无需处理底层的HTTP请求和响应,而是可以...
<br>HTML<br>HTML教程<br><br>HTML代码示例<br><br>HTML参考(Reference)<br><br>HTML知识库<br><br>CSS<br>CSS教程<br><br>CSS代码示例<br><br>CSS参考(Reference)<br><br>Javascript<br>Javascript教程<br><br>...
asp .net Label控件<br>用javascript操作 asp .net TextBox控件 下<br>用javascript操作asp.net label控件 外一篇<br>用javascript改变onclick调用的函数<br>用JavaScript加密保护网站页面<br>用Javascript检测网速...
书名:<br>---------------------------------<br>DOM Scripting Web Design with JavaScript and the Document Object Model<br>---------------------------------<br>语言:English<br>格式:PDF<br>打包:WinRAR
这是第一段文字在此处使用段落标记<p>我是第二段文字 </body> </html> ``` - **知识点**:`<p>`标记用于定义段落。 - **关键代码解析**:`<p>`标记用于区分不同的段落。 **例2-9**: 换行标记的应用。 ```html <html...
下面主要由LOGO、导航栏组成。通过a标签超链接组成,鼠标划过会有颜色变化,导航栏用无序列表ul更方便简洁。... <div class="box"> <!... <p id="shij"></p> <!--获取当前时间--> </div> </div> <div ...
**UglifyJS** 是一个广泛使用的JavaScript代码压缩工具,主要功能是将源代码压缩,减少文件大小,提高网页加载速度。它通过删除不必要的字符,如注释、空格、换行符,以及对变量名进行混淆来实现压缩。UglifyJS 也...
- `<create>`标签定义了一个可以被远程调用的服务,其中`creator`属性设为`spring`表示该服务由Spring容器管理,`javascript`属性指定了客户端调用时的JavaScript对象名称。 - `<param>`标签用于指定该服务在...
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="area.js"></script> <script> $(function(){ init("province","city","area"); }); </script> </head> <body> <!...
Direct Web Remoting (DWR) 是一个开源的Java库,允许Web应用程序在浏览器和服务器之间进行实时的、安全的通信,无需使用插件或复杂的JavaScript技术。它简化了Ajax(Asynchronous JavaScript and XML)开发,使得...
This book is both an example-driven programmer's guide and a keep-on-your-desk reference, with new chapters that explain everything you need to know to get the most out of JavaScript, including:<br>...
PageOffice是一个国产的打印插件,其强大之处在于其对Word的处理和它的在线编辑能力。准备工作包括下载Java版本的包,解压后需要把PageOffice.cab和pageoffice.jar两个包放到WEB-INF/lib中去,并在web.xml中加入以下...
<SCRIPT language="JavaScript" > function compute(op) { var num1,num2; num1=parseFloat(document.myform.num1.value); num2=parseFloat(document.myform.num2.value); if (op=="+") document.myform....
--[if lt IE 7]><script src="IE7.js" type="text/javascript"></script><![endif]--><br> 或<br><!--[if lt IE 8]><script src="IE8.js" type="text/javascript"></script><![endif]--><br><br>
│ ├<02 JavaScript> │ ├<03 BootStrap> │ ├<04 XML> │ ├<05 Tomcat> │ ├<06-Servlet和HTTP请求协议> │ ├<07 -Request和Respons> │ ├<08-Cookie和Session> │ ├<09-JSP,EL和JSTL> │ ├<10-综合案例...
< artifactId>gwt-material-addins</ artifactId> < version>2.5.0-rc1</ version> </ dependency> 快照版本2.5.0-快照 < dependency> < groupId>com.github.gwtmaterialdesign</ groupId> < artifactId>gwt-...