前端开发系列041-基础篇之TypeScript语言特性(一)
这篇文章我们开始来探讨TypeScript的语言特性,主要介绍数据类型方面的内容。
一、var、let和const关键字
在ES6前,JavaScript中只能通过var关键字来声明变量,且没有块级作用域。
在TypeScript中,我们声明变量的时候可以使用var、let或者是const
关键字。
//文件路径 ../01-数据类型/00-声明变量的关键字
//[01] var 关键字声明变量
console.log(var_zero); //undefined
var var_zero:number = 1;
console.log(var_zero); //1
//全局作用域
var var_one:string = '我是字符串_wendingding';
//函数作用域
function foo():void{
var var_two:string = '我是函数内的字符串';
}
foo();
console.log(var_one); //输出:我是字符串_wendingding
//报错: Cannot find name 'var_two'.
//console.log(var_two); 错误的演示
for (var var_i = 0; var_i < 3; var_i++) {
//循环三次,输出的结果均为3
setTimeout(function() { console.log(var_i); }, 1000);
}
console.log(var_i); //打印结果为:3
/****························****/
//[02] let关键字声明变量
//注意点:let关键字使用的时候必须先声明然后才能使用
//报错:Block-scoped variable 'let_zero' used before its declaration.
//console.log(let_zero); //错误的演示
//let let_zero:number = 1;
//全局作用域
let let_one:string = "wendingding";
//函数作用域
function bar():void{
var let_two:string = '我是函数内的字符串';
}
bar();
console.log(let_one);
//报错:Cannot find name 'let_two'.
//console.log(let_two); //错误的演示
for (let let_i = 0; let_i < 3; let_i++) {
//循环3次,输出的结果为0,1,2
setTimeout(function() { console.log(let_i); }, 1000);
}
//报错:Cannot find name 'let_i' 因为let_i的作用域为块级作用域
//console.log(let_i); //错误的演示
/****························****/
//[03] const关键字声明变量
const T1:number = 12345;
const T2:string = "建议那些不希望不修改的变量均使用const声明";
//报错 Cannot assign to 'T1' because it is a constant or a read-only property.
//T1 = 234; 错误的演示
//报错: 'const' declarations must be initialized.
//const T3:boolean; 错误的演示
let关键字声明变量的主要特点有块级作用域
、变量先声明后使用
以及不能重复定义等。const关键字和let在声明变量的时候基本一致,只是const声明的变量被赋值后不能再改变(注意:对于const来说,只声明不赋值会报错),作用域同let。
关于变量的作用域说明
var声明的变量
保存在最近的函数作用域中,如果不在任何函数中则在全局作用域中。
let和const声明的变量
保存在最近的比函数作用域小的块级作用域中,如果不在任何代码块中,则在全局作用域中。
二、可选的静态类型声明
TypeScript通过向JavaScript增加可选的静态类型声明(Optional static type notation
)来把JavaScript编程强类型的程序语言。可选的静态类型声明可以用来约束变量、函数等实体,这样编译器和开发工具就可以在开发过程中提供更好的正确性验证。另外,这种强类型的语言特性也能为代码提供更直观的表达,便于构建大型的程序架构。
需要注意的是,强类型的语言特性因为增加了类型检测机制所以需要额外的性能开销,但对于TypeScript来说,这些开销是在代码的编译过程中发生的,所以其实TypeScript并没有额外的运行时性能开销。
TypeScript能够对变量进行类型推导,但是在有些特殊情况下还无法准确的自动侦测出某些对象和变量的类型。在这些情况下,TypeScript允许我们对变量的类型进行明确的声明。这种允许声明变量类型的特性就被称为可选的静态类型声明(Optional static type notation
)。
选的静态类型的声明方式为关键字 变量名:类型
,这种风格源于类型理论,而且更加强调类型的声明时可选的,如果类型声明没有提供,那么TypeScript会通过检查赋给当前变量的值的类型来推导出变量类型,这个过程被称为类型推导(Type inference)
,当变量的类型无法被推测出来时(比如变量并没有被赋值),那么TypeScript会把该变量的类型设置为any,any类型可以表示任意的JavaScript值。
//01.可选的静态类型声明.ts
let num0; //未知的数据类型(any)
let num1 = 0; //number类型(类型推导)
let num2:number; //number类型(声明)
let num3:number = 123; //number类型(声明)
let num4:number = "string"; //报错:Type '"string"' is not assignable to type 'number'.
代码说明:上面代码中变量num2和num3通过类型声明的方式确定了它们是number类型的,num1因为没有提供类型声明,所以TypeScript尝试检测0的数据类型,然后推导出num1为number类型,num0因为既没有提供类型声明也没有任何赋值操作,所以TypeScript无法推导出其真实类型,因此设置其类型为any。
三、基本的数据类型
JavaScript语言中数据类型可以分为基本数据类型
(Primitive data types)和对象类型
(Object types)两种。其中,基本数据类型包括:布尔值、数值、字符串、null、undefined以及Symbol
,而对象类型主要有:对象、数组、函数
等。
TypeScript中的数据类型和JavaScript稍有不同,下面主要介绍TypeScript中的基本数据类型,主要有布尔类型(boolean)、数值类型(number)、字符串类型(string)、数组类型(array)、void类型以及枚举类型。
数值(number)
数值类型等同于JavaScript中的number类型,在TypeScript中所有的数字都是浮点数,它们全部都是number类型的。
字符串(string)
连续的一个或多个字符,在代码中需要使用单引号或双引号包住,可以交叉。
布尔类型(boolean)
布尔类型有两个可选的值,true或false。
数组类型(array)
TypeScript中的数组类型和JavaScript不太一样。数组类型在声明的时候比较特殊,通常有两种声明方式:关键字 数组名:类型[]
或者关键字 数组名:Array<类型>
后一种格式被称为泛型,后面会专门介绍。
枚举类型(enum)
枚举类型和其他面向对象语言中保持一致。我们可以通过enum 类型名{选项1,选项2,选项3,···}
的方式来定义,枚举类型中的成员默认从0开始依次递增。
void类型
void类型在所有类型都不存在的时候使用,是any类型的反面。
any类型
any类型可以表示任何类型,即能够表示任意的JavaScript数据。如果变量被声明为某个特定的基本类型,那么在赋值过程中改变其原本的类型是不被允许的,但如果该变量被声明为 any 类型,则允许接受任意类型的值。
any类型的值支持所有在JavaScript中对变量的操作,且在对any类型的值进行操作时仅仅进行最小静态检查,下面给出基本类型的代码示例。
//文件路径 ../01-数据类型/02-基本数据类型.ts
//01 布尔类型的值
//类型关键字(boolean)
//说明 true或者false
let bool1:boolean = true;
let bool2:boolean = false;
//02 字符串类型的值
//类型关键字(string)
//说明 用双引号或单引号括住一个或多个字符
let str1:string = "文顶顶";
let str2:string = 'wen_dingd_ding';
let str3:string = "Hi '王二!' 你好,我是老实人。"
//03 数值类型
//类型关键字(number)
//说明 同JavaScript中的number类型
let num1:number = 123;
let num2:number = 123.321;
//04 数组类型
//类型关键字(array)
//数组类型声明方式(一) 关键字 数组名:类型[]
let arr1:number[] = [1,2,3,4];
//let arr2:number[] = [1,3,5,'T',6]; //错误的演示,仅仅允许数字作为数组的元素
//let arr2:(string | number)[] = [1,3,5,'T',6]; //正确的处理方式
//数组类型声明方式(二) 关键字 数组名:array<类型>
let arr3:Array<number> = [2,4,6,8];
let arr4:Array<any> = [2,4,6,8,"T",false];
//05 any类型的值
let any1 ; //声明变量的时候没有进行初始化操作,无法通过类型推导得出真实类型,通常总是设置为any类型
let any2:any = "我现在是字符串"; //如果某个变量其类型可能会变化,建议使用any类型
any2 = false;
//错误的演示
//报错:Type '123' is not assignable to type 'string'.
let test:string = "字符串类型的值";
//test = 123; //把数值赋值给test变量
//06 枚举类型
enum Color {Red , Green , Yellow , Blue};
let a:Color = Color.Yellow;
console.log(a); //打印的结果为2,每个选项从0开始依次递增
//void类型
//声明一个返回值为void类型(没有返回值)的函数
function foo():void{
console.log("这是一个没有返回值的函数,返回值的类型为void");
}
foo();
//关于null和undefined
let test1:null = null;
let test2:undefined = undefined;
四、联合类型和类型别名
联合类型用来声明那些可以存储多种类型值的变量。想象以下,如果您在设计变量的时候,希望该变量可以存储字符串类型或者数字类型的值,不能存储除此之外的其它类型数据,那么这个时候就可以使用联合类型来声明了。
联合类型声明变量的语法格式=> 声明变量的关键字 变量名:(类型1 | 类型2)= 值
//文件路径: ../01-数据类型/03-联合类型.ts
let test0 :number = 1;
//报错:Type 'false' is not assignable to type 'number'.
//test0 = false; //错误的演示
let test1:(number | boolean) = 123;
test1 = true;
console.log(test1);
let test2:(number[] | string) = [1,2,3];
test2 = "我是字符串";
console.log(test2);
TypeScript中允许我们使用type关键字来给类型设置别名。类型别名这种特性可以提高代码的可阅读性,缩短代码,但需要有节制的使用。
//文件目录:../01-数据类型/04-类型别名.ts
type MyType = (string | boolean | number);
let value1:MyType = "我是字符串";
console.log(value1);
value1 = 123;
console.log(value1);
value1 = true;
console.log(value1);
//报错: Type 'number[]' is not assignable to type 'false'.
//value1 = [1,2,3]; 错误的演示
备注:该文章所有的示例代码均可以点击在Github托管仓库获取