一、解析顺序
步骤一:预解析阶段。该阶段的任务是先找出函数的声明将其提升到作用域最前面,然后再找出var操作符声明的变量并将其提升到作用域最前面但不赋值。
步骤二:执行阶段。赋值,运算,函数调用都在这个阶段。
一、变量提升
console.log(a); //undefined
var a = 10;
其实际执行过程相当于
var a;
console.log(a);
a = 10;
注:变量的提升其实就是将用var声明的变量,提升到作用域的顶端,然后在同样的作用域中书写变量赋值的地方给变量赋值
二、函数提升
-
两种创建函数的方式
//function definition 函数定义 function func(){ } //function expression 函数表达式 var a = func(){}
-
函数定义声明的函数可以提升声明,对于函数表达式,只有在执行到相应的语句时才进行解析。函数表达式创建的函数是在运行时进行赋值,且要等到表达式赋值完成后才能调用。
(1)函数定义声明函数func(); function func(){ console.log("hello"); }
其解析结果相当于
function func(){ console.log("hello"); } func();
(2)函数表达式声明函数
console.log(a) //undefined a(); //a is not a function var a = function func(){ console.log("hello"); }
其解析结果相当于
var a; console.log(a); //undefined a(); //a is not a function a = function(){ console.log("hello"); } a(); //hello
- 函数名指向内存地址,内存地址指向函数本身
- js解析器优先解析函数声明,然后解析使用var操作符声明的变量,但不赋值。遇到赋值操作符的时候才会赋值。
- 赋值操作是执行代码时的步骤。
-
一个demo没有想明白
func(); //undefined; 10; { func(); //嘿嘿 function func(){ console.log("嘿嘿"); } func(); //嘿嘿 } func(); //嘿嘿 function func(){ console.log(a); var a = 10; console.log(a); } func(); //嘿嘿
三、一些补充
-
解析与执行顺序
var a = 10; x(); function x(){ var b = 20; alert( b ); } alert( a ); /* 执行顺序: 执行全局作用域: 1、定义 var a ; function x(){ var b= 20; alert( b ); } 2、执行步骤 a = 10; x(); ====>新的作用域触发====>依照上面的规则:1、定义 var b; 2、执行步骤 b = 20; alert( b ); 弹出 20; 回来父级这层开始向下执行 alert( a ); 弹出10;
-
同局作用域 变量与函数重名。
var a; function a(){ alert(1); } a(); 先执行定义步骤 var a function a(){alert(1);} var a会被函数覆盖===>保留function a(){alert(1);} 再来执行步骤 a() ==>弹出1; function a(){ alert(1); } var a; consol.log(a); //[Function: a] var a = 10; function a(){ alert(1); } a(); 先执行定义步骤 var a function a(){alert(1);} var a会被函数覆盖===>保留function a(){alert(1);} 再来执行执行步骤 a = 10 a() ==>报错 现在a是10;
-
函数带有形参且调用时传了实参
function say(a, b){ //函数执行时相当于var a = 10,b; console.log(a,b); } say(10);
2021/3/13
推荐大家看这篇博客,可以更加从源头理解为什么
深入理解 JavaScript 执行上下文和执行栈
版权声明:本文为qq_41884544原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。