TypeScript入门(三)

785 阅读3分钟

一、类

TypeScript 是面向对象的 JavaScript,类描述了所创建的对象共同的属性和方法,TypeScript 支持面向对象的所有特性,比如 类、接口等。

定义类的关键字为 class,后面紧跟类名。类可以包含以下几个模块:

  • 字段:字段是类里面声明的变量。字段表示对象的有关数据。
  • 构造函数:类实例化时调用,可以为类的对象分配内存。
  • 方法:方法为对象要执行的操作。

使用方法:

class Greeter {
  static cname: string = "Greeter";// 静态属性
  greeting: string; // 成员属性
  constructor(message: string) {// 构造函数 - 执行初始化操作
    this.greeting = message;
  }

  static getClassName() {// 静态方法
    return "Class name is Greeter";
  } 
  greet() {// 成员方法
    return "Hello, " + this.greeting;
  }
}

// 编译生成的 ES5
"use strict";
var Greeter = /** @class */ (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.getClassName = function () {
        return "Class name is Greeter";
    };
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    Greeter.cname = "Greeter";
    return Greeter;
}());

类的继承

创建类时继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。

TypeScript 一次只能继承一个类,不支持继承多个类,但 TypeScript 支持多重继承(A 继承 B,B 继承 C)。

class Root { 
   str:string; 
} 
class Child extends Root {} 
class Leaf extends Child {} // 多重继承,继承了 Child 和 Root 类
 
var obj = new Leaf(); 
obj.str ="hello" 

继承类的方法重写

类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。

class PrinterClass { 
   doPrint():void {
      console.log("父类的 doPrint() 方法。") 
   } 
} 
 
class StringPrinter extends PrinterClass { 
   doPrint():void { 
      super.doPrint() // 调用父类的函数
      console.log("子类的 doPrint()方法。")
   } 
}

类和接口

类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用。

interface ILoan { 
   interest:number 
} 
 
class AgriLoan implements ILoan { 
   interest:number 
   rebate:number 
   constructor(interest:number,rebate:number) { 
      this.interest = interest 
      this.rebate = rebate 
   } 
} 
 
var obj = new AgriLoan(10,1)

二、对象

对象是包含一组键值对的实例。 值可以是标量、函数、数组、对象等。

var sites = {
    site1: "Runoob",
    site2: "Google",
    sayHello: function () { } // 类型模板,Typescript 中的对象必须是特定类型的实例,JavaScript 不需要
};
sites.sayHello = function () {
    console.log("hello " + sites.site1);
};
sites.sayHello();

三、命名空间

命名空间定义了标识符的可见范围,一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。

命名空间使用 namespace 来定义。如果我们需要在外部可以调用命名空间中的类和接口,则需要在类和接口添加 export 关键字。如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠///引用它。

使用方法

// IShape.ts
namespace Drawing { 
    export interface IShape { 
        draw(); 
    }
}

// Circle.ts 
/// <reference path = "IShape.ts" /> 
namespace Drawing { 
    export class Circle implements IShape { 
        public draw() { 
            console.log("Circle is drawn"); 
        }  
    }
}

// TestShape.ts
/// <reference path = "IShape.ts" />   
/// <reference path = "Circle.ts" />  
function drawAllShapes(shape:Drawing.IShape) { 
    shape.draw(); 
} 
drawAllShapes(new Drawing.Circle());

嵌套命名空间

命名空间支持嵌套,即你可以将命名空间定义在另外一个命名空间里头。成员的访问使用点号.来实现。

namespace Runoob { 
   export namespace invoiceApp { 
      export class Invoice { 
         public calculateDiscount(price: number) { 
            return price * .40; 
         } 
      } 
   } 
}

/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice(); 
console.log(invoice.calculateDiscount(500));

四、模块

模块是在其自身的作用域里执行,并不是在全局作用域,两个模块之间的关系是通过在文件级别上使用 importexport 建立的。

模块使用模块加载器去导入其它的模块。在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。 熟知的JavaScript模块加载器是服务于 Node.js 的 CommonJS 和服务于 Web 应用的 Require.js

使用方法

// IShape.ts
export interface IShape { 
   draw(); 
}

// Circle.ts 
import shape = require("./IShape"); 
export class Circle implements shape.IShape { 
   public draw() { 
      console.log("Cirlce is drawn (external module)"); 
   } 
}

// TestShape.ts
import shape = require("./IShape"); 
import circle = require("./Circle");  
function drawAllShapes(shapeToDraw: shape.IShape) {
   shapeToDraw.draw(); 
} 
drawAllShapes(new circle.Circle());