• typescripts学习


    可选与默认参数


    可选参数:在参数名后面,冒号前面添加一个问号,则表明该参数是可选的。如下代码:

    1. function buildName(firstName: string, lastName?: string) { //lastName为可选参数
    2. if (lastName)
    3. return firstName + " " + lastName;
    4. else
    5. return firstName;
    6. }
    7. var result1 = buildName("Bob"); //正确调用 Bob
    8. var result2 = buildName("Bob", "Adams"); //正确调用 Bob Adams

    默认参数:在参数名后直接给定一个值,如果这个值没有被传入,那么将会被赋值为默认值。如下代码:

    1. function buildName(firstName: string, lastName = "Smith") {
    2. return firstName + " " + lastName;
    3. }
    4.  
    5. var result1 = buildName("Bob"); //没有传入第二个参数,则被赋值为默认的smith,结果为:Bob Smith
    6. var result2 = buildName("Bob", "Adams"); //结果为:Bob Adams

    注:可选参数和默认参数必须在参数列表的最后。

    继承


      TypeScript中用关键字extends指明继承关系。例如,已经定义了类A,如果让类B继承A,我们把A叫做基类,B叫子类。可以用下面的方式定义类B。

    1. class B extends A {
    2. // 类B中的成员
    3. }

      如果我们要在子类中调用基类中的属性与方法就要使用super关键字。如下代码:

    1. class Animal { //定义基类
    2. name:string;
    3. constructor(theName: string) { this.name = theName; }
    4. move(meters: number) {
    5. document.write(this.name + " moved " + meters + "m.");
    6. }
    7. }
    8.  
    9. class Snake extends Animal { //继承基类
    10. constructor(name: string) {
    11. super(name); //调用基本类的构造函数
    12. }
    13. move() { //重写了基类的方法
    14. document.write("Slithering...<br>");
    15. super.move(5); //调用基类的方法
    16. }
    17. }
    18. var sam = new Snake("Python"); //声明Snake类
    19. sam.move();

    接口声明


      在TypeScript中,接口是用作约束作用的,在编译成JavaScript的时候,所有的接口都会被擦除掉,因为 JavaScript中并没有接口这一概念。TypeScript中接口是用关键字interface进行声明,例如:

    1. interface LabelledValue { //定义接口
    2. label: string; //定义属性
    3. }
    1. interface LabelledValue { //定义接口
    2. label: string;
    3. }
    4. function printLabel(labelledObj: LabelledValue) { //定义函数printLabel,其参数类型为接口类型
    5. document.write(labelledObj.label);
    6. }
    7. var myObj = {size: 10, label: "Size 10 Object"}; //定义含有接口中属性的对象
    8. printLabel(myObj); //调用函数

    可选属性


      有时不是所有定义在interface中的属性都是必须的,typescript中便为我们提供了可选属性。带有可选属性的interface定义和c#语言很相似,以?紧跟变量名后边表示。如下代码:

    1. interface SquareConfig { //定义了两个可选属性
    2. color?: string;
    3. width?: number;
    4. }
    5. function createSquare(config: SquareConfig): {color: string; area: number} {//定义函数
    6. var newSquare = {color: "white", area: 100};
    7. if (config.color) {
    8. newSquare.color = config.color;
    9. }
    10. if (config.width) {
    11. newSquare.area = config.width * config.width;
    12. }
    13. return newSquare;
    14. }
    15.  
    16. var mySquare = createSquare({color: "black"}); //调用函数,
    17. document.write(mySquare.color); //结果为: black

      大家可能会问既然是可选属性,可有可无的,那么为什么还要定义呢?对比起完全不定义,定义可选属性主要是:如果存在属性,能约束类型,而这也是十分关键的。

    方法类型


      在 JavaScript 中,方法 function 是一种基本类型。在面向对象思想中,接口的实现是靠类来完成的,而 function 作为一种类型,是不是能够实现接口呢?答案是肯定的。在 TypeScript 中,我们可以使用接口来约束方法的签名。

    1. interface SearchFunc {
    2. (source: string, subString: string): boolean; //定义一个匿名方法
    3. }
    4.  
    5. var mySearch: SearchFunc;
    6. mySearch = function(source: string, subString: string) { //实现接口
    7. var result = source.search(subString); //调用系统方法search查找字符串的位置
    8. if (result == -1) {
    9. return false;
    10. }
    11. else {
    12. return true;
    13. }
    14. }

      上面代码中,我们定义了一个接口,接口内约束了一个方法的签名,这个方法有两个字符串参数,返回布尔值。在第二段代码中我们声明了这个接口的实现。编译器仅仅检查类型是否正确(参数类型、返回值类型),因此参数的名字我们可以换成别的。

    数组类型


      在前面一节中我们学习了接口定义方法类型,这一节我们来学习接口定义数组类型。在数组类型中有一个“index”类型其描述数组下标的类型,以及返回值类型描述每项的类型。如下:

    1. interface StringArray { //定义数组接口
    2. [index: number]: string; //每个数组元素的类型
    3. }
    4.  
    5. var myArray: StringArray;
    6. myArray = ["Bob", "Fred"];

      在接口的定义里面,索引器的名字一般为 index(当然也可以改成别的,但一般情况下都是保持名字为 index)。索引器的类型只能为 number 或者 string。

    1. interface Array{
    2. [myindex: number]: number;
    3. }
    4.  
    5. interface Dictionary{
    6. [index: string]: any;
    7. }

    Class类型


      在C#和java中interface是很常使用的类型系统,其用来强制其实现类符合其契约。在TypeScript中同样也可以实现,通过类实现接口要用implements关键字。如下代码:

    1. interface IPrint{
    2. print();
    3. }
    4.  
    5. class A implements IPrint { //实现接口
    6. print(){ //实现接口中的方法
    7. document.write("实现接口");
    8. }
    9. }
    10.  
    11. var B=new A();
    12. B.print();

    接口继承


      和类一样,接口也能继承其他的接口。这相当于复制接口的所有成员。接口也是用关键字“extends”来继承。

    1. interface Shape { //定义接口Shape
    2. color: string;
    3. }
    4.  
    5. interface Square extends Shape { //继承接口Shape
    6. sideLength: number;
    7. }

    一个interface可以同时继承多个interface,实现多个接口成员的合并。用逗号隔开要继承的接口。

    1. interface Shape {
    2. color: string;
    3. }
    4.  
    5. interface PenStroke {
    6. penWidth: number;
    7. }
    8.  
    9. interface Square extends Shape, PenStroke {
    10. sideLength: number;
    11. }

    模块的声明


      前端数据验证在改善用户体验上有很大作用,在学了前面的知识,我们很可能会写出以下代码:

    1. interface StringValidator { //定义验证接口
    2. isAcceptable(s: string): boolean;
    3. }
    4.  
    5. var lettersRegexp = /^[A-Za-z]+$/;
    6. var numberRegexp = /^[0-9]+$/;
    7.  
    8. class LettersOnlyValidator implements StringValidator { //实现接口
    9. isAcceptable(s: string) {
    10. return lettersRegexp.test(s);
    11. }
    12. }
    13.  
    14. class ZipCodeValidator implements StringValidator { //实现接口
    15. isAcceptable(s: string) {
    16. return s.length === 5 && numberRegexp.test(s);
    17. }
    18. }
    19.  
    20. var strings = ['Hello', '98052', '101'];
    21. var validators: { [s: string]: StringValidator; } = {};
    22. validators['ZIP code'] = new ZipCodeValidator(); //实例化类
    23. validators['Letters only'] = new LettersOnlyValidator(); //实例化类
    24. for(var i=0;i<strings.length;i++){
    25. for (var name in validators) {
    26. document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); //调用类的方法
    27. }
    28. }

      那么这段代码最大的问题是什么呢?一个是没法复用,验证的封装和验证过程在同一个文件,验证的封装已经是可以复用的。另一个是接口和两个实现的类都直接挂接在全局变量上,假如数量一多的话,将会影响整个全局变量。

      而TypeScritp中模块的出现给我们解决了这一问题。使用 module 关键字来定义模块,并在末尾加花括号即可用; 用export 关键字使接口、类等成员对模块外可见。

    1. module Validation { //定义模块
    2. export interface StringValidator { //声明接口对外部可以使用
    3. isAcceptable(s: string): boolean;
    4. }
    5.  
    6. var lettersRegexp = /^[A-Za-z]+$/;
    7. var numberRegexp = /^[0-9]+$/;
    8.  
    9. export class LettersOnlyValidator implements StringValidator { //声明类对外部可用
    10. isAcceptable(s: string) {
    11. return lettersRegexp.test(s);
    12. }
    13. }
    14.  
    15. export class ZipCodeValidator implements StringValidator {
    16. isAcceptable(s: string) {
    17. return s.length === 5 && numberRegexp.test(s);
    18. }
    19. }
    20. }

    模块内容的调用


      在前面一节中我学习了模块的声明,而在模块声明完成以后,我们就可以调用这个模块了,调用模块中的接口、类、方法等。调用方法简单,就是用模块名后面跟一个点来调用类、接口、方法等。如下代码:

    1. module Validation { //定义模块
    2. export interface StringValidator { //声明接口对外部可以使用
    3. isAcceptable(s: string): boolean;
    4. }
    5.  
    6. var lettersRegexp = /^[A-Za-z]+$/;
    7. var numberRegexp = /^[0-9]+$/;
    8.  
    9. export class LettersOnlyValidator implements StringValidator { //声明类对外部可用
    10. isAcceptable(s: string) {
    11. return lettersRegexp.test(s);
    12. }
    13. }
    14.  
    15. export class ZipCodeValidator implements StringValidator {
    16. isAcceptable(s: string) {
    17. return s.length === 5 && numberRegexp.test(s);
    18. }
    19. }
    20. }
    21.  
    22. var strings = ['Hello', '98052', '101'];
    23. var validators: { [s: string]: Validation.StringValidator; } = {};
    24. validators['ZIP code'] = new Validation.ZipCodeValidator(); //使用模块中的类
    25. validators['Letters only'] = new Validation.LettersOnlyValidator();
    26. // 显示匹配结果
    27. for(var i=0;i<strings.length;i++){
    28. for (var name in validators) {
    29. document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); // 使用方法
    30. }
    31. }

    分隔模块到多个文件


      随着我们项目的扩展,我们的代码总不可能只写在一个文件里。为了更好地维护项目,我们会将特定功能放到一个文件里,然后加载多个文件实现我们想需要的功能。现在我们先将上面的代码分割到多个文件里。

    Validation.ts

    1. module Validation {
    2. export interface StringValidator {
    3. isAcceptable(s: string): boolean;
    4. }
    5. }

    LettersOnlyValidator.ts

    1. /// <reference path="Validation.ts" />
    2. module Validation {
    3. var lettersRegexp = /^[A-Za-z]+$/;
    4. export class LettersOnlyValidator implements StringValidator {
    5. isAcceptable(s: string) {
    6. return lettersRegexp.test(s);
    7. }
    8. }
    9. }

    ZipCodeValidator.ts

    1. /// <reference path="Validation.ts" />
    2. module Validation {
    3. var numberRegexp = /^[0-9]+$/;
    4. export class ZipCodeValidator implements StringValidator {
    5. isAcceptable(s: string) {
    6. return s.length === 5 && numberRegexp.test(s);
    7. }
    8. }
    9. }

    Test.ts

    1. /// <reference path="Validation.ts" />
    2. /// <reference path="LettersOnlyValidator.ts" />
    3. /// <reference path="ZipCodeValidator.ts" />
    4.  
    5. var strings = ['Hello', '98052', '101'];
    6. var validators: { [s: string]: Validation.StringValidator; } = {};
    7. validators['ZIP code'] = new Validation.ZipCodeValidator();
    8. validators['Letters only'] = new Validation.LettersOnlyValidator();
    9. for(var i=0;i<strings.length;i++){
    10. for (var name in validators) {
    11. document.write('"' + strings[i] + '" ' + (validators[name].isAcceptable(strings[i]) ? ' matches ' : ' does not match ') + name+"<br>"); //调用类的方法
    12. }
    13. }

      在项目中新建好以上四个文件,然后我们编译项目,如果我们代码编写没错的话,是能够编译通过的。另外,我们可以见到后面三个文件开头有类似于 C# 的文档注释,这是告诉 TypeScript 编译器该文件依赖于哪些文件,假如依赖的文件不存在的话,编译就会不通过。当然我们不写也是可以的,只不过编译器在编译时不会帮我们检查,一般来说,还是建议写上。 另外,在引用编译生成的 JavaScript 文件时,我们需要注意好顺序。以上面的代码为例,我们在 Html 代码中已经这么引用。

    1. <script src="Validation.js" type="text/javascript"/>
    2. <script src="LettersOnlyValidator.js" type="text/javascript"/>
    3. <script src="ZipCodeValidator.js" type="text/javascript"/>
    4. <script src="Test.js" type="text/javascript"/>
  • 相关阅读:
    【Leetcode】155: 最小栈(Python)
    【深入理解计算机系统】 八:AVR汇编语言
    【深入理解计算机系统】 七:AVR指令集架构
    【深入理解计算机系统】 六:AVR架构和运行环境
    nginx+lua 记一次特殊字符导致"丢包"问题
    python2.7 升级到 python3.6
    神奇的 SQL 之擦肩而过 → 真的用到索引了吗
    神奇的 SQL 之 HAVING → 容易被轻视的主角
    Delphi
    Windows authentication in linux docker container(转发)
  • 原文地址:https://www.cnblogs.com/mttcug/p/8120259.html
Copyright © 2020-2023  润新知