用代码告诉你什么是作用域和执行上下文

65 阅读3分钟

作用域/执行上下文

  • JavaScript分为解释阶段和执行阶段
  • 作用域是解释阶段,就是函数写的时候作用域就确定了
  • 执行上下文是执行代码的时候才确定,特别是this的指向

作用域

  • 全局作用域
  • 函数作用域
  • 块级作用域(ES6中 let const定义的变量有块级作用域,而var没有块级作用域)
{
    var username = 'lisi'
    let age2 = 11
}
let age = 12
console.log(age); //12
console.log(age2); //error
console.log(username); //lisi

作用域链就是现在当前作用域中找,找不到就去上一级作用域中找

执行上下文

执行上下文是JavaScript运行时环境中的一个概念,它是用于管理每个函数执行时相关变量、函数和作用域的一种机制。在JavaScript中,每当调用一个函数时,就会创建一个执行上下文,该执行上下文包含了该函数所有的变量、参数、内部声明的函数以及对父级作用域的引用等信息。执行上下文还会建立函数执行的作用域,并且在函数执行结束后进行清理。

说到底,执行上下文就是当前代码所执行的环境,你在全局中执行,就创建一个全局上下文,在函数中被执行就创建函数上下文

执行上下文分三种

  • 全局上下文:只有一个,浏览器中的全局对象就是 window对象,this 指向这个全局对象
  • 函数内部上下文:函数被调用就创建
  • Eval 函数执行上下文:但是用的不多,不讲
	var x = 10;
  function fn() {
    console.log(x);
  }
  function show(f) {
    var x = 20;
    f();
  }
  show(fn); //10 当前的执行上下文是全局

--------------------------------------------------------------
  
	let x = 10
  let obj = {
    x:30,
    fnn:function(){
      fn()
    }
  }
  obj.fnn() //10 当前的执行上下文是全局

----------------------------------------------------------------
  
  function test(){
    let x=40
    function inner(){
      console.log(x);
    }
    inner()
  }
  test() //40 test是在全局中,但是 inner()是在test中执行的

----------------------------------------------------------------
  
let x = 1;
function fn() {
    let x = 2;
    fn1();
    function fn1() {
        console.log(x);
    }
    fn2();
     function fn2() {
        let x = 3;
        fn1();
    } 
}
fn(); //2 , 2 
let b = 4;
let obj = {
    b: 2,
    fn1: function () {
        console.log(b);
    }
}
obj.fn1(); //4

//需要注意的是,尽管obj对象中存在一个属性b,但该属性只能通过obj.b来访问,
//而不能通过b来访问。因此,即使obj.fn1()函数中使用了console.log(b),
//它实际上是在访问全局作用域中的变量b,而不是对象obj中的属性b。
//如果想要访问obj对象中的属性b,可以使用console.log(obj.b)来打印该属性的值。

---------------------------------------------------------
  
let b = 4;
let obj = {
    b: 2,
    fn1: function () {
         let b = 5; 
        console.log(b);
    }
}
obj.fn1(); //5

----------------------------------------------------------

let b = 4;
let obj = {
    b: 2,
    fn1: function () {
        console.log(this.b);
    }
}
obj.fn1(); //2

//需要注意的是,这里使用了对象字面量语法来创建obj对象,其中包含一个名为b的属性。
//因此,obj对象中的属性b和全局作用域中的变量b是不同的变量。在上面的代码中,
//当obj.fn1()函数中使用this.b时,它引用的是obj对象中的属性b,
//而不是全局作用域中的变量b。
var obj = {
    canon:'5d4',
    fn1:function(){},
    fn2: function () {
      // let canon = '5d2'
      console.log(canon)
    }
  }
  obj.fn2() //语法错误
// fn2()是在全局中执行的,因为没有找到canon变量,先看自己内部有没,没有看全局,没有,则错误