- TypeScript 基础
- TypeScript - 首页
- TypeScript - 路线图
- TypeScript - 概述
- TypeScript - 环境搭建
- TypeScript - 基本语法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 变量
- TypeScript - let & const
- TypeScript - 运算符
- TypeScript 基本类型
- TypeScript - 类型
- TypeScript - 类型注解
- TypeScript - 类型推断
- TypeScript - 数字
- TypeScript - 字符串
- TypeScript - 布尔值
- TypeScript - 数组
- TypeScript - 元组
- TypeScript - 枚举
- TypeScript - any
- TypeScript - never
- TypeScript - 联合类型
- TypeScript - 字面量类型
- TypeScript - Symbols
- TypeScript - null vs. undefined
- TypeScript - 类型别名
- TypeScript 控制流
- TypeScript - 决策
- TypeScript - if 语句
- TypeScript - if else 语句
- TypeScript - 嵌套 if 语句
- TypeScript - switch 语句
- TypeScript - 循环
- TypeScript - for 循环
- TypeScript - while 循环
- TypeScript - do while 循环
- TypeScript 函数
- TypeScript - 函数
- TypeScript - 函数类型
- TypeScript - 可选参数
- TypeScript - 默认参数
- TypeScript - 匿名函数
- TypeScript - 函数构造器
- TypeScript - rest 参数
- TypeScript - 参数解构
- TypeScript - 箭头函数
- TypeScript 接口
- TypeScript - 接口
- TypeScript - 接口扩展
- TypeScript 类和对象
- TypeScript - 类
- TypeScript - 对象
- TypeScript - 访问修饰符
- TypeScript - 只读属性
- TypeScript - 继承
- TypeScript - 静态方法和属性
- TypeScript - 抽象类
- TypeScript - 访问器
- TypeScript - 鸭子类型
- TypeScript 高级类型
- TypeScript - 交叉类型
- TypeScript - 类型保护
- TypeScript - 类型断言
- TypeScript 类型操作
- TypeScript - 从类型创建类型
- TypeScript - keyof 类型运算符
- TypeScript - typeof 类型运算符
- TypeScript - 索引访问类型
- TypeScript - 条件类型
- TypeScript - 映射类型
- TypeScript - 模板字面量类型
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型约束
- TypeScript - 泛型接口
- TypeScript - 泛型类
- TypeScript 其他
- TypeScript - 三斜杠指令
- TypeScript - 命名空间
- TypeScript - 模块
- TypeScript - 环境声明
- TypeScript - 装饰器
- TypeScript - 类型兼容性
- TypeScript - Date 对象
- TypeScript - 迭代器和生成器
- TypeScript - Mixins
- TypeScript - 实用类型
- TypeScript - 装箱和拆箱
- TypeScript - tsconfig.json
- 从 JavaScript 到 TypeScript
- TypeScript 有用资源
- TypeScript 快速指南
- TypeScript - 有用资源
- TypeScript - 讨论
TypeScript 快速指南
TypeScript - 概述
JavaScript 最初被设计为客户端语言。Node.js 的发展也标志着 JavaScript 成为一种新兴的服务器端技术。然而,随着 JavaScript 代码的增长,它往往会变得越来越混乱,难以维护和重用代码。此外,它未能采用面向对象特性、强类型检查和编译时错误检查,这使得 JavaScript 无法在企业级成为成熟的服务器端技术。TypeScript 正是为了弥补这一差距而出现的。
什么是 TypeScript?
根据定义,“TypeScript 是用于应用程序规模开发的 JavaScript”。
TypeScript 是一种强类型的、面向对象的、编译型语言。它由微软的Anders Hejlsberg(C# 的设计者)设计。TypeScript 既是一种语言,也是一组工具。TypeScript 是 JavaScript 的类型化超集,编译成 JavaScript。换句话说,TypeScript 是 JavaScript 加上一些附加特性。
TypeScript 的特性
TypeScript 本质上是 JavaScript。TypeScript 从 JavaScript 开始,最终也得到 JavaScript。TypeScript 从 JavaScript 采用程序的基本构建块。因此,你只需要了解 JavaScript 就可以使用 TypeScript。所有 TypeScript 代码都会转换为等效的 JavaScript 代码以供执行。
TypeScript 支持其他 JS 库。编译后的 TypeScript 可以从任何 JavaScript 代码中使用。TypeScript 生成的 JavaScript 可以重用所有现有的 JavaScript 框架、工具和库。
JavaScript 就是 TypeScript。这意味着任何有效的.js文件都可以重命名为.ts文件,并与其他 TypeScript 文件一起编译。
TypeScript 是可移植的。TypeScript 可跨浏览器、设备和操作系统移植。它可以在任何 JavaScript 可以运行的环境中运行。与其他语言不同,TypeScript 不需要专用的虚拟机或特定的运行时环境来执行。
TypeScript 和 ECMAScript
ECMAScript 规范是脚本语言的标准化规范。已经发布了六个版本的 ECMA-262。标准的第 6 版代号为“Harmony”。TypeScript 与 ECMAScript 6 规范保持一致。
TypeScript 从 ECMAScript 5 规范(即 JavaScript 的官方规范)中采用了其基本语言特性。TypeScript 的语言特性,如模块和基于类的面向对象,与 EcmaScript 6 规范一致。此外,TypeScript 还包含泛型和类型注解等特性,这些特性并非 EcmaScript 6 规范的一部分。
为什么要使用 TypeScript?
TypeScript 比其他类似语言,如 CoffeeScript 和 Dart 编程语言更胜一筹,因为它扩展了 JavaScript。相比之下,Dart 和 CoffeeScript 等语言本身就是新的语言,需要特定于语言的执行环境。
TypeScript 的好处包括:
编译 - JavaScript 是一种解释型语言。因此,需要运行它才能测试其有效性。这意味着你编写所有代码只是为了发现没有输出,如果存在错误的话。因此,你必须花费数小时的时间来查找代码中的错误。TypeScript 编译器提供错误检查功能。如果 TypeScript 发现任何语法错误,它将编译代码并生成编译错误。这有助于在脚本运行之前突出显示错误。
强静态类型 - JavaScript 不是强类型语言。TypeScript 通过 TLS(TypeScript 语言服务)提供可选的静态类型和类型推断系统。未声明类型的变量的类型可能由 TLS 根据其值推断。
TypeScript支持现有 JavaScript 库的类型定义。TypeScript 定义文件(扩展名为.d.ts)为外部 JavaScript 库提供定义。因此,TypeScript 代码可以包含这些库。
TypeScript支持面向对象编程概念,如类、接口、继承等。
TypeScript 的组成部分
TypeScript 的核心包含以下三个组成部分:
语言 - 包括语法、关键字和类型注解。
TypeScript 编译器 - TypeScript 编译器 (tsc) 将 TypeScript 编写的指令转换为等效的 JavaScript 代码。
TypeScript 语言服务 - “语言服务”在核心编译器管道周围提供了一个额外的层,这些层是类似编辑器的应用程序。语言服务支持典型编辑器操作的常用集合,例如语句完成、签名帮助、代码格式化和概述、着色等。
声明文件
当 TypeScript 脚本被编译时,可以选择生成一个声明文件(扩展名为.d.ts),该文件充当编译后的 JavaScript 中组件的接口。声明文件的概念类似于 C/C++ 中的头文件。声明文件(扩展名为.d.ts的文件)为 jQuery、MooTools 等 JavaScript 库提供类型、函数调用和变量的智能感知。
TypeScript - 环境搭建
我们已经在线设置了 TypeScript 编程环境,以便你可以在进行理论学习的同时在线执行所有可用的示例。这让你对正在阅读的内容充满信心,并可以使用不同的选项来检查结果。随意修改任何示例并在线执行它。
var message:string = "Hello World" console.log(message)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var message = "Hello World"; console.log(message);
在本章中,我们将讨论如何在 Windows 平台上安装 TypeScript。我们还将解释如何安装 Brackets IDE。
你可以使用 www.typescriptlang.org/Playground 上的 TypeScript 在线测试你的脚本。在线编辑器显示编译器生成的相应 JavaScript 代码。
你可以使用Playground尝试以下示例。
var num:number = 12 console.log(num)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var num = 12; console.log(num);
上面程序的输出如下:
12
本地环境搭建
TypeScript 是一种开源技术。它可以在任何浏览器、任何主机和任何操作系统上运行。你需要以下工具来编写和测试 TypeScript 程序:
文本编辑器
文本编辑器帮助你编写源代码。一些编辑器的例子包括 Windows 记事本、Notepad++、Emacs、vim 或 vi 等。使用的编辑器可能因操作系统而异。
源文件通常使用扩展名.ts命名。
TypeScript 编译器
TypeScript 编译器本身就是一个.ts文件,编译成 JavaScript (.js) 文件。TSC(TypeScript 编译器)是一个源到源编译器(转译器)。
TSC 生成传递给它的.ts文件的 JavaScript 版本。换句话说,TSC 从作为输入给它的 TypeScript 文件生成等效的 JavaScript 源代码。这个过程称为转译。
但是,编译器会拒绝任何传递给它的原始 JavaScript 文件。编译器只处理.ts或.d.ts文件。
安装 Node.js
Node.js 是一个开源的、跨平台的服务器端 JavaScript 运行时环境。Node.js 可以在没有浏览器支持的情况下运行 JavaScript。它使用 Google V8 JavaScript 引擎来执行代码。你可以下载 Node.js 源代码或适用于你平台的预构建安装程序。Node 可在此处获取:https://node.org.cn/en/download
在 Windows 上安装
按照以下步骤在 Windows 环境中安装 Node.js。
步骤 1 - 下载并运行 Node 的 .msi 安装程序。
步骤 2 - 要验证安装是否成功,请在终端窗口中输入命令node –v。
步骤 3 - 在终端窗口中输入以下命令以安装 TypeScript。
npm install -g typescript
在 Mac OS X 上安装
要在 Mac OS X 上安装 node.js,你可以下载一个预编译的二进制包,这使得安装非常容易。访问https://node.org.cn/ 并单击安装按钮下载最新包。
按照安装向导安装.dmg中的包,这将同时安装 node 和npm。npm 是 Node 包管理器,它有助于安装 node.js 的附加包。
在 Linux 上安装
在安装 Node.js 和 NPM 之前,您需要安装一些依赖项。
Ruby 和 GCC。您需要 Ruby 1.8.6 或更高版本以及 GCC 4.2 或更高版本。
Homebrew。Homebrew 是最初为 Mac 设计的包管理器,但它已被移植到 Linux 上作为 Linuxbrew。您可以在 https://brew.sh.cn/ 了解更多关于 Homebrew 的信息,以及在 https://brew.sh.cn/linuxbrew 了解更多关于 Linuxbrew 的信息。
安装这些依赖项后,您可以使用终端上的以下命令安装 Node.js:
brew install node.
IDE 支持
TypeScript 可以在许多开发环境中构建,例如 Visual Studio、Sublime Text 2、WebStorm/PHPStorm、Eclipse、Brackets 等。这里将讨论 Visual Studio Code 和 Brackets IDE。此处使用的开发环境是 Visual Studio Code(Windows 平台)。
Visual Studio Code
这是一个来自 Visual Studio 的开源 IDE。它适用于 Mac OS X、Linux 和 Windows 平台。VScode 可在以下网址获取:https://vscode.js.cn/
在 Windows 上安装
步骤 1 − 下载适用于 Windows 的 Visual Studio Code。
步骤 2 − 双击 VSCodeSetup.exe 以启动安装过程。这只需要一分钟。
步骤 3 − 下面是 IDE 的屏幕截图。
步骤 4 − 您可以通过右键单击文件 → 在命令提示符中打开 来直接转到文件的路径。类似地,“在资源管理器中显示”选项会在文件资源管理器中显示文件。
在 Mac OS X 上安装
Visual Studio Code 的 Mac OS X 特定安装指南可在以下网址找到:
https://vscode.js.cn/Docs/editor/setup
在 Linux 上安装
Visual Studio Code 的 Linux 特定安装指南可在以下网址找到:
https://vscode.js.cn/Docs/editor/setup
Brackets
Brackets 是一个免费的开源 Web 开发编辑器,由 Adobe Systems 创建。它适用于 Linux、Windows 和 Mac OS X。Brackets 可在 http://brackets.io/ 获取。
Brackets 的 TypeScript 扩展
Brackets 支持通过扩展管理器添加额外功能的扩展。以下步骤说明了如何使用扩展管理器安装 TypeScript 扩展。
安装后,单击编辑器右侧的扩展管理器图标 。在搜索框中输入 typescript。
安装 Brackets TSLint 和 Brackets TypeScript 插件。
您可以通过添加另一个扩展 Brackets Shell,在 Brackets 本身中运行 DOS 提示符/shell。
安装后,您会在编辑器右侧找到 shell 图标 。单击该图标后,您将看到如下所示的 shell 窗口:
注意 − TypeScript 也可作为 Visual Studio 2012 和 2013 环境的插件使用 (https://typescript.net.cn/#Download).VS 2015 及更高版本默认包含 TypeScript 插件。
现在,一切就绪!!!
TypeScript - 基本语法
语法定义了一套编写程序的规则。每种语言规范都定义了自己的语法。TypeScript 程序由以下部分组成:
- 模块
- 函数
- 变量
- 语句和表达式
- 注释
您的第一个 TypeScript 代码
让我们从传统的“Hello World”示例开始:
var message:string = "Hello World" console.log(message)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var message = "Hello World"; console.log(message);
第 1 行声明一个名为 message 的变量。变量是程序中存储值的机制。
第 2 行将变量的值打印到提示符。这里,console 指的是终端窗口。log() 函数用于在屏幕上显示文本。
编译和执行 TypeScript 程序
让我们看看如何使用 Visual Studio Code 编译和执行 TypeScript 程序。请按照以下步骤操作:
步骤 1 − 使用 .ts 扩展名保存文件。我们将文件保存为 Test.ts。如果代码中存在任何错误,代码编辑器会在您保存时标记这些错误。
步骤 2 − 右键单击 VS Code 的“资源管理器”窗格中“工作文件”选项下的 TypeScript 文件。选择“在命令提示符中打开”选项。
步骤 3 − 要编译文件,请在终端窗口中使用以下命令。
tsc Test.ts
步骤 4 − 文件编译为 Test.js。要运行编写的程序,请在终端中输入以下内容。
node Test.js
编译器标志
编译器标志使您能够在编译期间更改编译器的行为。每个编译器标志都公开一个设置,允许您更改编译器的行为方式。
下表列出了一些与 TSC 编译器相关的常用标志。典型的命令行用法使用部分或全部开关。
序号 | 编译器标志和说明 |
---|---|
1. | --help 显示帮助手册 |
2. | --module 加载外部模块 |
3. | --target 设置目标 ECMA 版本 |
4. | --declaration 生成额外的 .d.ts 文件 |
5. | --removeComments 从输出文件中删除所有注释 |
6. | --out 将多个文件编译到单个输出文件中 |
7. | --sourcemap 生成源映射 (.map) 文件 |
8. | --module noImplicitAny 禁止编译器推断 any 类型 |
9. | --watch 监视文件更改并动态重新编译它们 |
注意 − 可以一次编译多个文件。
tsc file1.ts, file2.ts, file3.ts
TypeScript 中的标识符
标识符是赋予程序中元素(如变量、函数等)的名称。标识符的规则如下:
标识符可以包含字符和数字。但是,标识符不能以数字开头。
标识符不能包含特殊符号,下划线 (_) 或美元符号 ($) 除外。
标识符不能是关键字。
它们必须是唯一的。
标识符区分大小写。
标识符不能包含空格。
下表列出了一些有效和无效标识符的示例:
有效标识符 | 无效标识符 |
---|---|
firstName | Var |
first_name | first name |
num1 | first-name |
$result | 1number |
TypeScript ─ 关键字
关键字在语言环境中具有特殊含义。下表列出了 TypeScript 中的一些关键字。
break | as | any | switch |
case | if | throw | else |
var | number | string | get |
module | type | instanceof | typeof |
public | private | enum | export |
finally | for | while | void |
null | super | this | new |
in | return | true | false |
any | extends | static | let |
package | implements | interface | function |
new | try | yield | const |
continue | do | catch |
空格和换行符
TypeScript 忽略程序中出现的空格、制表符和换行符。您可以在程序中自由使用空格、制表符和换行符,并且您可以自由地以整洁一致的方式格式化和缩进程序,使代码易于阅读和理解。
TypeScript 区分大小写
TypeScript 区分大小写。这意味着 TypeScript 区分大写和小写字符。
分号是可选的
每行指令称为语句。TypeScript 中的分号是可选的。
示例
console.log("hello world") console.log("We are learning TypeScript")
单行可以包含多个语句。但是,这些语句必须用分号隔开。
TypeScript 中的注释
注释是提高程序可读性的一种方法。注释可用于包含有关程序的其他信息,例如代码作者、关于函数/结构的提示等。编译器会忽略注释。
TypeScript 支持以下类型的注释:
单行注释 ( // ) − // 和行尾之间的任何文本都被视为注释
多行注释 (/* */) − 这些注释可以跨越多行。
示例
//this is single line comment /* This is a Multi-line comment */
TypeScript 和面向对象
TypeScript 是面向对象的 JavaScript。面向对象是一种软件开发范例,遵循现实世界的建模。面向对象将程序视为对象的集合,这些对象通过称为方法的机制相互通信。TypeScript 也支持这些面向对象的组件。
对象 − 对象是任何实体的实时表示。根据 Grady Brooch 的说法,每个对象都必须具有三个特征:
状态 − 由对象的属性描述
行为 − 描述对象的行为方式
标识 − 一个唯一值,用于区分对象与一组类似的对象。
类 − 就 OOP 而言,类是创建对象的蓝图。类封装了对象的数据。
方法 − 方法促进对象之间的通信。
示例:TypeScript 和面向对象
class Greeting { greet():void { console.log("Hello World!!!") } } var obj = new Greeting(); obj.greet();
上面的示例定义了一个类 Greeting。该类有一个方法 greet()。该方法在终端上打印字符串“Hello World”。new 关键字创建类的对象 (obj)。该对象调用方法 greet()。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Greeting = (function () { function Greeting() { } Greeting.prototype.greet = function () { console.log("Hello World!!!"); }; return Greeting; }()); var obj = new Greeting(); obj.greet()
上面程序的输出如下:
Hello World!!!
TypeScript - 类型
类型系统表示语言支持的不同类型的值。类型系统会在程序存储或操作值之前检查其有效性。这确保代码按预期运行。类型系统还可以提供更丰富的代码提示和自动文档。
TypeScript 提供数据类型作为其可选类型系统的一部分。数据类型分类如下:
Any 类型
any 数据类型是 TypeScript 中所有类型的超类型。它表示动态类型。使用any 类型等同于选择退出变量的类型检查。
内置类型
下表说明了 TypeScript 中所有内置类型:
数据类型 | 关键字 | 说明 |
---|---|---|
Number | number | 双精度 64 位浮点数。它可以用来表示整数和小数。 |
String | string | 表示 Unicode 字符序列 |
Boolean | boolean | 表示逻辑值,true 和 false |
Void | void | 用于函数返回类型以表示非返回函数 |
Null | null | 表示对象值的故意缺失。 |
Undefined | undefined | 表示赋予所有未初始化变量的值 |
注意 − TypeScript 和 JavaScript 中没有整数类型。
Null 和 undefined ─ 它们一样吗?
null 和 undefined 数据类型经常是混淆的来源。null 和 undefined 不能用于引用变量的数据类型。它们只能作为值分配给变量。
但是,null 和 undefined 是不同的。用 undefined 初始化的变量表示该变量没有值或对象分配给它,而 null 表示该变量已被设置为值为 undefined 的对象。
用户自定义类型
用户自定义类型包括枚举 (enums)、类、接口、数组和元组。这些将在后面的章节中详细讨论。
TypeScript - 变量
根据定义,变量是“内存中命名的空间”,用于存储值。换句话说,它充当程序中值的容器。TypeScript 变量必须遵循 JavaScript 命名规则:
变量名可以包含字母和数字。
它们不能包含空格和特殊字符,下划线 (_) 和美元符号 ($) 除外。
变量名不能以数字开头。
必须在使用变量之前声明它。使用var关键字声明变量。
TypeScript 中的变量声明
在 TypeScript 中声明变量的类型语法是在变量名后包含一个冒号 (:),后跟其类型。就像在 JavaScript 中一样,我们使用var关键字声明变量。
声明变量时,您有四个选项:
在一个语句中声明其类型和值。
声明其类型但不声明值。在这种情况下,变量将设置为 undefined。
声明其值但不声明类型。变量类型将设置为赋值的數據類型。
既不声明值也不声明类型。在这种情况下,变量的数据类型将为 any,并将初始化为 undefined。
下表说明了如上所述的变量声明的有效语法:
序号 | 变量声明语法和说明 |
---|---|
1. | var name:string = ”mary” 该变量存储字符串类型的值 |
2. | var name:string; 该变量是一个字符串变量。默认情况下,变量的值设置为 undefined |
3. | var name = ”mary” 变量的类型是从值的數據類型推断出来的。这里,变量的类型为字符串 |
4. | var name; 变量的数据类型为 any。默认情况下,其值设置为 undefined。 |
示例:TypeScript 中的变量
var name:string = "John"; var score1:number = 50; var score2:number = 42.50 var sum = score1 + score2 console.log("name"+name) console.log("first score: "+score1) console.log("second score: "+score2) console.log("sum of the scores: "+sum)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var name = "John"; var score1 = 50; var score2 = 42.50; var sum = score1 + score2; console.log("name" + name); console.log("first score: " + score1); console.log("second score : " + score2); console.log("sum of the scores: " + sum);
上面程序的输出如下:
name:John first score:50 second score:42.50 sum of the scores:92.50
如果我们尝试将值赋给与类型不相同的变量,TypeScript 编译器将生成错误。因此,TypeScript 遵循强类型。强类型语法确保赋值运算符 (=) 两侧指定的类型相同。这就是以下代码会导致编译错误的原因:
var num:number = "hello" // will result in a compilation error
TypeScript 中的类型断言
TypeScript 允许将变量从一种类型更改为另一种类型。TypeScript 将此过程称为类型断言。语法是在 < > 符号之间放置目标类型,并将其放在变量或表达式之前。以下示例解释了这个概念:
示例
var str = '1' var str2:number = <number> <any> str //str is now of type number console.log(typeof(str2))
如果将鼠标指针悬停在 Visual Studio Code 中的类型断言语句上,它将显示变量数据类型的变化。基本上,如果 S 是 T 的子类型或 T 是 S 的子类型,它允许从类型 S 到 T 的断言成功。
之所以不称其为“类型转换”,是因为转换通常意味着某种运行时支持,而“类型断言”纯粹是编译时构造,以及向编译器提供提示以说明您希望如何分析代码的一种方式。
编译后,它将生成以下 JavaScript 代码。
"use strict"; var str = '1'; var str2 = str; //str is now of type number console.log(typeof (str2));
它将产生以下输出:
string
TypeScript 中的类型推断
鉴于 TypeScript 是强类型的,此功能是可选的。TypeScript 也鼓励变量的动态类型。这意味着 TypeScript 鼓励在没有类型的情况下声明变量。在这种情况下,编译器将根据分配给它的值来确定变量的类型。TypeScript 将找到代码中变量的第一次使用,确定其最初设置的类型,然后在此代码块的其余部分中假设此变量的相同类型。
以下代码片段解释了相同的内容:
示例:类型推断
var num = 2; // data type inferred as number console.log("value of num "+num); num = "12"; console.log(num);
在上面的代码片段中:
代码声明一个变量并将其值设置为 2。请注意,变量声明没有指定数据类型。因此,程序使用类型推断来确定变量的数据类型,即它为变量设置的第一个值的类型。在这种情况下,num 设置为 number 类型。
当代码尝试将变量的值设置为字符串时。编译器会抛出错误,因为变量的类型已设置为 number。
它将产生以下输出:
error TS2011: Cannot convert 'string' to 'number'.
TypeScript 变量作用域
变量的作用域指定变量的定义位置。程序中变量的可用性由其作用域决定。TypeScript 变量可以具有以下作用域:
全局作用域- 全局变量在编程结构之外声明。可以从代码中的任何位置访问这些变量。
类作用域- 这些变量也称为字段。字段或类变量在类内但方法之外声明。可以使用类的对象访问这些变量。字段也可以是静态的。可以使用类名访问静态字段。
局部作用域- 局部变量顾名思义是在方法、循环等结构中声明的。局部变量只能在其声明的结构内访问。
以下示例说明了 TypeScript 中的变量作用域。
示例:变量作用域
var global_num = 12 //global variable class Numbers { num_val = 13; //class variable static sval = 10; //static field storeNum():void { var local_num = 14; //local variable } } console.log("Global num: "+global_num) console.log(Numbers.sval) //static variable var obj = new Numbers(); console.log("Global num: "+obj.num_val)
在转译时,将生成以下 JavaScript 代码:
var global_num = 12; //global variable var Numbers = (function () { function Numbers() { this.num_val = 13; //class variable } Numbers.prototype.storeNum = function () { var local_num = 14; //local variable }; Numbers.sval = 10; //static field return Numbers; }()); console.log("Global num: " + global_num); console.log(Numbers.sval); //static variable var obj = new Numbers(); console.log("Global num: " + obj.num_val);
它将产生以下输出:
Global num: 12 10 Global num: 13
如果尝试在方法外部访问局部变量,则会导致编译错误。
error TS2095: Could not find symbol 'local_num'.
TypeScript - 运算符
什么是运算符?
运算符定义将在数据上执行的某些函数。运算符作用于的数据称为操作数。考虑以下表达式:
7 + 5 = 12
这里,值 7、5 和 12 是操作数,而 + 和 = 是运算符。
TypeScript 中的主要运算符可以分类为:
- 算术运算符
- 逻辑运算符
- 关系运算符
- 位运算符
- 赋值运算符
- 三元/条件运算符
- 字符串运算符
- 类型运算符
算术运算符
假设变量 a 和 b 中的值分别为 10 和 5。
运算符 | 说明 | 示例 |
---|---|---|
+ (加法) | 返回操作数的和 | a + b 为 15 |
- (减法) | 返回值的差 | a - b 为 5 |
* (乘法) | 返回值的积 | a * b 为 50 |
/ (除法) | 执行除法运算并返回商 | a / b 为 2 |
% (模) | 执行除法运算并返回余数 | a % b 为 0 |
++ (增量) | 将变量的值增加一 | a++ 为 11 |
-- (减量) | 将变量的值减少一 | a-- 为 9 |
关系运算符
关系运算符测试或定义两个实体之间的关系类型。关系运算符返回布尔值,即 true/false。
假设 A 的值为 10,B 的值为 20。
运算符 | 说明 | 示例 |
---|---|---|
> | 大于 | (A > B) 为 False |
< | 小于 | (A < B) 为 True |
>= | 大于或等于 | (A >= B) 为 False |
<= | 小于或等于 | (A <= B) 为 True |
== | 相等 | (A == B) 为 false |
!= | 不相等 | (A != B) 为 True |
逻辑运算符
逻辑运算符用于组合两个或多个条件。逻辑运算符也返回布尔值。假设变量 A 的值为 10,B 的值为 20。
运算符 | 说明 | 示例 |
---|---|---|
&& (与) | 只有当所有指定的表达式都返回 true 时,运算符才返回 true | (A > 10 && B > 10) 为 False |
|| (或) | 如果至少一个指定的表达式返回 true,则运算符返回 true | (A > 10 || B > 10) 为 True |
! (非) | 运算符返回表达式的结果的反义。例如:! (>5) 返回 false | !(A > 10) 为 True |
位运算符
假设变量 A = 2,B = 3
运算符 | 说明 | 示例 |
---|---|---|
& (按位与) | 它对每个整数参数的每一位执行布尔与运算。 | (A & B) 为 2 |
| (按位或) | 它对每个整数参数的每一位执行布尔或运算。 | (A | B) 为 3 |
^ (按位异或) | 它对每个整数参数的每一位执行布尔异或运算。异或意味着操作数一为真或操作数二为真,但两者不能同时为真。 | (A ^ B) 为 1 |
~ (按位非) | 它是一个一元运算符,通过反转操作数中的所有位来操作。 | (~B) 为 -4 |
<< (左移) | 它将第一个操作数中的所有位向左移动第二个操作数中指定的位数。新位用零填充。将值左移一位相当于将其乘以 2,左移两位相当于将其乘以 4,依此类推。 | (A << 1) 为 4 |
> (右移) | 二进制右移运算符。左操作数的值向右移动右操作数指定的位数。 | (A >> 1) 为 1 |
>> (带零的右移) | 此运算符与 >> 运算符类似,只是左侧移入的位始终为零。 | (A >>> 1) 为 1 |
赋值运算符
运算符 | 说明 | 示例 |
---|---|---|
= (简单赋值) | 将值从右侧操作数赋值给左侧操作数 | C = A + B 将 A + B 的值赋给 C |
+= (加法赋值) | 它将右操作数添加到左操作数,并将结果赋给左操作数。 | C += A 等效于 C = C + A |
-= (减法赋值) | 它从左操作数中减去右操作数,并将结果赋给左操作数。 | C -= A 等效于 C = C - A |
*= (乘法赋值) | 它将右操作数乘以左操作数,并将结果赋给左操作数。 | C *= A 等效于 C = C * A |
/= (除法赋值) | 它将左操作数除以右操作数,并将结果赋给左操作数。 |
注意- 位运算符也适用相同的逻辑,因此它们将变为 <<=、>>=、>>>=、&=、|= 和 ^=。
其他运算符
否定运算符 (-)
更改值的符号。让我们举个例子。
var x:number = 4 var y = -x; console.log("value of x: ",x); //outputs 4 console.log("value of y: ",y); //outputs -4
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var x = 4; var y = -x; console.log("value of x: ", x); //outputs 4 console.log("value of y: ", y); //outputs -4
它将产生以下输出:
value of x: 4 value of y: -4
字符串运算符:连接运算符 (+)
当“+”运算符应用于字符串时,它会将第二个字符串附加到第一个字符串的后面。下面的例子可以帮助我们理解这个概念。
var msg:string = "hello"+"world" console.log(msg)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var msg = "hello" + "world"; console.log(msg);
它将产生以下输出:
helloworld
字符串连接操作不会在字符串之间添加空格。多个字符串可以在单个语句中连接。
条件运算符 (?)
此运算符用于表示条件表达式。条件运算符有时也称为三元运算符。语法如下所示:
Test ? expr1 : expr2
Test − 指的是条件表达式
expr1 − 如果条件为真则返回的值
expr2 − 如果条件为假则返回的值
让我们来看下面的代码:
var num:number = -2 var result = num > 0 ?"positive":"non-positive" console.log(result)
第 2 行检查变量num的值是否大于零。如果num设置为大于零的值,则返回字符串“positive”,否则返回字符串“non-positive”。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var num = -2; var result = num > 0 ? "positive" : "non-positive"; console.log(result);
上面的代码片段将产生以下输出:
non-positive
类型运算符
typeof 运算符
它是一个一元运算符。此运算符返回操作数的数据类型。请看下面的例子:
var num = 12 console.log(typeof num); //output: number
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var num = 12; console.log(typeof num); //output: number
它将产生以下输出:
number
instanceof
此运算符可以用来测试一个对象是否属于指定的类型。instanceof 运算符的用法在类这一章中讨论。
TypeScript - 决策
决策结构要求程序员指定一个或多个条件供程序评估或测试,以及在确定条件为真时要执行的语句,以及可选地在确定条件为假时要执行的其他语句。
下面显示的是大多数编程语言中典型的决策结构的一般形式:
决策结构在执行指令之前会评估条件。TypeScript 中的决策结构分类如下:
序号 | 语句和说明 |
---|---|
1. | if 语句
一个 'if' 语句由一个布尔表达式后跟一个或多个语句组成。 |
2. | if...else 语句
一个 'if' 语句后面可以跟一个可选的 'else' 语句,当布尔表达式为假时执行。 |
3. | else…if 和嵌套 if 语句
你可以在另一个 'if' 或 'else if' 语句中使用一个 'if' 或 'else if' 语句。 |
4. | switch 语句
一个 'switch' 语句允许一个变量针对一个值的列表进行测试。 |
TypeScript - 循环
你可能会遇到这种情况,需要多次执行一段代码。通常情况下,语句是顺序执行的:函数中的第一个语句首先执行,然后是第二个,依此类推。
编程语言提供各种控制结构,允许更复杂的执行路径。
循环语句允许我们多次执行一个语句或一组语句。下面是在大多数编程语言中循环语句的一般形式。
TypeScript 提供不同类型的循环来处理循环需求。下图说明了循环的分类:
确定循环
迭代次数确定/固定的循环称为确定循环。for 循环是确定循环的一种实现。
序号 | 循环和说明 |
---|---|
1. | for 循环
for 循环是确定循环的一种实现。 |
不确定循环
当循环的迭代次数不确定或未知时,使用不确定循环。
不确定循环可以使用:
序号 | 循环和说明 |
---|---|
1. | while 循环
while 循环每次指定的条件计算结果为真时都执行指令。 |
2. | do…while
do…while 循环类似于 while 循环,只是 do...while 循环在第一次执行循环时不评估条件。 |
示例:while 与 do..while
var n:number = 5 while(n > 5) { console.log("Entered while") } do { console.log("Entered do…while") } while(n>5)
此示例最初声明了一个 while 循环。只有当传递给 while 的表达式计算结果为真时,才会进入循环。在此示例中,n 的值不大于零,因此表达式返回 false,并且循环被跳过。
另一方面,do…while 循环会执行一次语句。这是因为初始迭代不考虑布尔表达式。但是,对于后续迭代,while 会检查条件并将控制权移出循环。
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var n = 5; while (n > 5) { console.log("Entered while"); } do { console.log("Entered do…while"); } while (n > 5);
上面的代码将产生以下输出:
Entered do…while
break 语句
break 语句用于将控制权移出结构。在循环中使用break会导致程序退出循环。其语法如下:
语法
break
流程图
示例
现在,让我们来看下面的示例代码:
var i:number = 1 while(i<=10) { if (i % 5 == 0) { console.log ("The first multiple of 5 between 1 and 10 is : "+i) break //exit the loop if the first multiple is found } i++ } //outputs 5 and exits the loop
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var i = 1; while (i <= 10) { if (i % 5 == 0) { console.log("The first multiple of 5 between 1 and 10 is : " + i); break; //exit the loop if the first multiple is found } i++; } //outputs 5 and exits the loop
它将产生以下输出:
The first multiple of 5 between 1 and 10 is : 5
continue 语句
continue 语句跳过当前迭代中的后续语句,并将控制权返回到循环的开头。与 break 语句不同,continue 不会退出循环。它终止当前迭代并开始后续迭代。
语法
continue
流程图
示例
continue 语句的示例如下:
var num:number = 0 var count:number = 0; for(num=0;num<=20;num++) { if (num % 2==0) { continue } count++ } console.log (" The count of odd values between 0 and 20 is: "+count) //outputs 10
上面的例子显示了 0 到 20 之间偶数的数量。如果数字是偶数,循环会退出当前迭代。这是使用continue语句实现的。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var num = 0; var count = 0; for (num = 0; num <= 20; num++) { if (num % 2 == 0) { continue; } count++; } console.log(" The count of odd values between 0 and 20 is: " + count); //outputs 10
输出
The count of odd values between 0 and 20 is: 10
无限循环
无限循环是一个无限运行的循环。for循环和while循环可以用来创建一个无限循环。
语法:使用 for 循环创建无限循环
for(;;) { //statements }
示例:使用 for 循环创建无限循环
for(;;) { console.log(“This is an endless loop”) }
语法:使用 while 循环创建无限循环
while(true) { //statements }
示例:使用 while 循环创建无限循环
while(true) { console.log(“This is an endless loop”) }
TypeScript - 函数
函数是可读、可维护和可重用代码的构建块。函数是一组执行特定任务的语句。函数将程序组织成逻辑代码块。一旦定义,就可以调用函数来访问代码。这使得代码可重用。此外,函数使程序代码易于阅读和维护。
函数声明告诉编译器函数的名称、返回类型和参数。函数定义提供了函数的实际主体。
序号 | 函数和说明 |
---|---|
1. | 定义函数
函数定义指定了如何执行特定任务。 |
2. | 调用函数
必须调用函数才能执行它。 |
3. | 返回函数
函数也可以将值和控制权一起返回给调用者。 |
4. | 参数化函数
参数是将值传递给函数的一种机制。 |
可选参数
当不需要强制传递参数来执行函数时,可以使用可选参数。可以通过在其名称后附加问号来将参数标记为可选。可选参数应设置为函数中的最后一个参数。声明带可选参数的函数的语法如下:
function function_name (param1[:type], param2[:type], param3[:type])
示例:可选参数
function disp_details(id:number,name:string,mail_id?:string) { console.log("ID:", id); console.log("Name",name); if(mail_id!=undefined) console.log("Email Id",mail_id); } disp_details(123,"John"); disp_details(111,"mary","[email protected]");
上面的例子声明了一个参数化函数。这里,第三个参数,即 mail_id 是一个可选参数。
如果在函数调用期间未传递可选参数的值,则参数的值将设置为 undefined。
该函数仅当参数传递值时才打印 mail_id 的值。
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 function disp_details(id, name, mail_id) { console.log("ID:", id); console.log("Name", name); if (mail_id != undefined) console.log("Email Id", mail_id); } disp_details(123, "John"); disp_details(111, "mary", "[email protected]");
上面的代码将产生以下输出:
ID:123 Name John ID: 111 Name mary Email Id [email protected]
剩余参数
剩余参数类似于 Java 中的可变参数。剩余参数不限制可以传递给函数的值的数量。但是,传递的值必须全部为相同类型。换句话说,剩余参数充当相同类型多个参数的占位符。
要声明剩余参数,参数名称前面要加上三个点。任何非剩余参数都应放在剩余参数之前。
示例:剩余参数
function addNumbers(...nums:number[]) { var i; var sum:number = 0; for(i = 0;i<nums.length;i++) { sum = sum + nums[i]; } console.log("sum of the numbers",sum) } addNumbers(1,2,3) addNumbers(10,10,10,10,10)
函数 addNumbers() 声明接受一个剩余参数nums。剩余参数的数据类型必须设置为数组。此外,函数最多只能有一个剩余参数。
该函数被调用两次,分别传递三个和六个值。
for 循环遍历传递给函数的参数列表并计算它们的总和。
编译后,它将生成以下 JavaScript 代码:
function addNumbers() { var nums = []; for (var _i = 0; _i < arguments.length; _i++) { nums[_i - 0] = arguments[_i]; } var i; var sum = 0; for (i = 0; i < nums.length; i++) { sum = sum + nums[i]; } console.log("sum of the numbers", sum); } addNumbers(1, 2, 3); addNumbers(10, 10, 10, 10, 10);
上述代码的输出如下:
sum of numbers 6 sum of numbers 50
默认参数
函数参数也可以分配默认值。但是,这些参数也可以显式地传递值。
语法
function function_name(param1[:type],param2[:type] = default_value) { }
注意 - 参数不能同时声明为可选和默认。
示例:默认参数
function calculate_discount(price:number,rate:number = 0.50) { var discount = price * rate; console.log("Discount Amount: ",discount); } calculate_discount(1000) calculate_discount(1000,0.30)
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 function calculate_discount(price, rate) { if (rate === void 0) { rate = 0.50; } var discount = price * rate; console.log("Discount Amount: ", discount); } calculate_discount(1000); calculate_discount(1000, 0.30);
其输出如下:
Discount amount : 500 Discount amount : 300
此示例声明了函数calculate_discount。该函数有两个参数 - price 和 rate。
参数rate的值默认为0.50。
程序调用该函数,只传递参数 price 的值。这里,rate的值为0.50(默认)
调用相同的函数,但是有两个参数。rate的默认值被覆盖,并设置为显式传递的值。
匿名函数
不绑定到标识符(函数名)的函数称为匿名函数。这些函数在运行时动态声明。匿名函数可以接受输入并返回输出,就像标准函数一样。匿名函数在其初始创建后通常是不可访问的。
变量可以赋值为匿名函数。这样的表达式称为函数表达式。
语法
var res = function( [arguments] ) { ... }
示例─一个简单的匿名函数
var msg = function() { return "hello world"; } console.log(msg())
编译后,它将在 JavaScript 中生成相同的代码。
它将产生以下输出:
hello world
示例─带参数的匿名函数
var res = function(a:number,b:number) { return a*b; }; console.log(res(12,2))
匿名函数返回传递给它的值的乘积。
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var res = function (a, b) { return a * b; }; console.log(res(12, 2));
上述代码的输出如下:
24
函数表达式和函数声明─它们是同义词吗?
函数表达式和函数声明不是同义词。与函数表达式不同,函数声明由函数名称绑定。
两者之间的根本区别在于,函数声明在其执行之前被解析。另一方面,函数表达式只有在脚本引擎在执行过程中遇到它时才被解析。
当 JavaScript 解析器在主代码流中看到一个函数时,它假定为函数声明 (Function Declaration)。当函数作为语句的一部分出现时,它就是一个函数表达式 (Function Expression)。
函数构造器 (The Function Constructor)
TypeScript 也支持使用名为 Function() 的内置 JavaScript 构造器来定义函数。
语法
var res = new Function( [arguments] ) { ... }.
示例
var myFunction = new Function("a", "b", "return a * b"); var x = myFunction(4, 3); console.log(x);
new Function() 是对构造器的调用,它依次创建一个并返回函数引用。
编译后,它将在 JavaScript 中生成相同的代码。
上述示例代码的输出如下:
12
递归和 TypeScript 函数 (Recursion and TypeScript Functions)
递归是一种通过函数反复调用自身直到得到结果来迭代操作的技术。当需要在循环内用不同的参数重复调用同一个函数时,递归最为适用。
示例 - 递归 (Example – Recursion)
function factorial(number) { if (number <= 0) { // termination case return 1; } else { return (number * factorial(number - 1)); // function invokes itself } }; console.log(factorial(6)); // outputs 720
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
720
示例:匿名递归函数 (Example: Anonymous Recursive Function)
(function () { var x = "Hello!!"; console.log(x) })() // the function invokes itself using a pair of parentheses ()
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
Hello!!
Lambda 函数 (Lambda Functions)
Lambda 指的是编程中的匿名函数。Lambda 函数是一种表示匿名函数的简洁机制。这些函数也称为**箭头函数 (Arrow functions)**。
Lambda 函数 - 结构 (Lambda Function - Anatomy)
Lambda 函数由三个部分组成:
**参数 (Parameters)** - 函数可以选择性地包含参数
**胖箭头符号/lambda 符号 (=>)** - 也称为“goes to”运算符
**语句 (Statements)** - 表示函数的指令集
**提示 (Tip)** - 按照惯例,建议为简洁和精确的函数声明使用单个字母参数。
Lambda 表达式 (Lambda Expression)
这是一个指向单行代码的匿名函数表达式。其语法如下:
( [param1, parma2,…param n] )=>statement;
示例:Lambda 表达式 (Example: Lambda Expression)
var foo = (x:number)=>10 + x console.log(foo(100)) //outputs 110
程序声明一个 lambda 表达式函数。该函数返回 10 与传入参数的和。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var foo = function (x) { return 10 + x; }; console.log(foo(100)); //outputs 110
上述代码的输出如下:
110
Lambda 语句 (Lambda Statement)
Lambda 语句是一个指向代码块的匿名函数声明。当函数体跨越多行时,使用此语法。其语法如下:
( [param1, parma2,…param n] )=> { //code block }
示例:Lambda 语句 (Example: Lambda statement)
var foo = (x:number)=> { x = 10 + x console.log(x) } foo(100)
函数的引用被返回并存储在变量**foo**中。
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var foo = function (x) { x = 10 + x; console.log(x); }; foo(100);
上述程序的输出如下:
110
语法变体 (Syntactic Variations)
参数类型推断 (Parameter type Inference)
不必指定参数的数据类型。在这种情况下,参数的数据类型为 any。让我们看一下下面的代码片段:
var func = (x)=> { if(typeof x=="number") { console.log(x+" is numeric") } else if(typeof x=="string") { console.log(x+" is a string") } } func(12) func("Tom")
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var func = function (x) { if (typeof x == "number") { console.log(x + " is numeric"); } else if (typeof x == "string") { console.log(x + " is a string"); } }; func(12); func("Tom");
其输出如下:
12 is numeric Tom is a string
单个参数的可选圆括号 (Optional parentheses for a single parameter)
var display = x=> { console.log("The function got "+x) } display(12)
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var display = function (x) { console.log("The function got " + x); }; display(12);
其输出如下:
The function got 12
单个语句的可选大括号,无参数的空圆括号 (Optional braces for a single statement, Empty parentheses for no parameter)
以下示例展示了这两种语法变体。
var disp =()=> { console.log("Function invoked"); } disp();
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var disp = function () { console.log("Function invoked"); }; disp();
其输出如下:
Function invoked
函数重载 (Function Overloads)
函数能够根据提供的输入以不同的方式运行。换句话说,程序可以有多个同名但实现不同的方法。这种机制称为函数重载。TypeScript 支持函数重载。
要在 TypeScript 中重载函数,需要按照以下步骤操作:
**步骤 1** - 声明多个同名但函数签名不同的函数。函数签名包括以下内容。
参数的数据类型
function disp(string):void; function disp(number):void;
参数的数量
function disp(n1:number):void; function disp(x:number,y:number):void;
参数的顺序
function disp(n1:number,s1:string):void; function disp(s:string,n:number):void;
**注意** - 函数签名不包括函数的返回类型。
**步骤 2** - 声明必须后跟函数定义。如果重载期间参数类型不同,则应将参数类型设置为**any**。此外,对于上面解释的**情况 b**,可以考虑在函数定义期间将一个或多个参数标记为可选。
**步骤 3** - 最后,必须调用函数才能使其生效。
示例
现在让我们看一下下面的示例代码:
function disp(s1:string):void; function disp(n1:number,s1:string):void; function disp(x:any,y?:any):void { console.log(x); console.log(y); } disp("abc") disp(1,"xyz");
前两行描述了函数重载声明。该函数有两个重载:
接受单个字符串参数的函数。
分别接受两个类型为数字和字符串的值的函数。
第三行定义了函数。参数的数据类型设置为**any**。此外,这里第二个参数是可选的。
重载函数由最后两个语句调用。
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 function disp(x, y) { console.log(x); console.log(y); } disp("abc"); disp(1, "xyz");
上面的代码将产生以下输出:
abc 1 xyz
TypeScript - 数字
TypeScript 像 JavaScript 一样支持数值作为 Number 对象。Number 对象将数值字面量转换为 Number 类的实例。Number 类充当包装器,并使数值字面量的操作如同它们是对象一样。
语法
var var_name = new Number(value)
如果将非数值参数作为 Number 构造函数的参数传递,则返回 NaN(非数字)。
下表列出了 Number 对象的一组属性:
序号 | 属性和描述 (Property & Description) |
---|---|
1. | MAX_VALUE JavaScript 中数字可以具有的最大值 1.7976931348623157E+308。 |
2. | MIN_VALUE JavaScript 中数字可以具有的最小值 5E-324。 |
3. | NaN 等于非数值。 |
4. | NEGATIVE_INFINITY 小于 MIN_VALUE 的值。 |
5. | POSITIVE_INFINITY 大于 MAX_VALUE 的值。 |
6. | prototype Number 对象的静态属性。使用 prototype 属性可以为当前文档中的 Number 对象分配新的属性和方法。 |
7. | constructor 返回创建此对象实例的函数。默认情况下,这是 Number 对象。 |
示例
console.log("TypeScript Number Properties: "); console.log("Maximum value that a number variable can hold: " + Number.MAX_VALUE); console.log("The least value that a number variable can hold: " + Number.MIN_VALUE); console.log("Value of Negative Infinity: " + Number.NEGATIVE_INFINITY); console.log("Value of Negative Infinity:" + Number.POSITIVE_INFINITY);
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
TypeScript Number Properties: Maximum value that a number variable can hold: 1.7976931348623157e+308 The least value that a number variable can hold: 5e-324 Value of Negative Infinity: -Infinity Value of Negative Infinity:Infinity
示例:NaN (Example: NaN)
var month = 0 if( month<=0 || month >12) { month = Number.NaN console.log("Month is "+ month) } else { console.log("Value Accepted..") }
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
Month is NaN
示例:prototype (Example: prototye)
function employee(id:number,name:string) { this.id = id this.name = name } var emp = new employee(123,"Smith") employee.prototype.email = "[email protected]" console.log("Employee 's Id: "+emp.id) console.log("Employee's name: "+emp.name) console.log("Employee's Email ID: "+emp.email)
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 function employee(id, name) { this.id = id; this.name = name; } var emp = new employee(123, "Smith"); employee.prototype.email = "[email protected]"; console.log("Employee 's Id: " + emp.id); console.log("Employee's name: " + emp.name); console.log("Employee's Email ID: " + emp.email);
其输出如下:
Employee’s Id: 123 Emaployee’s name: Smith Employee’s Email ID: [email protected]
Number 方法 (Number Methods)
Number 对象仅包含作为每个对象定义一部分的默认方法。一些常用方法列在下面:
序号 | 方法和描述 (Methods & Description) |
---|---|
1. | toExponential()
强制数字以指数表示法显示,即使数字在 JavaScript 通常使用标准表示法的范围内。 |
2. | toFixed()
格式化一个数字,使其小数点右边有特定数量的位数。 |
3. | toLocaleString()
返回当前数字的字符串值版本,其格式可能会根据浏览器的本地设置而有所不同。 |
4. | toPrecision()
定义要显示的数字的总位数(包括小数点左边和右边的位数)。负精度将抛出错误。 |
5. | toString()
返回数字值的字符串表示形式。该函数传递基数,这是一个介于 2 和 36 之间的整数,用于指定表示数值的基数。 |
6. | valueOf()
返回数字的原始值。 |
TypeScript - 字符串
String 对象允许您使用一系列字符。它使用许多辅助方法来包装字符串原始数据类型。
语法
var var_name = new String(string);
下面列出了 String 对象中可用的方法及其说明:
序号 | 属性和描述 (Property & Description) |
---|---|
1. | 构造器 (Constructor)
返回创建对象的 String 函数的引用。 |
2. | 长度 (Length)
返回字符串的长度。 |
3. | 原型 (Prototype)
prototype 属性允许您向对象添加属性和方法。 |
String 方法 (String Methods)
下面列出了 String 对象中可用的方法及其说明:
序号 | 方法和描述 (Method & Description) |
---|---|
1. | charAt()
返回指定索引处的字符。 |
2. | charCodeAt()
返回一个数字,指示给定索引处字符的 Unicode 值。 |
3. | concat()
组合两个字符串的文本并返回一个新字符串。 |
4. | indexOf()
返回调用 String 对象中指定值的第一次出现的索引,如果未找到则返回 -1。 |
5. | lastIndexOf()
返回调用 String 对象中指定值的最后一次出现的索引,如果未找到则返回 -1。 |
6. | localeCompare()
返回一个数字,指示引用字符串在排序顺序中是在给定字符串之前、之后还是与之相同。 |
7. | match() 用于将正则表达式与字符串匹配。 |
8. | replace()
用于查找正则表达式和字符串之间的匹配项,并将匹配的子字符串替换为新的子字符串。 |
9. | search()
执行对正则表达式和指定字符串之间匹配项的搜索。 |
10. | slice()
提取字符串的一部分并返回一个新字符串。 |
11. | split()
通过将字符串分割成子字符串,将 String 对象分割成字符串数组。 |
12. | substr()
返回字符串中从指定位置开始的指定数量的字符。 |
13. | substring()
返回字符串中两个索引之间的字符。 |
14. | toLocaleLowerCase()
字符串中的字符转换为小写,同时尊重当前区域设置。 |
15. | toLocaleUpperCase()
字符串中的字符转换为大写,同时尊重当前区域设置。 |
16. | toLowerCase()
返回转换为小写的调用字符串值。 |
17. | toString()
返回表示指定对象的字符串。 |
18. | toUpperCase()
返回转换为大写的调用字符串值。 |
19. | valueOf()
返回指定对象的原始值。 |
TypeScript - 数组
使用变量存储值具有以下限制:
变量本质上是标量的。换句话说,变量声明一次只能包含一个值。这意味着要在程序中存储 n 个值,需要 n 个变量声明。因此,当需要存储大量值时,使用变量是不可行的。
程序中的变量以随机顺序分配内存,从而难以按声明顺序检索/读取值。
TypeScript 引入了数组的概念来解决这个问题。数组是值的同质集合。简而言之,数组是相同数据类型值的集合。它是一种用户定义类型。
数组的特性 (Features of an Array)
以下是数组特性的列表:
数组声明分配顺序内存块。
数组是静态的。这意味着一旦初始化,数组就不能调整大小。
每个内存块代表一个数组元素。
数组元素由唯一的整数标识,该整数称为元素的下标/索引。
与变量一样,数组也应在使用前声明。使用 var 关键字声明数组。
数组初始化是指填充数组元素。
数组元素值可以更新或修改,但不能删除。
声明和初始化数组 (Declaring and Initializing Arrays)
要在 Typescript 中声明和初始化数组,请使用以下语法:
语法
var array_name[:datatype]; //declaration array_name = [val1,val2,valn..] //initialization
没有数据类型的数组声明被认为是 any 类型。此类数组的类型在初始化期间从数组第一个元素的数据类型推断。
例如,像这样的声明:**var numlist:number[] = [2,4,6,8]** 将创建一个如下所示的数组:
数组指针默认指向第一个元素。
**数组可以在单个语句中声明和初始化**。其语法如下:
var array_name[:data type] = [val1,val2…valn]
**注意** - [] 对称为数组的维度。
访问数组元素 (Accessing Array Elements)
数组名称后跟下标用于引用数组元素。其语法如下:
array_name[subscript] = value
示例:简单数组 (Example: Simple Array)
var alphas:string[]; alphas = ["1","2","3","4"] console.log(alphas[0]); console.log(alphas[1]);
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var alphas; alphas = ["1", "2", "3", "4"]; console.log(alphas[0]); console.log(alphas[1]);
上述代码的输出如下:
1 2
示例:单语句声明和初始化 (Example: Single statement declaration and initialization)
var nums:number[] = [1,2,3,3] console.log(nums[0]); console.log(nums[1]); console.log(nums[2]); console.log(nums[3]);
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var nums = [1, 2, 3, 3]; console.log(nums[0]); console.log(nums[1]); console.log(nums[2]); console.log(nums[3]);
其输出如下:
1 2 3 3
数组对象 (Array Object)
也可以使用 Array 对象创建数组。Array 构造函数可以传递。
表示数组大小的数值,或
逗号分隔值的列表。
以下示例显示了如何使用此方法创建数组。
示例
var arr_names:number[] = new Array(4) for(var i = 0;i<arr_names.length;i++;) { arr_names[i] = i * 2 console.log(arr_names[i]) }
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var arr_names = new Array(4); for (var i = 0; i < arr_names.length; i++) { arr_names[i] = i * 2; console.log(arr_names[i]); }
其输出如下:
0 2 4 6
示例:Array 构造函数接受逗号分隔的值 (Example: Array Constructor accepts comma separated values)
var names:string[] = new Array("Mary","Tom","Jack","Jill") for(var i = 0;i<names.length;i++) { console.log(names[i]) }
编译后,它将生成以下 JavaScript 代码:
//Generated by typescript 1.8.10 var names = new Array("Mary", "Tom", "Jack", "Jill"); for (var i = 0; i < names.length; i++) { console.log(names[i]); }
其输出如下:
Mary Tom Jack Jill
数组方法 (Array Methods)
下面列出了 Array 对象的方法及其说明。
序号 | 方法和描述 (Method & Description) |
---|---|
1. | concat()
返回一个新数组,该数组由该数组与其他数组和/或值连接而成。 |
2. | every()
如果数组中的每个元素都满足提供的测试函数,则返回 true。 |
3. | filter()
创建一个新数组,其中包含此数组中所有使提供的筛选函数返回 true 的元素。 |
4. | forEach()
为数组中的每个元素调用一个函数。 |
5. | indexOf()
返回数组中等于指定值的元素的第一个(最小)索引,如果未找到则返回 -1。 |
6. | join()
将数组的所有元素连接成一个字符串。 |
7. | lastIndexOf()
返回数组中等于指定值的元素的最后一个(最大)索引,如果未找到则返回 -1。 |
8. | map()
创建一个新数组,其中包含对这个数组中每个元素调用提供的函数的结果。 |
9. | pop()
移除数组的最后一个元素,并返回该元素。 |
10. | push()
向数组的末尾添加一个或多个元素,并返回数组的新长度。 |
11. | reduce()
将一个函数同时应用于数组的两个值(从左到右),以将其归约为单个值。 |
12. | reduceRight()
将一个函数同时应用于数组的两个值(从右到左),以将其归约为单个值。 |
13. | reverse()
反转数组元素的顺序——第一个元素成为最后一个,最后一个元素成为第一个。 |
14. | shift()
移除数组的第一个元素,并返回该元素。 |
15. | slice()
提取数组的一部分并返回一个新数组。 |
16. | some()
如果此数组中至少有一个元素满足提供的测试函数,则返回 true。 |
17. | sort()
对数组的元素进行排序。 |
18. | splice()
向数组添加和/或从数组中移除元素。 |
19. | toString()
返回表示数组及其元素的字符串。 |
20. | unshift()
向数组的开头添加一个或多个元素,并返回数组的新长度。 |
数组解构
指的是分解实体的结构。TypeScript 在数组上下文中使用时支持解构。
示例
var arr:number[] = [12,13] var[x,y] = arr console.log(x) console.log(y)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var arr = [12, 13]; var x = arr[0], y = arr[1]; console.log(x); console.log(y);
其输出如下:
12 13
使用 for…in 循环遍历数组
可以使用for…in循环遍历数组。
var j:any; var nums:number[] = [1001,1002,1003,1004] for(j in nums) { console.log(nums[j]) }
循环执行基于索引的数组遍历。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var j; var nums = [1001, 1002, 1003, 1004]; for (j in nums) { console.log(nums[j]); }
上面代码的输出如下:
1001 1002 1003 1004
TypeScript 中的数组
TypeScript 支持数组中的以下概念:
序号 | 概念和描述 |
---|---|
1. | 多维数组
TypeScript 支持多维数组。多维数组最简单的形式是二维数组。 |
2. | 将数组传递给函数
您可以通过指定数组的名称(不带索引)来将指向数组的指针传递给函数。 |
3. | 从函数返回数组
允许函数返回数组 |
TypeScript - 元组
有时,可能需要存储各种类型值的集合。数组不能满足此目的。TypeScript 为我们提供了一种称为元组的数据类型,有助于实现此目的。
它表示异构值集合。换句话说,元组允许存储不同类型的多个字段。元组也可以作为参数传递给函数。
语法
var tuple_name = [value1,value2,value3,…value n]
例如
var mytuple = [10,"Hello"];
您也可以在 Typescript 中声明一个空元组,并选择稍后对其进行初始化。
var mytuple = []; mytuple[0] = 120 mytuple[1] = 234
访问元组中的值
元组值分别称为项。元组是基于索引的。这意味着可以使用其对应的数字索引访问元组中的项。元组项的索引从零开始,一直延伸到 n-1(其中 n 是元组的大小)。
语法
tuple_name[index]
示例:简单元组
var mytuple = [10,"Hello"]; //create a tuple console.log(mytuple[0]) console.log(mytuple[1])
在上面的示例中,声明了一个元组mytuple。元组分别包含数值和字符串类型的值。
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
10 Hello
示例:空元组
var tup = [] tup[0] = 12 tup[1] = 23 console.log(tup[0]) console.log(tup[1])
编译后,它将在 JavaScript 中生成相同的代码。
其输出如下:
12 23
元组操作
TypeScript 中的元组支持各种操作,例如推送新项、从元组中移除项等。
示例
var mytuple = [10,"Hello","World","typeScript"]; console.log("Items before push "+mytuple.length) // returns the tuple size mytuple.push(12) // append value to the tuple console.log("Items after push "+mytuple.length) console.log("Items before pop "+mytuple.length) console.log(mytuple.pop()+" popped from the tuple") // removes and returns the last item console.log("Items after pop "+mytuple.length)
push() 将项添加到元组中
pop() 移除并返回元组中的最后一个值
编译后,它将在 JavaScript 中生成相同的代码。
上述代码的输出如下:
Items before push 4 Items after push 5 Items before pop 5 12 popped from the tuple Items after pop 4
更新元组
元组是可变的,这意味着您可以更新或更改元组元素的值。
示例
var mytuple = [10,"Hello","World","typeScript"]; //create a tuple console.log("Tuple value at index 0 "+mytuple[0]) //update a tuple element mytuple[0] = 121 console.log("Tuple value at index 0 changed to "+mytuple[0])
编译后,它将在 JavaScript 中生成相同的代码。
上述代码的输出如下:
Tuple value at index 0 10 Tuple value at index 0 changed to 121
解构元组
解构指的是分解实体的结构。TypeScript 在元组上下文中使用时支持解构。
示例
var a =[10,"hello"] var [b,c] = a console.log( b ) console.log( c )
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var a = [10, "hello"]; var b = a[0], c = a[1]; console.log(b); console.log(c);
其输出如下:
10 hello
TypeScript - 联合类型
TypeScript 1.4 使程序能够组合一种或两种类型。联合类型是表达可以是几种类型之一的值的强大方法。使用管道符号 (|) 组合两种或多种数据类型来表示联合类型。换句话说,联合类型写成由竖线分隔的类型序列。
语法:联合字面量
Type1|Type2|Type3
示例:联合类型变量
var val:string|number val = 12 console.log("numeric value of val "+val) val = "This is a string" console.log("string value of val "+val)
在上面的示例中,变量的类型是联合类型。这意味着变量可以包含数字或字符串作为其值。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var val; val = 12; console.log("numeric value of val " + val); val = "This is a string"; console.log("string value of val " + val);
其输出如下:
numeric value of val 12 string value of val this is a string
示例:联合类型和函数参数
function disp(name:string|string[]) { if(typeof name == "string") { console.log(name) } else { var i; for(i = 0;i<name.length;i++) { console.log(name[i]) } } } disp("mark") console.log("Printing names array....") disp(["Mark","Tom","Mary","John"])
函数 disp() 可以接受字符串类型或字符串数组类型的参数。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 function disp(name) { if (typeof name == "string") { console.log(name); } else { var i; for (i = 0; i < name.length; i++) { console.log(name[i]); } } } disp("mark"); console.log("Printing names array...."); disp(["Mark", "Tom", "Mary", "John"]);
输出如下:
Mark Printing names array…. Mark Tom Mary John
联合类型和数组
联合类型也可以应用于数组、属性和接口。以下是联合类型与数组一起使用的示例。
示例:联合类型和数组
var arr:number[]|string[]; var i:number; arr = [1,2,4] console.log("**numeric array**") for(i = 0;i<arr.length;i++) { console.log(arr[i]) } arr = ["Mumbai","Pune","Delhi"] console.log("**string array**") for(i = 0;i<arr.length;i++) { console.log(arr[i]) }
程序声明一个数组。数组可以表示数字集合或字符串集合。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var arr; var i; arr = [1, 2, 4]; console.log("**numeric array**"); for (i = 0; i < arr.length; i++) { console.log(arr[i]); } arr = ["Mumbai", "Pune", "Delhi"]; console.log("**string array**"); for (i = 0; i < arr.length; i++) { console.log(arr[i]); }
其输出如下:
**numeric array** 1 2 4 **string array** Mumbai Pune Delhi
TypeScript - 接口
接口是一种语法约定,实体应符合该约定。换句话说,接口定义了任何实体都必须遵守的语法。
接口定义属性、方法和事件,这些是接口的成员。接口仅包含成员的声明。派生类负责定义成员。它通常有助于提供派生类将遵循的标准结构。
让我们考虑一个对象:
var person = { FirstName:"Tom", LastName:"Hanks", sayHi: ()=>{ return "Hi"} };
如果我们考虑对象的签名,它可能是:
{ FirstName:string, LastName:string, sayHi()=>string }
为了跨对象重用签名,我们可以将其定义为接口。
声明接口
interface 关键字用于声明接口。以下是声明接口的语法:
语法
interface interface_name { }
示例:接口和对象
interface IPerson { firstName:string, lastName:string, sayHi: ()=>string } var customer:IPerson = { firstName:"Tom", lastName:"Hanks", sayHi: ():string =>{return "Hi there"} } console.log("Customer Object ") console.log(customer.firstName) console.log(customer.lastName) console.log(customer.sayHi()) var employee:IPerson = { firstName:"Jim", lastName:"Blakes", sayHi: ():string =>{return "Hello!!!"} } console.log("Employee Object ") console.log(employee.firstName); console.log(employee.lastName);
此示例定义了一个接口。customer 对象的类型为 IPerson。因此,它现在将绑定到对象以根据接口定义所有属性。
具有以下签名的另一个对象仍然被视为 IPerson,因为该对象是根据其大小或签名进行处理的。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var customer = { firstName: "Tom", lastName: "Hanks", sayHi: function () { return "Hi there"; } }; console.log("Customer Object "); console.log(customer.firstName); console.log(customer.lastName); console.log(customer.sayHi()); var employee = { firstName: "Jim", lastName: "Blakes", sayHi: function () { return "Hello!!!"; } }; console.log("Employee Object "); console.log(employee.firstName); console.log(employee.lastName);
上述示例代码的输出如下:
Customer object Tom Hanks Hi there Employee object Jim Blakes Hello!!!
接口不需要转换为 JavaScript。它只是 TypeScript 的一部分。如果您查看 TS Playground 工具的屏幕截图,当您声明接口时,不会像类一样发出任何 JavaScript 代码。因此,接口对运行时 JavaScript 没有任何影响。
联合类型和接口
以下示例显示了联合类型和接口的用法:
interface RunOptions { program:string; commandline:string[]|string|(()=>string); } //commandline as string var options:RunOptions = {program:"test1",commandline:"Hello"}; console.log(options.commandline) //commandline as a string array options = {program:"test1",commandline:["Hello","World"]}; console.log(options.commandline[0]); console.log(options.commandline[1]); //commandline as a function expression options = {program:"test1",commandline:()=>{return "**Hello World**";}}; var fn:any = options.commandline; console.log(fn());
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 //commandline as string var options = { program: "test1", commandline: "Hello" }; console.log(options.commandline); //commandline as a string array options = { program: "test1", commandline: ["Hello", "World"] }; console.log(options.commandline[0]); console.log(options.commandline[1]); //commandline as a function expression options = { program: "test1", commandline: function () { return "**Hello World**"; } }; var fn = options.commandline; console.log(fn());
其输出如下:
Hello Hello World **Hello World**
接口和数组
接口可以定义数组使用的键的类型以及它包含的条目的类型。索引可以是字符串类型或数字类型。
示例
interface namelist { [index:number]:string } var list2:namelist = ["John",1,"Bran"] //Error. 1 is not type string interface ages { [index:string]:number } var agelist:ages; agelist["John"] = 15 // Ok agelist[2] = "nine" // Error
接口和继承
接口可以被其他接口扩展。换句话说,接口可以继承自其他接口。Typescript 允许接口继承自多个接口。
使用 extends 关键字在接口之间实现继承。
语法:单接口继承
Child_interface_name extends super_interface_name
语法:多接口继承
Child_interface_name extends super_interface1_name, super_interface2_name,…,super_interfaceN_name
示例:简单接口继承
interface Person { age:number } interface Musician extends Person { instrument:string } var drummer = <Musician>{}; drummer.age = 27 drummer.instrument = "Drums" console.log("Age: "+drummer.age) console.log("Instrument: "+drummer.instrument)
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var drummer = {}; drummer.age = 27; drummer.instrument = "Drums"; console.log("Age: " + drummer.age); console.log("Instrument: " + drummer.instrument);
其输出如下:
Age: 27 Instrument: Drums
示例:多接口继承
interface IParent1 { v1:number } interface IParent2 { v2:number } interface Child extends IParent1, IParent2 { } var Iobj:Child = { v1:12, v2:23} console.log("value 1: "+this.v1+" value 2: "+this.v2)
Iobj 对象的类型为接口 leaf。leaf 接口凭借继承现在具有两个属性——v1 和 v2。因此,Iobj 对象现在必须包含这些属性。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Iobj = { v1: 12, v2: 23 }; console.log("value 1: " + this.v1 + " value 2: " + this.v2);
上述代码的输出如下:
value 1: 12 value 2: 23
TypeScript - 类
TypeScript 是面向对象的 JavaScript。TypeScript 支持面向对象编程功能,例如类、接口等。就 OOP 而言,类是创建对象的蓝图。类封装对象的数。Typescript 对此概念提供了内置支持,称为类。JavaScript ES5 或更早版本不支持类。Typescript 从 ES6 获取此功能。
创建类
使用 class 关键字在 TypeScript 中声明类。其语法如下:
语法
class class_name { //class scope }
class 关键字后跟类名。命名类时必须遵守标识符规则。
类定义可以包含以下内容:
字段 - 字段是在类中声明的任何变量。字段表示与对象相关的数据
构造函数 - 负责为类的对象分配内存
函数 - 函数表示对象可以执行的操作。它们有时也称为方法
这些组件组合在一起被称为类的成员数据。
考虑 typescript 中的 Person 类。
class Person { }
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Person = (function () { function Person() { } return Person; }());
示例:声明类
class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log("Engine is : "+this.engine) } }
此示例声明了一个 Car 类。该类有一个名为 engine 的字段。声明字段时不使用 var 关键字。上面的示例为该类声明了一个构造函数。
构造函数是类的特殊函数,负责初始化类的变量。TypeScript 使用 constructor 关键字定义构造函数。构造函数是一个函数,因此可以参数化。
this 关键字指的是类的当前实例。在这里,参数名称和类字段的名称相同。因此,为了避免歧义,类字段以 this 关键字为前缀。
disp() 是一个简单的函数定义。请注意,这里没有使用 function 关键字。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log("Engine is : " + this.engine); }; return Car; }());
创建实例对象
要创建类的实例,请使用 new 关键字后跟类名。其语法如下:
语法
var object_name = new class_name([ arguments ])
new 关键字负责实例化。
表达式的右侧调用构造函数。如果构造函数已参数化,则应向其传递值。
示例:实例化类
var obj = new Car("Engine 1")
访问属性和函数
可以通过对象访问类的属性和函数。使用“.”点表示法(称为句点)来访问类的成员数据。
//accessing an attribute obj.field_name //accessing a function obj.function_name()
示例:将它们放在一起
class Car { //field engine:string; //constructor constructor(engine:string) { this.engine = engine } //function disp():void { console.log("Function displays Engine is : "+this.engine) } } //create an object var obj = new Car("XXSY1") //access the field console.log("Reading attribute value Engine as : "+obj.engine) //access the function obj.disp()
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Car = (function () { //constructor function Car(engine) { this.engine = engine; } //function Car.prototype.disp = function () { console.log("Function displays Engine is : " + this.engine); }; return Car; }()); //create an object var obj = new Car("XXSY1"); //access the field console.log("Reading attribute value Engine as : " + obj.engine); //access the function obj.disp();
上述代码的输出如下:
Reading attribute value Engine as : XXSY1 Function displays Engine is : XXSY1
类继承
TypeScript 支持继承的概念。继承是程序从现有类创建新类的一种能力。扩展以创建新类的类称为父类/超类。新创建的类称为子类/子类。
类使用“extends”关键字从另一个类继承。子类继承所有属性和方法,但私有成员和构造函数除外。
语法
class child_class_name extends parent_class_name
但是,TypeScript 不支持多重继承。
示例:类继承
class Shape { Area:number constructor(a:number) { this.Area = a } } class Circle extends Shape { disp():void { console.log("Area of the circle: "+this.Area) } } var obj = new Circle(223); obj.disp()
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var Shape = (function () { function Shape(a) { this.Area = a; } return Shape; }()); var Circle = (function (_super) { __extends(Circle, _super); function Circle() { _super.apply(this, arguments); } Circle.prototype.disp = function () { console.log("Area of the circle: " + this.Area); }; return Circle; }(Shape)); var obj = new Circle(223); obj.disp();
上述代码的输出如下:
Area of the Circle: 223
上面的示例声明了一个 Shape 类。Circle 类扩展了该类。由于类之间存在继承关系,子类,即 Car 类,可以隐式访问其父类的属性,即 area。
继承可以分为:
单继承 - 每个类最多可以从一个父类继承
多继承 - 类可以从多个类继承。TypeScript 不支持多重继承。
多级继承 - 下面的示例显示了多级继承的工作方式。
示例
class Root { str:string; } class Child extends Root {} class Leaf extends Child {} //indirectly inherits from Root by virtue of inheritance var obj = new Leaf(); obj.str ="hello" console.log(obj.str)
Leaf 类凭借多级继承从 Root 类和 Child 类继承属性。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var Root = (function () { function Root() { } return Root; }()); var Child = (function (_super) { __extends(Child, _super); function Child() { _super.apply(this, arguments); } return Child; }(Root)); var Leaf = (function (_super) { __extends(Leaf, _super); function Leaf() { _super.apply(this, arguments); } return Leaf; }(Child)); var obj = new Leaf(); obj.str = "hello"; console.log(obj.str);
其输出如下:
输出
hello
TypeScript ─ 类继承和方法覆盖
方法覆盖是一种机制,子类通过该机制重新定义超类的。下面的示例说明了这一点:
class PrinterClass { doPrint():void { console.log("doPrint() from Parent called…") } } class StringPrinter extends PrinterClass { doPrint():void { super.doPrint() console.log("doPrint() is printing a string…") } } var obj = new StringPrinter() obj.doPrint()
super关键字用于引用类的直接父类。此关键字可用于引用变量、属性或方法的超类版本。第13行调用doWork()函数的超类版本。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var PrinterClass = (function () { function PrinterClass() { } PrinterClass.prototype.doPrint = function () { console.log("doPrint() from Parent called…"); }; return PrinterClass; }()); var StringPrinter = (function (_super) { __extends(StringPrinter, _super); function StringPrinter() { _super.apply(this, arguments); } StringPrinter.prototype.doPrint = function () { _super.prototype.doPrint.call(this); console.log("doPrint() is printing a string…"); }; return StringPrinter; }(PrinterClass)); var obj = new StringPrinter(); obj.doPrint();
上述代码的输出如下:
doPrint() from Parent called… doPrint() is printing a string…
static关键字
static关键字可以应用于类的成员数据。静态变量在其值保留到程序执行结束。静态成员通过类名来引用。
示例
class StaticMem { static num:number; static disp():void { console.log("The value of num is"+ StaticMem.num) } } StaticMem.num = 12 // initialize the static variable StaticMem.disp() // invoke the static method
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var StaticMem = (function () { function StaticMem() { } StaticMem.disp = function () { console.log("The value of num is" + StaticMem.num); }; return StaticMem; }()); StaticMem.num = 12; // initialize the static variable StaticMem.disp(); // invoke the static method
上述代码的输出如下:
The value of num is 12
instanceof运算符
instanceof运算符如果对象属于指定的类型,则返回true。
示例
class Person{ } var obj = new Person() var isPerson = obj instanceof Person; console.log(" obj is an instance of Person " + isPerson);
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var Person = (function () { function Person() { } return Person; }()); var obj = new Person(); var isPerson = obj instanceof Person; console.log(" obj is an instance of Person " + isPerson);
上述代码的输出如下:
obj is an instance of Person True
数据隐藏
类可以控制其成员数据对其他类成员的可见性。此功能称为数据隐藏或封装。
面向对象使用访问修饰符或访问说明符的概念来实现封装的概念。访问说明符/修饰符定义类的数据成员在其定义类之外的可见性。
TypeScript支持的访问修饰符如下:
序号 | 访问说明符和描述 |
---|---|
1. | public 公共数据成员具有普遍的访问权限。类中的数据成员默认是公共的。 |
2. | private 私有数据成员只能在其定义这些成员的类中访问。如果外部类成员尝试访问私有成员,编译器将抛出错误。 |
3. | protected 受保护的数据成员可被与其相同的类中的成员以及子类成员访问。 |
示例
现在让我们来看一个例子,看看数据隐藏是如何工作的:
class Encapsulate { str:string = "hello" private str2:string = "world" } var obj = new Encapsulate() console.log(obj.str) //accessible console.log(obj.str2) //compilation Error as str2 is private
该类具有两个字符串属性str1和str2,它们分别是公共成员和私有成员。该类已实例化。该示例返回编译时错误,因为私有属性str2在声明它的类之外被访问。
类和接口
类也可以实现接口。
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) console.log("Interest is : "+obj.interest+" Rebate is : "+obj.rebate )
AgriLoan类实现了Loan接口。因此,它现在绑定到该类上,将其属性interest包含为其成员。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var AgriLoan = (function () { function AgriLoan(interest, rebate) { this.interest = interest; this.rebate = rebate; } return AgriLoan; }()); var obj = new AgriLoan(10, 1); console.log("Interest is : " + obj.interest + " Rebate is : " + obj.rebate);
上述代码的输出如下:
Interest is : 10 Rebate is : 1
TypeScript - 对象
一个对象是一个实例,它包含一组键值对。值可以是标量值、函数,甚至是其他对象的数组。语法如下:
语法
var object_name = { key1: “value1”, //scalar value key2: “value”, key3: function() { //functions }, key4:[“content1”, “content2”] //collection };
如上所示,一个对象可以包含标量值、函数和数组和元组之类的结构。
示例:对象字面量表示法
var person = { firstname:"Tom", lastname:"Hanks" }; //access the object values console.log(person.firstname) console.log(person.lastname)
编译后,它将在 JavaScript 中生成相同的代码。
上述代码的输出如下:
Tom Hanks
TypeScript类型模板
假设你在JavaScript中创建了一个对象字面量,如下所示:
var person = { firstname:"Tom", lastname:"Hanks" };
如果你想向对象添加一些值,JavaScript允许你进行必要的修改。假设我们稍后需要向person对象添加一个函数,这就是你可以这样做的方式。
person.sayHello = function(){ return "hello";}
如果你在TypeScript中使用相同的代码,编译器会报错。这是因为在TypeScript中,具体对象应该具有类型模板。TypeScript中的对象必须是特定类型的实例。
你可以使用方法模板在声明中解决这个问题。
示例:TypeScript类型模板
var person = { firstName:"Tom", lastName:"Hanks", sayHello:function() { } //Type template } person.sayHello = function() { console.log("hello "+person.firstName) } person.sayHello()
编译后,它将在 JavaScript 中生成相同的代码。
上述代码的输出如下:
hello Tom
对象也可以作为参数传递给函数。
示例:对象作为函数参数
var person = { firstname:"Tom", lastname:"Hanks" }; var invokeperson = function(obj: { firstname:string, lastname :string }) { console.log("first name :"+obj.firstname) console.log("last name :"+obj.lastname) } invokeperson(person)
该示例声明了一个对象字面量。函数表达式通过传递person对象来调用。
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var person = { firstname: "Tom", lastname: "Hanks" }; var invokeperson = function (obj) { console.log("first name :" + obj.firstname); console.log("last name :" + obj.lastname); }; invokeperson(person);
其输出如下:
first name :Tom last name :Hanks
你可以动态创建和传递匿名对象。
示例:匿名对象
var invokeperson = function(obj:{ firstname:string, lastname :string}) { console.log("first name :"+obj.firstname) console.log("last name :"+obj.lastname) } invokeperson({firstname:"Sachin",lastname:"Tendulkar"});
编译后,它将生成以下 JavaScript 代码。
//Generated by typescript 1.8.10 var invokeperson = function (obj) { console.log("first name :" + obj.firstname); console.log("last name :" + obj.lastname); }; invokeperson({ firstname: "Sachin", lastname: "Tendulkar" }); invokeperson({ firstname: "Sachin", lastname: "Tendulkar" });
其输出如下:
first name :Sachin last name :Tendulkar
鸭子类型
在鸭子类型中,如果两个对象共享相同的属性集,则认为它们属于相同的类型。鸭子类型验证对象中是否存在某些属性,而不是它们的实际类型,以检查它们的适用性。这个概念通常用以下短语解释:
“当我看到一只鸟像鸭子一样行走,像鸭子一样游泳,像鸭子一样嘎嘎叫,我就称这只鸟为鸭子。”
TypeScript编译器实现了鸭子类型系统,允许动态创建对象,同时保持类型安全。以下示例显示了如何将不显式实现接口但包含所有必需成员的对象传递给函数。
示例
interface IPoint { x:number y:number } function addPoints(p1:IPoint,p2:IPoint):IPoint { var x = p1.x + p2.x var y = p1.y + p2.y return {x:x,y:y} } //Valid var newPoint = addPoints({x:3,y:4},{x:5,y:1}) //Error var newPoint2 = addPoints({x:1},{x:4,y:3})
TypeScript - 命名空间
命名空间是一种逻辑分组相关代码的方法。这在TypeScript中是内置的,不像JavaScript那样,变量声明进入全局作用域,如果在同一个项目中使用了多个JavaScript文件,则有可能覆盖或误解相同的变量,这将导致JavaScript中的“全局命名空间污染问题”。
定义命名空间
命名空间定义以关键字namespace开头,后跟命名空间名称,如下所示:
namespace SomeNameSpaceName { export interface ISomeInterfaceName { } export class SomeClassName { } }
应该在命名空间外部访问的类或接口应该用关键字export标记。
要在另一个命名空间中访问类或接口,语法将是namespaceName.className
SomeNameSpaceName.SomeClassName;
如果第一个命名空间在单独的TypeScript文件中,则应使用三斜杠引用语法来引用它。
/// <reference path = "SomeFileName.ts" />
以下程序演示了命名空间的使用:
FileName :IShape.ts ---------- namespace Drawing { export interface IShape { draw(); } } FileName :Circle.ts ---------- /// <reference path = "IShape.ts" /> namespace Drawing { export class Circle implements IShape { public draw() { console.log("Circle is drawn"); } FileName :Triangle.ts ---------- /// <reference path = "IShape.ts" /> namespace Drawing { export class Triangle implements IShape { public draw() { console.log("Triangle is drawn"); } } FileName : TestShape.ts /// <reference path = "IShape.ts" /> /// <reference path = "Circle.ts" /> /// <reference path = "Triangle.ts" /> function drawAllShapes(shape:Drawing.IShape) { shape.draw(); } drawAllShapes(new Drawing.Circle()); drawAllShapes(new Drawing.Triangle()); } } }
可以使用以下命令编译和执行上述代码:
tsc --out app.js TestShape.ts node app.js
编译后,它将生成以下JavaScript代码(app.js)。
//Generated by typescript 1.8.10 /// <reference path = "IShape.ts" /> var Drawing; (function (Drawing) { var Circle = (function () { function Circle() { } Circle.prototype.draw = function () { console.log("Cirlce is drawn"); }; return Circle; }()); Drawing.Circle = Circle; })(Drawing || (Drawing = {})); /// <reference path = "IShape.ts" /> var Drawing; (function (Drawing) { var Triangle = (function () { function Triangle() { } Triangle.prototype.draw = function () { console.log("Triangle is drawn"); }; return Triangle; }()); Drawing.Triangle = Triangle; })(Drawing || (Drawing = {})); /// <reference path = "IShape.ts" /> /// <reference path = "Circle.ts" /> /// <reference path = "Triangle.ts" /> function drawAllShapes(shape) { shape.draw(); } drawAllShapes(new Drawing.Circle()); drawAllShapes(new Drawing.Triangle());
编译并执行上述代码后,将产生以下结果:
Circle is drawn Triangle is drawn
嵌套命名空间
你可以像这样在一个命名空间内定义另一个命名空间:
namespace namespace_name1 { export namespace namespace_name2 { export class class_name { } } }
你可以使用点(.)运算符访问嵌套命名空间的成员,如下所示:
FileName : Invoice.ts namespace tutorialPoint { export namespace invoiceApp { export class Invoice { public calculateDiscount(price: number) { return price * .40; } } } } FileName: InvoiceTest.ts /// <reference path = "Invoice.ts" /> var invoice = new tutorialPoint.invoiceApp.Invoice(); console.log(invoice.calculateDiscount(500));
可以使用以下命令编译和执行上述代码:
tsc --out app.js InvoiceTest.ts node app.js
编译后,它将生成以下JavaScript代码(app.js)。
//Generated by typescript 1.8.10 var tutorialPoint; (function (tutorialPoint) { var invoiceApp; (function (invoiceApp) { var Invoice = (function () { function Invoice() { } Invoice.prototype.calculateDiscount = function (price) { return price * .40; }; return Invoice; }()); invoiceApp.Invoice = Invoice; })(invoiceApp = tutorialPoint.invoiceApp || (tutorialPoint.invoiceApp = {})); })(tutorialPoint || (tutorialPoint = {})); /// <reference path = "Invoice.ts" /> var invoice = new tutorialPoint.invoiceApp.Invoice(); console.log(invoice.calculateDiscount(500));
编译并执行上述代码后,将产生以下结果:
200
TypeScript - 模块
模块的设计理念是组织用TypeScript编写的代码。模块大致分为:
- 内部模块
- 外部模块
内部模块
内部模块出现在早期版本的TypeScript中。它用于将类、接口、函数逻辑地分组到一个单元中,并可以在另一个模块中导出。这种逻辑分组在最新版本的TypeScript中被称为命名空间。因此,内部模块已过时,我们可以使用命名空间代替。内部模块仍然受支持,但建议使用命名空间而不是内部模块。
内部模块语法(旧)
module TutorialPoint { export function add(x, y) { console.log(x+y); } }
命名空间语法(新)
namespace TutorialPoint { export function add(x, y) { console.log(x + y);} }
两种情况下生成的JavaScript相同
var TutorialPoint; (function (TutorialPoint) { function add(x, y) { console.log(x + y); } TutorialPoint.add = add; })(TutorialPoint || (TutorialPoint = {}));
外部模块
TypeScript中的外部模块用于指定和加载多个外部js文件之间的依赖关系。如果只使用一个js文件,则外部模块不相关。传统上,JavaScript文件之间的依赖关系管理是使用浏览器脚本标签(<script></script>)完成的。但这不可扩展,因为它在加载模块时非常线性。这意味着没有异步选项来加载模块,而不是一个接一个地加载文件。例如,当你为服务器(例如NodeJs)编写js程序时,你甚至没有脚本标签。
从单个主JavaScript文件加载依赖js文件有两种场景。
- 客户端 - RequireJs
- 服务器端 - NodeJs
选择模块加载器
为了支持加载外部JavaScript文件,我们需要一个模块加载器。这将是另一个js库。对于浏览器,最常用的库是RequieJS。这是AMD(异步模块定义)规范的实现。AMD可以分别加载所有文件,即使它们相互依赖,而不是一个接一个地加载文件。
定义外部模块
在针对CommonJS或AMD的TypeScript中定义外部模块时,每个文件都被视为一个模块。因此,在外部模块中使用内部模块是可选的。
如果你正在将TypeScript从AMD迁移到CommonJs模块系统,则不需要额外的工作。唯一需要更改的是编译器标志。与JavaScript不同,从CommonJs迁移到AMD或反之亦然存在开销。
声明外部模块的语法是使用关键字“export”和“import”。
语法
//FileName : SomeInterface.ts export interface SomeInterface { //code declarations }
要在另一个文件中使用已声明的模块,请使用如下所示的import关键字。仅指定文件名,不使用扩展名。
import someInterfaceRef = require(“./SomeInterface”);
示例
让我们用一个例子来理解这一点。
// 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)"); } } // Triangle.ts import shape = require("./IShape"); export class Triangle implements shape.IShape { public draw() { console.log("Triangle is drawn (external module)"); } } // TestShape.ts import shape = require("./IShape"); import circle = require("./Circle"); import triangle = require("./Triangle"); function drawAllShapes(shapeToDraw: shape.IShape) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle());
为AMD系统编译主TypeScript文件的命令是:
tsc --module amd TestShape.ts
编译后,它将为AMD生成以下JavaScript代码。
文件:IShape.js
//Generated by typescript 1.8.10 define(["require", "exports"], function (require, exports) { });
文件:Circle.js
//Generated by typescript 1.8.10 define(["require", "exports"], function (require, exports) { var Circle = (function () { function Circle() { } Circle.prototype.draw = function () { console.log("Cirlce is drawn (external module)"); }; return Circle; })(); exports.Circle = Circle; });
文件:Triangle.js
//Generated by typescript 1.8.10 define(["require", "exports"], function (require, exports) { var Triangle = (function () { function Triangle() { } Triangle.prototype.draw = function () { console.log("Triangle is drawn (external module)"); }; return Triangle; })(); exports.Triangle = Triangle; });
文件:TestShape.js
//Generated by typescript 1.8.10 define(["require", "exports", "./Circle", "./Triangle"], function (require, exports, circle, triangle) { function drawAllShapes(shapeToDraw) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle()); });
为Commonjs系统编译主TypeScript文件的命令是
tsc --module commonjs TestShape.ts
编译后,它将为Commonjs生成以下JavaScript代码。
文件:Circle.js
//Generated by typescript 1.8.10 var Circle = (function () { function Circle() { } Circle.prototype.draw = function () { console.log("Cirlce is drawn"); }; return Circle; })(); exports.Circle = Circle;
文件:Triangle.js
//Generated by typescript 1.8.10 var Triangle = (function () { function Triangle() { } Triangle.prototype.draw = function () { console.log("Triangle is drawn (external module)"); }; return Triangle; })(); exports.Triangle = Triangle;
文件:TestShape.js
//Generated by typescript 1.8.10 var circle = require("./Circle"); var triangle = require("./Triangle"); function drawAllShapes(shapeToDraw) { shapeToDraw.draw(); } drawAllShapes(new circle.Circle()); drawAllShapes(new triangle.Triangle());
输出
Cirlce is drawn (external module) Triangle is drawn (external module)
TypeScript - 环境声明
环境声明是一种告诉TypeScript编译器实际源代码存在于其他位置的方法。当你使用一堆第三方js库(如jquery/angularjs/nodejs)时,你无法用TypeScript重写它。在使用这些库时确保类型安全和智能感知对于TypeScript程序员来说将是一个挑战。环境声明有助于将其他js库无缝集成到TypeScript中。
定义环境
按照约定,环境声明保存在扩展名为(d.ts)的类型声明文件中。
Sample.d.ts
上述文件不会被编译成JavaScript。它将用于类型安全和智能感知。
声明环境变量或模块的语法如下:
语法
declare module Module_Name { }
环境文件应在客户端TypeScript文件中引用,如下所示:
/// <reference path = " Sample.d.ts" />
示例
让我们通过一个例子来理解这一点。假设你得到一个类似于此代码的第三方JavaScript库。
FileName: CalcThirdPartyJsLib.js var TutorialPoint; (function (TutorialPoint) { var Calc = (function () { function Calc() { } Calc.prototype.doSum = function (limit) { var sum = 0; for (var i = 0; i <= limit; i++) { Calc.prototype.doSum = function (limit) { var sum = 0; for (var i = 0; i <= limit; i++) { sum = sum + i; return sum; return Calc; TutorialPoint.Calc = Calc; })(TutorialPoint || (TutorialPoint = {})); var test = new TutorialPoint.Calc(); } } } } }
作为TypeScript程序员,你将没有时间将此库重写为TypeScript。但你仍然需要使用doSum()方法并保证类型安全。你可以做的是环境声明文件。让我们创建一个环境声明文件Calc.d.ts
FileName: Calc.d.ts declare module TutorialPoint { export class Calc { doSum(limit:number) : number; } }
环境文件不包含实现,它只是类型声明。现在需要在TypeScript文件中包含声明,如下所示。
FileName : CalcTest.ts /// <reference path = "Calc.d.ts" /> var obj = new TutorialPoint.Calc(); obj.doSum("Hello"); // compiler error console.log(obj.doSum(10));
以下代码行将显示编译器错误。这是因为在声明文件中,我们指定了输入参数将是数字。
obj.doSum("Hello");
注释掉上面的行并使用以下语法编译程序:
tsc CalcTest.ts
编译后,它将生成以下JavaScript代码(CalcTest.js)。
//Generated by typescript 1.8.10 /// <reference path = "Calc.d.ts" /> var obj = new TutorialPoint.Calc(); // obj.doSum("Hello"); console.log(obj.doSum(10));
为了执行代码,让我们添加一个带有脚本标签的html页面,如下所示。添加编译后的CalcTest.js文件和第三方库文件CalcThirdPartyJsLib.js。
<html> <body style = "font-size:30px;"> <h1>Ambient Test</h1> <h2>Calc Test</h2> </body> <script src = "CalcThirdPartyJsLib.js"></script> <script src = "CalcTest.js"></script> </html>
它将显示以下页面:
在控制台中,你可以看到以下输出:
55
同样,您可以根据需要将 jquery.d.ts 或 angular.d.ts 集成到项目中。