初始化全局对象

  • js引擎会在执行代码之前,会在堆内存中创建一个全局对象:Global Object(GO)
    • 该对象 所有的作用域(scope)都可以访问;
    • 里面会包含Date、Array、String、Number、setTimeout、setInterval等等;
    • 其中还有一个window属性指向自己;

执行上下文

  • js引擎内部有一个执行上下文栈(简称ECS),它是用于执行代码的调用栈。
  • 那么现在它要执行谁呢?执行的是全局的代码块:
    • 全局的代码块为了执行会构建一个 Global Execution Context(GEC);
    • GEC会 被放入到ECS中 执行;
  • GEC被放入到ECS中里面包含两部分内容:
    • 第一部分:在代码执行前,在parser转成AST的过程中,会将全局定义的变量、函数等加入到GlobalObject中,但是并不会 赋值;
      • 这个过程也称之为变量的作用域提升
    • 第二部分:在代码执行中,对变量赋值,或者执行其他的函数;

认识VO对象

  • 每一个执行上下文会关联一个VO(Variable Object,变量对象),变量和函数声明会被添加到这个VO对象中。
  • 当全局代码被执行的时候,VO就是GO对象了

全局代码执行过程(执行前)

1
2
3
4
5
6
7
8
9
10
11
var message = "Global Message"

function foo() {
var message = "Foo Message"
console.log("foo function")
}

var num1 = 10
var num2 = 20
var result = num1 + num2
console.log(result)

image.png

全局代码执行过程(执行后)

image.png

函数如何被执行呢?

  • 在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(简称FEC), 并且压入到EC Stack中。
  • 因为每个执行上下文都会关联一个VO,那么函数执行上下文关联的VO是什么呢?
    • 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object);
    • 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数;
    • 这个AO对象会作为执行上下文的VO来存放变量的初始化;

函数的执行过程(执行前)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var message = "Global Message"

function foo(num) {
var message = "Foo Message"
var age = 18
var height = 1.88
console.log("foo function")
}

foo(123)

var num1 = 10
var num2 = 20
var result = num1 + num2
console.log(result)

image.png

函数的执行过程(执行后)

image.png

函数代码查找变量

1**.函数中有自己的变量定义**

1
2
3
4
5
6
7
8
9
// 1.函数中有自己的message
var message = "Global Message"

function foo () {
console.log(message)
var message = "foo message"
}

foo()

image.png
2.函数中没有变量定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 2.函数中没有自己的message
var message = "Global Message"

function foo () {
console.log(message)
}

foo()//Global Message


var obj = {
name: "obj",
bar: function () {
var message = "bar message"
foo()// 简单来说:只需要看foo在何处定义
}
}

obj.bar()//Global Message

函数的多次执行(第一次123)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var message = "Global Message"

function foo(num) {
var message = "Foo Message"
var age = 18
var height = 1.88
console.log("foo function")
}

foo(123)
foo(321)

var num1 = 10
var num2 = 20
var result = num1 + num2
console.log(result)

image.png

函数的多次执行(第二次321)

image.png

作用域提升面试题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
	// 1.面试题一:
var n = 100
function foo () {
n = 200
}
foo()
console.log(n)//200

// 2.面试题二:
var n = 100
function foo () {
console.log(n)
var n = 200
console.log(n)
}
foo()// undefined 200

// 3.面试题三:
var n = 100

function foo1 () {
console.log(n)
}
function foo2 () {
var n = 200
console.log(n)
foo1()
}
foo2()// 200 100

// 4.面试题四:
var n = 100
function foo () {
console.log(n)
return
var n = 200
}
foo()// undefined

// 5.在开发中可能会出现这样错误的写法
function foo () {
message = "Hello World"
}
foo()
console.log(message)//Hello World

// 6.面试题五:
function foo () {
var a = b = 100
}
foo()
console.log(a)//a is not defined
console.log(b)//100