搜索
首页web前端js教程JS中强烈打字的语言借用技术

Borrowing Techniques from Strongly Typed Languages in JS

本文探讨如何在 JavaScript 代码中运用强类型语言的技巧。这些技巧不仅能减少代码错误,还能缩减代码量。虽然本文以 JavaScript 为例,但这些技巧也适用于大多数弱类型语言。

关键要点:

  • 在 JavaScript 中应用强类型语言的技巧可以减少 bug 并缩减代码量。
  • “一致类型规则”(规定所有值只有一种类型)可以应用于 JavaScript 以提高代码质量和可读性。
  • 应在模块边缘执行类型检查和类型转换,以防止隐式类型强制转换导致的 bug 并简化代码。
  • 应仔细考虑在 JavaScript 中使用“null”和“undefined”,尤其是在处理对象和数组等引用类型时。
  • TypeScript 是一个推荐用于在 JavaScript 中强制执行更强类型语义的工具,它具有早期错误检测和更清晰的代码文档等优点。

JavaScript 类型系统

首先快速回顾一下 JavaScript 数据类型系统的工作原理。JavaScript 将其值分为两类:

  • 原始类型,例如 String、Number 和 Boolean。将原始类型赋值给变量时,始终会创建一个新值,它是所赋值值的副本。
  • 引用类型,例如 Object 和 Array。赋值引用类型始终复制相同的引用。为了阐明这一点,让我们来看下面的代码示例:
var a = [];
var b = a;

a.push('Hello');

当我们更改 a 时,变量 b 也会发生变化,因为它们都引用同一个数组。所有引用类型的工作方式都是如此。JavaScript 不会强制执行任何类型,这意味着任何变量都可以在任何时候保存任何数据类型。本文其余部分将讨论此方法的缺点,以及如何应用强制执行类型的语言中的简单技巧来编写更好的 JavaScript 代码。

引入一致类型规则

一致类型规则在理论上很简单:所有值都应该只有一种类型。强类型语言在编译器级别强制执行此规则,它们不允许您随意混合和匹配类型。弱类型赋予我们很大的自由度。一个常见的例子是将数字连接到字符串中。您不需要执行像在 C 等语言中那样繁琐的类型转换。别担心,我不会告诉您放弃所有便利。一致类型规则只需要您注意变量和函数的行为方式,这样您的代码就会得到改进。

变量中的类型

首先,让我们看看该规则如何应用于变量。它非常简单:您的变量应该始终只有一种类型。

var a = [];
var b = a;

a.push('Hello');

上面的示例显示了问题所在。此规则要求我们假装此示例中的最后一行代码会抛出错误,因为当我们第一次定义变量 text 时,我们赋予它字符串类型的 value,现在我们正在为其赋值一个数字。一致类型规则意味着我们不允许这样更改变量的类型。当您的变量一致时,更容易推断您的代码。它尤其有助于更长的函数,在这些函数中,很容易忽略变量的来源。当在不遵守此规则的代码库中工作时,我意外地导致了许多错误,因为我看到声明了一个变量,然后假设它会保持相同的类型——因为让我们面对现实,这有意义,不是吗?通常没有理由将不同的类型分配给同一个变量。

函数参数中的类型

相同的规则也适用于此。函数的参数也应该保持一致。一个错误的例子:

var text = 'Hello types';

// 错误!不要这样做!
text = 1;

这里有什么问题?通常认为,根据类型检查来分支逻辑是不好的做法。对此有一些例外,但通常更好的选择是使用多态性。您应该努力确保函数参数也只有一种类型。如果您忘记考虑不同的类型,它会减少出现问题的可能性,并使代码更简单,因为您不必编写代码来处理所有不同类型的案例。编写 sum 函数的更好方法如下:

function sum(a, b) {
  if (typeof a === 'string') {
    a = 1;
  }

  return a + b;
}

然后,您在调用代码中而不是在函数中处理类型检查。从上面可以看出,该函数现在简单多了。即使我们必须将类型检查移动到其他地方,我们越早在代码中执行它们,效果就越好。我们将在本文后面讨论类型检查和 typeof 的使用,包括如果使用不当,类型检查如何轻松级联。

函数返回值中的类型

这与其他两个相关:您的函数应该始终返回相同类型的 value。我们可以在这里举 AngularJS 的一个例子。AngularJS 提供了一个将文本转换为小写的函数,称为 angular.lowercase。还有一个标准函数,String.prototype.toLowerCase。我们可以比较它们的行为来更好地理解规则的这一部分:

function sum(a, b) {
  return a + b;
}

变量 a 将包含您期望的内容:“hello types”。但是,b 将包含什么?它将是一个空字符串吗?函数会抛出异常吗?或者它可能只是 null?在这种情况下,b 的 value 为 null。请注意,立即很难猜测结果是什么——我们一开始就有三种可能的结果。对于 Angular 函数,对于非字符串值,它将始终返回输入。现在,让我们看看内置函数的行为:

var a = [];
var b = a;

a.push('Hello');

第一次调用的结果相同,但第二次调用会抛出异常。内置函数遵循一致类型规则,并且不允许不正确的参数类型。返回值也始终是一个字符串。所以我们可以说内置函数更好,但您可能想知道究竟是如何做到这一点的?让我们考虑一下此类函数的典型用例。我们在代码中的某个点使用它来将字符串转换为小写。正如 JavaScript 代码中经常发生的那样,我们不能 100% 确定我们的输入是否总是字符串。没关系,因为我们是优秀的程序员,我们假设我们的代码没有任何错误。如果我们使用不遵守这些规则的 AngularJS 函数会发生什么?非字符串值会毫无问题地通过它。它可能会通过几个函数,我们甚至可能会通过 XMLHttpRequest 调用发送它。现在错误的值在我们的服务器中,并最终进入数据库。您可以看到我的意思,对吧?如果我们使用遵守规则的内置函数,我们会在那时立即发现该错误。每当您编写函数时,请确保其返回的类型一致。下面显示了一个不好的例子:

var text = 'Hello types';

// 错误!不要这样做!
text = 1;

同样,与变量和参数一样,如果我们有这样的函数,我们就无法对它的行为做出假设。我们将需要使用 if 来检查返回 value 的类型。我们可能会在某个时候忘记它,然后我们手中就会出现另一个错误。我们可以通过多种方式重写它,以下是一种解决此问题的方法:

function sum(a, b) {
  if (typeof a === 'string') {
    a = 1;
  }

  return a + b;
}

这次我们确保所有路径都返回一个字符串。现在更容易推断函数的结果了。

null 和 undefined 是特殊的

到目前为止,我们实际上只讨论了原始类型。当涉及到对象和数组时,您应该遵循相同的规则,但需要注意两个特殊情况。处理引用类型时,有时需要指示没有 value。一个很好的例子是 document.getElementById。如果找不到匹配的元素,它将返回 null。这就是为什么我们将 null 视为与任何对象或数组共享类型的原因,但仅限于那些对象或数组。您应该避免从可能返回 Number 等原始值的函数中返回 null。undefined 也可以被认为是引用的“无值”。出于大多数目的,它可以被视为等于 null,但由于其在其他面向对象语言中的语义,null 更为可取。

数组和 null

使用数组时,您还应该考虑空数组通常比 null 更好。尽管数组是引用类型,您可以使用 null 与它们一起使用,但通常返回空数组更有意义。让我们来看下面的例子:

var a = [];
var b = a;

a.push('Hello');

这可能是数组最常见的用法之一。您从函数中获取一个数组,然后对其进行迭代以执行其他操作。如果 getListOfItems 在没有项目时返回 null,上面的代码会发生什么?它会抛出错误,因为 null 没有长度(或任何其他属性)。当您考虑像这样使用数组,甚至是 list.forEach 或 list.map 时,您可以看到当没有值时返回空数组通常是一个好主意。

类型检查和类型转换

让我们更详细地了解类型检查和类型转换。您应该何时进行类型检查?您应该何时进行类型转换?

类型转换

类型转换的第一个目标应该是确保您的值的类型正确。数值应该是数字而不是字符串,依此类推。第二个目标应该是您只需要转换一次 value。进行类型转换的最佳位置是在源处。例如,如果您从服务器获取数据,则应该在处理接收到的数据的函数中进行任何必要的类型转换。从 DOM 解析数据是一个非常常见的错误开始出现的地方。假设您有一个包含数字的文本框,并且您想读取它。或者,它可能只是某个 HTML 元素中的属性,它甚至不必是用户输入。

var text = 'Hello types';

// 错误!不要这样做!
text = 1;

由于您可以从 DOM 获取的值通常是字符串,因此在读取它们时进行类型转换非常重要。在某种程度上,您可以将其视为模块的“边缘”。数据通过读取它的函数进入您的 JavaScript 模块,因此它必须将数据转换为正确的格式。通过在模块边缘进行类型转换,我们确保内部不必处理它。这在很大程度上减少了隐式类型强制转换导致错误的可能性。它还允许我们编写更少的代码,因为我们不允许错误的值从边缘进入模块。

