1.1块级作用域
ES6之前没有块级作用域,ES5的var没有块级作用域的概念,只有function有作用域的概念,ES6的let、const引入了块级作用域。
ES5之前if和for都没有作用域,所以很多时候需要使用function的作用域,比如闭包。
1.1.1 什么是变量作用域
变量在什么范围内可用,类似Java的全局变量和局部变量的概念,全局变量,全局都可用,局部变量只在范围内可用。ES5之前的var是没有块级作用域的概念,使用var声明的变量就是全局的。
{
var name = 'zzz';
console.log(name);
}
console.log(name);
上述代码中{}外的console.log(name)
可以获取到name值并打印出来,用var声明赋值的变量是全局变量,没有块级作用域。
1.1.2 没有块级作用造成的问题
if块级
var func;
if(true){
var name = 'zzz';
func = function (){
console.log(name);
}
func();
}
name = 'ttt';
func();
console.log(name);
代码输出结果为'zzz','ttt','ttt'
,第一次调用func(),此时name=‘zzz’,在if块外将name置成‘ttt’,此时生效了,if没有块级作用域。
for块级
定义五个按钮,增加事件,点击哪个按钮打印“第哪个按钮被点击了”。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<script ./vue.min.js></script>
<script>
var btns = document.querySelectorAll('button');
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click',function(){
console.log('第'+ i +'个被点击了');
})
}
</script>
</body>
</html>
for块级中使用var
声明变量i时,是全局变量,点击任意按钮结果都是“第五个按钮被点击了”。说明在执行btns[i].addEventListener('click',function())
时,for块级循环已经走完,此时i=5
,所有添加的事件的i都是5。
改造上述代码,将for循环改造,由于函数有作用域,使用闭包能解决上述问题。
for (var i = 0; i < btns.length; i++) {
(function(i) {
btns[i].addEventListener('click',function(){
console.log('第'+ i +'个被点击了');
})
})(i)
}
结果如图所示,借用函数的作用域解决块级作用域的问题,因为有块级作用域,每次添加的i都是当前i。
在ES6中使用let/const解决块级作用域问题,let和const有块级作用域,const定义常量,在for块级中使用let解决块级作用域问题。
const btns = document.querySelectorAll('button');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click',function(){
console.log('第'+ i +'个被点击了');
})
}
结果和使用闭包解决一致.
1.2 const的使用
1.注意一:const用来定义常量,赋值后不能再赋值,再次赋值会报错。
<script>
//1.定义常量,赋值后不能再赋值,在赋值报错
const count = 1
// count = 2 //不可以被修改
</script>
2.注意二const不能只声明不赋值,会报错。
<script>
//2.只声明不赋值,必须赋值
// const count;
</script>
3.注意三const常量含义是你不能改变其指向的对象,例如user,但是你可以改变user属性。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<script>
const user = {
name: '张三',
age: 18
}
console.log(user);
user.name = '李四'
user.age = 20
console.log(user);
</script>
</body>
</html>
const内存地址理解
对象count一开始只想0x10的地址,直接将count(给count重新赋值,指向一个新的对象)指向地址改为0x20会报错,const是常量,无法更改对象地址。
对象user一开始指向0x10地址,user有name
、age
、两个属性,此时修改属性Name='李四'
,user对象的地址未改变,不会报错。
1.3 ES6的增强写法
1.3.1 ES6的对象属性增强型写法
ES5写法:
<script>
const name = 'long'
const age = 19
const height = 2.0
//ES5写法
const user = {
name: name,
age: age,
height: height
}
console.log('ES5:')
console.log(user)
ES6写法
//ES6写法
const usr = {
name,age,height
}
console.log('ES6:')
console.log(usr)
</script>
1.3.2 ES6对象的函数增强型写法
ES6之前对象内定义函数
const obj = {
abc:function() {
console.log("蓝眼睛小妖怪");
}
}
ES6写法:
const obj = {
abc() {
console.log("蓝眼睛小妖怪");
}
}