Jansiel Notes

Javascript中的“域”、“预”、“译”,你真的掌握了吗?

一、作用域的概念

1、作用域有三种:全局作用域、函数作用域、块级作用域。(模块作用域)

(1)全局作用域:这时最高级别的作用域,在这定义的函数以及变量可以在代码的所有地方被访问。在浏览器的环境中,全局变量实际是window对象的属性。例如:

1var a = 123
2function foo(){}
3//在全局中定义了变量a 函数foo()
4

(2)函数作用域(局部作用域):在每个函数内部声明的变量(未使用const、let关键字)、function声明的函数,这些对象具有局部作用域,它们只可以在函数内部访问。例如:

1function foo(){
2    var a;
3    function add(){}
4}
5

(3)块级作用域:这个作用域是在ES6引入了let和const关键字,避免因var声明的变量的变量提升(接下来会进行解释)现象,导致的让人匪夷所思的行为。这个作用域可以简单的理解为:{} + let/const例如:

 1if(...){
 2    let a = 6;
 3    const b = 6
 4}
 5while(...){
 6    let a = 6;
 7    const b =6
 8}
 9for(){
10    let a = 6;
11    const b =6;
12}
13function foo(){
14    let a = 6;
15    const b =6;
16}
17

注:(1) 以上作用域所指的是全局 、函数体 、块 的域,而词法作用域则是变量 声明 的地方,注意不是 调用 的地方。例如:我们的寝室是一个域,则该域的词法作用域就是这一栋寝室楼。

(2)欺骗词法作用域:

eval:可以让原本不属于这里的代码,变得好像天生被定义了在这一样。

1 function foo(a,str){
2    eval(str) //相当于var b = 2;
3    console.log(a,b)
4}
5foo(1,'var b = 2')
6

whit(){} 当修改对象中不存在的属性时,这个属性会被定义在全局,变为全局变量,造成数据泄露。

 1function foo(obj){
 2    with(obj){
 3        a = 2
 4    }
 5}
 6var o2= {
 7    b :1
 8}
 9foo(o2)
10console.log(a) //输出a = 2,此时的a为全局变量
11

2、声明提升的概念与示例

概念:在变量声明和函数声明在代码执行前被提升,或者说移到,其包含的作用域的顶部的过程,发生在JS的编译阶段,导致了变量和函数可以在被声明之前就被访问。

1console.log(a); //变量a只是声明被提示,输出undefined
2var a = 6;
3
4//编译器会将代码整理为
5//var a;
6//console.log(a);
7//a = 6;
8

即使函数 foo() 在调用之后声明,但由于声明提升,他在执行开始时,就可以使用了,因此能正常输出。

1foo();
2function foo(){
3    console.log('你好')
4}
5

二、“预备与编译”--预编译的概念

1、预编译发生在代码被执行之前,是JS引擎对代码的预处理,保证了变量和函数在使用之前已经被正确的设置。

2、全局预编译:

(1)创建全局执行上下文GO(Global Object)。

(2)寻找变量声明,变量名作为GO的属性名,值为undefined。

(3)在全局找函数声明,函数名作为GO的属性名,值为函数体

画图实例:
Jansiel_Essay_1717407566285

3、函数中的预编译

(1)创建函数的执行上下文对象AO(Activation Object)。

(2)找到形参和变量声明,将形参和变量声明作为AO的属性名,值为undefined。

(3)将实参和形参统一

(4)在函数体内找到函数声明,将函数名作为AO的属性名,值为函数体。

画图实例:
Jansiel_Essay_1717407589580

注: 以上的执行上下文是被放在一个栈内,AO对象被放在变量环境中。在执行上下文中除了变量环境外,还有一个词法环境,用于 let const 声明的变量的存储,这保证了它们可以遵守块级作用域的规则,处于临时死区,直到声明被执行才可被访问。这个栈叫做 调用栈

画图实例:

Jansiel_Essay_1717407611093

总结

有了这些基本知识的储备,我相信大家对接下来的闭包的等概念的理解会更加的轻松、简单,咱们下期不见不散!