执行上下文与作用域

104 阅读2分钟

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

全局上下文

全局上下文是最外层的上下文,在浏览器中通常用window来表示,好我们打印一下window看一下

QQ截图20220531100616.jpg

window身上有非常多的属性,所有通过var定义的变量和函数都会成为window对象的属性和方法,上下文会在所有代码执行完毕后销毁,

函数上下文

每个函数都有自己的上下文,函数开始执行时会被推入到一个上下文栈中,在函数执行完后会从上下文中弹出,

var color = "blue"

function changeColor() {
  if(color === 'blue') {
    color = 'red'
  }else {
    color = 'black'
  }
}

changeColor()的作用域包含两个对象,一个是它自己的变量对象,另一个是全局上下文的变量对象,函数内部可以访问到color,通过作用域链去找到。

var color = "blue"
function changeColor() {
  let anotherColor = "red"
  console.log(tempColor)

  function swapColors() {
    let tempColor = anotherColor;
    anotherColor = color;
    color = tempColor
  }

  swapColors()

}
  1. window
    1. color
    2. changeColor
      1. anotherColor
      2. swapColors
        - tempColor

以上是这段代码的作用域链,可以发现内部上下文可以通过作用域链访问到外部上下文中的一切,但是外部上下文不能访问内部的一切

变量声明

使用var声明

function add(num1,num2) {
  var sum = num1 + num2;
  return sum
}

let res = add(1,2);
console.log(res) // 3 
console.log(sum) //sum is not defined

此时sum在全局上下文中没有声明,将代码改写一下如下:

function add(num1,num2) {
  sum = num1 + num2;
  return sum
}

let res = add(1,2);
console.log(res) // 3 
console.log(sum) // 3

调用add()函数之后,sum被添加到全局上下文,var声明被拿到函数或者全局作用域的顶部, 验证一下变量提升:

function fn() {
  console.log(name)  //undefined
  var name = 'kobe'
  
  // 相当于
  var name 
  name = 'kobe'
}

fn()

使用let声明

let作用域的块级的,let与var 另一个区别是在同一个作用域不能声明两次,不存在变量提升。重复的var声明会被忽略

使用const声明

const用来声明常量,声明基本数据类型不可以做修改。

const res = 'kobe';
res = '11' // Assignment to constant variable.