容易被忽略的JS脚本特性

2014-06-19  来源:本站原创  分类:javascript技巧  人气:2 

容易被忽略的JS脚本特性,学习js的朋友可以参考下。

一、容易被忽略的局部变量

var a = 5;
(function(){
alert(a);
var a = a ++;
alert(a);
})()
alert(a);

思考这段代码的执行结果。
执行后,看看是否和你想象的一致?
ok,这段代码里核心的知识点是 var a = a++,其中两个变量 a 都是匿名函数内部的局部变量,是同一个,和全局变量 a 是不一样的。
为什么?我们来看看ECMA规范对变量声明语句的定义:

复制代码 代码如下:

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.

声明中提到:进入作用域环境后,变量就会被创建,并赋予初始值undefined。在变量声明语句执行时才会把赋值表达式的值指派给该变量,而并不是在该变量被创建时。
因此上面的代码可以等价于:

复制代码 代码如下:

var a;
a = 5;
(function(){
var a;
alert(a);
a = a ++;
alert(a);
})()
alert(a);

这样应该会更容易理解了。
二、容易被忽略的全局变量


复制代码 代码如下:

(function(){
var a = b = 5;
})()
alert(b);

这是玉伯几天前分享到的知识点,蛮有意义的,在此也做个分析。
首先,考虑执行结果为什么是:5。
ok,原因出在 var a = b = 5 这句。
为深入分析这个语句,我们继续要参照ECMA规范对声明语句的定义:
var a = b = 5;等同为 var a; a = b = 5;两条语句,后者是赋值表达式,其在ECMA中的定义是这样的:

复制代码 代码如下:

Simple Assignment ( = )
The production AssignmentExpression : LeftHandSideExpression =
AssignmentExpression is evaluated as follows:
1. Evaluate LeftHandSideExpression.
2. Evaluate AssignmentExpression.
3. Call GetValue(Result(2)).
4. Call PutValue(Result(1), Result(3)).
5. Return Result(3).

对于a = b = 5;先执行左边表达式 a,这是一个标识符表达式,根据规范第 10.1.4,其执行方式如下:

复制代码 代码如下:

During execution, the syntactic production PrimaryExpression : Identifier
is evaluated using the following algorithm:
1. Get the next object in the scope chain. If there isn't one, go to step 5.
2. Call the [[HasProperty]] method of Result(1), passing the Identifier as
the property.
3. If Result(2) is true, return a value of type Reference whose base
object is Result(1) and whose property name is the Identifier.
4. Go to step 1.
5. Return a value of type Reference whose base object is null and whose
property name is the Identifier.

搜寻作用域链,找到最近的一个 a 的引用,很明显,在匿名函数内部作用域就可以找到,于是变量 a 确定下来。
接着再执行右边的表达式 b = 5 ,还是一个赋值表达式,重复赋值规则第一步,因为变量 b 在匿名函数环境内未声明过,所以接着去 window 全局环境下去找 window.b ,被隐式声明为全局变量,最后赋值为 5,根据规则第五步,表达式的结果也会再赋值给 a。最终达到 a 和 b 都为 5 ,区别是 a 是局部变量,而 b 是全局变量。
我们再来理一下 (function(){var a = b = 5})() 表达式内部整体的执行顺序:
1.匿名函数内创建变量a;
2.赋予初始值undefined;
3.取得变量a的引用; //a
4.取得变量b的引用; //window.b
5.对数字5求值;
6.赋值5给b的引用:window.b;
7.返回b = 5的结果5给a的引用:a;
8.返回a = 5的结果5;
很明显,中间的一个步骤使得变量 b 被声明为全局变量,明白之后,我们不难找到代码的优化点:只需将变量 b 显式声明为局部变量:

复制代码 代码如下:

