JavaScript学习之旅-7(原创)
在上一篇文章中,我们主要学习在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:如果一个变量在函数(方法)体内部申明,则该变量的作用域为整个函数体,在函数外不可引用该变量。
无法在函数体外引用变量aB:如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。(只能用在自己的方法内)
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:如果数组本身还有嵌套,也可以通过下面的形式进行解构赋值。(注意嵌套层次和位置要保持一致)
解构赋值 - 2C:解构赋值还可以忽略某些元素
解构赋值 - 3注意,这里的 z 成功打印出了数值,但是 x y 都抛出了异常,所以我们还是需要严格遵循代码规范去编写代码
D:如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性:
解构赋值 - 4从图中我们清楚的可以看到,我们成功的将 person对象的 name、age、passport全部成功的打印出来了。
E:对一个对象进行解构赋值时,同样可以直接对嵌套的对象属性进行赋值,但需要保证对应层次一致即可。 如下图
解构赋值 - 5F:使用解构赋值对对象属性进行赋值时,如果对应的属性不存在,变量将被赋值为undefined。
G:解构赋值还可以使用默认值,这样就避免了不存在的属性返回undefined的问题,如下图
解构赋值 - 6这里没有在person对象中声明single字段,但是我们可以直接在解构赋值里面使用默认值。
H:有些时候,如果变量已经被声明了,再次赋值的时候,正确的写法也会报语法错误,如下图
解构赋值 - 7解决办法1:不单独声明 var变量 x,y,两行合并成一行
解决办法2:使用括号,如下图(推荐用法):
解构赋值的格式问题目前支持解构赋值的浏览器包括Chrome,Firefox,Edge等。
本篇文章学习的是关于变量的作用域与解构赋值,篇幅较长内容也很多,需要自己耗时间多消化,变量的作用域与解构赋值的基本内容就结束了。
未完待续。。。
如果这篇文章对你有帮助,希望各位看官留下宝贵的star,谢谢。
Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用,也希望大家尊重笔者的劳动成果。