用 Implement.js 在 JavaScript 中实现接口

用 Implement.js 在 JavaScript 中实现接口

原文:https://medium.com/hackernoon/implementing-interfaces-in-javascript-with-implement-js-8746838f8caa

在这篇博文中,我将介绍接口的概念,以及它们在动态语言中是如何有用的。我还将使用 Implement.js 库将这个概念引入 JavaScript,并向您展示如何从接口中获得一些额外的实用工具。

什么是接口?

Google 将界面定义为“两个系统、主体、组织等的结合点。相遇和互动”,这个定义适用于编程中的接口。在软件开发中,接口是在对象上强制实施特定属性的结构——在大多数语言中,这个对象是一个类。

这里有一个 Java 接口的例子:

在上面的例子中,Car接口描述了一个类,它有两个没有返回类型的方法,这两个方法都采用一个整数参数。每个函数的实现细节由类决定,这就是为什么这两个方法都没有主体。为了确保一个类实现了Car接口,我们使用了implements关键字:

Simple

JavaScript 的接口

接口不是 JavaScript 中的东西,至少不是。JavaScript 是一种动态语言,类型变化如此频繁,以至于开发人员可能都没有意识到,因此人们认为没有必要在 JavaScript 所基于的 ECMAScript 标准中添加接口。

然而,JavaScript 作为后端语言以 Node.js 的形式大规模发展,随之而来的是不同的需求和可能有不同意见的不同人群。除此之外,这种语言正迅速成为前端工具;已经到了许多开发人员将在内部编写绝大部分 HTML 的地步。JSX 格式的 js 文件。

因此,随着语言承担更多的角色,确保我们最重要的数据结构之一是我们所期望的,这是很有帮助的。JavaScript 可能有class关键字,但实际上这只是一个未实例化的构造函数,一旦被调用,它只是一个对象。对象无处不在,因此有时确保它们与特定的形状相匹配是有益的。

最近在工作中,我发现一个案例,一个开发人员期望作为 API 响应的一部分返回的属性是true,但是却得到了"true",导致了一个 bug。这是一个容易犯的错误,如果我们有一个界面,这也是可以避免的。

但是等等,还有呢!

只要稍加修改,接口就可以用来改变物体的形状。想象一下,实现一个“严格的”接口,其中不允许接口之外的属性,我们可以删除或重命名这些属性,甚至在遇到它们时抛出一个错误。

所以现在我们有了一个接口,当我们缺少某些属性时,它会告诉我们,但当我们有意外的属性时,或者如果属性的类型不是我们所期望的,它也会告诉我们。这增加了其他可能性,例如重构来自 API 的响应,同时在接口的标准行为之上增加额外的安全层。如果我们让接口抛出错误,我们也可以在单元测试中使用接口。

实现. js

Implement.js 是一个试图给 JavaScript 带来接口的库。这个想法很简单:定义一个接口,定义它的属性类型,并使用它来确保一个对象是您所期望的。

设置

首先安装软件包:

npm install implement-js

接下来,创建一个. js 文件并导入implementInterfacetype:

我们的第一个界面

要创建一个接口,只需调用Interface并传入一个字符串作为接口的名称——不推荐这样做,但是如果省略名称,将会生成一个惟一的 ID。这将返回一个函数,该函数接受一个属性都是type对象的对象,还可以传递第二个参数,该参数带有显示警告、抛出错误、删除或重命名属性、确保仅接口的属性存在或者扩展现有的Interface的选项。

这是一个描述汽车的界面:

它有一个应该是 number 类型的seats属性,一个包含必须自己实现Passenger接口的对象的乘客数组,它还包含一个应该是函数的beep属性。errorstrict选项已经被设置为 true,这意味着当接口的属性丢失时,以及当发现接口上的属性而不是时,将会抛出错误。

实现我们的接口

现在我们想实现我们的接口,在一个简单的例子中,我们将使用对象文字创建一个对象,看看我们是否能够实现我们的接口。

首先,我们创建一个Ford对象,然后我们将尝试针对我们的Car接口实现它:

正如我们从上面的评论中看到的,这抛出了一个错误。让我们回头看看我们的Car界面:

我们可以看到,当所有属性都存在时,严格模式也成立,这意味着附加属性fuelType导致抛出错误。另外,尽管我们有一个passengers属性,但它不是一个数组。

为了正确实现接口,我们移除了fuelType并更改了passengers的值,这样它就是一个包含实现Passenger接口的对象的数组:

"但是 JavaScript 不是面向对象的语言!"

诚然,虽然接口通常与面向对象语言相关联,JavaScript 是一种使用原型继承的多范式语言,但接口仍然非常有用。

例如,使用implement-js我们可以轻松地重构 API 响应,同时确保它没有偏离我们的预期。这里有一个结合redux-thunk使用的例子:

首先,我们将扩展了User接口的TwitterUser接口定义为具有twitterIdtwitterUsername属性的对象。trim是真实的意思,即我们将丢弃任何没有在TwitterUser界面上描述的属性。由于我们的 API 以不友好的格式返回属性,我们将属性从twitter_usernametwitter_id重命名为它们自己的 camelcase 版本。

接下来,我们用redux-thunk定义一个异步动作,该动作触发一个 API 调用,我们使用我们的TwitterUser接口来丢弃我们不想要的属性,并确保它用正确的类型实现我们期望的属性。如果你更喜欢保持你的动作创建者纯粹(er)或者不使用redux-thunk,你可能想要检查twitterService.getUser里面的接口并返回结果。

注意:当扩展一个接口时选项不被继承

单元测试也是使用接口的合适场所:

概括起来

我们已经看到了接口在 JavaScript 中是如何有用的:即使它是一种高度动态的语言,检查对象的形状和它的属性是一种特定的数据类型也为我们提供了额外的安全层,否则我们将会错过它。通过构建接口的概念和使用implement-js,我们还能够在增加安全性的基础上获得额外的效用。

推特: @josh_jahans


本站为非盈利网站,作品由网友提供上传,如无意中有侵犯您的版权,请联系删除