(function(){
var a,b;
a = b = 5;
})()
相关文章
  • 容易被忽略的JS脚本特性 2014-06-19

    容易被忽略的JS脚本特性,学习js的朋友可以参考下. 一.容易被忽略的局部变量 var a = 5; (function(){ alert(a); var a = a ++; alert(a); })() alert(a); 思考这段代码的执行结果. 执行后,看看是否和你想象的一致? ok,这段代码里核心的知识点是 var a = a++,其中两个变量 a 都是匿名函数内部的局部变量,是同一个,和全局变量 a 是不一样的. 为什么?我们来看看ECMA规范对变量声明语句的定义: 复制代码 代码如下

  • javascript实现js脚本的的异步加载 2014-11-17

    javascript实现js脚本的的异步加载,和图片的异步加载稍有不同,script的异步加载需要借助dom,因此有了局限性 <html> <head> <meta charset="utf-8" /> <title>Javascript</title> <meta http-equiv="X-UA-Compatible" content="IE=7"> </head&

  • 怎么判断js脚本加载完成 2013-10-12

    本篇文章主要是对判断js脚本加载完成的方法进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 在"按需加载"的需求中,我们经常会判断当脚本加载完成时,返回一个回调函数,那如何去判断脚本的加载完成呢? 我们可以对加载的 JS 对象使用 onload 来判断(js.onload),此方法 Firefox2.Firefox3.Safari3.1+.Opera9.6+ 浏览器都能很好的支持,但 IE6.IE7 却不支持.曲线救国 -- IE6.IE7 我们可以使用 js.onreadys

  • asp.net后台如何输出js脚本使用什么方法可以实现 2013-11-06

    asp.net后台如何输出js脚本,用page.ClientScript.RegisterStartupScript方式实现,实现示例如下,感兴趣的朋友不要错过 用page.ClientScript.RegisterStartupScript方式实现 代码为: /**//// <summary> /// 弹出JavaScript小窗口 /// </summary> /// <param name="js">窗口信息</param> pub

  • JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE) 2013-12-06

    这篇文章主要是对JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 HTML元素,属性已经十分丰富了.但是,在某些场合下,也会显得捉襟见肘,这时候自定义属性就发挥了十分关键的作用. Html元素的自定义属性,使用起来,十分方便,例如: <input type="button" value="Click Me, Baby!" /> 假设我们现在需要限制

  • [对联广告] JS脚本类 2014-02-27

    //**************************************************************************************** //& 作者: 哇哇鱼 //& 日期: 2004年12月31日 //& 网站: http://www.13smile.com/ //& Blog: http://blog.csdn.net/bpfish //& 名称: [对联广告] JS脚本类 //& 作用: 显示页面的对联广告

  • wap手机图片滑动切换特效无css3元素js脚本编写 2014-03-24

    手机图片滑动切换,网上有很多这样的例子,但都借助于其他组件,让代码混乱的不行,本例无css3元素js脚本编写,需要的朋友可以参考下 手机图片滑动切换,网上有很多这样的例子,但都借助于其他组件,让代码混乱的不行:还有就是用到css3里的 transform:translate(x,y);移动元素,不过发现在不支持css3的设备上马上完蛋了,所 有下定决心自己做一个,谁知出现了很多的问题,其中最重要的是给图片加链接,网页中的上下滚动条不能在拖动图片的时候滚动,并且不能兼容pc机器上的拖动:在这里就简

  • 一个奇葩的最短的 IE 版本判断JS脚本 2014-05-08

    这篇文章主要介绍了一个奇葩的最短的 IE 版本判断JS脚本,非常酷的一段代码,需要的朋友可以参考下 使用 conditional comment 来判断 IE 的版本.嗯,是早早有人提出,但没有认真看代码.昨天刚好在看 CSS3 PIE 的时候看到,觉得是不是不靠谱.今天看到 Paul Irish 也提起,那么,推荐一下吧.这是作者博客上写的: // ---------------------------------------------------------- // A short sni

  • ASP.NET中常用输出JS脚本的类实例 2014-10-13

    这篇文章主要介绍了ASP.NET中常用输出JS脚本的类实例,针对过去的js脚本输出类进行了一定的改进,在进行asp.net程序开发时非常具有实用价值,需要的朋友可以参考下 本文实例讲述了ASP.NET中常用输出JS脚本的类,针对过去输出js脚本的类进行了一定的改进.在项目开发中非常具有实用价值.分享给大家供大家参考.具体如下: 很多时候在ASP.NET中我们经常需要输出一些JS脚本,比如弹出一个警告窗口,返回到历史页面等JS功能,我看到网上流传得比较广的是马先光写的一个JScript类,这个类基

  • 通过js脚本复制网页上的一个表格的不错实现方法 2014-10-15

    今天有人问我一个问题:如何通过js脚本复制网页上的一个表格?看起来似乎比较有难度,不过还是搞定了,顺便把解决这个问题的过程记录下来,希望能对写脚本的兄弟们有所帮助. 以前没有写过这种脚本,不过想起来前不久刚看到一个脚本可以实现全选HTML编辑器的内容,于是想到一个方案:使用脚本将该表格插入HTML编辑器中,然后全选HTML编辑器内容,执行HTML编辑器的复制命令,即可实现复制表格功能,很快搞定: 测试 测试表格 测试表格 测试表格 测试表格 文字 [Ctrl+A 全选 注:如需引入外部Js需刷新

  • wap图片滚动特效无css3元素纯js脚本编写 2014-10-20

    手机图片滑动切换,网上有很多这样的例子,但都借助于其他组件,让代码混乱的不行,本例介绍的是无css3元素纯js脚本编写的wap图片滚动特效 手机图片滑动切换,网上有很多这样的例子,但都借助于其他组件,让代码混乱的不行:还有就是用到css3里的 transform:translate(x,y);移动元素,不过发现在不支持css3的设备上马上完蛋了,所以下定决心自己做一个,谁知出现了很多的问题,其中最重要的是给图片加链接,网页中的上下滚动条不能在拖动图片的时候滚动,并且不能兼容pc机器上的拖动:在这

  • 兼容IE和FF的js脚本代码小结(比较常用) 2014-11-18

    做BS开发就难免会用到javascript,而每个浏览器对javascript的支持有不同.这就需要我们程序员去兼容他们下面是兼容IE和FF的js脚本做法和分解(部分选自网上,经本人整理),希望对大家有帮助. /*以下以 IE 代替 Internet Explorer,以 MF/FF 代替 Mozzila Firefox */ //window.event IE:有window.event对象 FF:没有window.event对象.可以通过给函数的参数传递event对象.如onmousemov

  • 上传图片预览JS脚本 Input file图片预览的实现示例 2014-11-30

    需要一个用户上传头像预览的功能,因此写了一段上传图片预览JS脚本,Input file图片预览的实现,需要的朋友可以看看 在深圳做项目的时候,需要一个用户上传头像预览的功能!是在网上找了好多,都不太满意.要么是flash的,要么是Ajax上传后返回图片路径的,要么压根就是不能用的.幸运的是在这个项目以前有人写过一个图片预览的功能,还被我给翻了出来,在这里做个记录,方便自己以后用,也方便其他需要的朋友! 代码很简单,如下: <!DOCTYPE html PUBLIC "-//W3C//DTD

  • js脚本获取webform服务器控件的方法 2014-12-20

    asp.net webform中获取服务器控件,js脚本获取服务器控件需要使用ClientID,下面有个示例,大家可以参考下 asp.net webform中获取服务器控件,js脚本获取服务器控件需要使用ClientID web前台获取控件: <%=TextBox1.ClientID %>会打印出TextBox1的控件ID js脚本中获取webform控件:(实现当鼠标移到控件时,控件颜色变成红色) <script type="text/javascript">

  • ASP.NET中常用的用来输出JS脚本的类 2015-01-30

    在ASP.NET中我们经常需要输出一些JS脚本,比如弹出一个警告窗口,返回到历史页面等JS功能,我看到网上好多这方面的代码,以下代码是其中之一. 整个程序的代码如下: using System; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; /// <summary> /// 弹出JavaScript小窗口 /// </summary> ///

  • PhotoShop给图片自动添加边框及EXIF信息的JS脚本 2015-02-27

    这篇文章主要介绍了PhotoShop给图片自动添加边框及EXIF信息的JS脚本,本文给出效果图和实现代码,需要的朋友可以参考下 作为一名"摄影爱好者"(好吧我承认我不太合格,我才玩摄影没几天-_-!!)总有一件事情避免不了,就是让照片带上EXIF的参数,虽然本人的部落格已经安装了插件可以显示出EXIF信息,但是感觉插件还是不太给力,此外还要考虑到一些综合的操作,比如批量的调整大小,增加版权信息等等. 当然,好在我们还要PS,我们还可以写PS的脚本让他来按照我们的想法来进行某些操作:)嘿

  • 兼容主流浏览器的iframe自适应高度js脚本 2015-03-17

    兼容主流浏览器的 iframe 自适应高度,很实用的,具体的js脚本如下,感兴趣的朋友可不要错过 兼容主流浏览器的 Iframe 自适应高度,js脚本如下: //iframe 高度自适应 function iframeAutoFit(iframeObj) { setTimeout(function () { if (!iframeObj) return; iframeObj.height = (iframeObj.Document ? iframeObj.Document.body.scroll

  • 利用asp:scriptmanager和updatepanel进行异步更新,然后再回调js脚本 2012-07-25

    这几天一直在弄asp.net的开发, 其中一个功能是要求要对页面进行异步更新,更新完了之后还要再回调js脚本,对返回的页面内容再 进一步加工. 在网上搜索,然后再自己实验,搞了差不多一个下午才搞定,贴出来吧. 关键点就是...在页面的C#代码中,当异步要求的操作完成后,加上这么一句来回调js ScriptManager.RegisterStartupScript(this.panel2, this.GetType(), "", "alert('ok!');", tr

  • Page_Load事件 js脚本 aspx执行顺序 2013-06-28

    示例: 实现目的:某对象被使用时,将此对象对应的功能按钮禁止: 后台代码:Page_Load() 事件下的代码 前台代码:对象不确定,这里采用对象的动态绑定 运行效果:页面初始化时,对应的被占用对象的总功能按钮不会被禁止,点击页面中任一按钮时,此功能按钮才会被禁止. 分析:对于页面的初始化,代码执行顺序: 1) Page_Load事件,包括if(!isPostBack){}中的语句: 2)向IE发出请求,IE先执行页面中的脚本语句,此时页面呈现: 对于页面中的按钮,代码执行顺序: 1)IE会先查

  • WiFi流量劫持-- JS脚本缓存投毒 2015-04-30

    在上一篇<WiFi流量劫持-- 浏览任意页面即可中毒>构思了一个时光机原型,让我们的脚本通过HTTP缓存机制,在未来的某个时刻被执行,因此我们可以实现超大范围的入侵了. 基于此原理,我们用NodeJS来实现一个简单的样例.得益于node强大的IO管理,以及各种封装好的网络模块,我们可以很容易实现这个想法: 开启一个特殊的DNS服务:所有域名都解析到我们的电脑上.并把Wifi的DHCP-DNS设置为我们的电脑IP. 之后连上Wifi的用户打开任何网站,请求都将被我们的node服务收到.我们根据h