变量提升、函数提升
a = 100;
console.log(a);
var a;
test();
function test() {
a = 101;
console.log(a);
}
运行结果:
100
101
c、java等使用变量之前需要声明变量/定义、初始化变量。JS中使用变量前无需声明/定义,因此产生“变量提升/函数提升”的概念。
var a = 10;
(function() {
var a = b = 100; // 等价于 (没有var) b = 100, var a = b;
})();
console.log(a);
console.log(b);
1. 从函数内部找b,寻找失败,转向函数外部寻找b。
2. 函数外部找b,找不到就在全局创建b。 var b = 100;
运行结果:
10
100
实例:(知识点:变量提升、this概念)
a = 100;
console.log(a);
var a;
test();
function test() {
a = 101;
console.log(a);
console.log(this.a);
}
运行结果:
100
101
undefined
this == window, node环境无window,因此this.a为undefined。
小知识:
变量声明和变量定义的区别?
-
变量声明分为2种
-
需要建立存储空间。例如:int a; 声明时为a建立了存储空间。
-
无需创建存储空间。例如: extern int a; a在其他地方定义。
-
通常将建立空间的称为“定义”,不建立空间的称为“声明”。(可认为定义是声明的一个特例)
JS预解析
JS解析器执行JS代码时分为两个过程:预解析过程和执行代码过程。
预解析过程
-
只找var/function声明的。
-
先提升var,再提升function。
-
遇到变量和函数重名了,只留下函数。
-
遇到函数重名了,根据代码的上下文顺序,留下最后一个,变量也是一样。
console.log(a);
var a=1;
console.log(a);
function a(){console.log(2);}
console.log(a);
var a=3;
console.log(a);
function a(){console.log(4);}
console.log(a);
1.找到第一个var存值为undefined(注意不会为其赋值为1,而是undefined)
2.function a(){console.log(2);}代替前面var
3.var =3不会替代function
4.function a(){console.log(4);}替代function a(){console.log(2);}
5.预解析结果:把a=function a(){console.log(4);}存在预解析的仓库里面
- 函数中的变量只会提前到函数的作用域中的最前面,不会出去。
- 预解析会分段(多对的script标签中函数重名,预解析的时候不会冲突)。
<script>
function f1() {
console.log("哈哈");
}
</script>
<script>
f1();
function f1() {
console.log("嘎嘎");
}
</script>
- 作用域链
作用域链 : 执行表达式时,先在自己预解析中找,如果没有找到,会向它的父级作用域找,如果找不到,报错。
f1();
console.log(a); // ReferenceError: a is not defined
function f1() {
var a=9;
console.log(a);
}
参考链接:
https://blog.csdn.net/weixin_42787326/article/details/81328757 (JavaScript 解析器、预解析、变量提升、函数提升)