一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!
Posted 贪吃ღ大魔王
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!相关的知识,希望对你有一定的参考价值。
前言
ts是什么?ts其实是TypeScript的一个简称,就跟javascript简称为js一样,官方给的解释是,ts它是js的超集,其实js的代码本质上都是ts编译的,例如写一个js代码 document.write() ,上面的提示就是ts,如图:
系统里面写的是ts代码,所以ts是js的超集,是给js添加拓展功能的语言,这样的语言曾经还有一个叫as,但是这个语言已经没了,它其实就是flash语言。但我么开发需要完善js的话,必须得有这样的一个东西,所以微软拿着这个as的语法开发了ts这个语言,也就是说as和ts的语法基本是一样的,只不过ts是微软开发的,然后推广的不错,现在随着我们编程越来越全民化,ts使用的也就越来越多,包括在找工作中,如果你的薪资是在12k以上的话,基本上都会问你会不会ts,现在的编程很多情况下都是用到ts,因为它能给js添加拓展功能,比如:可以进行各种各样的模块化开发,像之前提到的AMD,CMD开发,CommonJS,es6的模块化规范。假设现在在客户端开发,有没有一种开发场景,既可以用AMD,也可以用CMD,CommonJS,es6的,答案是没有,因为CommonJS是只能在nodejs中使用,es6的模块化开发只能在服务器中用,它们都是有各自限制的。但是ts中,想用什么都可以,它是支持全场景的。ts它更像后端,他的语法跟java最相似,这样有什么好处?大家知道js是弱类型语言,比如一个变量先定义一个数字型,然后再重新赋值一个字符串型的,这样的话这个变量的类型就改变了,这种弱类型开发是对项目有一定的安全隐患的,比如就用这个变量去做其他事情,它有可能变成其他类型的数据,所以对开发来说是有安全隐患的,所以必须得有ts来规范js开发,消除这个安全隐患,这就是为什么ts像java、#c这些后端语言,这些强类型语言定义变量的时候,需要先声明这些变量的类型是什么,一旦定义这个变量的类型后,后期是不允许修改类型的,有了这样的规范约束后,开发就更加安全了。
现在ts使用的场景是非常广泛:js的提示(编辑器内置了规范语法的ts),主流框架vue,react在底层写框架的时候用的也是ts。
说这么多,下面直接介绍ts,也就是TypeScript。
TypeScript
简介
ts是一个给js添加特性的扩展语言。
- TypeScript是由微软开发的一款开源的编程语言。
- TypeScript是JavaScript的超集,遵循最新的es6、es5规范。TypeScript扩展了JavaScript的语法。
- TypeScript更像后端java、C#这样的面向对象语言,可以让js开发大型企业项目。
- 谷歌也在大力支持TypeScript的推广,谷歌的angular2.x+就是基于TypeScript语法。
- 最新的vue、React也可以集成TypeScript。
- nodeJs矿建Nestjs、midway中用的就是TypeScript语法。
能给js增加的功能有
- 类型批注和编译时类型检查
- 类型推断
- 类型擦除
- 接口
- 枚举
- Mixin
- 泛型编程
- 名字空间
- 元组
- Await
- 类
- 模块
- lambda 函数的箭头语法
- 可选参数以及默认参数
js 是一个弱类型的语言,但ts是强类型的,语法很相像,但ts算是扩展的js的语法,ts通过类型注解,提供编译js时的静态类型检查。
编译
ts无法直接运行,所以只能编译成js运行。类似sass用来编译css,不能直接运行。
编译工具 - typescript
在全局任意位置下,先检测是否安装过ts
tsc --version
npm install -g typescript
检测是否安装成功:
tsc -v
ts文件的后缀是ts,编译命令:
tsc 被编译的文件
会在被编译文件的同级目录下生成一个同名的js文件。
生成自定义名称路径的文件:
tsc 被编译的文件 --outFile 编译后的文件路径
初始化命令:
tsc --init
执行初始化命令后,会生成一个tsconfig.json文件,如下:
其中常用配置项说明:
代表ts要转换后js版本
"target": "es5"
如果ts是以模块形式书写的,使用什么样的模块化规范,默认是commonJS
"module": "amd"
配置输出目录,可自己设置
"outDir": "./"
上面的配置项配置好以后,执行监视命令会自动编译:
tsc -w
使用amd规范的时候,需要将require.js文件拷贝到项目根目录下,且需要一个出口文件:
<script src="require.js" data-main="main.js"></script>
将ts编译成js,自动生成目标js文件
tsc 目标js文件
ts基础类型
在定义变量的时候需要指定类型,且定义好类型以后就不能改变他的类型了 - 强类型。
数值型
let decLiteral: number = 6; // 十进制
let hexLiteral: number = 0xf00d; // 16进制
let binaryLiteral: number = 0b1010; // 二进制
let octalLiteral: number = 0o744; // 8进制
let num: Number = 5; // 此时大写Number类型可以赋值为数值对象类型
num = new Number(10);
布尔值
let isDone: boolean = false;
let bool: Boolean = true; // 首字母大写的类型可以赋值为对象类型
boolean这种类型只能赋值两个值:true/false
var bool: boolean = true
var bool: boolean = new Boolean(true)
Boolean这种类型除了上面的字面量方式的两个值,还可以使用构造函数方式
var bool: Boolean = false;
var bool: Boolean = new Boolean(true)
字符串
var str: string = 'asdfasdf';
var str1: String = new String('43563456')
数组
ts写的数组,其中的数据必须是同一个类型,但不指定长度
数组中所有数据的值类型必须是数字
var arr: number[] = [1,2,3];
var arr: Array<string> = ['a','b'];
声明二维数组
var arr: number[]
var brr: number[][] = [
[1,2,3],
[4,5,6]
];
元组 Tuple
ts中的元组表示不同类型数据组成的集合,通常会固定长度,同样可以使用下标访问元素和给元素赋值
元组中就可以放不同类型的数据
元组在定义的时候就将长度固定了
var x: [string,number] = ['a',2];
console.log(x);
console.log(x[0]);
错误
x[2] = 20
不能加长度
let x: [string, number];
x = ['hello', 10];
x[2] = 'world'; // 不能加长度
可以给元素push一个值,这个值必须是string或number的类型,其他类型不允许
x.push('aaaa')
错误
x.push(true) // 错误
当给元组中并不存在的下标进行赋值的时候,会使用联合类型:
x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型
x[6] = true; // Error, 布尔不是(string | number)类型
枚举
ts中的枚举相当于在定义变量类型,这个类型有固定的取值范围,默认值从0开始,向后递增,使用指定的键来换换取到值,如果一个变量使用了这个类型,那他的值就必须从这个类型中选择,不能随便赋值:
枚举 - 必须使用指定的集合中的值
枚举类型,其实是给数字起了一些名字,让我们可以通过这个名字获取到对应的数字
默认情况,第一个名字对应的值是0,依次向后递增
enum Color {Red,Green,Blue};
var c: Color = Color.Blue; // 2
如果给其中某一个名字赋值了,他后面的名字对应的值,是根据这里的值向后递增
enum Color {Red,Green = 5,Blue};
var c: Color = Color.Blue; // 6
每个值可以指定
enum Color {Red=3,Green = 4,Blue=2};
var c: Color = Color.Blue; // 2
可以指定非数字的值
enum Color {Red='男',Green = '女',Blue='不男不女'};
var c: Color = Color.Blue; // 不男不女
通过对应值的数字获取到对应的名字 - 名字是字符串类型
enum Color {Red,Green=5,Blue};
var c: string = Color[6] // Blue
如果我们指定了其中的值是非数字型的,就不能使用这个骚操作了
enum Color {Red='red',Green = 'green',Blue='blue'};
var c: string = Color['red']; // 这个地方的值必须是数字才行
Any
Any类型,表示弱类型,也就是当我们定义一个变量的时候,不能确定变量值的类型的时候,这个类型我们又爱又恨
使用:
var a:any = 20
var b:any = 'asdfasdf'
var c:any = [1,2,3]
注意:本来我们使用ts编写代码,为的是限制类型,减少安全隐患,但是如果使用了any类型,就跟直接写js一样了,失去了意义,所以若非迫不得已,尽量不要使用。
Void
这种类型,一般用于函数执行后,不使用return返回结果的时候,就指定返回结果是void
声明变量的时候不使用它 - 当函数没有返回值的时候,返回类型指定为void
function fn(a:number,b:number):void
{
console.log(a*b);
}
Undefined
这种类型主要用于参数和返回值,用于变量毫无意义,因为定义一个变量指定为undefined类型时,以后也就只能是undefined类型了,函数中的用法:
function fn(num:number|undefined):number|undefined
{
return num;
}
undefined - 未定义类型
var a:undefined = undefined
定义变量不用undefined,因为定义了没有用
通常会用在函数的参数里面
希望fn函数的参数a是可选项
function fn(a:number|undefined):void
{
console.log(a);
}
fn(undefined)
函数可选项
参数名后面,类型的冒号之前加 ? 表示这个参数是可选项
undefined通常用在函数返回值,如果返回的是undefined就需要在返回值的地方指定undefined类型
function fn(a?:number):number|undefined
{
return a;
}
fn()
Null
null类型 - 空 - 这个数据要被销毁啦
通常在定义复杂数据类型,且在后期需要给赋值为null的时候使用
var a:number|null = 10;
使用变量a计算 - 完成
让内存回收这个变量
a = null
Never
never类型表示永远不存在的值的类型,例如,一个函数中抛出的错误,函数中有死循环永远不可能返回 …
function fn():never
{
throw new Error('错误')
}
function fn():never
{
return fn()
}
fn()
Object
对象类型:
var obj: object = {
name:"张三"
}
错误写法 - 对象默认不允许添加键值对
obj.name = '张三';
类型断言
如果在一段代码执行后的类型种类的可能性比较多,就需要假设这是一种什么类型 - 这种操作就叫做断言。
如果一个表达式的结果有可能是多种类型,最终需要肯定其中一种
var abcd: any = [1, 2, 3, 4, 5];
断言abcd变量是一个数组
(abcd as [string,number]).push(6)
(abcd as string) += 'ddd'
函数声明
在ts中,函数定义比起js中,多了参数类型和返回值的类型定义:
函数的定义,参数的类型声明,返回值的类型声明
function fn(a:number,b:number):number
{
// console.log(a+b);
return a+b
}
var res = fn(1,2)
参数默认值
function fn(a:number,b:number=3):number
{
return a+b
}
var res = fn(1)
但是在表示参数为可选项的时候,写法稍有不同:
参数可选项 - ?表示可有可无
function fn(a:number,b?:number):number
{
if(!b){
return a+5
}
return a+b
}
// var res = fn(1)
var res = fn(1,3)
带有默认值的参数,必须放在所有参数的最后面
可选项参数,必须放在所有参数的最后面
展开运算符和合并运算符同样可以使用在ts中,但是要注意运算符后面的变量的类型设置。
计算不定实参的和
function sum(...arr:Array<number>){
var sum = 0;
for(var i=0;i<arr.length;i++){
sum += arr[i]
}
return sum;
}
var res = sum(1,2,3);
console.log(res);
函数重载:通过 为同一个函数提供多个函数类型定义 来实现多种功能的目的。例:
function outputName(name:string):string
{
return "我叫"+name
}
var s1 = outputName('张三')
console.log(s1);
function outputAge(age:number):string
{
return "我今年"+age+"岁了"
}
var s2 = outputAge(12)
console.log(s2);
有多个函数结构非常类似,可以声明一个函数的结构,让函数遵循这个结构
function output(name:string):string; 定义了一个函数结构 - 名字叫output
function output(age:number):string;
function output(name:any):any
{
return "我今年"+name+"岁了";
}
var res = output(12)
console.log(res);
var res1 = output('李四')
console.log(res1);
var res2 = output(true) 报错的,因为函数的结构要求是参数string或number
console.log(res2);
ts中的类
定义
定义方式跟es6的定义方式类似
class 类名{
constructor(){
}
}
class Person{
// 静态属性 - 用类名直接调用的属性
static weight:number;
// 类的属性要定义在这里
name:string; // 表示类中有一个属性叫name
// 在ts类中,属性和方法前面可以加一个修饰符:
/*
public - 公开的 - 在哪里都能用
protected - 受保护的
private - 私有的
*/
public age:number; // public可以省略的
protected sex:string; // 受保护的只能在类里面用,类的外面不能用的
private height:number; // 私有的只能在类里面使用,类外面不能用
constructor(name:string,age:number,sex:string,height:number,weight:number){
// 给属性赋值的时候,必须在这个类中是本来就有这个属性才行
this.name = name
this.age = age
this.sex = sex
this.height = height;
// this.weight = weight;
Person.weight = weight;
this.init()
}
private init(){
// console.log(this.age);
// console.log(this.sex);
console.log(this.height);
console.log("这是初始化方法");
}
static fly(){
console.log("飞的更高");
}
}
var p = new Person('张三',12,'男',120,150)
console.log(p);
// console.log(p.age);
// console.log(p.sex); // 受保护的属性不能类的外面使用
// console.log(p.height) // 私有属性不能类的外面使用
// p.init()
console.log(Person.weight);
Person.fly()
继承
ts中类的继承和es6的继承是一样,使用extends关键字,然后在构造函数中调用super函数相当于在调用父类的构造函数。
如果子类和父类有同名的方法,在子类调用这个方法的时候先在子类里面找,如果子类没有再到父类里面找。
class Person{
// 静态属性 - 用类名直接调用的属性
static weight:number;
// 类的属性要定义在这里
name:string; // 表示类中有一个属性叫name
// 在ts类中,属性和方法前面可以加一个修饰符:
/*
public - 公开的 - 在哪里都能用
protected - 受保护的
private - 私有的
*/
public age:number; // public可以省略的
protected sex:string; // 受保护的只能在类里面用,类的外面不能用的
private height:number; // 私有的只能在类里面使用,类外面不能用
constructor(name:string,age:number,sex:string,height:number,weight:number){
// 给属性赋值的时候,必须在这个类中是本来就有这个属性才行
this.name = name
this.age = age
this.sex = sex
this.height = height;
// this.weight = weight;
Person.weight = weight;
this.init()
}
private init(){
// console.log(this.age);
// console.log(this.sex);
console.log(this.height);
console.log("这是初始化方法");
}
static fly(){
console.log("飞的更高");
}
}
var p = new Person('张三',12,'男',120,150)
console.log(p);
// console.log(p.age);
// console.log(p.sex); // 受保护的属性不能类的外面使用
// console.log(p.height) // 私有属性不能类的外面使用
// p.init()
console.log(Person.weight);
Person.fly()
类的修饰符
在类中定义属性的时候,提供了3个修饰符:
- public:公有的 - 在类里面、子类中、类的外面都可以访问
- protected:受保护的 - 在类里面、子类中可以访问,在类外面不能访问
- private:私有的 - 在类里面可以访问,在子类和类的外面都不能访问
public可以省略
例:
静态属性和方法
es5中静态方法使用:
// 模拟jquery的封装
function $(element){
return new Ele(element);
}
$.get = function(obj以上是关于一篇博文:带你TypeScript入门,两万字肝爆,建议收藏!的主要内容,如果未能解决你的问题,请参考以下文章
一篇博文:带你 gulp入门 0基础必看,万字肝爆,建议收藏~
1小时0基础带你Git入门,保姆式教学,万字肝爆! 建议收藏~
十几年老Java咳血推荐:MySQL索引原理失效情况,两万字肝爆,建议收藏!