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编译器不容许开展泛型函数上的类型参数。