es6学习过程(一)
一、let关键字的用途
在平时我们写代码的时候,都是用var来声明一个变量(其实也没有其他的关键字了==)。但是在es6出来以后,除了var,还可以使用let来声明变量。
为什么会出现let而不仅仅使用var就好了呢? 那是因为var这个关键字在某些时候是很坑的。
var的不足之处
1.如果使用var声明的变量会影响到其他的作用域。
比如说下面这个例子,从例子来上看我们是想让执行arr[8]的时候弹出8的,但是为什么会弹出的是10呢?
刚开始的时候我也比较困惑,但是我在for的下面打印了一次i我就明白了。因为for循环结束以后,i已经变为10了。此时在执行arr[8]的时候实际上执行的就是function{alert(i)} 这个函数。 那么此时的i是多少呢? 上面已经提到了,此时的i是10。 所以弹框弹出来的自然就是10了。
那么怎样才能达到我们想要的效果呢?
很简单!将for循环里面的var变成let就可以了。
为什么用let可以,但是使用var就不行了呢?
这是因为let声明的变量仅仅在自己的块级作用域中起作用,出了自己的作用域就不起作用了。 在案例中,若是将var变成let,控制台中就会报错,i is not defined 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
var arr = [];
for (var i=0;i<10;i++){
arr[i]=function () {
alert(i)
}
}
console.log(i); //i = 10
arr[8]() // i = 10
</script>
</body>
</html>
2.使用var声明变量会出现“变量提升”的现象
我们都知道,js的代码是从上到下一条一条的执行的。但是这里控制台打印为什么不会报错呢?
那是因为在js中,js会将script标签中用到的所有变量在一开始的时候就将它们全部的声明在当前所在的作用域,所以并不会出现报错而是出现未定义的情况。
所以,先声明再调用这个习惯是非常重要的,也更符合常理。
<script>
console.log(a);
var a = 10;
</script>
再举个栗子
在这个案例中,为什么打印出来的a会是undefined?
可能很多同学会在想,a是不可能等于500了,但是为什么连100块都不给我 ==。
那为什么a会不等于100呢?
那是因为在函数里面又一次的声明了a;前面我说过,在js中,js会将script标签中用到的所有变量在一开始的时候就将它们全部的声明在当前所在的作用域。在这里就相当于在执行console之前再次声明了a变量;这就意味着此时的a已经被重新定义了,前面的a等于100在这个作用域中已经是无效的了,此时的a是undefined,a已经在这个函数中已经被重置了,所以a是不会等于100的。
还需要注意的是:
1.let不会存在变量提升的情况
2.在同一个块级作用域中,不允许重复声明同一个变量
3.函数内不能用let重新声明函数的参数
变形之后
<script>
var a = 100;
(function () {
var a;
console.log(a);
a = 500;
})()
</script>
变形之前
<script>
var a = 100;
(function () {
console.log(a);
var a = 500;
})()
</script>
二、关键字const
const和let一样,也是用来声明变量的,但是const是专门用来声明一个常量的。 以前在js中是没有这些概念的,无论什么变量都是用var声明的。但是呢,在其他语言中是有const这个说法的,别的我不知道,但是在php中是有的。并且常量是不可改变的。
常量的特点:
1.不可以修改,否则会报错
2.只在块级作用域中起作用,和let一样
3.const和let一样,不存在变量提升,必须先声明后使用
4.不可重复声明一个变量
5.声明以后不赋值是会报错的
如果常量是一个变量呢?
在这里我先说明一个重点,在赋值的过程中,我们可以分为传值赋值和传址赋值。 在平常中我更喜欢称为普通赋值和引用赋值。 其实意思都差不多。
举个简单的栗子:
这个就是传值赋值,很简单吧。
var a = 10;
var b = a;
a = 20;
console.log(a)
console.log(b)
那什么是引用赋值呢?
在这个栗子中,为什么b的值会随着a改变而进行改变呢? 为什么不像上面的栗子那样保持为原来的值呢?
那是因为a它是一个对象,b复制的其实是a在内存中的地址。所以a无论改变,b都是指向a在内存中的位置,所以b是会随着a改变而进行改变。同理,b的改变也会引起a的改变,因为他们指向的都是同一个内存地址。
var a = {
name:'小白'
};
var b = a;
a.name = '小黑';
console.log(a) //{ name: '小黑' }
console.log(b) //{ name: '小黑' }
坑
然后我突然脑洞大开拿了数组试了一下,发现了一个我以前都不知道的坑。
下面这种例子中b为什么会等于[1,2,3]而不是[4,5,6]呢? 数组不也是一个对象吗? 按理说不应该也是引用的关系吗? 但是为什么会这样呢?
原来是因为:原来a和b都是指向同一个内存地址,但是在a = [4,5,6]的时候,a实际上已经指向了另一个内存地址了,而b指向的还是原来的内存地址。所以a的改变已经完全和b没有关系了。
var a = [1,2,3];
var b = a;
a = [4,5,6];
alert(b); //[1,2,3]
但是:
下面这个栗子中,a改变的实际上是用一个内存地址中的对象,所以a改变b也会改变。
var a = [1,2,3];
var b = a;
a.pop();
alert(b); //[1,2]
不是说好要讲const的吗? 怎么扯的那么远==
回到我们的const关键字,用const来声明一个对象类型的常量,就是传址赋值。而不可修改的是对象在内存中的地址,而不是对象本身。对象本身是可以随便修改的。