TS的变量声明

  1. 在typescript里面推荐大家使用let关键字来代替大家所熟悉的JavaScript关键字varlet关键字是JavaScript的一个新概念,TypeScript实现了它

  2. 我们先使用typescirpt的语法将var声明变量的几个问题和使用let声明做一个对比

变量声明提升 (作用域规则)

function f(flag: boolean):any {
    if (flag) {
        var x:number = 10;
    }
    return x;
}
console.log(f(true));
console.log(f(false));

大家会发现,我们将变量x定义在if语句块内部,但是却能在外部访问它;这就是var的函数作用域;并且flag为false的时候,也会有打印(undefined),而不是说not defined; 这就是var的变量声明提升
如果换为let, x就只能在if块里面使用,当flag为false时,就会显示x没有定义,通过看编译后的源代码我们也能够发现ts转为js,tsc将变量名直接都改变了,当然就找不到x这个变量的定义了
当用let声明一个变量,它使用的是词法作用域或块作用域;块作用域变量在包含它们的块或for循环之外是不能访问的; 并且没有声明提升

多次重复声明同一个变量不会报错

var a:number = 1;
var a:number = 2;
console.log(a)  

javascript里面不会提升我们是否多次声明了同一个变量,遇到这种情况,js会对忽略后续的声明;但是会执行它的重新赋值操作
如果换位let, 在编译阶段就不会通过;会告诉我们 无法重新声明块范围变量“a”

for循环作用域问题

for (var i:number = 0; i < 5; i++) {
    setTimeout(function f(): void {
        console.log(i);
    }, 1000);
}

最后的结果不是我们希望的 01234,而是5个5,这是因为我们传给setTimeout的每一个函数表达式实际上都引用了相同作用域里(var声明的变量只有函数作用域和全局作用域,)的同一个i; 在循环结束后,i的值为5。 所以当函数被调用的时候,它会打印出5个5

我们可以利用IIFE立即自执行函数表达式,创造多个函数作用域出来,为获取到的变量创建了一个新的变量环境

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

当let声明出现在循环体里时拥有完全不同的行为。 不仅是在循环里引入了一个新的变量环境,而是针对 每次迭代都会创建这样一个新作用域。 这就是我们在使用立即执行的函数表达式时做的事

      for (let i: number = 0; i < 5; i++) {
        setTimeout(function f(): void {
          console.log(i);
        }, 100 * i);
      }

const声明是声明变量的另一种方式

与let声明相似,但是就像它的名字所表达的,它们被赋值后不能再改变。 换句话说,它们拥有与 let相同的作用域规则,但是不能对它们重新赋值

let l1: number = 9;
l1 = 10;
const c2: number = 9;
c2 = 10;

但是对于复杂数据类型有的点特殊

const c2: any = {
    name: 'jack'
};

下面直接改是不行的,因为相当于给变量b重新开辟了一个内存空间,地址发生了改变,constant类型的值不能更改

c2 = {
   name: 'Lucy'
};

但是下面的代码是可以正常执行的,因为改变的是复杂数据类型的值,它们都存储在堆里面,只是一个引用,它们的值就是地址还是保存在栈里面,没有更改

c2.name = 'Lucy';

选择 let还是const

  1. 所有变量除了你计划去修改的都应该使用const。使用 const也可以让我们更容易的推测数据的流动
  2. 基本原则就是如果一个变量不需要对它写入,那么其它使用这些代码的人也不能够写入它们,并且要思考为什么会需要对这些变量重新赋值。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章