浅谈JavaScript中的作用域

前言

JavaScript中存在一个Scope的特性,也就是作用域,在学习的过程中不是很好理解,让我们在这浅谈一下作用域。

一、作用域是什么东西?

在百度百科中我们可以查询到,作用域的定义是

作用域(scope),程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

换句话说,作用域决定了代码中变量和其它数据的可见性和可访问性,这里我们举一个例子来帮助我们理解

function outSide()
    {
        var tt="数据1";
    }
    console.log(tt);//显示:Uncaught ReferenceError: tt is not defined
    
复制代码

从上述代码中我们可以得知作用域的基本概念,变量tt在全局作用域中未声明,而console.log(tt)这条语句处在全局作用域下,无法得到变量tt的值,所以会报错。作用域决定了变量的生命周期(与函数、块级作用域相关) 任何变量都有生存周期,通俗的理解作用域就是函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。作用域相当于一个独立的小房间,让房间里的变量不会外泄出去。也就是说,作用域最大的用处就是用于隔离变量,这样同名的变量在不同作用域下就不会产生冲突,因为它们都在自己的小房间里。

二、分别有哪些作用域?

  1. 全局作用域
  2. 函数作用域
  3. 块级作用域

这里我们要知道,JavaScript在ES6之前是没有块级作用域的,从ES6开始,才给我们提供了块级作用域这个概念。

三、这些作用域的作用

  • 全局作用域

在全局声明的变量拥有的作用域叫做全局作用域,即这个变量在代码的任何一个地方都能被访问到。那么要如何定义变量,才能让其拥有全局作用域呢,经过查阅,大致有以下几种方式

1. 最外层函数和处在最外层函数之外的变量

    var dd="我是在外层函数外定义的变量"
    function outSide()//外层函数
    {
        var tt="数据1";//函数内的变量,这是内层变量
        console.log(tt)
    }
    outSide()//数据
    console.log(dd)//我是在外层函数外定义的变量
    console.log(tt);//Uncaught ReferenceError: tt is not defined
复制代码

从上面的代码可知,外层函数outSide()和在外层变量dd可以在全局当中被访问,而内层变量tt不行,因为内层变量tt位于函数定义域内,无法被访问,访问结果是Uncaught ReferenceError: tt is not defined

2. 没有定义但直接赋值的对象

    function outSide()//外层函数
    {
        tt="数据1"
         var dd="数据2"
         console.log(dd)
    }
    outSide()
    console.log(tt)
复制代码

QQ图片20210417135928.png

在这我们能发现,原本处于函数定义域中的tt能被访问了,因为它此时拥有全局定义域

3. 所有window对象的属性都拥有全局定义域

window的内置属性一般都有全局定义域,例如window.name,window.status等

虽然变量定义在全局定义域中可以在代码的各个地方被访问,但是也有不便利的地方,例如容易产生命名冲突,这在今后与别人合作的工作当中十分不便。

  • 函数作用域

函数作用域和全局作用域相反,它是将变量在函数内部进行声明,属于局部作用域,属于这个函数的全部变量可以在整个函数的范围内使用及复用。

  • 块级作用域

es6之后,块级作用域可以通过es6新增的let和const命令来进行声明变量,所声明的变量只能在指定的块作用域内被访问,从而达到隔离变量的作用。

块级作用域会在以下情形被创建①一个函数内部②代码块内部({})

注意,部分块语句,不会创造一个新的块级作用域,比如if,switch,for,while等语句,确的说在其中定义的变量将保存在已经存在的作用域当中

if(true)
{

         var dd="数据1"
        
    }
   
    console.log(dd)
 
复制代码

QQ图片20210417195716.png

由结果可知,原本在函数定义域内的变量dd,可在全局中被访问。

let可以将变量的作用域限制在当前的代码块当中,这也是它用来替代var来定义变量原因,它和var的语法一致。
与var生声明的变量相比,let声明的变量不会提升到代码块的顶部,因为在解析代码时,JavaScript引擎也会注意到出现在块后面的let声明,只不过在此之前不能以任何方式来引用未声明的变量,在let声明之前的执行瞬间被称为“暂时性死区”(temporal dead zone),在此阶段引用任何后面的才声明的变量都会抛出ReferenceError。所以如果你想要在全局中使用let声明的变量,你要手动将其声明放于顶部。

   //name会被提升
   console.log(name)//undefined
   var name="yyds"

   console.log(age)//ReferenceError:age没有被定义
   var age=18
复制代码

以上为个人学习中所得,如有不准确或者疑问的地方可在评论进行讨论与指正,谢谢。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享