事实上var的设计可以看成JavaScript语言设计上的错误. 但是这种错误多半不能修复和移除, 以为需要向后兼容.
大概十年前, Brendan Eich就决定修复这个问题, 于是他添加了一个新的关键字: let.
我们可以将let看成更完美的var
块级作用域
JS
中使用
var
来声明一个变量时
,
变量的作用域主要是和函数的定义有关
.
针对于其他块定义来说是没有作用域的,比如
if/for
等,这在我们开发中往往会引起一些问题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//ES5之前因为if和for都没有块级作用域的概念,所以在很多时候,我们都必须借助于
// function的作用域来解决应用外面变量的问题
//1.变量作用域:变量在什么范围内是可用
// {
// var name = 'why';
// console.log(name);
// }
// console.log(name);
//2.没有块级作用域引起的问题: if的块级
// var func;
// if (true){
// var name = 'why';
//
// func = function () {
// console.log(name);
// }
//
// //func();
// }
//
// name = 'kobe';
//
// func(); //打印kobe
var name = 'why';
function abc(name) { //此name在function作用域中
console.log(name);
}
name = 'kobe';
abc('aaa'); //打印aaa
//3.没有块级作用域引起的问题:for的块级
//为什么闭包可以解决问题: 函数是一个作用域
// var btns = document.getElementsByTagName("button");
// for (var i = 0;i<btns.length;i++){
// // (function (num) {//0
// // btns[i].addEventListener('click',function () {
// // console.log("第"+num+"个按钮被点击"); //实际上有五个函数
// // })
// // })(i)
// btns[i].addEventListener('click',function () {
// console.log("第"+i+"个按钮被点击"); //只会打印 第5个按钮被点击
// });
// }
//ES6:
const btns = document.getElementsByTagName("button");
for (let i = 0;i<btns.length;i++){
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击");
})
}
</script>
</body>
</html>
观察前面ES5的写法 以及控制台的输出,可以看到for循环后 控制台只会打印 第5个按钮被点击 ;可以用闭包的形式解决,但是过于麻烦。
使用ES6写法后 可以得到想要的结果
可以得出:在使用ES6 let的时候变量都会有自己的作用域 别人的更改与它无关 类似于es5中function的作用域,而var是全局的 会根据i的改变而改变。
总结:ES5中的var是没有块级作用域的,ES6中的let是有块级作用域的
块级作用域(es5没闭包-有闭包)比较:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
//1.没有块级作用域引起的问题:for的块级
//为什么闭包可以解决问题: 函数是一个作用域
var btns = document.getElementsByTagName("button");
for (var i = 0;i<btns.length;i++){
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //只会打印 第5个按钮被点击
});
}
//1.情况一:ES5中没有使用闭包(错误的方式)
i = 5;
{
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //只会打印 第5个按钮被点击
});
}
{
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //只会打印 第5个按钮被点击
});
}
{
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //只会打印 第5个按钮被点击
});
}
//2.情况二:ES5中使用闭包
var btns = document.getElementsByTagName("button");
for (var i = 0;i<btns.length;i++){
(function (num) {//0
btns[i].addEventListener('click',function () {
console.log("第"+num+"个按钮被点击"); //实际上有五个函数
})
})(i)
}
(function (num) {//i = 0
btns[i].addEventListener('click',function () {
console.log("第"+num+"个按钮被点击"); //实际上有五个函数
})
})(0)
(function (num) {//i = 1
btns[i].addEventListener('click',function () {
console.log("第"+num+"个按钮被点击"); //实际上有五个函数
})
})(1)
//3. ES6中的let
for (let i = 0;i<btns.length;i++){
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击");
});
}
i = 2;
{ i = 0
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //第0个按钮被点击
});
}
{i = 1
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //第1个按钮被点击
});
}
{i = 2
btns[i].addEventListener('click',function () {
console.log("第"+i+"个按钮被点击"); //第2个按钮被点击
});
}
</script>
</body>
</html>
const的使用
const关键字
在很多语言中已经存在
,
比如
C/C++
中
,
主要的作用是将某个变量修饰为常量
.
在
JavaScript
中也是如此
,
使用
const
修饰的标识符为常量
,
不可以再次赋值
.
什么时候使用const呢?
当我们修饰的标识符不会被再次赋值时
,
就可以使用
const
来保证数据的安全性
.
建议
:
在
ES6
开发中
,
优先使用
const,
只有需要改变某一个标识符的时候才使用
let.
const的注意:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//注意一:一旦给const修饰的标识符被赋值之后,不能被修改
// const name = 'why';
// name = 'abc'; //不可以被修改
//注意二:在使用const定义标识符,必须进行赋值
// const name;
//注意三:常量的含义是指向的对象不能修改,但是可以改变对象内部的属性。
const obje = {
name: 'why',
age: 18,
height: 1.88
}
//obj = {} //错误的
console.log(obje);
obje.name = 'kobe';
obje.age = 40;
obje.height = 1.87;
console.log(obje);
</script>
</body>
</html>
对象的增强写法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
//angular -> google
//TypeScript(microsoft) -> ts有类型检测
//flow(facebook) ->
//const obj = new Object();
// const obj = {
// name: 'why',
// age: 18,
// run: function () {
// console.log('在奔跑');
// },
// eat: function () {
// console.log('在吃东西');
// }
// }
//1.属性的增强写法
const name = 'why';
const age = 18;
const height = 1.88;
//ES5的写法
// const obj = {
// name: name,
// age: age,
// height: height
// }
//ES6的写法
const obj = {
name,
age,
height
}
console.log(obj);
//2.函数的增强写法
//ES5的写法
const obj = {
run: function () {
},
eat: function () {
}
}
//ES6的写法
const obj = {
run() {
},
eat() {
}
}
</script>
</body>
</html>