TypeScript基础知识
1.什么是TypeScript?
TypeScript是微软开发的,javascript的超集,遵循ES6规范(2015年推出)。
javascript实现了ES5规范,TypeScript实现了ES6规范。
es6属于js的规范实现,浏览器会去适配,ts不会。
以后浏览器升级,就会按照ES6的方向类适配。
然而typscript只是说我们开发人员用的语言,到时候还是要编译成ES5、ES6的规范的,才能在浏览器跑
TypeScript是Angular2的开发语言,通俗的说angular2是用TypeScript编写的。
2.搭建TypeScript开发环境compiler(编辑器)——ts转js
2.1在线compiler
在TypeScript官网上的playground
2.2本地compiler
sudo npm install -g typescript
tsc --version
使用方法:
(1).新建ts文件,并编写TypeScript代码
(2)执行tsc+文件名
(3)发现生成js代码
也可以选择适应IDE(例如webstorm的IDE),自动转为js文件
3.字符串的新特性
3.1多行字符串
let name = `aaa
bb`;
编译后的js
var name = "aaa\nbb";
3.2字符串模板
var myname='mingming';
function getname(){
return myname;
}
let str = `hello ${myname}`;
console.log(`hello ${getname()}`)
console.log(`<div>${myname}</div>`);
编译后的js
var myname = 'mingming'; function getname() { return myname; } var str = "hello " + myname; console.log("hello " + getname()); console.log("<div>" + myname + "</div>");
3.3自动拆分字符串
function test (template,name,age) { console.log(template); console.log(name); console.log(age); } var myName = "zhang san"; var getAge = function () { return 18; } test `hello my name is ${myName},i 'm ${getAge()}`;
3.参数的新特性
let myname: string = "zhang san";
编译后的js
var myname = "zhang san";
编译以后没有类型声明,只是开发阶段减少开发人员错误的可能性
注意:TypeScript具有类型推断机制,通俗的说就是变量在第一次赋值时,推断变量类型。
因此,如果之后赋值的参数类型和第一次复制的参数类型不相同,就会报错。
除非定义是any类型,例如
let test:any = "zhang san"; test = 4;
可以定义的类型有,string,any,number,boolean,void(函数特有类型,表示返回值为空)
function test1(): void{ return; } function test2(): string{ return 'myname'; } function test3(age:number){ }
自定义类型
class Person { name: string; age: number; } let zhangsna: Person = new Person(); zhangsna.name = 'zhangsan'; zhangsna.age = 5;
4.默认值
function test(a: string, b: string = "jojo") { } test('a');
5.可选参数
function test(a: string, b?: string) { } test('a');
注意:默认值要放在后面,可选参数不可放在必选参数之前
6.Rest and Spread 操作符(...)
用来声明任意数量的方法参数
function fun1(...args) { console.log(args); } fun1(1,2,3);
7.generator函数(控制函数的执行过程,手工暂停和恢复代码执行)
function* doSomething () { console.log("start"); yield; console.log("end"); } //调用generator函数,必须赋值给一个变量 let func1 = doSomething(); //通过next()来调用 func1.next(); func1.next();
8.destructuring析构表达式
function getStock() { return{ code: "IBM", price:100 } } // var { code, price } = getStock(); //但是变量的命名和字段必须一样 var {code: codeX, price} = getStock();//当你定义的变量与对象的变量不一样时,可以将其重命名 console.log(codeX,price);
当对象中的字段是一个对象
function getStock() { return{ code: "IBM", price:{ price1: 100, price2: 120 } } } let { code: codeX, price: { price2 } } = getStock(); console.log(codeX,price2);
数组使用析构表达式
var array1 = [1, 2, 3]; var [ , num1, num2] = array1; console.log(num1); console.log(num2);
var array1 = [1, 2, 3,4]; function doSomething([num1,num2,...others]) { console.log(num1); console.log(num2); console.log(others); } doSomething(array1);
9. 箭头函数
用来声明匿名函数,消除传统匿名函数的this指针问题
//单行的话可以省略{},多行的不能省。 let sum = (arg1, arg2) => arg1 + arg2; let sum2 = (arg1, arg2) => { arg1 + arg2; }
//返回偶数 var array = [1, 2, 3, 4]; console.log(array.filter(function (value) { return value % 2 == 0; }));
消除传统函数存在的this问题
javacript(这段代码会获取不到this.name)
function getStock(name: string) { this.name = name; setInterval(function () { console.log("name is "+this.name); },2000); } var stock =new getStock("IBM");
TypeScript
function getStock(name: string) { this.name = name; setInterval(()=>{ console.log("name is " +this.name); },1000); } var stock =new getStock("IBM");
编译后的javascript
function getStock(name) { var _this = this; this.name = name; setInterval(function () { console.log("name is " + _this.name); }, 1000); } var stock = new getStock("IBM");
10.循环
forEach(),只会打印集合中的值,不会打印数组的属性值。不能用break,跳出这个循环。
var myArray = [1, 2, 3]; myArray.forEach(value => console.log(value));
for in ,原理是循环键值对。
var myArray = [1, 2, 3]; for (var n in myArray) { console.log(myArray[n]); }
for of跟forEach()区别在于可以break,跳出这个循环。循环的是值而不是键。
var myArray = [1, 2, 3]; for (var n of myArray) { console.log(n); }
for of 和forEach只能用来遍历数组,不能用来遍历对象
for in 可以遍历数组和对象
11.get和set存取器(在取值和赋值的时候会自动调用)
/*存取器*/
class Person {
private _age: number;
/*相当于java中的getAge()*/
get age() {
return this._age;
}
/*相当于java中的setAge()*/
set age(inputAge: number) {
/*这里可以做一些逻辑处理 */
if (inputAge < 0 || inputAge > 150) {
alert("年龄异常");
} else {
this._age = inputAge;
}
}
say() {
console.log(`i'm ${this._age} years old`);
}
}
let p = new Person();
//p._age=23;//错误,这里访问不到
p.age = 6;//这里相当于调用java中的setAge()方法。
console.log(p.age);
p.say();
12.类
12.1 类的属性、方法、构造函数
class Person{
// 构造函数———使用关键字new的时候,会被调用且只调用一次
constructor(name:string) {
console.log('构造函数');
this.name_ = name;
}
private name_;
public getName() {
console.log(this.name_);
}
set name(name) {
this.name_ = name;
}
}
var p1 = new Person('bata');
p1.getName();
class Person{
// 构造函数-声明属性
constructor(private name_:string) {
console.log('构造函数');
}
public getName() {
console.log(this.name_);
}
set name(name) {
this.name_ = name;
}
}
var p1 = new Person('bata');
p1.getName();
访问控制符
private(类的内部可以访问) 、 public(公开-默认)、protected (类的内部和累的子类可以访问)
12.2类的继承
class Person{ // 构造函数-声明属性 constructor(private name_:string) { } public getName() { console.log(this.name_); } set name(name) { this.name_ = name; } } // 继承类可以获得被继承类的所有的属性和方法(protected属性的不可访问) class Employee extends Person { code: string; work() { console.log(); } } var e1 = new Employee('super'); e1.getName(); e1.code = '3746375';
12.3 super关键字的用法
class Person{ // 构造函数-声明属性 constructor(private name_:string) { } public getName() { console.log(this.name_); } set name(name) { this.name_ = name; } } // 继承类可以获得被继承类的所有的属性和方法(protected属性的不可访问) class Employee extends Person { em_code: string; constructor(name: string, code: string) { // 子类的构造函数必须调用父类的构造函数 super(name); this.em_code = code; } say() { // super调用父类方法 super.getName(); console.log('someone say'); } get code() { return this.em_code; } } var e1 = new Employee('super','3746375'); e1.say();
13. 泛型
class Person{ // 构造函数-声明属性 constructor(private name_:string) { } public getName() { console.log(this.name_); } set name(name) { this.name_ = name; } } // 继承类可以获得被继承类的所有的属性和方法(protected属性的不可访问) class Employee extends Person { em_code: string; constructor(name: string, code: string) { // 子类的构造函数必须调用父类的构造函数 super(name); this.em_code = code; } say() { // super调用父类方法 super.getName(); console.log('someone say'); } get code() { return this.em_code; } }
// 生命数组只能放Person类型的数据 var workers: Array<Person> = []; workers[0] = new Person('zhangsan'); workers[1] = new Employee('lisi','5465645645');
14. 接口-用来建立某种代码约定
14.1 接口作为方法的参数的类型声明
interface IPerson{ name: string; age: number; } // 1.接口作为方法的参数的类型声明 class Person{ constructor(public config:IPerson) { } } var p1 = new Person({ name: "zhangsan", age: 34 });
14.2implements关键字声明实现接口的类
interface Animal { eat(); } // implements关键字声明实现接口的类--必须实现接口里面声明的方法 class Sheep implements Animal { eat(){ console.log('ea grasst'); } } class Tiger implements Animal { eat(){ console.log('eat meat'); } }
15 模块
将代码分割成可重用的单元,并决定哪些资源(类、方法、变量)可供外部使用,哪些资源只能在模块内部使用
一个ts文件就是一个模块
a.ts
import { func3 } from "./b"; export var prop1; var prop2; export function func1(){ } function func2(){ } export class class1{ } class class2{ } func3;
b.ts
import { prop1, func1, class1 } from "./a"; console.log(prop1); func1(); new class1(); export function func3(){ }
16. 注解(annotation)
注解为程序的元素(类、方法、变量)加上更直观更明了的说明,这些说明信息与程序的业务逻辑无关,而是工指定的工具或框架使用。
@Component({ selector: 'app-destop', templateUrl: './destop.component.html', providers: [SysMockService], styleUrls: ['./destop.component.css'] })
17.类型定义文件
在依赖包的@types中的有,
文件命名为index.d.ts