静态类型在 JavaScript 中是一种负担吗?

简介: 我年轻的时候曾经是一位动态类型的忠实拥趸,因为动态类型方便、自由。假设在我需要编写一段为我服务的小程序时,如果 runtime 强制需要我去做一些向上向下转型的工作,恐怕我会崩溃。

image.png

原文作者:UC 国际研发 Randy

最近我在公司的项目中遇到很多由于类型不匹配所导致的不可预估的问题。比如说,我们的程序产生了一个纯数字的 unique id, 存到数据库中被识别为 number 类型,但是客户端需要的是字符串,导致一条数据在没有办法在客户端正常显示。

我年轻的时候曾经是一位动态类型的忠实拥趸,因为动态类型方便、自由。假设在我需要编写一段为我服务的小程序时,如果 runtime 强制需要我去做一些向上向下转型的工作,恐怕我会崩溃。

但是,在享受自由的同时,我们却很容易写出这样的程序:

image.png

image.png

这是一个用于生成签名字符串的函数,从逻辑上看,这段代码没有问题。但是,当另一个对这个函数内部实现不了解的开发人员使用它时,会返回意想不到的结果:
image.png

使用者希望把 timestamp 用作 salt,但是 signStr 并不是意料中的由 timestamp 和 appId 拼接而成的 signString, 而是 appId 和 timestamp 相加的运算结果。而这种错误是在编译时无法感知的。

然而,如果我们用静态类型的 TypeScript 做同样的事情:

image.png

在编译时,就会抛出类型错误的提示,这时就会知道,你的 salt 应该用一个 toString() 来转换成字符串。

类型检查是一种负担吗?

我认为不是。起码在构建大规模的应用程序时,静态类型会帮助你避免大多数的运行时错误。

而 code base 并不是衡量应用程序规模的唯一指标。只要符合以下某种情况,就认为这个程序是大规模的:

1.code base 很大

2.超过 2 人维护的程序

3.被多人依赖的模块

在以上这些情况下,类型声明变得尤为重要。你可能认为你能记住变量是什么类型,但在程序的世界里生存的不仅仅是字面量。

在团队共同维护代码的时候,如果没有类型声明,你绝对有可能传入一个非预期的参数。所以,类型声明是开发者与开发者之间的传达信息的过程——我要的是什么类型,你就只能给我什么类型。

类型声明也是开发者给编辑器传达信息的手段。只有显示的类型声明,编辑器和 IDE 才能判断函数中的形参应该有怎样的行为,才能给开发者正确的代码提示,才能安全地为你进行 Refact.

image.png

静态类型的 JavaScript

JavaScript 虽然是一门面向对象的语言,但相对于 C++, Java 这类语言来说,它的抽象能力很弱。在构建大规模的 JavaScript 应用程序时,我常常怀念写 Java (Android) 时可以写 interface, 可以写 abstract. 在编写 JavaScript 程序中,很难舒服地运用一些设计模式。

We designed TypeScript to meet the needs of the JavaScript programming teams that build and maintain large JavaScript programs.
—— TypeScript Language Specification

TypeScript 引入了 Interface, Enum, Generic, abstract class 等等,这些表达能力正是在构建大规模 JavaScript 程序时所缺失的。不是说没有 TypeScript, ECMAScript 就不能实现这些,而是 TypeScript 在代码层面赋予了这些约定。

比如,用 TypeScript 实现 Singleton:

image.png

理论上,被编译出来的 ECMAScript 代码照样可以顺利地 new Person(), 但 TypeScript 会在编译时提醒你,这个类不应该被实例化。

我不打算在本文对 TypeScript 作出详细的指南,我只希望大家可以认识到,严谨的类型检查和面向对象表达能力对代码的健壮性和可维护性有很大的正面作用。ECMAScript 是一门自由灵活的语言,但绝不代表我们就应该为这种灵活承担过高的出错概率。况且,TypeScript 在严格类型检查的同时,又保留了 ECMAScript 的自由性(你甚至可以用 any 类型来规避类型检查)。