function sum(a, b) {
  if (typeof a === 'string') {
    a = 1;
  }

  return a + b;
}

typeof 和类型检查

您应该只将 typeof 用于验证,而不是根据类型分支逻辑。对此有一些例外,但这是一个很好的经验法则。让我们来看两个例子:

function sum(a, b) {
  return a + b;
}

这是一个使用 typeof 进行验证的示例。我们确保传递给函数的参数是正确的类型。但是,下面的示例显示了根据类型分支逻辑的含义。

var a = [];
var b = a;

a.push('Hello');

不要这样做。虽然有时可能需要这样做,但这通常是设计不良的标志。如果您发现自己经常执行这种逻辑,那么您可能应该在代码的早期将 value 转换为正确的类型。如果您最终在代码中使用了大量 typeof,这可能表示您可能需要转换要比较的值。类型检查通常会扩散,这通常是关于类型的设计不良的标志。如前所述,您应该尝试在模块边缘进行类型转换,因为它允许您避免 typeof 级联。如果您尽早进行转换,则之后调用的任何函数都不必进行类型检查或类型转换。这也适用于对象:如果您发现自己使用 instanceof 进行大量检查或检查对象上是否存在属性,则表示您可能应该以不同的方式构造数据。与 typeof 相同的规则也适用于 instanceof:您应该尝试避免它,因为它可能是设计不良的标志。但是,有一种情况是不可避免的:

var text = 'Hello types';

// 错误!不要这样做!
text = 1;

如果您的代码需要对异常类型进行特定处理,instanceof 通常是一个不错的选择,因为 JavaScript catch 不允许像其他一些语言那样按类型区分。在大多数其他情况下,您应该尝试避免 instanceof。

结论

正如我们所发现的,JavaScript 的弱类型为我们带来了极大的自由,但我们也必须谨慎行事。否则,我们将最终陷入一个类型混乱的局面,没有任何意义。通过确保我们的代码遵循一致类型规则,我们可以避免很多麻烦。当我们知道类型时,更容易推断我们的代码。我们不必在代码中构建许多类型检查来防止错误。如果您没有使用强类型语言,这似乎很困难,但在您需要调试或维护代码时,它会得到很大的回报。有关该主题的更多信息,我建议您查看 TypeScript。它是一种类似于 JavaScript 的语言,但它为该语言添加了更强的类型语义。它还有一个编译器,当您尝试执行一些愚蠢的操作(例如混合和匹配类型)时,它会吐出错误。

关于 JavaScript 中强类型语言的常见问题解答 (FAQ)

强类型语言和弱类型语言有什么区别?

强类型语言是指变量绑定到特定数据类型的语言,任何与该类型不一致的操作都会导致错误。示例包括 Java 和 C 。另一方面,像 JavaScript 这样的弱类型语言允许变量保存任何类型的数据,并且在必要时会自动进行类型转换。如果处理不当,这种灵活性可能会导致意想不到的结果。

如何在 JavaScript 中强制执行强类型?

JavaScript 本身是一种弱类型语言,但您可以使用 TypeScript(JavaScript 的静态类型超集)来强制执行强类型。TypeScript 为 JavaScript 添加了静态类型,允许在编译时进行类型检查。这有助于在开发过程的早期发现错误。“严格模式”是 JavaScript 中的另一个方法,它通过为不安全的动作抛出错误来使语言的行为更像强类型语言。

使用强类型语言的好处是什么?

强类型语言提供了一些好处。它们可以帮助在编译时而不是运行时捕获错误,这可以节省大量调试时间。它们还使代码更具自文档性,因为变量的数据类型清楚地表明了它们的使用方式。此外,它们可以使代码更可预测且更容易推断,因为它们可以防止意外的类型转换。

我可以将 JavaScript 用作强类型语言吗?

虽然 JavaScript 默认情况下不是强类型语言,但您可以使用 TypeScript 或 Flow 等工具来强制执行强类型。这些工具为 JavaScript 添加了静态类型,允许在编译时进行类型检查。这有助于在开发过程的早期发现错误。但是,需要注意的是,这些工具不会改变 JavaScript 的底层性质;它们只是在它之上提供了一层类型安全性。

什么是 TypeScript,它与 JavaScript 的关系如何?

TypeScript 是由 Microsoft 开发的 JavaScript 静态类型超集。它为 JavaScript 添加了静态类型,允许在编译时进行类型检查。这有助于在开发过程的早期发现错误。TypeScript 代码被转换为 JavaScript,这意味着它可以在任何 JavaScript 运行的地方运行。它与 JavaScript 完全兼容,可以使用 JavaScript 的所有功能。

使用强类型语言的缺点是什么?

