TypeScrpt中变量申明次要有三种形式:var,let和const。

var申明

讲讲var的特点

1.变量晋升
2.可反复申明,后申明笼罩前申明
3.var的作用域,来看上面的例子:

function f(flag:boolean) {    if(flag) {        var x = 10;    }}f(true); // returns "10"f(false); // returns "undefined"

能够看到,咱们将变量X定义在if语句内,然而却能够在if语句里面拜访它。这是因为var申明能够在蕴含他的函数,模块命名空间或全局作用域外部的任何地位被拜访。此为var作用域或函数作用域,函数参数也应用函数作用域。

let申明

let与var的写法统一

let hello = "Hello!";

次要区别在语义上。

块作用域

当用let申明一个变量,它应用的是词法作用域或块作用域。var申明的变量能够在蕴含他们的函数外拜访,与var不同的是,块作用域变量在蕴含他们的块或for循环之外是不能拜访的。
来看上面的例子:

function f(flag:boolean) {    let a = 100;    if(flag) {        let b = a + 1;        return b;    }    return b; // 报错}

咱们在函数外部用let定义了a,b两个变量。a的作用域是f函数体内,而b的作用域是if语句内,if语句内能够拜访a,然而if语句外无法访问到b,因而在if语句外拜访b会报错。

块级作用域的特点之一是没有变量晋升,也就是不能在被申明之前读写,这也是与var不同的中央。

const申明

const也是申明变量的一种形式。

const  = 3.14

const领有与let雷同的作用域规定,然而不能对他们从新赋值。

const age = 18;const Tom = {    name: "Tom",    age: age    };//报错Tom = {    name: "Jerry",    age: age};//okTom.name = "tom";Tom.age--;

通过以上例子不难看出,在给Tom从新赋值对象时报错,然而批改Tom的属性值时失常运行。这是因为const定义的变量的不能批改的含意是不能批改变量的援用。
如果const定义的变量为简略数据类型:字符串、数字等类型,不能批改;如果const定义的变量为简单数据类型:对象、数组等,不能批改其援用,但能够批改其属性的值。

解构

解构赋值语法是一种 Javascript 表达式。能够将数组中的值或对象的属性取出,赋值给其余变量。

构造数组

let array = [1, 2];let [first, second] = array;console.log(first); // 1console.log(second); // 2

这里通过解构创立了first和second两个变量。
作用域函数参数:

function f([first, second]: [number, nnumber]) {    console.log(first);    console.log(second);} f([1,2])

也能够在数组里应用...开展操作符创立残余变量:

let [first, ...rest] = [1, 2, 3, 4];console.log(first); // 1console.log(rest); // [2, 3, 4]

也能够疏忽不关怀的尾随元素或其余元素:

let [first] = [1, 2, 3, 4];console.log(first); // 1let [,second,, last] = [1, 2, 3, 4];console.log(second); // 2console.log(last); // 4

解构对象

let o = {    a: "foo",    b: 5,    c: "bar" };let {a, b} = o;

这里通过o.a和o.b创立了a和b,能够疏忽不须要的属性,例如这里的c。
在后面咱们讲到,能够对没有申明的数组解构,对象同样也能够。

({ a, b } = { a:"bar", b:10 });

这里要留神,在javascript中通常会以 { 起始的语句解析为一个块,因而咱们在这里用括号将其括起来。
也能够用...开展操作符创立残余变量:

let { a, ...restProperty } = o;let rest = restProperty.b + restO=Property.c.length;

属性重命名

能够给属性以不同的名字:

let { a: newName1, b: newName2 } = o;

这里咱们将a重命名为newName1,b重命名为newName2,能够将a作为newName1,b作为newName2。
须要留神的是,这里的:是重命名的作用,并不是批示类型,如果要同时指定类型,依然须要在气象写上残缺的模式。

let { a:newName1, b: newName2 }: { a:string, b: number } = o;

默认值

在函数调用时,有时咱们并不会传所有参数,此时,能够为函数参数给默认值。

function f(args: {a: string, b?: number}) {        let { a, b = 18 } = args;}

这里,咱们给函数参数b给定了默认值为18。

开展

开展操作符与解构相同,它能够将一个数组开展为另一个数组,或将一个对象开展为另一个对象。例如:

let first = [1,2];let second = [3,4];let bothPlus = [0, ...first, ...second,5];

这里,bothPlus的值为[0, 1 ,2, 3, 4, 5],开展操作创立了first和second的一份浅拷贝,他们不会被开展操作所扭转。
同解构一样,也能够开展对象:

let cat = { name: "Tom", age: 18 };let Tom = { ...cat, gender: male };

Tom的值为{ name: "Tom", age: 18, gender: male },对象的开展较于数组的开展更为简单。同数组的开展一样,它从左至右进行,但后果仍为对象。这意味着,开展对象前面的属性会笼罩后面的属性。

let cat = { name: "Tom", age: 18, gender: female };let Tom = { ...cat, gender: male };

这里,Tom的值为{ name: "Tom", age: 18, gender: male }。
另外,开展对象,仅蕴含对象本人的可枚举属性。因而,当开展对象是,会失落对象自身的办法:

class Cat {    name: "Tom";    hunt() {        console.log("抓老鼠~");    }}let Tom = new Cat();let smallTom = { ...Tom };console.log(smallTom.name); // TomsmallTom.hunt; //报错

其次,Typescript编译器不容许开展泛型函数上的类型参数。