细说JS系列(八)

45 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

铃铛说点题外话

上一篇我们详细说了变量提升和函数提升,这一篇我们就根据几个案例详细的说说函数的执行过程

铃铛说正文

var message = "hello global"

function foo(){
    console.log(message)
}

function bar(){
    var message = "hello bar"
    foo()
}

bar()

上面这段代码的输出结果是:hello global。接下来我们详细说说这个函数的执行过程

  1. 第一步会创建一个全局作用域下的变量messagehello global
  2. 创建一个ECStrack(调用栈),这里面存在一个foo函数执行上下文,函数会开辟一块新的内存地址存放函数的信息:执行console.log(message)
  3. 继续开辟新的内存地址存放bar函数的信息,这里面存放着执行信息foo调用了foo函数
  4. 最后调用bar函数

输出结果:所以这里首先会调用函数bar,在函数bar里定义message变量的值为hello bar,之后调用函数foo,这里函数foo只有一个输出语句,输出变量message的值。这里需要注意,函数foo函数里面输出的值。这里需要注意函数foo里的输出语句实际是在要函数foo函数作用域内查找,如果自身查找不到会去上一级父级作用域进行查找。这里函数foo中并没有变量message所以回去函数foo的父级查找是否存在该变量,这里也就是全局的hello global,所以最终结果为hello global

这里可能也会有一部分同学不明白函数foo是怎么查找到父级作用域的变量的,其实很简单,这里涉及到一个新的知识点:作用域和作用域链。实际上父子作用域之间是通过一条作用域链连接在一起的,让我们能查找到父级的变量。

跟铃铛说再见

这里也留下了一个谜题:作用域和作用域链,我放在下一篇详细说说作用域和作用域链