js-词法分析:为什么变量与函数会出现声明提升?

函数在运行阶段之前还存在一个非常重要的阶段叫做词法分析阶段,该阶段主要分几步做了几件事:

第一步:分析参数

第二步:分析var变量声明

第三步:分析函数声明

具体步骤:

  1. 在函数运行前,生成Active Object(活动对象AO)。

  2. 把收到的形参作为AO属性,属性值为实参值。

  3. 分析var变量声明。如 var age。

    如果AO上没有age属性,则在AO上添加对应的属性,值为undefined,如AO = {age: undefined}

    如果AO上存在该属性,则不作任何操作

  4. 分析函数声明,如function foo () {}。则把函数赋给AO.foo属性;如果AO.foo已存在则会被覆盖。

1.词法分析例子

function a(b) {
    console.log(b); //[Function: b]

    function b() {
        console.log(b); //[Function: b]
    }

    b()
}

a(1)

分析以上词法分析阶段以及运行阶段如下:

词法分析阶段

  1. AO = {}

  2. 分析参数 AO = {b: undefined},接收实参 AO = {b: 1}

    1. 分析var变量:没有
    2. 分析函数声明 AO = {b: function () {console.log(b)}}

运行阶段

  1. console.log(b) 从AO中找b,发现b是个函数
  2. b() //由作用域找向外层函数中的b

稍微修改下代码,思考如下例子

function a(b) {
    console.log(b); //1

    b = function () {
        console.log(b); //[Function: b]
    }

    b()
}

a(1)

词法分析阶段

  1. AO = {}
  2. 分析参数 AO = {b: undefined} -> {b: 1}
  3. 分析var变量声明 没有
  4. 分析函数声明 没有。注意:b = function () {}是赋值过程,在执行期执行

运行阶段

  1. console.log(b) 从AO中找b,找到,并打印1
  2. b = function () {console.log(b)} ,b进行赋值操作后,AO = {b:function () {console.log(b)}}
  3. b(),执行函数b,里面有console.log(b),b会沿着作用域向外找,找到AO中的b,即是自己

2.函数声明与函数表达式

//函数声明
function a () {}

//函数表达式
var a = function () {}

函数声明与函数表达式的最重要的区别就是是否会在词法分析阶段进行解析。函数声明会在词法分析阶段被解析,而函数表达式会先以变量的形式在词法分析阶段解析,然后在执行期进行赋值。

a() // a
function a() {
  console.log('a');  
}

b() //b is not a function
var b = function () {
    console.log('b');
}
//自己思考下

所以词法分析阶段是变量声明提升以及函数声明提升的根本原因

3.一个有趣的函数

//一个有趣的函数
(function (a, undefined) {})('我是a')

上面是一个立即执行的匿名函数,有两个形参,但是为什么外部只传入一个参数?

其实这主要是因为undefined不是js中的保留关键字,所以undefined可以作为变量名使用,这样操作会造成一个结果,就是使用typeof进行undefined判断时产生影响。所以在函数中第二个形参是undefined但是又不传实参,所以结果就是undefined = undefined(理解起来就是变量名undefined的值是undefined)。在这个函数中就可以避免undefined带来的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值