javascript的作用域链变量提升及预解析
Posted 傻了吧爷会飞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript的作用域链变量提升及预解析相关的知识,希望对你有一定的参考价值。
一、javascript的作用域链
- 如果函数中还有函数,或者块级作用域又嵌套块级作用域,那么在这个作用域中就又可以诞生一个作用域,这样的嵌套作用域形成了链状的结果就是作用域链。
- 查找原则:从上到下,从里到外,即先找局部作用域里找,然后子对象会一级一级向上寻找所有父对象的变量。
<script>
/* 函数作用域链 */
var num=1;//0级作用域
function test(){
var num=10;//1级作用域
function func(){
var num=89;//2级作用域
function func1(){
var str='orange';//3级作用域
console.log(num);//89 现在当前作用域中找,若当前作用域中无法找到就去上一级作用域中找
}
func1();
}
func();
}
test();
/* 块级作用域链 */
let arr=[3,8,0]//0级作用域
{
let arr=[10,7,3];//1级作用域
{
console.log(arr);//[10, 7, 3] 2级作用域
{
console.log(num);//1 3级作用域
}
}
}
</script>
二、变量提升及预解析
1、变量提升
- JavaScript 中,函数及变量的声明都将被提升到函数的最顶部。
- var变量提升时,只将var定义的变量提升到此作用域的最顶部,不提升赋值。
- 函数声明提升只提升函数到此作用域的最顶部,不直接调用。(注意:函数提升分为函数表达式和函数声明,只有函数声明才会提升)
- 先提升var,再提升函数。
2、预解析
- 预解析规则: 对于script是自上而下进行解析,对于函数是由里到外进行解析。
- 预解析规则:JavaScript “预解析”过程中,遇到重名的内容,只保留一个。(重名变量或重名函数,保留最后的一个。变量和函数重名,只保留函数。)
<script>
console.log(num);//undefined
var num=10;
var num=8;
console.log(num);//8 (重名变量或重名函数,只保留最后一个)
/*
预解析:
var num;// 把变量的声明提升到当前作用域的最顶部
console.log(num);
num=10;
num=8;
console.log(num)
*/
</script>
<script>
var num=10;
function test(){
console.log(num);//undefined
var num=56;
function func(){
console.log(num);//56 func函数作用域中若找不到num,往上一层作用域找
}
func();
}
test();
/*
预解析:
var num;
function test(){
var num;
console.log(num);
num=56;
function func(){
console.log(num);//56
}
func();
}
num=10;
test();
*/
</script>
注意1:var和function同名时,function的优先级高于var(变量和函数重名,只保留函数)。
<script>
console.log(num);//打印num函数
var num=10;
function num(){
console.log('hello');
}
console.log(num);//10
/*
预解析:
// var和function同名时,function的优先级高于var。
function num(){
console.log('hello');
}
var num;
console.log(num);
num=10;
console.log(num);
*/
</script>
注意2:变量以函数的参数传入时,变量在函数作用域中变成了局部变量 。
<script>
var a=4;
function test(a){
console.log(a);//4
var a=7;
var b=6;
function func(){
return a+b
}
console.log(func());//13
};
test(a);
/*
预解析:
var a;
a=4;
function test(a){
var a;
var b;
a=4;
console.log(a);//4
a=7;
b=6;
function func(){
return a+b //7+6
}
console.log(func());//13
};
test(a);
*/
</script>
<script>
var a=20;
var b=12;
function test(a){
console.log(a);//20
a=45;
b=23;
}
test(a);
console.log(a);//20
console.log(b);//23
/*
预解析:
var a;
var b;
function test(a){//a以函数的参数传入时,a在函数作用域中变成了局部变量
var a;
a=20;
console.log(a);
a=45;
b=23;//b还是全局变量
}
a=20;
b=12;
test(a);
console.log(a);//20
console.log(b);//23
*/
</script>
注意3:如果函数赋值给变量时,只有变量预解析,函数不会预解析。
<script>
console.log(test);//undefined
test();//test is not a function
var test=function(){
//函数表达式
}
/*
预解析:
var test;
console.log(test);
test();
test=function(){
//函数表达式
}
*/
</script>
注意4:let定义的变量不会预解析,只会遵守JavaScript的“从上到下”的运行规则。
<script>
var a=20;
test();
function test(){
console.log(a);//undefined
console.log(b);// 报错
var a=3;
let b=100;
}
/*
预解析:
var a;
function test(){
var a;
console.log(a);
console.log(b);
a=3;
let b=100; //let定义的变量不会预解析,只会遵守JavaScript的“从上到下”的运行规则。
}
a=20;
test();
*/
</script>
学习的课程:李南江的前端课程 (他的简书https://www.jianshu.com/p/c73f5124d69f)
学习的文章:https://blog.csdn.net/weixin_42614080/article/details/90114780(预解析)
以上是关于javascript的作用域链变量提升及预解析的主要内容,如果未能解决你的问题,请参考以下文章