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

 更新时间:2018年02月05日 16:34:31   投稿:laozhang  
本篇文章主要给大家详细分析了js的作用域、预解析机制以及相关代码分析,对此感兴趣的朋友学习下吧。

虽然,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

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

相关文章

  • 微信小程序input、textarea层级过高穿透的问题解决

    微信小程序input、textarea层级过高穿透的问题解决

    微信小程序原生组件camera、canvas、input、live-player、live、pusher、map、textarea、video的层级是最高的,那么如何解决微信小程序input、textarea层级过高穿透,本文就详细的介绍一下
    2021-11-11
  • 封装html的select标签的js操作实例

    封装html的select标签的js操作实例

    本文将为大家介绍下正如标题所示的select操作:清空所有的选项、添加一个选项、根据值、选中一个选项、根据下标,选中一个选项,感兴趣的朋友可以参考下哈,希望对大家有所帮助
    2013-07-07
  • Bootstrap 树控件使用经验分享(图文解说)

    Bootstrap 树控件使用经验分享(图文解说)

    很多项目中使用树来展示层级关系,还有些树是为了选中项然后其他地方调用选中项。今天脚本之家小编给大家带来了Bootstrap 树控件使用经验分享,需要的朋友参考下吧
    2017-11-11
  • 简单的分页代码js实现

    简单的分页代码js实现

    简单的分页代码js实现,分享给大家,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • 问题解析有JSDoc还需要TypeScript吗

    问题解析有JSDoc还需要TypeScript吗

    这篇文章主要介绍了有JSDoc还需要TypeScript的问题示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • layer.alert回调函数执行关闭弹窗的实例

    layer.alert回调函数执行关闭弹窗的实例

    今天小编就为大家分享一篇layer.alert回调函数执行关闭弹窗的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • 让你彻底掌握es6 Promise的八段代码

    让你彻底掌握es6 Promise的八段代码

    Promise对象可以理解为一次执行的异步操作,使用promise对象之后可以使用一种链式调用的方式来组织代码;让代码更加的直观,下面这篇文章主要跟大家分享了让大家彻底掌握es6 Promise的八段代码,需要的朋友可以参考下。
    2017-07-07
  • 微信二次分享报错invalid signature问题及解决方法

    微信二次分享报错invalid signature问题及解决方法

    基于微信公众号开发的h5页面(使用jssdk接口),由用户A分享给用户B,用户B再次分享这个页面时,不能成功分享。这篇文章主要介绍了微信二次分享报错invalid signature问题及解决方法,需要的朋友可以参考下
    2019-04-04
  • react基本安装与测试示例

    react基本安装与测试示例

    这篇文章主要介绍了react基本安装与测试,结合实例形式分析了react基本安装命令、引用与测试相关实现技巧,需要的朋友可以参考下
    2020-04-04
  • js关闭当前页面(窗口)的几种方式总结

    js关闭当前页面(窗口)的几种方式总结

    js关闭当前页面(窗口)的几种方式总结,需要的朋友可以参考一下
    2013-03-03

最新评论