面试官:聊聊作用域问题

共 2666字,需浏览 6分钟

 ·

2021-05-01 10:00

全局作用域

script 标签所在的区域就是所谓的全局作用域,全局作用域有一个全局的对象 window

我们所有定义的变量,函数,类,对象等等都是作用域 window 对象身上的

var a = 1
// 就是在window 对象上加上一个 a 属性

局部作用域(特指函数作用域)

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

foo(2)

会产生一个局部作用域,暂且叫做 fooScope, 这个作用域里面存储着这个局部作用域里面的所有变量定义,函数定义,对象定义等等。值得注意的是,全局作用域 globalScope 总是被我们忽视了,局部作用域是可以访问全局作用域的。

所以


globalScope(顶层)
    |
    |
fooScope(当前)

发出疑问

  1. 既然局部作用域能够访问全局作用域的变量,那么局部作用域能不能修改全局作用域变量的值呢?

答案是可以的,我们来看个简单的例子

var a = 1
function foo({
    a = a + 1
    console.log(a); // 2
}
foo()

console.log(a) // 2

函数参数是值引用

var a = 1
function foo(a{
    a = a + 1
    console.log(a)
}
foo(a) // 2

console.log(a) // 1 说明全局中的 a 与函数参数的 a 存储的地方不一样

嵌套作用域

var a = 1
function foo(a{
    function bar(a{
        console.log("bar ===>", a)
        console.log(this)
    }
    console.log("foo"this)
    bar(a)
}
foo(a)

打印出来的顺序如下:

foo: window
bar===> 1
window

先来说说这个 a 的寻找过程:

  1. bar 执行,会在自己的作用域 barScope 找这个变量 a
  2. 发现找不到,会在 fooScope 作用域找,发现找不到
  3. 就找到全局作用域 window 中,发现有 a 这个变量

我们来验证下寻找的过程:

var a = 1
function foo({
    var a = 2
    function bar({
        console.log("bar ===>", a)
        console.log(this)
    }
    console.log("foo"this)
    bar()
}
foo()

打印出来如下:

foo:window
bar===>2
bar:window

所以找到要用到的变量之后,就会停止寻找了。

执行顺序

  1. 词法解析

    解析全局作用域,函数,变量

  2. 语法解析

    生成程序结构树

  3. 代码生成

  4. 执行代码

var a = 1
function foo({
    var a = 2
    function bar(a{
        console.log("bar ===>", a)
        console.log("bar ===>",this)
    }
    console.log("foo"this)
    bar(a)
}
foo()

所以

解析阶段

  1. 全局作用域 有变量 a
  2. foo 作用域 有 fooScope.a/window.a
  3. bar 作用域 有barScope/fooScope.a/window.a

执行阶段

  1. bar 执行返回,销毁
  2. foo 执行返回,销毁
  3. window

这样就形成了作用域链


浏览 58
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报