美文网首页前端开发
JavaScript学习之旅-7(原创)

JavaScript学习之旅-7(原创)

作者: 骑小猪看流星 | 来源:发表于2018-04-02 12:03 被阅读394次

    在上一篇文章中,我们主要学习在JavaScript中,如何定义函数(也称方法),使用函数,如何使用arguments去规避传参的风险。这一篇文章我们主要学习在JavaScript中变量的作用域与解构赋值。

    概念一:在JavaScript中,用var申明的变量实际上是有作用域的。

    我们首先来复习下在Java中成员变量和局部变量是如何定义和使用的。

    成员变量:

    在类里面定义的变量叫做成员变量;

    如果在变量有static关键字修饰,就叫作静态变量或类变量;

    如果该变量没有static关键字修饰,就叫作非静态变量或实例变量;

    局部变量:

    方法内定义的变量、形参、代码块中定义的变量都叫做局部变量;

    另外,成员变量可以不显式初始化,它们可以由系统设定默认值;

    但是局部变量没有默认值,在使用前必须赋值才可以使用。

    还有,在内存中的位置也不一样。

    成员变量在所在类被实例化后,存在堆内存中;局部变量在所在方法调用时,存在栈内存空间中。

    复习完了Java,那么首先讨论变量的作用域的第一个话题,在JavaScript中,变量的全局作用域是什么?

    首先,不在任何函数内定义的变量,就具有全局作用域。如下图

    全局变量

    实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性,既然是绑定在window中,我们就可以直接使用,如下图

    window全局使用变量

    我们在学习函数的基础的时候说道每一个function有两种表达形式:一种是纯粹的function,还有一种是function就可以代表一个var变量,因此,每一个具体的函数如果用var变量来表示的话,这也是一个全局变量

    直接使用方法

    综上:使用window对象,也可以直接调用上面的test方法,实践检测:

    window对象调用

    结论:根据上面的例子,我们可以判断JavaScript实际上有一个全局作用域。任何变量(函数也视为变量),如果没有在当前函数作用域中找到,就会继续往上查找,最后如果在全局作用域中也没有找到,则报ReferenceError错误(也就是类似我们java的空指针)。

    老司机可能会说,上面说到了,全局变量会绑定到window上。如果不同的JavaScript文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,这种情况该怎么处理?

    解决办法:减少命名冲突的一个有效方法是把 自己的所有变量和函数全部绑定到一个全局变量中。

    我们可以把自己的代码放入到自己唯一INFO中(根据自己的需求去定义即可),这样会大大减少全局变量冲突的可能,而且会显著提高代码的阅读性和质量。

    说完了JavaScript变量的全局作用域,那么局部作用域是什么?

    由于JavaScript的变量作用域实际上是在函数内部,但是我们在for循环等语句中是无法定义具有局部作用域的变量的。为了解决块级作用域,ES6引入了新的关键字let,用let关键字替代var可以申明一个块级作用域的变量。

    常量:

    在JavaScript中,声明常量的方式有两种,第一种是在全局变量中使用,变量名全部大写,这一种是通过书写规范去表示这是一个常量,不要修改它的值;但是在 ES6 标准中,引入了新的关键字 const 去定义常量,这里就不演示了。(简单理解就是Java中的final关键字)

    关于var申明的变量实际上是有作用域的必须记住的一些概念:

    A:如果一个变量在函数(方法)体内部申明,则该变量的作用域为整个函数体,在函数外不可引用该变量。

    无法在函数体外引用变量a

    B:如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。(只能用在自己的方法内)


    不同函数申明同名变量不影响  

    C:JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行


    内外部变量的限制规则

    D:如果内部函数和外部函数的变量名重名怎么办?那么,内部函数的变量将“屏蔽”外部函数的变量。

    拓展:变量提升


    变量提升

    JavaScript的方法定义有个特点,它首先会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部,第三行的 var x = 'Hello, ' + y ;  这一行并没有报错,原因是变量y在稍后申明了。但是console.log 显示 Hello, undefined,说明变量 y 的值为undefined。这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。因此我们在方法内部定义变量时,请严格遵守“在方法内部首先申明所有变量,然后在使用”这一开发原则。

    说完了JavaScript中变量的作用域,接下来我们在谈谈解构赋值。

    解构赋值:

    什么是解构赋值?

    解构赋值 就是可以同时对一组变量进行赋值。从ES6开始,JavaScript引入了这一新特性,它大大提高了开发效率。它为什么会提高开发效率,我们先从数组说起。

    首先,如何把一个数组的元素分别赋值给几个变量?有人说,简单,洋洋洒洒就是以下代码

    数组元素赋值变量

    嗯,上面的方式的确做到了,轻松无痛苦。但是使用了新特性解构赋值的话,先看图

    解构赋值 - 1 

    使用了解构赋值就只有两行代码 即可完成上面的事情(x, y, z分别被赋值为数组对应元素)。

    需要注意的有以下几点:

    A:对数组元素进行解构赋值时,多个变量要用[ ... ]括起来

    B:如果数组本身还有嵌套,也可以通过下面的形式进行解构赋值。(注意嵌套层次和位置要保持一致)

    解构赋值 - 2   

    C:解构赋值还可以忽略某些元素

    解构赋值 - 3

    注意,这里的  z 成功打印出了数值,但是 x y 都抛出了异常,所以我们还是需要严格遵循代码规范去编写代码

    D:如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性:

    解构赋值 - 4

    从图中我们清楚的可以看到,我们成功的将 person对象的 name、age、passport全部成功的打印出来了。

    E:对一个对象进行解构赋值时,同样可以直接对嵌套的对象属性进行赋值,但需要保证对应层次一致即可。 如下图

    解构赋值 - 5

    F:使用解构赋值对对象属性进行赋值时,如果对应的属性不存在,变量将被赋值为undefined。

    G:解构赋值还可以使用默认值,这样就避免了不存在的属性返回undefined的问题,如下图

    解构赋值 - 6

    这里没有在person对象中声明single字段,但是我们可以直接在解构赋值里面使用默认值。

    H:有些时候,如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误,如下图

    解构赋值 - 7

    解决办法1:不单独声明 var变量 x,y,两行合并成一行

    解决办法2:使用括号,如下图(推荐用法):

    解构赋值的格式问题

    目前支持解构赋值的浏览器包括Chrome,Firefox,Edge等。

    本篇文章学习的是关于变量的作用域与解构赋值,篇幅较长内容也很多,需要自己耗时间多消化,变量的作用域与解构赋值的基本内容就结束了。

    未完待续。。。

    如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。

    Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。

    相关文章

      网友评论

      本文标题:JavaScript学习之旅-7(原创)

      本文链接:https://www.haomeiwen.com/subject/luwjcftx.html