js执行原理、作用域链底层解析

298 阅读2分钟

一、js执行原理

var name = "why"

console.log(num1);

var num1 = 20
var num2 = 30
var result = num1 + num2

console.log(result);

1.代码在运行前会先被解析,V8引擎(引擎因浏览器而异)内部会创建一个对象(GlobalObject简称为go)

var GlobalObject = {
    String: "类",
    Date: "类",
    setTimeout: "函数",
    window: globalObject,
    name: undefined,
    num1: undefined,
    num2: undefined,
    result: undefined 
}

2.运行代码

  • v8引擎为了执行代码内部会创建一个执行上下文栈(函数调用栈)
  • 因为我们执行的是全局代码,为了全局代码能够正常执行需要创建一个全局执行上下文(全局代码需要被执行时才会创建)

image.png

3.函数执行过程

var name = "why"
foo(123)
function foo(num){
    console.log(m)  //undefined
    var m = 10
    var n = 20
    console.log("foo")  //foo
}
  • 代码在被解析时V8引擎会创建一个对象(GlobalObject简称为go)
var GlobalObject = {
    String: "类",
    window: globalObject,
    name: undefined,
    foo: 0xa00(内存地址)
}
  • js引擎遇到函数时会独立创建一个空间存储函数(存储函数的父级作用域和函数代码块)
  • 当函数被调用时(foo())会通过GO对象找到函数的内存地址,通过内存地址找到存储函数的空间,将函数(函数有独立的执行上下文)放入全局执行上下文栈

image.png

  • 当函数执行完时,函数的执行上下文会弹出栈且销毁

image.png

二、作用域链

  • 当我们查找一个变量时,真实的查找路径是沿着作用域链来查找的
var name = "why"
foo(123)
function foo(num){
    console.log(m)  
    var m = 10
    var n = 20
    
    function bar(){
        console.log(name)
    }
    
    bar()
}
  • 当函数被调用时(foo())会通过GO对象找到函数的内存地址,通过内存地址找到存储函数的空间,将函数(函数有独立的执行上下文)放入全局执行上下文栈
  • 执行到bar函数时又会开辟一个bar函数的执行上下文

image.png

  • 当bar函数执行完时,函数的执行上下文会弹出栈且销毁,这时foo函数也执行完后该执行上下文也会弹出栈且销毁

image.png