JavaScript 是什么?
由于 TypeScript 扩展了 JavaScript,因此从 JavaScript 讲起是个不错的起点。JavaScript 常用于创建网站。构建网站时你会用到三种语言:HTML、CSS 和 JavaScript(JS)。大致来说:HTML 定义页面上呈现的内容,CSS 定义页面的视觉样式,而 JS 定义页面的交互行为。
我们把这些技能的组合称为“前端”开发者。你用三种语言在 Safari、Firefox、Edge 或 Chrome 等浏览器中创建页面。鉴于 Web 在商业与信息共享方面如此普及,市场对擅长这三种语言的人才有着巨大的需求。
与“前端”开发者角色相对应的是“后端”开发者的技能组合,即创建与浏览器通信(向其传递 HTML/CSS/JS)或与其他服务通信(更直接地发送数据)的计算机服务。编写这类代码并不一定需要 HTML、CSS 或 JS,但你的工作成果通常最终会以这些技术呈现,因为它很可能要在浏览器中展示。
编程语言是做什么的?
编程语言是人类与计算机沟通的一种方式。人们阅读代码的次数远多于编写代码的次数——因此开发者创造出的编程语言,要能用少量代码很好地解决特定问题。下面是一个 JavaScript 示例:
var name = "Danger"
console.log("Hello, " + name)第一行创建了一个变量(可以把它理解为一个存放其他内容的盒子),第二行把文本 "Hello, Danger" 输出到控制台(例如 DOS 或终端)。
JavaScript 被设计为脚本语言,也就是说代码从文件顶部开始,逐行向下执行。作为对比,下面是同样行为在 Java 中的写法,Java 有着不同的语言约束:
class Main {
public static void main(String[] args) {
String name = "Danger";
System.out.println("Hello, " + name);
}
}这两段代码做的是同一件事,但 Java 版本包含许多并非用于直接告诉计算机做什么的词,例如 class Main {、public static void main(String[] args) {,以及多出来的两个 }。有些行末尾还有分号。这两种编程语言本身没有对错之分,只是 Java 面向的是与 JavaScript 不同的构建目标,这些额外的代码在构建 Java 应用的约束下是合理的。
不过,为了切中要点,我想请大家对比其中一行特别的语句:
// JavaScript
var name = "Danger"
// Java
String name = "Danger";这两行都声明了一个名为 name 的变量,其值为 "Danger"。
JavaScript 中用缩写 var 声明变量。而在 Java 中,你需要说明变量包含哪种数据。本例中变量包含一个 String。(字符串是编程术语,指一组字符。它们 "look like this"。如果你想了解更多,这个 5 分钟视频是不错的入门。)
这两个变量都包含字符串,区别在于 Java 中的变量只能包含字符串,因为我们在创建变量时就是这么声明的。而在 JS 中,变量可以变成任何内容,比如数字或日期列表。
举例说明:
// Before in JS
var name = "Danger"
// Also OK
var name = 1
var name = false
var name = ["2018-02-03", "2019-01-12"]
// Before in Java
String name = "Danger";
// Not OK, the code wouldn't be accepted by Java
String name = 1;
String name = false
String name = new String[]{"2018-02-03", "2019-01-12"};这些取舍在 1995 年这两门语言被创造时的语境下是合理的。JavaScript 最初被设计为一门小而精的编程语言,用于处理网站上的简单交互。而 Java 则是专门为构建能在任何计算机上运行的复杂应用而打造的。它们预期会被用于不同规模的代码库,因此语言要求程序员编写不同类型的代码。
Java 要求程序员更明确地写出变量的值,因为他们预期人们构建的程序更为复杂。而 JavaScript 更注重易读性,省略了具体细节信息,并预期代码库会小得多。
TypeScript 是什么?
TypeScript 是一门编程语言——它包含 JavaScript 的全部内容,并在此基础上有所扩展。沿用上面的例子,我们来对比“Hello, Danger”在 JavaScript 与 TypeScript 中的写法:
// JavaScript
var name = "Danger"
console.log("Hello, " + name)
// TypeScript
var name = "Danger"
console.log("Hello, " + name)
// Yep, you're not missing something, there's no difference由于 TypeScript 的目标只是扩展 JavaScript,我们前面看到的 JavaScript 代码本身就能作为 TypeScript 工作。TypeScript 为 JavaScript 添加的扩展,旨在帮助你更明确地说明代码中使用了哪些类型的数据,有点像 Java。
下面是同一个示例,只不过用 TypeScript 更明确地说明了变量的类型:
var name: string = "Danger"
console.log("Hello, " + name)这个额外的 : string 让读者能够确定 name 只会是字符串。以这种方式标注变量也为 TypeScript 提供了核对这些类型是否匹配的机会。这非常有用,因为当变量只有一两个时,跟踪值类型的变化似乎很容易,但一旦数量达到数百个,跟踪起来就是很大的负担。编写类型能帮助程序员对自己的代码更有信心,因为类型能够捕获错误。
简单来说,我们把这些标注称为“类型”。TypeScript 的名字也由此而来。TypeScript 的标语之一是“可伸缩的 JavaScript”,意思是这些额外的类型标注让你能够处理更大的项目。因为你可以提前验证代码的正确性,也就无需理解每一处改动会如何影响程序的其余部分。
在 90 年代,甚至可能直到 5 到 10 年前,JavaScript 应用不引入类型所付出的代价都还算可以接受,因为当时所构建程序的规模和复杂度仅限于网站的前端。而如今,JavaScript 几乎无处不在,被用来构建几乎所有在计算机上运行的东西。大量移动端和桌面应用在底层都使用 JavaScript 与 Web 技术。
这些应用的构建与理解都复杂得多,而添加类型能大幅降低改进这些程序的复杂度。
TypeScript 能解决哪些问题?
通常,确保代码中没有 bug 的需求可以通过编写自动化测试来应对,然后手动验证代码是否按预期工作,最后再让另一个人确认它看起来是否正确。
然而,没有多少公司有 Microsoft 那样的规模,但编写大型代码库中的 JavaScript 所面临的许多问题都是相同的。许多 JavaScript 应用由数十万个文件构成。对单个文件的一处改动可能影响任意数量的其他文件,就像往池塘里扔一颗石子,涟漪会扩散到岸边。
验证项目各个部分之间的连接很快就会变得耗时,而使用像 TypeScript 这样带类型检查的语言可以自动完成这件事,并在开发过程中即时给出反馈。
这些特性使 TypeScript 能帮助开发者对自己的代码更有信心,并节省大量验证自己是否不小心破坏了项目的时间。