[查遗补漏] 考察作用域的一道题

再来一题:关于变量提升和作用域的

var a = 10;
(function () {
    console.log(a) // 输出:undefined
    a = 5
    console.log(window.a) // 输出:10 
    var a = 20;
    console.log(a); // 输出:20
})()

// 前提是在浏览器中执行,node中 window.a会报错 window is not defined
复制代码

简单点的分析

  1. 在立即执行函数中,var a = 20; 语句定义了一个局部变量a,由于js的变量声明提升机制,局部变量a的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined,最后一条语句会打印20

  2. 由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明,因此它产生的效果是对局部的变量a赋值,此时window.a 依旧是最开始赋值的10

相当于:

var a = 10;
(function () {
    var a; // 在函数作用域中,变量提升至此
    console.log(a) 
    a = 5
    console.log(window.a) //这里的window.a 在全局作用域中
    a = 20;
    console.log(a);
})()
复制代码

进阶分析

  1. 函数作用域可以访问全局作用域
var a = 123;
(function(){
  console.log(a) // 123
  a = 456
}());
console.log(a) // 456
复制代码

步骤解析:

var a = undefined;
a = 123;
(function(){
  console.log(a) // 函数作用域寻找变量a
  console.log(window.a) // 结果没找到,那么他会向上寻找,直到找到该变量,若最后没有找到,那么就会报该变量未定义
  window.a = 456 // 因为找到的是window的变量`a`所以此处会修改window的变量`a`
}());
console.log(a) // 456
复制代码

在这里实际还涉及到隐式声明,所以我在下面会说明

  1. 全局作用域中无法访问局部作用域的变量
(function(){
  var a = 456
}());
console.log(a) // Error: a is not defined
复制代码

步骤解析: window已经是全局作用域了,在这里并没有发现变量a所以不会继续向上寻找,直接输出 a is not defined

  1. 当局部作用域中进行隐式声明时,默认会在全局作用域中声明该变量
(function(){
  a = 456
}());
console.log(a) // 456
复制代码

参见及感谢

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享