我永远认为使用没有类型验证的 JavaScript 会让我快乐,无论她有多大的坑。我仍然可以用她愉快地写脚本抢这个抢那个,用她来写各种各样的 bot,无须考虑类型转换。但当我用她来写一些不是为了让我快乐的程序的时候,我希望她在运行时不要跑偏,还希望她长得像真正的 OOP 。

静态类型的 JavaScript 就像开始做手机后的罗永浩,你能看出他们的妥协,他们本不是这样。但他们是真正要上场合了,才不得不这样,即使他们根本不是你喜欢的样子。

目录
相关文章
|
9天前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
18 0
|
2月前
|
前端开发 JavaScript 搜索推荐
Next.js 适合什么类型的项目开发?
【8月更文挑战第4天】Next.js 适合什么类型的项目开发?
147 3
|
9天前
|
JavaScript 前端开发
JavaScript返回判断类型有哪些?
JavaScript返回判断类型有哪些?
19 0
|
2月前
|
缓存 JavaScript 前端开发
|
2月前
|
JavaScript 前端开发
在JavaScript如何确认数据的类型?
# `typeof` 与 `instanceof` 数据类型判断 `typeof` 操作符用于确定变量的基本数据类型,例如: - "string" - "number" - "boolean" - "undefined" 但对于引用类型如对象和数组,包括 `null`,它返回 "object"。 `instanceof` 用于检查对象是否为特定构造函数的实例,返回布尔值。它能准确识别数组等复杂类型,通过检查对象的原型链来确定其是否属于某个构造函数的实例。 两者结合使用可全面判断数据类型。
31 2
|
2月前
|
JavaScript 前端开发 UED
探秘 JavaScript 错误背后的真相——揭开异常类型的神秘面纱,让你的代码从此无懈可击!
【8月更文挑战第23天】本文深入探讨了JavaScript中常见的异常类型,包括`ReferenceError`(未定义的引用)、`TypeError`(类型错误)、`SyntaxError`(语法错误)、`RangeError`(范围错误)、`EvalError`(评估错误)以及`URIError`(URI错误),并通过示例展示了如何有效地诊断与处理这些异常。此外,还介绍了如何自定义错误类以适应特定场景的需求。掌握这些异常处理技巧对于构建稳定可靠的Web应用程序至关重要。
36 0
|
2月前
|
JavaScript 前端开发 安全
TypeScript:解锁JavaScript的超级英雄模式!类型系统如何化身守护神,拯救你的代码免于崩溃与混乱,戏剧性变革开发体验!
【8月更文挑战第22天】TypeScript作为JavaScript的超集,引入了强大的类型系统,提升了编程的安全性和效率。本文通过案例展示TypeScript如何增强JavaScript:1) 显式类型声明确保函数参数与返回值的准确性;2) 接口和类加强类型检查,保证对象结构符合预期;3) 泛型编程提高代码复用性和灵活性。这些特性共同推动了前端开发的标准化和规模化。
54 0
|
2月前
|
JavaScript 前端开发
javascript 异常问题之JavaScript中的异常有哪些类型,可以举例说明吗
javascript 异常问题之JavaScript中的异常有哪些类型,可以举例说明吗
|
3月前
|
JavaScript
JS字符串数据类型转换,字符串如何转成变量,+号只要有一个是字符串,就会把另外一个转成字符串,- * / 都会把数据转成数字类型,数字型控制台是蓝色,字符型控制台是黑色,
JS字符串数据类型转换,字符串如何转成变量,+号只要有一个是字符串,就会把另外一个转成字符串,- * / 都会把数据转成数字类型,数字型控制台是蓝色,字符型控制台是黑色,
|
3月前
|
JavaScript 前端开发 安全
JavaScript数据类型与类型判断
【7月更文挑战第1天】JavaScript基础涉及多种数据类型,如字符串、数字、布尔值、undefined、null、Symbol和BigInt(ES新特性)。对象、数组和函数属于引用类型。类型判断可通过typeof(不准确判断null和Array)、instanceof(检查原型链)和Object.prototype.toString方法。理解这些对编写健壮的代码至关重要。
35 0