目录
变量中的类型
函数参数中的类型
函数返回值中的类型
数组和 null
类型转换
typeof 和类型检查
强类型语言和弱类型语言有什么区别?
如何在 JavaScript 中强制执行强类型?
使用强类型语言的好处是什么?
我可以将 JavaScript 用作强类型语言吗?
什么是 TypeScript,它与 JavaScript 的关系如何?
使用强类型语言的缺点是什么?
JavaScript 中的“严格模式”是如何工作的?
什么是 JavaScript 中的类型强制?
如何避免 JavaScript 中的类型强制?
强类型语言在 JavaScript 中的未来如何?
首页 web前端 js教程 JS中强烈打字的语言借用技术

JS中强烈打字的语言借用技术

Feb 21, 2025 am 08:38 AM

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

热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

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

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

前端热敏纸小票打印遇到乱码问题怎么办? 前端热敏纸小票打印遇到乱码问题怎么办? Apr 04, 2025 pm 02:42 PM

前端热敏纸小票打印的常见问题与解决方案在前端开发中,小票打印是一个常见的需求。然而,很多开发者在实...

神秘的JavaScript:它的作用以及为什么重要 神秘的JavaScript:它的作用以及为什么重要 Apr 09, 2025 am 12:07 AM

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

如何实现视差滚动和元素动画效果,像资生堂官网那样?
或者:
怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? 如何实现视差滚动和元素动画效果,像资生堂官网那样? 或者: 怎样才能像资生堂官网一样,实现页面滚动伴随的动画效果? Apr 04, 2025 pm 05:36 PM

实现视差滚动和元素动画效果的探讨本文将探讨如何实现类似资生堂官网(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演变:当前的趋势和未来前景 JavaScript的演变:当前的趋势和未来前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript难以学习吗? JavaScript难以学习吗? Apr 03, 2025 am 12:20 AM

学习JavaScript不难,但有挑战。1)理解基础概念如变量、数据类型、函数等。2)掌握异步编程,通过事件循环实现。3)使用DOM操作和Promise处理异步请求。4)避免常见错误,使用调试技巧。5)优化性能,遵循最佳实践。

如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? 如何使用JavaScript将具有相同ID的数组元素合并到一个对象中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中将具有相同ID的数组元素合并到一个对象中?在处理数据时,我们常常会遇到需要将具有相同ID�...

Zustand异步操作:如何确保useStore获取的最新状态? Zustand异步操作:如何确保useStore获取的最新状态? Apr 04, 2025 pm 02:09 PM

zustand异步操作中的数据更新问题在使用zustand状态管理库时,经常会遇到异步操作导致数据更新不及时的问题。�...

See all articles