JavaScript的作用域

目录

作用域

1. 全局作用域

2. 函数作用域

浏览器执行JavaScript的过程

1.语法分析

2.预编译(预解析)

3.逐行执行

案例分析1:

[[scopes]]

案例分析2:


作用域

作用域表示一个代码区域,也表示一个运行环境

1. 全局作用域

在全局作用域中声明的变量,会被提升到脚本块的顶部,并且会成为全局对象的属性。

2. 函数作用域

在函数作用域中声明的变量,会被提升到函数的顶部,并且不会成为全局对象的属性.

浏览器执行JavaScript的过程

1.语法分析

基本语法检测,有没有基本的语法错误,例如中文标点符号等

2.预编译(预解析)

1. 全局预编译:

① 全局执行代码之前,生成一个GO(Global Object)

②分析变量的声明,var a

如果GO对象上有没有a属性,如果没有,则直接添加a属性,值为undefined

如果GO对象上已经存在a属性,则不做任何操作

③分析函数声明,function fn

如果GO对象已经存在fn属性,直接将整个函数体覆盖,如果不存在就添加fn属性,值为函数体

2. 函数预编译:

①函数运行前的一瞬间,生成Active Object(活动对象),后面简称AO

②函数声明的参数(形参),形成AO对象的属性名,属性值为实参的值,未传递实参则为undefined

③分析变量声明,如 var a 如果AO对象上还没有a属性,则添加AO属性,值为undefined 如果AO对象上已经有a属性,则不做任何影响

④分析函数声明,如 function foo(){} 则把函数赋给foo属性 如果此前foo属性存在,则覆盖

3.逐行执行

浏览器按照预编译分析出来的AO,GO逐行执行代码

注:分析过了变量、函数声明的就不用管。后续只需要管赋值即可

案例分析1:

       g = 100;
       function fn(){
            console.log(g);
            g = 200;
            console.log(g);
            var g = 300;
        }
        fn();
        var g;
        console.log(g);

先创建GO,分析变量提升问题,此时GO里有:

GO{
    g:undefined,
    fn:function () {}
}

然后逐行执行代码:给g赋值:100;

GO{
    g:100,
    fn:function () {}
}

调用fn(),生成AO,分析变量提升

AO{
    g:undefined
}

然后再逐行执行代码,函数内部第一行输出的g,先在自己的作用域里找,AO里面有g,此时为undefined所以输出undefined,然后给g赋值200,所以第二个输出g为200;然后给g赋值300;

GO{
    g:100,
    fn:function () {}
}
AO{
    g:300

 }

第三次输出g,是在函数外部输出,外部GO里g=100;所以输出100

[[scopes]]

它是函数的一个私有属性,GO,AO存储在其中;

函数在定义时,函数的scopes属性会自动存储GO;

函数在运行,scopes属性中会继续添加当前函数预编译后的AO,会以栈的形式存储,形成作用域链

当函数运行时,会创建一个新的叫做执行上下文的对象,这个对象中定义了一个函数执行时的环境(var、function、this、document)。函数每次执行都会创建一个独一无二的执行上下文,在函数执行完后,就会销毁掉它所创建的执行上下文;

查询变量时沿着作用域链自顶部向下查询,如果查询到作用域链的底部(GO),还没有找到变量,系统就会报错(变量 is not defined)

案例分析2:

function a(){
      function b(){
           var bb =  234;
           c = 111;  //c没有var关键字声明,会自动生成在全局作用域中(GO)
           console.log(a);  
           console.log(c);
      }
      var a = 123;
      b();
      console.log(c);  
  }
var global = 100;
a();
console.log(c);

---------------

GO{
    global:100
    a:function(){}
    c:111
}

//调用a,生成aAO;

aAO{
    a:123,
    b:function(){}
}
//调用b,生成bAO;

bAO{
    bb:234,
}

  按步骤分析完GO,a的AO,b的AO后

     

函数a定义后      a的scopes属性    ,存储了GO              

GO

                             

 函数a被执行的时候   a的scopes属性,添加自己的AO

                           

aAO
GO

函数b定义后      b的scopes属性    ,存储了GO  和外部a函数的AO                   

aAO
GO

函数b被执行的时候 ,生成自己的AO 添加到 scopes                   

bAO
aAO
GO

查询变量时沿着作用域链自顶部向下查询,如果查询到作用域链的底部(GO),还没有找到变量,系统就会报错(变量 is not defined)

所以依次输出:123,111,111,111

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JavaScript 作用域指的是变量、函数和对象可以被访问的范围。在 JavaScript 中,作用域分为全局作用域和局部作用域两种。 全局作用域指的是在函数外定义的变量和函数,它们可以被整个程序访问。在浏览器中,全局作用域指的是 window 对象。 局部作用域指的是在函数内部定义的变量和函数,它们只能在函数内部被访问。在 JavaScript 中,每当一个函数被调用时,都会创建一个新的局部作用域JavaScript 使用词法作用域(也称为静态作用域)规则来决定变量的作用域。这意味着函数的作用域是在函数定义时确定的,而不是在函数调用时确定的。因此,在函数内部定义的变量可以在函数外部访问,但函数外部定义的变量不能在函数内部访问。 例如,下面的代码演示了 JavaScript 中的作用域: ``` var x = 10; // 全局变量 function foo() { var y = 20; // 局部变量 console.log(x); // 可以访问全局变量 x console.log(y); // 可以访问局部变量 y } foo(); console.log(x); // 可以访问全局变量 x console.log(y); // 不能访问局部变量 y ``` 在上面的例子中,变量 x 是在全局作用域中定义的,可以在函数内部和外部访问。变量 y 是在函数内部定义的,只能在函数内部访问。函数 `foo()` 调用后,可以在函数内部访问变量 x 和 y。函数调用结束后,只能在全局作用域中访问变量 x,无法访问变量 y。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值