一、JavaScript-变量作用域
1.在JavaScript中{}外面的作用域, 我们称之为全局作用域;
2.在JavaScript中函数后面{}中的的作用域, 我们称之为"局部作用域";
3.在ES6中只要{}没有和函数结合在一起, 那么应该"块级作用域";
4.块级作用域和局部作用域区别;
4.1在块级作用域中通过var定义的变量是全局变量;
4.2在局部作用域中通过var定义的变量是局部变量;
无论是在块级作用域还是在局部作用域, 省略变量前面的let或者var就会变成一个全局变量;
例:
if(false){
// 块级作用域
}
{
// var num = 678; // 全局变量
// let num = 678; // 局部变量
num = 678; // 全局变量
}
console.log(num);
function test() {
// var num = 123; // 局部变量
// let num = 123; // 局部变量
num = 123; // 全局变量
}
test();
注意点: 在不同的作用域范围内, 是可以出现同名的变量的;
注意点: 初学者在研究"作用域链"的时候最好将ES6之前和ES6分开研究;
例:
https://blog.csdn.net/hbzyin/article/details/78025777
二、ES6之前作用域链
1.需要明确:
1.ES6之前定义变量通过var;
2.ES6之前没有块级作用域, 只有全局作用域和局部作用域;
3.ES6之前函数大括号外的都是全局作用域;
4.ES6之前函数大括号中的都是局部作用域;
2.ES6之前作用域链
1.1. 全局作用域我们又称之为0级作用域;
2.2. 定义函数开启的作用域就是1级/2级/3级/…作用域;
2.3. JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链;
0 —> 1 ----> 2 ----> 3 ----> 4
2.4.除0级作用域以外, 当前作用域级别等于上一级+1;
3.变量在作用域链查找规则
3.1 先在当前找, 找到就使用当前作用域找到的;
3.2 如果当前作用域中没有找到, 就去上一级作用域中查找;
3.3 以此类推直到0级为止, 如果0级作用域还没找到, 就报错;
三、ES6作用域链
1.需要明确:
1.ES6定义变量通过let;
2.ES6除了全局作用域、局部作用域以外, 还新增了块级作用域;
3.ES6虽然新增了块级作用域, 但是通过let定义变量并无差异(都是局部变量);
4.在ES6中如果在循环中通过let定义的变量, 那么这个变量是一个局部变量;
2.ES6作用域链
1.1. 全局作用域我们又称之为0级作用域 ;
2.2. 定义函数或者代码块都会开启的作用域就是1级/2级/3级/…作用域;
2.3. JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链;
0 —> 1 ----> 2 ----> 3 ----> 4
2.4. 除0级作用域以外, 当前作用域级别等于上一级+1
3.变量在作用域链查找规则
3.1 先在当前找, 找到就使用当前作用域找到的;
3.2 如果当前作用域中没有找到, 就去上一级作用域中查找;
3.3 以此类推直到0级为止, 如果0级作用域还没找到, 就报错;
四、JavaScript-预解析
1.什么是预解析?
浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码;
也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,这个加工处理的过程, 我们就称之为预解析;
2.预解析规则
2.1将变量声明和函数声明提升到当前作用域最前面;
2.2将剩余代码按照书写顺序依次放到后面;
3.注意点
通过let定义的变量不会被提升(不会被预解析);
注意点:
1.在高级浏览器中, 不会对{}中定义的函数进行提升;
2.只有在低级浏览器中, 才会按照正常的方式解析;
例:下列程序的执行结果是什么?
注意点:
如果变量名称和函数名称同名, 那么函数的优先级高于变量;一定要记住, 在企业开发中千万不要让变量名称和函数名称重名;
console.log(value); // 会输出函数的定义
var value = 123;
function value() {
console.log("fn value");
}
console.log(value); // 会输出123
-End