8

1.TypeScript概述

1.1始于JavaScript,归于JavaScript
TypeScript从今天数以百万计的JavaScript开发者所熟悉的语法和语义开始。使用现有的JavaScript代码,包括流行的JavaScript库,并从JavaScript代码中调用TypeScript代码。
TypeScript可以编译出纯净、 简洁的JavaScript代码,并且可以运行在任何浏览器上、Node.js环境中和任何支持ECMAScript 3(或更高版本)的JavaScript引擎中。
1.2强大的工具构建 大型应用程序
类型允许JavaScript开发者在开发JavaScript应用程序时使用高效的开发工具和常用操作比如静态检查和代码重构。

类型是可选的,类型推断让一些类型的注释使你的代码的静态验证有很大的不同。类型让你定义软件组件之间的接口和洞察现有JavaScript库的行为。
1.3先进的 JavaScript
TypeScript提供最新的和不断发展的JavaScript特性,包括那些来自2015年的ECMAScript和未来的提案中的特性,比如异步功能和Decorators,以帮助建立健壮的组件。

这些特性为高可信应用程序开发时是可用的,但是会被编译成简洁的ECMAScript3(或更新版本)的JavaScript。

2.字符串新特性

2.1多行字符串
不需要使用+号拼接字符串,可读性强,写法简单。 `号在tab键上面。

let content = `aaa
bbb
ccc`;

2.2字符串模板
将变量name使用${name}拼接到字符串中。

let name = 'zhiyu';

let getName = () => {
  return 'z哥';
}

console.log(`my name is ${name}`);  // my name is zhiyu
console.log(`my name is ${getName()}`);// my name is z哥

2.3自动拆分字符串
将字符串中模板变量和非模板变量自动拆分。

let name = 'zhiyu';

let getAge = () => {
  return 24;
}

function test(template, name, age) {
  console.log(template);
  console.log(name);
  console.log(age);
}


test`我是${name},我${getAge()}岁`; // ["我是", ",我", "岁"]  zhiyu 24

3.参数新特性

3.1参数类型
在参数后面使用冒号来指定参数的类型

let myName: string = 'zhiyu';
 myName = 18; // 错误 Type '18' is not assignable to type 'string'.

let allType: any = 'haha'; // any类型可以赋值任何类型
allType = 12;
allType = true;

let age: number = 24;  // number类型
let man: boolean = true; // boolean类型

// void不需要任何返回值
function testVoid(): void {
 return '';  //  错误 Type '""' is not assignable to type 'void'.
}

//返回string类型的值
function testString(): string {
  return '';
}

//传入的参数age必须为number,返回number
function getAge(age: number): number {
  return age + 1;
}
getAge(23);
 getAge('23'); // 错误 Argument of type '"23"' is not assignable to parameter of type 'number'.


// 自定义Person类型
class Person{
  name:string;
  age:number;
}

let zhiyu:Person = new Person();
zhiyu.name = 'zhiyu';
zhiyu.age = 24;

3.2参数默认值
在参数后面使用等号来指定参数的默认值

function test(a: string, b: string, c: string) {
  console.log(a);
  console.log(b);
  console.log(c);
}

test('xxx','yyy','zzz'); // 'xxx' 'yyy' 'zzz'

// 参数设置默认值应该写在最后,c的默认值是zhiyu,调用test2时不传c参数,则c是zhiyu
function test2(a: string, b: string, c: string = 'zhiyu') {
  console.log(a);
  console.log(b);
  console.log(c);
}

test2('xxx','yyy'); // 'xxx' 'yyy' 'zhiyu'
test2('xxx','yyy','uuu'); // 'xxx' 'yyy' 'uuu'

3.3可选参数
在方法的参数声明后面使用问号来表明参数为可选参数

// 可选参数应该声明的必选参数后面,需要在方法里面处理不传可选参数时的情况
function test(a: string, b?: string, c: string = 'zhiyu') {
  console.log(a);
  b ? console.log(b) : () => { };
  console.log(c);
}

test('xxx'); // 'xxx' 'zhiyu'

4.函数新特性

4.1Rest and Spread 操作符
用来声明任意数量的方法参数

function test(...args) {
  args.forEach((arg) => {
    console.log(arg);
  })
}

test(1, 2); // 1 2
test(4, 5, 6, 7, 8, 9, 10); // 4 5 6 7 8 9 10


function test2(a: number, b: number, c: number) {
  console.log(a);
  console.log(b);
  console.log(c);
}

let args = [1, 2];
let args2 = [4,5,6,7];

// 将任意数量的参数变为固定数量的参数
// 该写法在ts中暂时不支持,但是编译出来的js可以实现功能
test2(...args); // 1 2 undefined
test2(...args2); // 4 5 6

4.2 generator函数
控制函数的执行过程,手工暂停和恢复代码执行

function* doSomething() {
  console.log('start');
  yield;
  console.log('middle');
  yield;
  console.log('end');
}

// 定义一个变量func1
let func1 = doSomething();
func1.next(); // start
func1.next(); // middle
func1.next(); // end

// 当股票价格低于15元时购买该股票
function* getStockPrice(stock: string) {
  while (true) {
    yield Math.random() * 100;
  }
}

let getStock = getStockPrice('IBM');
let limitPrice = 15;
let price = 100;
while (price > limitPrice) {
  price = getStock.next().value;
  console.log(`current prcie is ${price}`);
}

console.log(`buying at ${price}`);
// current prcie is 76.11991753923921
// current prcie is 6.342549180037449
// buying at  6.342549180037449

4.3 destructuring析构表达式
通过表达式将对象或数组拆解成任意数量的变量
对象析构表达式

function getInfo() {
  return {
    myAge: 24,
    myName: 'zhiyu'
  }
}

let { myAge, myName } = getInfo();
console.log(myAge); // 24
console.log(myName); // zhiyu

// myAgeTemp  myNameTemp 为别名
let { myAge: myAgeTemp, myName: myNameTemp } = getInfo();
console.log(myAgeTemp); // 24
console.log(myNameTemp); // zhiyu


function getInfo2() {
  return {
    myAge2: 24,
    myName2: {
      name1: 'zhiyu',
      name2: 'z哥'
    }
  }
}

let { myAge2, myName2 } = getInfo2();
console.log(myAge2);  // 24
console.log(myName2);   // {name1: "zhiyu", name2: "z哥"}

// myName2后再写一个析构表达式,可以获取name2的值
let { myAge2: myAge2temp, myName2: { name2 } } = getInfo2();
console.log(myAge2temp);  // 24
console.log(name2);   // z哥

数组的析构表达式

let array = [1, 2, 3, 4];

let [number1, number2] = array;
console.log(number1); // 1
console.log(number2); // 2

let [num1, , , num2] = array;
console.log(num1); // 1
console.log(num2); // 4

let [, , num3, num4] = array;
console.log(num3); // 3
console.log(num4); // 4


let [no1, no2, ...others] = array;
console.log(no1); // 1
console.log(no2); // 4
console.log(others); // [3, 4]


function test([no1, no2, ...others]) {
  console.log(no1); // 1
  console.log(no2); // 4
  console.log(others); // [3, 4]
}
test(array);

5.表达式与循环

5.1箭头表达式
用来声明匿名函数,消除传统匿名函数的this指针问题

function getName(name:string){
  this.name = name;
  setTimeout(function(){
      console.log('name is ' + this.name)
  },1000);
}
var getName2Temp = new getName('zhiyu'); // name is    ,此时this指向Window


function getName2(name:string){
  this.name = name;
  setTimeout(() =>{
      console.log('name is ' + this.name)
  },1000);
}
var getName2Temp = new getName2('z哥');  // name is z哥


let array1 = [1,2,3,4];
console.log(array1.filter(value => value%2 === 0)); // [2, 4]

5.2forEach for in for of 循环

let array = [1, 2, 3, 4];
array['desc'] = 'four numbers';

array.forEach(value => console.log(value)); // 1 2 3 4

for (let i in array) {
  console.log(i); // 0 1 2 3 desc
}

for (let i in array) {
  console.log(array[i]); // 1 2 3 4 four numbers
}

for (let j of array) {
  console.log(j); // 1 2 3 4
}
for (let j of 'four') {
  console.log(j); // 'f' 'o' 'u' 'r'
}

6.class

6.1 定义一个类,并实例化

class Person {
  name;
  eat() {
    console.log(this.name);
  }
}

let p1 = new Person();
p1.name = 'zhiyu';
p1.eat(); // zhiyu

let p2 = new Person();
p2.name = 'z哥';
p2.eat(); // z哥

6.2 构造函数

class Person {
  // 在constructor声明属性的时候必须指定修饰符public private protected其中之一
  constructor(public name: string) {
  }
  eat() {
    console.log(this.name);
  }
}

// 实例化必须指定name
let p1 = new Person('zhiyu');
p1.eat(); // zhiyu

let p2 = new Person('z哥');

p2.eat(); // z哥

6.3 extends关键字

class Person {
  // 在constructor声明属性的时候必须指定修饰符public private protected其中之一
  constructor(public name: string) {
  }
  eat() {
    console.log(this.name);
  }
}

class Employee extends Person {
  code: string;
  work() {
    console.log(this.code + ' is working');
  }
}

let e1 = new Employee('zzz');
e1.code = '123';
e1.work(); // 123 is working

6.4 super关键字

class Person {
  // 在constructor声明属性的时候必须指定修饰符public private protected其中之一
  constructor(public name: string) {
  }
  eat() {
    console.log('eating');
  }
}

class Employee extends Person {

  constructor(name: string, code: string) {
    super(name);
    this.code = code;
  }
  code: string;

  work() {
    super.eat();
    this.doWork();
  }
  private doWork() {
    console.log('working');
  }
}
let e1 = new Employee('zzz', '111');
e1.work(); // eating   working

7.泛型

参数化的类型,一般用来限制集合的内容

class Person {
  // 在constructor声明属性的时候必须指定修饰符public private protected其中之一
  constructor(public name: string) {
  }
  eat() {
    console.log('eating');
  }
}

class Employee extends Person {

  constructor(name: string, code: string) {
    super(name);
    this.code = code;
  }
  code: string;

  work() {
    super.eat();
    this.doWork();
  }
  private doWork() {
    console.log('working');
  }
}

// 指定数组元素为Person类
let workers: Array<Person> = [];
workers[0] = new Person('z');
// Employee继承Person类,是Person类的子类
workers[1] = new Employee('zzz', '111');
workers[1] = 1; // 错误 Type '1' is not assignable to type 'Person'.

8.interface

接口用来建立某种代码约定,使其他开发者在调用某个方法或者创建新的类的时候必须遵循接口所定义的代码约定。
8.1限制传入参数必须为某种类型

interface IPerson {
  name: string;
  age: number;
}

class Person {
  constructor(public config: IPerson) {
  }
}

let p1 = new Person({
  name: 'zhiyu',
  age: 24
})

8.2 implements关键字实现interface

interface Animal {
  eat();
}


// 必须实现eat(),否则报错
class Sheep implements Animal {
  eat() {
    console.log('I eat grass');
  }
}


class Tiger implements Animal {
  eat() {
    console.log('I eat meat');
  }
}

9.module

模块可以帮助开发者将代码分割为可重用的单元。开发者可以决定将模块中哪些资源(类,方法,变量)暴露出去供外部使用,哪些资源仅供内部使用。

// a.ts

export let prop1;
let prop2;
export class Clazz1 {

}
class Clazz2 {

}
export function func1() {

}
function func2() {

}
// b.ts
import { prop1, func1, Clazz1 } from './a'

console.log(prop1);
func1();
new Clazz1()

kkkk
221 声望125 粉丝

There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvi...