容易被忽略的JS脚本特性


Posted in Javascript onSeptember 13, 2011

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

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; 
})()
Javascript 相关文章推荐
使用js获取地址栏中传递的值
Jul 02 Javascript
巧用jquery解决下拉菜单被Div遮挡的相关问题
Feb 13 Javascript
JavaScript实现简单的tab选项卡切换
Jan 05 Javascript
jQuery动态改变多行文本框高度的方法
Sep 07 Javascript
js实现导航吸顶效果
Feb 24 Javascript
js捆绑TypeScript声明文件的方法教程
Apr 13 Javascript
element-ui 时间选择器限制范围的实现(随动)
Jan 09 Javascript
Vue js 的生命周期(看了就懂)(推荐)
Mar 29 Javascript
vue用ant design中table表格,点击某行时触发的事件操作
Oct 28 Javascript
微信小程序淘宝首页双排图片布局排版代码(推荐)
Oct 29 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
Nov 07 Javascript
ES6学习教程之Promise用法详解
Nov 22 Javascript
Javascript学习笔记-详解in运算符
Sep 13 #Javascript
使用原生javascript创建通用表单验证——更锋利的使用dom对象
Sep 13 #Javascript
ie下动态加态js文件的方法
Sep 13 #Javascript
使用Json比用string返回数据更友好,也更面向对象一些
Sep 13 #Javascript
TextArea不支持maxlength的解决办法(jquery)
Sep 13 #Javascript
JQuery与JSon实现的无刷新分页代码
Sep 13 #Javascript
js Event对象的5种坐标
Sep 12 #Javascript
You might like
PHP fgetcsv 定义和用法(附windows与linux下兼容问题)
2012/05/29 PHP
PHP字符串长度计算 - strlen()函数使用介绍
2013/10/15 PHP
PHP版微信公众平台红包API
2015/04/02 PHP
Symfony2联合查询实现方法
2016/03/18 PHP
Laravel多用户认证系统示例详解
2018/03/13 PHP
php实现等比例压缩图片
2018/07/26 PHP
php实现构建排除当前元素的乘积数组方法
2018/10/06 PHP
html数组字符串拼接的最快方法
2009/09/16 Javascript
验证码按回车不变解决方法
2013/03/29 Javascript
node.js中的http.response.end方法使用说明
2014/12/14 Javascript
js实现仿阿里巴巴城市选择框效果实例
2015/06/24 Javascript
js变形金刚文字特效代码分享
2015/08/20 Javascript
javascript设置和获取cookie的方法实例详解
2016/01/05 Javascript
Javascript实现单例模式
2016/01/24 Javascript
JS判断是否为JSON对象及是否存在某字段的方法(推荐)
2016/11/29 Javascript
浅谈javascript alert和confirm的美化
2016/12/15 Javascript
JS实现控制图片显示大小的方法【图片等比例缩放功能】
2017/02/18 Javascript
详解Vue.js入门环境搭建
2017/03/17 Javascript
DVA框架统一处理所有页面的loading状态
2017/08/25 Javascript
Python算法应用实战之栈详解
2017/02/04 Python
利用python打印出菱形、三角形以及矩形的方法实例
2017/08/08 Python
Python编程使用NLTK进行自然语言处理详解
2017/11/16 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
对python 调用类属性的方法详解
2019/07/02 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
浅析HTML5页面元素及属性
2021/01/20 HTML / CSS
手工社团活动方案
2014/02/17 职场文书
女生节标语
2014/06/26 职场文书
党员自我对照检查材料
2014/08/19 职场文书
写给医生的感谢信
2015/01/22 职场文书
户外活动总结
2015/02/04 职场文书
公司放假通知范文
2015/04/14 职场文书
2019年特色火锅店的创业计划书模板
2019/08/28 职场文书
亲情作文之母爱
2019/09/25 职场文书
Python OpenCV实现传统图片格式与base64转换
2021/06/13 Python
mysql连接查询中and与where的区别浅析
2021/07/01 MySQL