你还在用var声明变量吗?

819 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

变量声明的问题

ES5之前是通过var声明变量,既然通过var能声明变量,为什么ES6要新增声明变量的方式呢?那么使用var会导致什么问题呢?

允许重复声明变量,导致数据被覆盖。

var a = 1;
function print(){
    console.log(a)
}
// ...
var a = 2;
print();//2

当我们书写的代码量较多时,根本就记不清之前声明过哪些变量。一但变量重复,之前写的函数可能就会产生冲突,造成不必要的bug。

变量提升,怪异的数据访问、闭包。

if(Math.random()<0.5){
    var a = 'a';
    console.log(a);
}else{
    // 没有声明也能访问a
    console.log(a);
}
console.log(a);

如果随机数小于0.5,则声明变量a,赋值为'a',输出a。
如果随机数不小于0.5,则输出a。
因为变量提升,这段代码其实是有问题的,逻辑就变成了,先声明变量a。由于变量提升,导致了怪异的代码书写。

当我们想要实现一个按钮每次点击输出编号,尝试用var来声明变量。

var body = document.querySelector('body');
for( var i = 1; i <= 10; i++){
    var btn = document.createElement('button');
    btn.innerHTML = '按钮' + 1;
    body.appendChild(btn);
    btn.addEventListener('click', function(){
        console.log(i)
    })
}

image.png

每一个按钮点击之后使用同一个变量i,输出11。

var body = document.querySelector('body');
for( var i = 1; i <= 10; i++){
    var j = i;
    var btn = document.createElement('button');
    btn.innerHTML = '按钮' + 1;
    body.appendChild(btn);
    btn.addEventListener('click', function(){
        console.log(j)
    })
}

image.png 当尝试用变量j来保存i, 我们发现每次输出的却变成了10。 原因是变量j也会提升,这两种情况都导致我们的需求无法实现。 我们为了实现这个需求,不惜写一些丑陋的代码。

var body = document.querySelector('body');
for( var i = 1; i <= 10; i++){
    var btn = document.createElement('button');
    btn.innerHTML = '按钮' + 1;
    body.appendChild(btn);
    (function (i) {
        btn.addEventListener('click', function(){
            console.log(i)
        })
    })(i)
}

全局变量挂载到全局对象,全局对象成员污染。

image.png

当我们写了很多个js文件,在全局对象上就挂载了很多个变量,难免会造成变量冲突问题。 image.png

window的成员也会被覆盖,最常见的就是window.name。