容易被忽略的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 相关文章推荐
JavaScript基本概念初级讲解论坛贴的学习记录
Feb 22 Javascript
Mootools 1.2教程 输入过滤第二部分(字符串)
Sep 15 Javascript
自己用jQuery写了一个图片的马赛克消失效果
May 04 Javascript
快速实现jQuery多级菜单效果
Feb 01 Javascript
JS中setTimeout和setInterval的最大延时值详解
Feb 13 Javascript
基于AGS JS开发自定义贴图图层
Mar 31 Javascript
JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题
Jun 30 Javascript
Vue filter 过滤当前时间 实现实时更新效果
Dec 20 Javascript
关于vue3.0中的this.$router.replace({ path: '/'})刷新无效果问题
Jan 16 Javascript
使用Node.js实现base64和png文件相互转换的方法
Mar 11 Javascript
vue 使用原生组件上传图片的实例
Sep 08 Javascript
vue组件添加事件@click.native操作
Oct 30 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正则匹配文章中的远程图片地址并下载图片至本地
2015/09/29 PHP
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
实现laravel 插入操作日志到数据库的方法
2019/10/11 PHP
JQuery 动态扩展对象之另类视角
2010/05/25 Javascript
Firebug入门指南(Firefox浏览器)
2010/08/21 Javascript
JavaScript获取页面上某个元素的代码
2011/03/13 Javascript
js模拟滚动条(横向竖向)
2013/02/22 Javascript
JS判断数组中是否有重复值得三种实用方法
2013/08/16 Javascript
Js判断参数(String,Array,Object)是否为undefined或者值为空
2013/11/04 Javascript
javascript手工制作悬浮菜单
2015/02/12 Javascript
JavaScript获取网页中第一个图片id的方法
2015/04/03 Javascript
jQuery基于正则表达式的表单验证功能示例
2017/01/21 Javascript
nodeJS(express4.x)+vue(vue-cli)构建前后端分离实例(带跨域)
2017/07/05 NodeJs
基于 Immutable.js 实现撤销重做功能的实例代码
2018/03/01 Javascript
JavaScript日期工具类DateUtils定义与用法示例
2018/09/03 Javascript
vue地址栏直接输入路由无效问题的解决
2018/11/15 Javascript
AjaxFileUpload.js实现异步上传文件功能
2019/04/19 Javascript
Postman内建变量常用方法实例解析
2020/07/28 Javascript
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
2017/06/15 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
2019/01/29 Python
Python利用itchat库向好友或者公众号发消息的实例
2019/02/21 Python
浅谈PySpark SQL 相关知识介绍
2019/06/14 Python
如何利用Python开发一个简单的猜数字游戏
2019/09/22 Python
pygame实现俄罗斯方块游戏(AI篇1)
2019/10/29 Python
Python连接mysql方法及常用参数
2020/09/01 Python
Python调用SMTP服务自动发送Email的实现步骤
2021/02/07 Python
新加坡领先的时尚生活方式零售品牌:CHARLES & KEITH
2018/01/16 全球购物
英国受欢迎的运动鞋和街头服装商店:Footasylum
2018/06/12 全球购物
目标管理责任书
2014/04/15 职场文书
工地宣传标语
2014/06/18 职场文书
植物生产学专业求职信
2014/08/08 职场文书
团代会邀请函
2015/02/02 职场文书
追悼词范文大全
2015/06/23 职场文书
2016年教师师德师风承诺书
2016/03/25 职场文书
班组长如何制订适合本班组的工作计划?
2019/07/10 职场文书
导游词之丹东鸭绿江
2019/10/24 职场文书