let与const 为什么会出现?
在ES6以前声明变量只能用var的方式来声明,但是var声明的变量有很多的问题,所以出现了let和const 下面我们先举例证明一下 var声明的变量有哪些问题
var声明的变量会提升作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(web)
</script>
当我们在没有声明变量而直接使用变量的时候,会产生异常 web is not defined
但是如果 我们用var声明变量 却不会报错 而是undefined
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(web)
var web="wo shi zi fu"
</script>
造成这种很不符合逻辑现象的原因是,浏览器在执行js代码的时会先解析一遍js代码 将var 声明的变量提升到作用域的最上方 此时代码成为了:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
var web;
console.log(web)
web="wo shi zi fu"
</script>
代码变成了 先声明后赋值 这就是变量提升的效果
var声明的全局变量会成为window对象的属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
var web = "wo shi zi fun"
console.log(web)
console.log(window.web);
</script>
这样很容易造成全局污染 例如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(window.screenLeft)
</script>
screenLeft 为浏览器到屏幕左边的距离为921 利用var声明的变量会轻易改变window对象的属性 这是很危险的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(window.screenLeft)
var screenLeft=100;
console.log(window.screenLeft);
</script>
let的使用
let声明的变量是拥有块级作用域的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
var i = 10;
for (var i = 0; i < 5; i++) {
console.log(i);
}
console.log(" ")
console.log(i);
</script>
var 声明的变量没有块级作用域 所以在for循环中的i改变了全局声明的i'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
let i = 10;
for (let i = 0; i < 5; i++) {
console.log(i);
}
console.log(" ")
console.log(i);
</script>
用let声明的变量 会有自己的作用域,不会被其他作用域干扰
- 当一个作用域内有let声明的变量时,此时在let声明之前的执行瞬间被称为"暂时性死区" 在此阶段引用任何后边才声明的变量都会抛出 ReferenceError*
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(web);
var web = "wo shi web";
console.log(message);
let message = "wo shi message"
</script>
利用let暂时性死区这个特性 很巧妙的解决了var变量提升的问题
let 声明的变量不会绑定到window对象身上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
console.log(window.screenLeft);
let screenLeft =100;
console.log(window.screenLeft);
</script>
const使用
const 和let 使用情况相似都拥有块级作用域 不同的是const 在用一作用域声明的变量不可以改变引用地址且必须在声明时赋值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
const obj={
name:"con",
age:12
}
obj.name="xxx";
console.log(obj);
</script>
const 声明的对象不可以改变引用的指向,但是可以改变对象的属性 如果要解决这个问题,可以使用Object.freeze来锁定对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量的声明</title>
</head>
<body>
</body>
</html>
<script>
const obj={
name:"con",
age:12
}
Object.freeze(obj);
obj.name="xxx";
console.log(obj);
</script>
最佳实战
1:因为let const 有明确的作用域 声明位置 以及不变的值 所以不应该再使用var来声明变量 2: const优先 let次之 使用const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作.只有在提前知道未来会有修改时再用let.