详解javascript 声明变量时 var let const 有什么区别

79 阅读2分钟

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

image.png 但是如果 我们用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>

image.png

造成这种很不符合逻辑现象的原因是,浏览器在执行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>

image.png

这样很容易造成全局污染 例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>变量的声明</title>
</head>
<body>

</body>
</html>
<script>
    console.log(window.screenLeft)
</script>

image.png 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>

image.png

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>

image.png 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>

image.png 用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>

image.png

利用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>

image.png

const使用

const 和let 使用情况相似都拥有块级作用域 不同的是const 在用一作用域声明的变量不可以改变引用地址且必须在声明时赋值

image.png

image.png

<!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>

image.png

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>

image.png

最佳实战

1:因为let const 有明确的作用域 声明位置 以及不变的值 所以不应该再使用var来声明变量 2: const优先 let次之 使用const 声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作.只有在提前知道未来会有修改时再用let.