详解js的作用域、预解析机制


Posted in Javascript onFebruary 05, 2018

虽然,ES6在我们工作中应用得越来越广泛,但是还是很多项目保留着ES5的写法,所以,今天,带着大家重新巩固下ES5下的作用域及预解析机制。

概念:

作用域:域,指的是一个空间、范围、区域,作用指的是在域内可进行读写操作。一个变量的作用域是程序源代码中定义的这个变量的区域。

在ES5中,只存在全局和函数级作用域,在ES6中,引入了块级作用域,js的预解析机制大概分为两个过程:预解析和自上而下逐行解读

预解析:js解析器会先把var定义的变量、function、参数等一些东西存储进仓库里面(内存)。变量var在正式运行之前,都赋值为undefined,function函数在运行之前,就是整个函数块

逐行解读

表达式=、+、-、*、/、++、--、!、%.....number()、参数都可以赋值

遇到重名的,只留下一个,变量和函数重名,函数优先级高于变量,只留下函数

函数调用(函数是一个作用域,遇到作用域都会按照先进行预解析,然后逐行解读的过程执行),先局部找参数,局部找不到就自下向上找(作用域链)

概念扯了一大段,估计初学者还是有点晕乎乎,老司机就可以提前下车了,接下来,咋们举几个小栗子,结合上面的理论,深入理解。

实践

例1:

alert(a); //error: a is not defined
a = 3;

分析:

预解析

上面说过,预解析时只会把var 、 function 、参数等存储起来,所以:

整个作用域没有找到var function 参数

逐行解读

预解析后,内存中存在a且被赋值了underfind整个变量,所有,代码执行过程中程序直接报错。

例2:

alert(a); //undefined
var a = 3;

分析:

预解析

上面说过,预解析时只会把var 、 function 、参数等存储起来,所以:

执行到第二行时,a 的值是未定义。

逐行解读

第一行:预解析后,内存中存在a且被赋值了underfined

例3:

alert(a);          // function a (){ alert(4); }
var a = 1;
alert(a);          // 1
function a (){ alert(2); }
alert(a);          // 1
var a = 3;    
alert(a);          // 3
function a (){ alert(4); }
alert(a);          // 3

分析:

域解析

上面说过,预解析时只会把var 、 function 、参数等存储起来,所以:

执行到第二行时,a 的值是未定义。

执行到第四行时,a 的值是函数本身,也就是function a(){alert(2);}。

执行到第六行时,a 的值还是第四行时的值,也就是function a(){alert(2);},因为函数的优先级比变量高。

执行到第八行时,a 的值就变成了function a(){alert(4);} ,因为当两个函数重名时,遵循代码从上往下执行。

逐行解读

预解析完成之后,就是代码逐行执行了,

第一行:会弹出function a(){alert(4);} ,因为预解析完成之后,被存进内存的a 的值就是function a(){alert(4);}

第二行:第二行里有表达式,a 被赋了一个新的值1 表达式会改变变量的值。表达式可以改变预解析的值。

第三行:a现在被赋值为1,所有会弹出1

第四行:只是函数的声明,并没有用到表达式,而且也没有函数的调用,所以不会改变a 的值。

第五行:因为a的值没有变化,所以还是1

第六行:使用了表达式,a 被赋了一个新的值3

第七行:会弹出3

第八行:函数的声明,不会改变a 的值。

第九行:a的值没有改变,所以还是3

通过上面的栗子,相信大家应该对变量作用域的预解析过程有一定的了解了,接下来,咋们再举几个函数作用域的栗子

例4:

var a=1;
function fn1(){
  alert(a); //undefined
  var a = 2;
}
fn1();
alert(a) //1

例5:

var a=1;
function fn1(a){
  alert(a); //1
  var a = 2;
}
fn1(a);
alert(a) //1

例6:

var a=1;
function fn1(a){
  alert(a); //1
  a = 2;
}
fn1(a);
alert(a) //1

例7:

var a=1;
function fn1(){
  alert(a); //1
  a = 2;
}
fn1(a);
alert(a) //2

这几个栗子想必不用在一步步分析吧,不过就一点小改动,可能结果就截然不同,所以,大家还是需要仔细琢磨下。