虽然强类型语言提供了许多好处,但它们也有一些缺点。它们可能更冗长,需要更多代码才能完成与弱类型语言相同的任务。它们还需要一个编译步骤,这可能会减慢开发过程。此外,它们可能不太灵活,并且对于某些任务(例如处理动态数据)更难使用。

JavaScript 中的“严格模式”是如何工作的?

“严格模式”是 JavaScript 中的一项功能,它使语言的行为更像强类型语言。它会为不安全的动作抛出错误,例如为只读属性赋值或在声明之前使用变量。这有助于在开发过程的早期发现错误。要启用“严格模式”,只需在 JavaScript 文件或函数的顶部添加“use strict;”一行即可。

什么是 JavaScript 中的类型强制?

类型强制是 JavaScript 中的一项功能,其中语言在必要时会自动将一种数据类型转换为另一种数据类型。例如,如果您尝试添加数字和字符串,JavaScript 将在执行加法之前将数字转换为字符串。虽然这很方便,但如果处理不当,它也可能导致意想不到的结果。

如何避免 JavaScript 中的类型强制?

避免 JavaScript 中类型强制的一种方法是使用“严格模式”,它会为不安全的动作抛出错误。另一种方法是使用“===”运算符而不是“==”运算符进行比较,因为前者不执行类型强制。此外,您可以使用 TypeScript 或 Flow 等工具为 JavaScript 添加静态类型,这有助于在编译时捕获与类型相关的错误。

强类型语言在 JavaScript 中的未来如何?

强类型语言在 JavaScript 中的使用可能会在未来增加,因为它们提供了许多好处,例如尽早捕获错误并使代码更可预测。TypeScript 和 Flow 等工具越来越流行,并且正在开发新的工具和功能以使 JavaScript 更具类型安全性。但是,JavaScript 的灵活性和动态性将使其继续成为许多开发人员的首选。

以上是JS中强烈打字的语言借用技术的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Python vs. JavaScript:您应该学到哪种语言?Python vs. JavaScript:您应该学到哪种语言?May 03, 2025 am 12:10 AM

选择Python还是JavaScript应基于职业发展、学习曲线和生态系统:1)职业发展:Python适合数据科学和后端开发,JavaScript适合前端和全栈开发。2)学习曲线:Python语法简洁,适合初学者;JavaScript语法灵活。3)生态系统:Python有丰富的科学计算库,JavaScript有强大的前端框架。

JavaScript框架:为现代网络开发提供动力JavaScript框架:为现代网络开发提供动力May 02, 2025 am 12:04 AM

JavaScript框架的强大之处在于简化开发、提升用户体验和应用性能。选择框架时应考虑:1.项目规模和复杂度,2.团队经验,3.生态系统和社区支持。

JavaScript,C和浏览器之间的关系JavaScript,C和浏览器之间的关系May 01, 2025 am 12:06 AM

引言我知道你可能会觉得奇怪,JavaScript、C 和浏览器之间到底有什么关系?它们之间看似毫无关联,但实际上,它们在现代网络开发中扮演着非常重要的角色。今天我们就来深入探讨一下这三者之间的紧密联系。通过这篇文章,你将了解到JavaScript如何在浏览器中运行,C 在浏览器引擎中的作用,以及它们如何共同推动网页的渲染和交互。JavaScript与浏览器的关系我们都知道,JavaScript是前端开发的核心语言,它直接在浏览器中运行,让网页变得生动有趣。你是否曾经想过,为什么JavaScr

node.js流带打字稿node.js流带打字稿Apr 30, 2025 am 08:22 AM

Node.js擅长于高效I/O,这在很大程度上要归功于流。 流媒体汇总处理数据,避免内存过载 - 大型文件,网络任务和实时应用程序的理想。将流与打字稿的类型安全结合起来创建POWE

Python vs. JavaScript:性能和效率注意事项Python vs. JavaScript:性能和效率注意事项Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差异主要体现在:1)Python作为解释型语言,运行速度较慢,但开发效率高,适合快速原型开发;2)JavaScript在浏览器中受限于单线程,但在Node.js中可利用多线程和异步I/O提升性能,两者在实际项目中各有优势。

JavaScript的起源:探索其实施语言JavaScript的起源:探索其实施语言Apr 29, 2025 am 12:51 AM

JavaScript起源于1995年,由布兰登·艾克创造,实现语言为C语言。1.C语言为JavaScript提供了高性能和系统级编程能力。2.JavaScript的内存管理和性能优化依赖于C语言。3.C语言的跨平台特性帮助JavaScript在不同操作系统上高效运行。

幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具