var let 和 const

227 阅读2分钟

var

  • 如果使用关键字 var 声明一个变量,那么这个变量就属于当前的函数作用域,如果声明是发生在任何函数外的顶层声明,那么这个变量就属于全局作用域

  • 我们可以在函数内部定义变量,并且我们也可以在其它函数内部访问相同的变量

function f() {
    var a = 10;
    return function g() {
        var b = a + 1;
        return b;
    }
}

var g = f();
g(); // returns 11;
  • 上面的例子里,g函数可以获取到f函数里定义的a变量。 每当 g被调用时,它都可以访问到f里的a变量。 即使当 g在f已经执行完后才被调用,它仍然可以访问及修改a
function f() {
    var a = 1;
    a = 2;
    var b = g();
    a = 3;

    return b;

    function g() {
        return a;
    }
}

f(); // returns 2
  • 变量 x是定义在if语句里面,但是我们却可以在语句的外面访问它。 这是因为 var声明可以在包含它的函数,模块,命名空间或全局作用域内部任何位置被访问
function f(flag: boolean) {
    if (flag) {
        var x = 10;
    }
    return x;
}

f(true);  // return '10'
f(false); // return 'undefined'
  • 这些作规则可能会引发一些错误。 其中之一就是,多次声明同一个变量并不会报错
function sumMatrix(matrix: number[][]) {
    var sum = 0;
    for (var i = 0; i < matrix.length; i++) {
        var currentRow = matrix[i];
        for (var i = 0; i < currentRow.length; i++) {
            sum += currentRow[i];
        }
    }

    return sum;
}
for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}
  • 最后输出结果是10个10
  • 传给setTimeout的每一个函数表达式实际上都引用了相同作用域里的同一个i,setTimeout在若干毫秒后执行一个函数,并且是在for循环结束后。 for循环结束后,i的值为10。 所以当函数被调用的时候,它会打印出 10

let

  • 当用let声明一个变量,它使用的是块作用域。 不同于使用 var声明的变量那样可以在包含它们的函数外访问,块作用域变量在包含它们的块或for循环之外是不能访问的
function f(flag: boolean) {
    let a = 100;

    if (flag) {
        let b = a + 1;
        return b;
    }

    // Error: 'b' doesn't exist here
    return b;
}
  • 这里定义了2个变量a和b。 a的作用域是f函数体内,而b的作用域是if语句块里
  • 拥有块级作用域的变量的另一个特点是,它们不能在被声明之前读或写。 虽然这些变量始终“存在”于它们的作用域里,但在直到声明它的代码之前的区域都属于 暂时性死区

const

  • const与 let的作用域规则相同,但是不能对它们重新赋值。
  • const变量的内部状态是可修改的
const age = 9;
const user = {
    name: "bob",
    age: age,
}

// Error
user = {
    name: "Kitty",
    age: age
};

// all "okay"
kitty.name = "Rory";
kitty.name = "Cat";
kitty.age--;