ES6——let和const命令

let和const命令

1.1 let应用循环定义i

这里就可以体现let声明的优势啦
看看下面两个循环分别应该输出什么 想想为什么结果不一样呢?

var a = [];
        for(var i=0 ; i<10 ; i++){
            a[i] = function(){
                console.log(i);
            }
        }
        a[6]();
var a = [];
        for(let i=0 ; i<10 ; i++){
            a[i] = function(){
                console.log(i);
            }
        }
        a[6]();

怎么样呢?结果和你想的一样吗
执行结果分别为10和6
两个程序的区别在于分别用var和了let定义了循环中的i,那么为什么输出结果不同呢?

主要原因就在于这两者的定义变量作用域不同,

  • var声明的变量作用域如果在方法里声明则为局部变量(该方法内可以使用)
    否则为全局变量(整个程序都可以使用哦),
  • 而let定义的变量呢,属于只能在定义它的块级作用域里使用哦(什么是块级作用域请看下面解释哦)
    知道这个,来看看具体代码:
  • 前者var定义的i是全局变量(没在方法中定义哦),那么每个for循环定义的i都是同一个i,所以随着每次循环的推进,i也在不断变化等到循环结束之后,i的值就更新为10了。
    而在循环里面,只是对数组的每个值进行函数赋值,并没有执行函数,真正执行函数是等到循环结束之后,这时候程序找的i还是之前那个不断更新的i,所以此时输出i为10,
  • 后者let呢,每次循环定义的i都不同,自然就没什么更新啦,所以最后数组赋值分别为0到9

块级作用域简单来说:就是作用范围局限在一个括号内,比如if语句的{} 又或者for循环中的{}

1.2 let声明暂时性死区

听起来很高级的样子 其实就是说在变量在let声明之前都是不可以使用的,否则会报错,下面程序为不太好发现的“死区”现象

function(x = y, y = 3){
            return[x,y];
        }

怎么样?找到错误了吗?
如果找到恭喜你很棒
没有的话也祝贺你找到自己一个可以学习的点,那么就来看看下面的解释吧

这里的y在没有声明之前就使用了(给x赋值),所以会出错
函数形参声明相当于let声明定义(再插一嘴,形参定义过的变量在函数里面再用let声明也是会出错的哦 原因是let变量不能重复声明)

再来看看另一个容易忽视的例子吧

let x = x;

同样会报错,还是“暂时性死区”的锅

1.3 块级作用域

块级作用域也是es6新增的,在es5并没有这个说法,就导致有一些trouble存在,比如在函数里面定义重名的变量(和全局变量重名),就会覆盖外层变量,导致无法在函数内调用到外层变量
另一个trouble就是用来计数的变量(比如i)循环之后会暴露为全局变量

1.3.1作用域的嵌套

由于let这个特性,也比较好理解作用域的嵌套啦,就是外层作用域是没办法读取内层作用域的变量的

1.3.2函数在块级作用域的声明

再来说说函数在块级作用域的声明吧
(ES5之前是不允许的哦,ES6新增的func)
理论上对于ES6块级作用域中声明的函数,效果是类似于let声明一样,但是由于不兼容问题,对于浏览器具体的实现就更改为类似var了,可以通过下面的例子理解一下:

function fn(){
            console.log("I am here");
        }
        (function(){
            if(false){
                function fn(){
                    console.log('Can you find me?');
                }
            }
            fn();
        })();

上面程序执行结果会出错,报错为 :fn is not a function ,上面一行输出fn为undefined 自然不能当函数调用啦,undefined的原因也很简单,就是在立即执行函数里面用function声明了fn(相当于var声明提升了),但是由于没有进入if语句所有没有进行赋值,所以最后fn就是undefined啦
所以呢,尽量在块级作用域少地声明函数,或者可以使用函数表达式(赋值语句)代替函数声明语句
另外在块级作用域中声明函数不加大括号也会报错哦,如下

	if(true)
		function fn()
			console.log("test");
			

1.3 const声明变量特性的本质

const定义的变量是不可以修改滴,实际上呢,并不是变量的值不可以改变,而是变量指向的那个内存地址不可以改变。
就比如const声明的对象中的属性和方法以及数组中的元素是可以改变的,但是呢如果更改了其引用就有问题了 见下方两种赋值就是错的哦

	const obj = {a:1};
	obj = {};//此时就将obj指向了另一个对象了
	const arr = [];
	arr = ['1'];

js中变量的存储方式

js中的变量根据存储类型分为两类,一类为基本数据类型(包括Number,String,Undefined,Null,Boolean)另一类为引用类型(对象),那么这两种的区别是什么呢?
对于基本数据类型,是栈存储,对于变量存储的就是具体的值,各个之间是独立的,更改一个变量不会影响其他变量
而对于引用类型(对象),是堆存储,每次声明一个对象,都会在堆内存开辟一个空间(对应一个地址),变量里面实际存储的值为在堆内存中地址(对象引用),那么如果两个变量存的是一个地址(对象引用),那么通过其中一个变量当更改数据,另一个也会跟着改变

另外呢,如果真的想用const让对象的属性也冻结不能更改的话,可以用Object.freeze()方法来实现
看看下面的代码我相信你就理解啦

	const obj = Object.freeze();
    obj.a = 1;//error

1.4 ES6声明变量的6种方法

1.4.1顶层对象的属性

  • 什么是顶层对象呢 对于浏览器来是window 对于node来说是global
  • 在es5中 顶层对象和全局对象是等价滴(var b和window.b等价) 因为这个等价所造成的一些trouble es6便通过一些规定 让这两者区分开
  • 规定是:var和function定义的全局变量还是属于顶层对象(window)滴,巴特const let定义的就不属于啦 比如let b = 1;这时候无法通过window.b找到这个b

1.4.2golbal对象

ES5中的顶层对象在各种实现中不统一,比如在浏览器和node中顶层对象分别为window和global,而同一段代码想通过this取到顶层对象在全局环境和函数中的this指向也不同,所以es6为了在所有情况下都取得顶层对象,可以通过垫片库获取顶层对象(import即可)

三、总结

最后呢 让我们来回顾一下都收获了哪些吧~

首先呢就是有关let和const声明变量问题

  • let应用
  • 有关let暂时性死区的易错点
  • const定义的变量实际上是不能改变变量指向的那个内存地址
  • 有关顶层对象和全局对象分隔
  • 块级作用域:嵌套和函数声明问题

解构赋值

  • 数组解构赋值
  • 对象解构赋值 :内部机制(同名),嵌套赋值
  • 字符串 数值 解构赋值
  • 具体应用:交换数值,提取JSON数据,模块提取,函数参数,函数返回多个值,函数参数,遍历Map结构

怎么样?通过上述这些点,你可以回忆起具体解释吗?如果有模糊的话就是要及时回顾复习哦~

完结撒花❀

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值