变量提升+函数提升+执行上下文

210310

一、变量声明提升
  • 通过var定义(声明)的变量,在定义语句之前就可以访问到
  • 值:undefined
二、函数声明提升
  • 通过function声明的函数,在之前就可以直接调用
  • 值:函数定义(对象)
var a = 3
function fn(){
    /*相当于先声明了a var a;a = undefined
    先在自身函数中找变量,再去全局找
    */
    console.log(a) //undefined
    var a = 4
}
fn()  //undefined

console.log(b) //undefined //变量提升
fn2() //可调用 函数提升
fn3() //变量提升,不可执行
var b = 3
function fn2(){
    console.log(‘fn2‘)
}
var fn3 = function(){
    console.log(‘fn3‘)
}

注意: 测试一:

function a(){}
var a
console.log(typeof a)  //function

测试二:

var c = 1  //=>①var c
function c(c){
    console.log(c)
    var c = 3  //无关
}
//=>②c = 1 =>c typeof number
c(2) //报错c is not a function
三、执行上下文
  1. 代码分类(位置)

    • 全局代码
    • 函数(局部)代码
  2. 全局执行上下文

    • 在执行全局代码前将window确定为全局执行上下文

    • 对全局数据进行预处理(收集数据)

      • var定义的全局变量==>(初始化赋值)undefined,添加为window的属性
      • function声明的全局函数==>赋值(函数对象),添加为window的方法
      • this==>赋值(window)
    • 开始执行全局代码

      c = 3 //特殊:未执行语句之前,window中不包含此变量,需用var定义
      console.log(a1,window.a1) //undefined
      a2() //a2()
      console.log(this) //window
      var a1 = 2
      function a2(){
          console.log(‘a2()‘)
      }
      console.log(a1) //2
      
  3. 函数执行上下文

    • 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)

    • 对局部数据进行预处理

      • 形参变量==>赋值(实参)==>添加为执行上下文的属性
      • arguments==>赋值(实参列表),添加为执行上下文的属性
      • var定义的局部变量==>undefined,添加为执行上下文的属性
      • function声明的函数==>赋值(函数对象),添加为执行上下文的方法
      • this==>赋值(调用函数的对象)
    • 开始执行函数体代码

      function f1(a1){
          console.log(a1)
          console.log(a2)
          a3()
          console.log(this)
          console.log(arguments)
      
          var a2 = 3
          function a3(){
              console.log(‘a3()‘)
          }
      }
      f1(2,3) //2,undefined,a3(),window,2 3
      

210314执行上下文栈

  1. 在全局代码运行前,js引擎就会创建一个栈来存储管理所有的执行上下文对象
  2. 在全局执行上下文(window)确定后,将其添加到栈中(压栈)
  3. 在函数执行上下文创建后,将其添加到栈中(压栈)
  4. 在当前函数执行完后,将栈顶的对象移出(出栈)
  5. 当所有的代码执行完毕,栈中只剩下window
//调用一次函数产生一次执行上下文栈n+1(window)
//1、进入window全局执行上下文
var a = 10
var bar = function(x){
    var b = 5
    //2、进入foo执行上下文
    foo(x + b)
}
var foo = function(y){
    var c = 5
    console.log(a + c + y)
}
//3、进入bar函数执行上下文
bar(10)  //30

变量提升+函数提升+执行上下文

变量提升+函数提升+执行上下文

console.log(‘global begin:‘ + i)
var i = 1
foo(1)
function foo(i){
    if(i == 4){
        return
    }
    console.log(‘foo() begin:‘ + i)
    foo(i + 1)//递归调用:在函数内部调用自己
    console.log(‘foo() end:‘ + i)
}
console.log(‘global end:‘ + i)
/*函数依次输出:
global begin:undefined
foo() begin:1
foo() begin:2
foo() begin:3
foo() end:3
foo() end:2
foo() end:1
global end:1
整个过程中产生了五个执行上下文
*/

变量提升+函数提升+执行上下文

变量提升+函数提升+执行上下文

上一篇:typedef复杂声明


下一篇:解决端口占用的情况