JavaScript接口关键字的正确使用方法

9
首先,不,我不想为我的JavaScript代码创建任何类似于Java的接口。我看到这些问题随处可见,虽然我在JavaScript方面仍然是相对新手,但我知道这些并不是语言的一部分。
然而,我很好奇interface关键字的实际用途是什么。例如,Math是一个接口,包含定义(但没有实现)。我认为(可能完全错误),这是为了提供一种手段,让语言的定义者强制执行在各种JavaScript引擎中实现一组行为。这是正确的吗?
此外,我希望有一个“静态类”,其中包含许多实用方法。我喜欢Math.sqrt(3)具有大写字母的外部命名空间('Math'),其中有许多逻辑上相似的方法和值。也许只是因为我有Java/Ruby背景,让我想要在分组对象上使用大写字母。这是不好的形式吗?
var ShapeInspections = {
  isSymmetrical: function (s) {
    // determine if shape is symmetrical
  },
  numAngles: function (s) {
    // return the number of angles
  }
}

一个纯属创造的例子,但把“模块”这样命名是否违反惯用法?

在我看来,这完全没问题,而且我经常使用这种模式。 - meskobalazs
1
“interface” 关键字?!它被保留以备将来使用,但即使在 ES6 中也没有定义其用途。 - Alnitak
通常大写字母表示构造函数,不要使用它们。或者使用它们,但可能会让其他开发人员感到困惑。我在集合函数中使用大写字母来表示集合,但这是一种不好的做法,只是因为我比较奇怪。 - Adam Tolley
不要将经典继承和所有相关的负面影响与接口的概念混淆,因为在像C#和Java这样的语言中,接口对于避免单一继承非常有用。接口有很多用途,而且良好定义的类型并不是本质上邪恶或不灵活的。然而,我建议在js中保持对OOP的健康恐惧。 - Adam Tolley
4个回答

8

好的,就像其他答案一样,你知道在Javascript世界中,关键字interface没有真正的用例。

你提到的Math示例让我怀疑你在谈论一种称为模块模式的设计模式,这种模式广泛用于JavaScript代码的作用域。有许多方法可以使您的代码模块化。例如,就像OddDev回答您的那样,著名的原型模式可以以模块化的方式嵌入您的代码(就像您的Math示例)。以下是具有私有变量和函数的揭示原型模式示例,以增加灵活性:

/* Example from: 
    http://www.innoarchitech.com/scalable-maintainable-javascript-modules */
var myPrototypeModule = (function (){

   var privateVar = "Alex Castrounis",
       count = 0;

   function PrototypeModule(name){
    this.name = name;
   }

   function privateFunction() {
      console.log( "Name:" + privateVar );
      count++;
   }

   PrototypeModule.prototype.setName = function(strName){
      this.name = strName;
   };

   PrototypeModule.prototype.getName = function(){
      privateFunction();
   };

   return PrototypeModule;     
})();

但这还不是全部。其他选项包括Scoped module patternPOJO module pattern等等。请查看如何编写高可扩展性和可维护性的JavaScript:模块,它有一套非常简单而全面的示例。
到目前为止,我们谈论了纯JavaScript。如果您可以在代码中使用库,则可以使用令人惊叹的库,例如RequirejsCommonsJS等,以帮助您使用开箱即用功能。请查看Addy Osmani关于使用AMD、CommonJS和ES Harmony编写模块化JavaScript的文章。

我一定会查看Castrounis的文章。谢谢! - Eric Haynes
链接现在已经失效,这是一个网络存档版本:https://web.archive.org/web/20170117083505/http://www.innoarchitech.com/scalable-maintainable-javascript-modules/ - Nick Gimbal

6
在javascript中,interface关键字是一个FutureReservedWord,因此目前它什么也不做,尽管在未来的规范中可能会发生改变(请参见ECMAScript 5.1,第7.6.1.2节)。在ES6草案中,这也是一样的。
至于你的模块,这是一个完全惯用的解决方案。将函数“命名空间化”始终是一个好主意,因为它可以尽可能地保持全局作用域的干净。

0
我认为(也许完全错误),这些是为了提供一种手段,让语言的定义者强制实现在各种JS引擎中实现一组行为。这正确吗?
不,这是不正确的。像“Math”等的东西都是包含函数的对象。如果您使用例如“Math.pow(...)”,则只需执行存储在“Math”对象中的函数即可。请查看此示例:
var Math = {};
Math.prototype.pow = function(){
 alert("stuff");
}

var ShapeInspections = { isSymmetrical: function (s) { // 判断形状是否对称 }, numAngles: function (s) { // 返回角的数量 } } 这只是一个纯粹牵强的例子,但像这样命名“模块”并不违反惯例。
关于接口关键字,为了明确起见: 以下标记在严格模式代码中出现时也被认为是FutureReservedWords(参见10.1.1)。 在任何将FutureReservedWord的出现放置在其中会产生错误的上下文中,在严格模式代码中出现任何这些标记都必须产生等效的错误: 实现 让 私有 公共 yield 接口 包 保护 静态
它只是预留了一些可能在未来使用的关键字,所以不用过于担心 :) http://www.ecma-international.org/ecma-262/5.1/#sec-7.6

0
不要混淆 IDL 中指定的“接口”和 interface 关键字。后者保留用于潜在的将来使用,但在 ECMAScript 中实际上尚未被使用(即使在 ES6 中也是如此)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接