Javascript 相关文章推荐
如何用javascript判断录入的日期是否合法
Jan 08 Javascript
修改jquery.lazyload.js实现页面延迟载入
Dec 22 Javascript
同一页面多个商品倒计时JS 基于面向对象的javascript
Feb 16 Javascript
javascript 用函数语句和表达式定义函数的区别详解
Jan 06 Javascript
只需五句话搞定JavaScript作用域(经典)
Jul 26 Javascript
JavaScript 最佳实践:帮你提升代码质量
Dec 03 Javascript
javascript 中iframe高度自适应(同域)实例详解
May 16 Javascript
ES6的解构赋值实例详解
May 06 Javascript
微信小程序npm引入vant-weapp的踩坑记录
Aug 01 Javascript
Vue CLI3移动端适配(px2rem或postcss-plugin-px2rem)
Apr 27 Javascript
vue样式穿透 ::v-deep的具体使用
Jun 04 Javascript
详解Javascript实践中的命令模式
May 05 Javascript
Vue使用枚举类型实现HTML下拉框步骤详解
Feb 05 #Javascript
jQuery实现动态显示select下拉列表数据的方法
Feb 05 #jQuery
详解vue静态资源打包中的坑与解决方案
Feb 05 #Javascript
理解Koa2中的async&await的用法
Feb 05 #Javascript
zTree 树插件实现全国五级地区点击后加载的示例
Feb 05 #Javascript
使用vue如何构建一个自动建站项目
Feb 05 #Javascript
在 webpack 中使用 ECharts的实例详解
Feb 05 #Javascript
You might like
网站当前的在线人数
2006/10/09 PHP
php使用ob_start()实现图片存入变量的方法
2014/11/14 PHP
PHP实现链式操作的原理详解
2016/09/16 PHP
用Javascript做flash做的事..才完成的一个类.Auntion Action var 0.1
2007/02/23 Javascript
使用node.js 获取客户端信息代码分享
2014/11/26 Javascript
Javascript常用字符串判断函数代码分享
2014/12/08 Javascript
Javascript实现单张图片浏览
2014/12/18 Javascript
JavaScript设计模式之抽象工厂模式介绍
2014/12/28 Javascript
javascript实现全角半角检测的方法
2015/07/23 Javascript
jQuery实现鼠标悬停背景翻转的黑色导航菜单代码
2015/09/14 Javascript
bootstrap导航、选项卡实现代码
2016/12/28 Javascript
javascript添加前置0(补零)的几种方法
2017/01/05 Javascript
jquery.zclip轻量级复制失效问题
2017/01/08 Javascript
基于JavaScript中字符串的match与replace方法(详解)
2017/12/04 Javascript
JS设计模式之访问者模式定义与用法分析
2018/02/05 Javascript
React BootStrap用户体验框架快速上手
2018/03/06 Javascript
新版vue-cli模板下本地开发环境使用node服务器跨域的方法
2018/04/03 Javascript
浅谈Webpack打包优化技巧
2018/06/12 Javascript
nuxt.js 缓存实践
2018/06/25 Javascript
vue下history模式刷新后404错误解决方法
2018/08/18 Javascript
vue中导出Excel表格的实现代码
2018/10/18 Javascript
vue动态循环出的多个select出现过的变为disabled(实例代码)
2019/11/10 Javascript
《javascript设计模式》学习笔记七:Javascript面向对象程序设计组合模式详解
2020/04/08 Javascript
django表单的Widgets使用详解
2019/07/22 Python
Python 动态导入对象,importlib.import_module()的使用方法
2019/08/28 Python
Python json读写方式和字典相互转化
2020/04/18 Python
详解如何将 Canvas 绘制过程转为视频
2021/01/25 HTML / CSS
Smallable意大利家庭概念店:设计师童装及家居装饰
2018/01/08 全球购物
提高EJB性能都有哪些技巧
2012/03/25 面试题
2014乡镇“三八”国际劳动妇女节活动总结
2014/03/01 职场文书
职工代表大会主持词
2014/04/01 职场文书
师德演讲稿范文
2014/05/06 职场文书
中学清明节活动总结
2014/07/04 职场文书
国家机关领导干部民主生活会对照检查材料思想汇报
2014/09/17 职场文书
计划生育工作总结2015
2015/04/03 职场文书
Python+pyaudio实现音频控制示例详解
2022/07/23 Python