基本类型
- TS的基本类型和JS的基本类型完全相同。
object/boolean/number/string
null/undefined
symbol:es6新加,实例唯一且不可改变
let you: boolean/string/number = false/'xxx'/100;
let list: number[]/Array<number> = [1,2,3];
- 与java类型比较:
- TS可以根据指定的变量进行类型推断,中途更改变量类型会触发TS编译报错。
- 类型断言——提前指定类型,第一种用“尖括号”;第二种用关键字as。
let oneString:any = "this is jack";
let oneLength:number = (<string>oneString).length;
let oneLength:number = (oneString as string).length; // jsx中类型断言只能使用as
除基本类型外,TS还有泛型,枚举,symbol,iterator,generator等。
泛型
- 泛型函数和泛型变量
当需要表达函数的参数类型和返回值类型必须保持一致,使用any会导致类型混乱,这时我们可以考虑使用泛型。
function hello<T>(arg:T):T{
retrun arg;
}
// 或
function hello<T>(arg:T[]):T[]{
retrun arg;
}
// 或
function hello<T>(arg:Array<T>):Array<T>{
retrun arg;
}
先给hello函数通过<>添加泛型T,再申明参数类型T和返回值类型T。
在使用泛型函数时,可以给泛型赋值,也可以省略。
let out = hello<string>('hello world');
let out = hello('hello world'); // 让TS根据传入道德参数类型推断出泛型T的值
凡事皆有例外,再某些特殊复杂的情况下,类型推断会失灵的,这时就需要我们明确地给泛型T赋值。
枚举
- 数字枚举和字符串枚举
TS支持数字类型枚举和字符串类型枚举。
enum OrderStatus{
Start=1,
Unpaid, // 默认递增,也可以赋值
Shipping,
Shipped,
Complete
}
- 如果枚举中都不赋值,默认从0开始,依次递增。
- 枚举值都必须是确定的。
- 字符串枚举都必须赋值。
- 数字枚举的反向映射
由于TS枚举代码会编译成JS代码实现,所以数字枚举可以从key到value正向映射,也可以从value到key反向映射。
// TS枚举
enum Enum {
A = 1;
}
// JS枚举实现
(function (Enum){
Enum[Enum["A"] = 1] = "A";
})(Enum || (Enum = {}));
// 正向映射
const a = Enum.A; //1
//反向映射
const nameOfA = Enum[a]; //"A"
- 字符串枚举没有反响映射;
symbol
es6新加,实例唯一且不可改变。
TS中使用symbol类型和es6一样通过Symbol构造函数创建;
const symbol1 = Symbol();
const symbol2 = Symbol('hello');
const symbol3 = Symbol('hello');
console.log(symbol2 === symbol3); // 实例唯一,false。
- symbol可以像字符串一样用作对象属性的健;
const symbol = Symbol();
const obj = {
[symbol]: "hello";
};
console.log(obj[symbol]); // "hello"
iterator
实现了Symbol.iterator方法的对象,Symbol.iterator方法返回供迭代的值。
eg:array、map、set、string、int32Array、uint32Array等内置类型。
常用的 for...of/in/each等会调用可迭代对象的Symbol.iterator方法。
const array =[1,false,'hello'];
for (let val of array){
console.log(val); // 1 , false, 'hello'
}
for (let i in array){
console.log(i); // 0,1,2
}
总结:
1. for...of 迭代的是对象的键,而for...in迭代的是对象的值。
2. for...of 只可操作可迭代对象,而for...in可操作任意对象。
\
Set是不重复数组,没有下标,for in和下标访问无效或报错,有size没length。
const nameSet= new Set('Js','Ja','Ph','Py');
nameSet[9] = 'Ru';
generator...yield
generator函数的语法是function * , MDN文档中称为生成器。调用generator方法,会返回一个generator对象。generator对象遵循迭代器接口,可以使用常见的next,return,throw函数。
generator函数的实质是允许一个函数暂停执行,当调用next() 之后,函数执行到yield语句时会暂停并返回yield的值对象,再次调用会接着上次返回第二个yield返回值对象。
所以我的理解是generator是间断执行函数,也可以叫片段执行函数。
其中return函数一般通过yield关键词来实现;
如果在generator函数中直接使用return,return之前的函数仍然可以分段执行,return之后的代码无效;
// 创建generator函数
function * generatorFn(){
console.log('执行代码片段一');
yield 1;
console.log('执行代码片段二');
yield 2;
console.log('执行代码片段三');
const num = yield 3;
console.log('执行结束'+num);
}
// 生成 generator 对象
const gen = generatorFn();
// 调用next(), 让代码分片段执行
console.log(gen.next());
// 执行代码片段一
// {value: 1, done: false};
console.log(gen.next());
// 执行代码片段二
// {value: 2, done: false};
console.log(gen.next());
// 执行代码片段三
// {value: 3, done: false};
console.log(gen.next(4));
// 执行结束4
// {value: undefined, done: true};
yield 有两种用法:
- 返回当前next函数返回值;//实现return功能
- 接收下一个next函数的传参;
下面看gen.throw函数
function * generator(){
try {
yield 1;
}catch(error){
console.log(error.message);
}
}
const gen = generator();
console.log(gen.next());
// {value: 1, done:false}
console.log(gen.throw(new Error('执行出错')));
// 执行出错
// {value: undefined, done: true}
在generator函数中使用return;
// 创建generator函数
function* generatorFn() {
console.log('执行代码片段一');
yield 1;
console.log('执行代码片段二');
return '333';
yield 2;
console.log('执行代码片段三');
const num = yield 5;
console.log('执行结束' + num);
}
// 生成 generator 对象
const gen = generatorFn();
// 调用next(), 让代码分片段执行
console.log(gen.next());
// 执行代码片段一
// {value: 1, done: false};
console.log(gen.next());
// 执行代码片段二
// {value: '333', done: false};
console.log(gen.next());
// {value: undefined, done: false};
console.log(gen.next(3));
// {value: undefined, done: true};
直接使用return函数,return之前的部分依旧可以分段执行,return之后的代码无效;