1 深入V8引擎原理
2 JS执行上下文
3 全局代码执行过程
4 函数代码执行过程
5 作用域和作用域链
源代码->抽象语法树->字节码。
其中的字节码在函数执行的时候,由于参数的类型是一样的,所以有优化的机器码,但是如果参数类型发生变化,又要重新生成机器码然后优化(性能降低)。
有函数会被优先解析,其次是变量。就是下图这样子也能正常运行。如果还有一个变量叫bar的话函数会被参数覆盖,输出的是参数值。
下图是右边代码的初始状态的堆栈图(左边是上下文执行栈ECS;右边是GO、AO等等)
这里执行到函数foo了,会创建AO,然后在绿色的块表示执行函数里面的每一行的过程。
函数的代码里面的message打印如果是在赋值前,那么只要函数里面有这个参数的创建就会发生作用域的效果先在AO里面找,message打印为undefined。
函数通过作用域链查找参数
作用域链在对象被创建的时候就已经确定了,而不是由你在哪里执行决定。
下图的foo函数
函数里面嵌套函数的时候,执行上下文的过程
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> // 1.面试题一: // var n = 100 // function foo() { // n = 200 // } // foo() // console.log(n) // 2.面试题二: // var n = 100 // function foo() { // console.log(n) // var n = 200 // console.log(n) // } // foo() // 3.面试题三: // var n = 100 // function foo1() { // console.log(n) // } // function foo2() { // var n = 200 // console.log(n) // foo1() // } // foo2() // 4.面试题四: // var n = 100 // function foo() { // console.log(n) // return // var n = 200 // } // foo() // 5.在开发中可能会出现这样错误的写法,在函数里面定义了全局变量 //这个变量在全局都能用。 // function foo() { // message = "Hello World" // } // foo() // console.log(message) // 6.面试题五: 这里的b相当于上面5的写法,虽然在函数里面定义了变量,却能在 //全局使用这个变量。原因是没有声明这个变量。 function foo() { var a = b = 100 } foo() console.log(b) </script> </body> </html>
这里的js运行很复杂,一直创建对象,这是因为为了后续的闭包提供条件。