一、泛型的认识
泛型可以简单理解为类型变量,它是一种特殊的变量,只用于表示类型而不是值。
二、定义一个简单的泛型
-
1、定义泛型
function identity<T>(arg: T): T { return arg; }
identity
就叫泛型函数 -
2、直接调用这个函数(推荐)
console.log(identity('hello')); console.log(identity(20));
-
3、指定类型的调用
console.log(identity<string>('hello')); console.log(identity<number>(20)); console.log(identity<Array<number>>([1,2,3,4]));
三、Symbol
的使用
传统的
javascript
中数据类型有七种string
,number
,boolean
,null
,undefined
,object
,及ES6
中的Symbol
,数组属于object
,函数属于object
数据类型
-
1、
Symbol
表示唯一的,创建一个Symbol
必须创建对象的方式创建let sym1 = Symbol(); let sym2 = Symbol('key'); //可以不写key let sym3 = Symbol('key');
-
2、两个
Symbol
进行比较是false
console.log(sym2== sym3); //false
-
3、如果用
Symbol
表示对象的key
只能用[]
访问let obj1 = { [sym1]:'hello word', name:'zhansan' }; console.log(obj1['name']); console.log(obj1[sym1]);
-
4、可以用
Symbol
来做类里面的函数名称class C1{ [sym1](){ return 'C1' } } let c1 = new C1(); console.log(c1[sym1]());
-
5、使用
Symbol.for()
创建两个相同的Symbol
let sym4 = Symbol.for('key1'); let sym5 = Symbol.for('key1'); console.log(`sys4是否等于sym5:${sym4==sym5}`);
-
6、
Symbol.keyFor(xx)
获取一个Sysmbol
的key
console.log(`${Symbol.keyFor(sym4)}`); //结果是key1
-
7、
match
的使用对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时
class MyMatcher { [Symbol.match](string) { return 'hello world'.indexOf(string); } foo(string){ return 'hello world'.indexOf(string); } } console.log('h'.match(new MyMatcher())) // 0 console.log((new MyMatcher()).foo('h')) // 0
8、更多关于
Symbol
的请查阅ES6中Symbol
四、关于迭代中的for...of
与for...in
的区别
- 1、
for..in
迭代的是对象的键的列表 - 2、
for..on
迭代的出来的是值 - 3、
ES3
或者ES5
中使用for..of
会报错
五、模块的认识
传统的
javascript
开发过程中要使用模块化开发一般使用seajs
、Require.js
类的处理,模块在其自身的作用域里执行,而不是在全局作用域里,这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的。
- 1、两个模块之间的关系是通过在文件级别上使用
imports
和exports
建立的 -
2、任何声明(比如变量,函数,类,类型别名或接口)都能够通过添加
export
关键字来导出// 导出一个变量 export const numberRegexp = /^\d+$/; //导出一个接口 export interface StringValidator { isAcceptable(s: string): boolean; } // 导出一个类 export class Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } say(): string { return `我的名字叫:${this.name}--,我今年:${this.age}`; } } // 导出一个函数 export const foo = function foo(...arg): number { return arg.reduce((pre, next) => { return (pre + next) }) } // 默认导出,一个文件只能有一个默认导出 export default class Animal { private name: string; private color: string; constructor(name: string, color: string) { this.name = name; this.color = color; } cay():string{ return `${this.color}的${this.name}在叫`; } }
-
3、别的文件引入这个文件
import Animal,{numberRegexp, StringValidator, Person, foo} from '文件路径'; console.log(numberRegexp.test('123')); console.log(foo(1,2,3,4)); let person = new Person('李四',20); console.log(person.say()); let dog = new Animal('大黄狗','黄色'); console.log(dog.cay());
-
4、导入的时候定义别名,避免名字一样的冲突
import Animal,{numberRegexp as numReg, StringValidator, Person, foo} from '文件路径';
六、使用命名空间namespace
,
传统的
javascript
开发中一般定义一个对象,或者即使函数,typescript
解决了这个问题,在命名空间里面的东西,需要对外暴漏的就使用export
,不需要的就不暴漏出去
-
1、定义的格式
// 在命名空间里面定义一系列的验证器 namespace Validation { //定义一个数字的验证器 export const numberRegexp = /^[0-9]+$/; //定义一个字母的验证器 export const lettersRegexp = /^[A-Za-z]+$/; }
-
2、使用
// 使用 console.log(Validation.numberRegexp.test('123')); console.log(Validation.lettersRegexp.test('123'));
-
3、命名空间分文件的使用
-
1、定义一个接口的命名空间
***Validation.ts文件*** namespace Validation { export interface StringValidator { isAcceptable(s: string): boolean; } }
-
2、定义一个实现上面这个命名空间的接口文件
***LettersOnlyValidator.ts文件*** //下面三个正斜杠表示引入别的文件 /// <reference path="Validation.ts" /> namespace Validation { const lettersRegexp = /^[A-Za-z]+$/; export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } } let letter = new Validation.LettersOnlyValidator(); console.log(letter.isAcceptable('asdA'));
-
-
4、模块与命名空间结合起来
-
1、定义一个带命名空间的模块
***Validation.ts文件*** export namespace Validation1{ export const numberRegexp = /^[0-9]+$/; }
-
2、使用
import * as test from './Validation'; console.log(test.Validation1.numberRegexp.test('123'));
-