TypeScript进修笔记—变量的声明

从var声明提及

一直以来我们都是经由过程var关键字定义JavaScript变量。

var a = 10;

var声明的变量var声明能够在包括它的函数,模块,定名空间或全局作用域内部任何位置被接见。
比方在别的函数内部接见雷同的变量:

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

这些作用域划定规矩可能会激发一些毛病。

  • 第1个题目就是屡次声明同一个变量并不会报错。比方下面这个例子:
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;
}
sumMatrix([[1,2],[3,4]])

平常以为,运转的效果应该为10。但效果并非如此,由于一切i都援用雷同的函数作用域内的变量,里层的for轮回会掩盖变量i,所以如今的效果是3而不是10。所以运用var声明时,它不在意你声明多少次你只会获得1个。

  • setTimeout中的非常

看下面这段代码:

for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}

我们希冀的效果是:每隔100*i毫秒打印出1个数字,递次为1-10,但现实打印出的全部都是10。这是由于setTimeout在多少毫秒后实行一个函数,而且是在for轮回完毕后。 for轮回完毕后,i的值为10。 所以当函数被挪用的时刻,它会打印出 10!我们不能不应用一个马上实行函数处理这个题目:

for(var i = 0; i < 10; i++){
    (function(i){setTimeout(()=>console.log(i), i * 100);})(i)
}

var声明的变量带给我们这么多搅扰,所以在typescript中加入了let对变量举行声明。

let声明

let与var的写法一致:

let hello = "Hello!";

let声明的变量和var声明的变量有许多差别之处,let处理了var变量带来的搅扰。

  • 块作用域

当用let声明一个变量,它运用的是块作用域。 差别于运用 var声明的变量那样能够在包括它们的函数外接见,块作用域变量在包括它们的块或for轮回以外是不能接见的。

function f(input: boolean) {
    let a = 100;
    if (input) {
        let b = a + 1;
        return b;
    }
    return b;
}

在上面代码中,a能够在if语句中被接见,由于a在函数语句中声明,在if语句以外,而b就不能在if语句块以外被接见,由于b是在if语句块中被声明的。
在catch语句里声明的变量也具有一样的作用域划定规矩。

try {
    throw "oh no!";
}
catch (e) {
    console.log("Oh well.");
}
console.log(e);        //error

在catch语句块外,e是不能被接见的。

在let语句声明之前接见let声明的变量,效果为undefined。

function foo() {
    // okay to capture 'a'
    return a;
}
console.log(foo());            //
let a = 10;        
  • 重定义及屏障

var声明时,不管你声明多少次,你只会获得1个。

var x = 10;
console.log(x);        //10
var x = 20;
console.log(x);        //20

let声明,须要遵照块作用域划定规矩,在一个块作用域中反复声明变量会发生毛病提醒,另一个用var声明也不允许。

function g() {
    let x = 100;
    var x = 100; // error: can't have both declarations of 'x'
}

块级作用域变量能够用函数作用域变量来声明。 然则块级作用域变量须要在显著差别的块里声明。

function f(condition, x){
    if(condition){
        let x = 100;
        return x;
    }
    return x;
}
console.log(f(true, 0));        //100
console.log(f(false, 0));       //0

在一个嵌套作用域里引入一个新名字的行动称做屏障。 它是一把双刃剑,它可能会不小心肠引入新题目,同时也可能会处理一些毛病。 比方,假定我们如今用 let重写之前的sumMatrix函数。

function sumMatrix(matrix: number[][]){
    let sum = 0;
    for(let i = 0; i < matrix.length; i++){
        let current = matrix[i];
        for(let i = 0; i < current.length; i++){
            sum += current[i];
        }
    }
    return sum;
}
console.log(sumMatrix([[1,2],[3,4]]));      //10

此次能够获得准确的效果10,由于内层轮回中的i屏障了外层轮回中的i。但这类写法是不引荐的。

  • 块级作用域变量的猎取
function theCityThatAlwaysSleeps() {
    let getCity;
    if (true) {
        let city = "Seattle";
        getCity = function() {
            return city;
        }
    }
    return getCity();
}

上面这段代码能够一般实行。由于我们已经在city的环境里猎取到了city,所以就算if语句实行完毕后我们依然能够接见它。
当let声明出如今轮回体里时具有完整差别的行动,针对每次迭代都邑建立一个新作用域。所以在 setTimeout例子里我们仅运用let声明就能够了。

for(let i = 0; i < 10; i ++){
    setTimeout(()=>console.log(i), i*100);
}

会输出与预感一致的效果:1 2 3 4 5 6 7 8 9

const 声明

const 声明是声明变量的另一种体式格局。它们与let声明类似,然则就像它的名字所表达的,它们被赋值后不能再转变。

const numLivesForCat = 9;

它们具有与 let雷同的作用域划定规矩,然则不能对它们从新赋值。

const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
}
// Error
kitty = {
    name: "Danielle",
    numLives: numLivesForCat
};

但const变量内部的状况照样能够转变的。

const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
}
// all "okay"
kitty.name = "Rory";
kitty.name = "Kitty";
kitty.name = "Cat";
kitty.numLives--;

let与const的区分

末了,说说let与const的区分,援用官网的发起:

运用最小特权准绳,一切变量除了你计划去修正的都应该运用const。 基本准绳就是假如一个变量不须要对它写入,那末别的运用这些代码的人也不能够写入它们,而且要思索为何会须要对这些变量从新赋值。 运用 const也能够让我们更轻易的推想数据的活动。

    原文作者:黄先生
    原文地址: https://segmentfault.com/a/1190000013824321
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