协慌网

登录 贡献 社区

可以使用哪些技术在 JavaScript 中定义类,它们的权衡是什么?

我更喜欢在大型项目中使用 OOP,例如我现在正在从事的项目。我需要用 JavaScript 创建几个类,但是,如果我没有记错的话,至少有两种方法可以做到这一点。语法是什么,为什么要用这种方式呢?

我想避免使用第三方库 - 至少在一开始。
在寻找其他答案时,我找到了文章 “使用 JavaScript 进行面向对象的编程”,第 I 部分:继承 - 文档 JavaScript ,该文章讨论了 JavaScript 中的面向对象的编程。有更好的继承方法吗?

答案

这是不使用任何外部库即可完成此操作的方法:

// Define a class like this
function Person(name, gender){

   // Add object properties like this
   this.name = name;
   this.gender = gender;
}

// Add methods like this.  All Person objects will be able to invoke this
Person.prototype.speak = function(){
    alert("Howdy, my name is" + this.name);
};

// Instantiate new objects with 'new'
var person = new Person("Bob", "M");

// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"

现在,真正的答案要复杂得多。例如,JavaScript 中没有类。 JavaScript 使用基于prototype的继承方案。

此外,还有许多流行的 JavaScript 库,它们具有自己的样式,它们近似于 JavaScript 中的类功能。您将至少要签出PrototypejQuery

确定其中哪一个是 “最佳” 是在 Stack Overflow 上发起一场神圣战争的好方法。如果您正着手进行一个较大的 JavaScript 大型项目,那么绝对值得学习流行的库并按自己的方式去做。我是一个原型人,但是 Stack Overflow 似乎倾向于 jQuery。

就只有 “一种方法”,而没有对外部库的任何依赖,我写的方式就差不多了。

在 JavaScript 中定义类的最好方法是不定义类。

严重地。

有几种不同的面向对象的风格,其中一些是:

  • 基于类的 OO(由 Smalltalk 首次引入)
  • 基于原型的 OO(由 Self 首次引入)
  • 基于多方法的 OO(我认为是 CommonLoops 首次引入的)
  • 基于谓词的面向对象(不知道)

可能还有其他我不认识的人。

JavaScript 实现了基于原型的 OO。在基于原型的 OO 中,通过复制其他对象(而不是从类模板实例化)来创建新对象,并且方法直接存在于对象中而不是类中。继承是通过委托完成的:如果对象没有方法或属性,则在其原型(即从其克隆的对象)上查找该对象,然后在该原型的原型上进行查找,依此类推。

换句话说:没有类。

JavaScript 实际上对该模型做了一个很好的调整:构造函数。可以说,不仅可以通过复制现有对象来创建对象,还可以 “凭空” 构造它们。 new关键字调用一个函数,则该函数将成为构造函数,并且this关键字将不会指向当前对象,而是指向一个新创建的 “空” 对象。因此,您可以按自己喜欢的任何方式配置对象。这样,JavaScript 构造函数就可以在传统的基于类的 OO 中担当类的角色之一:充当新对象的模板或蓝图。

现在,JavaScript 是一种非常强大的语言,因此,如果需要,在 JavaScript 中实现基于类的 OO 系统非常容易。但是,只有在确实有需要时才应该这样做,而不仅仅是因为 Java 就是这样做的。

ES2015 课程

在 ES2015 规范中,您可以使用类语法,它只是原型系统的基础。

class Person {
  constructor(name) {
    this.name = name;
  }
  toString() {
    return `My name is ${ this.name }.`;
  }
}

class Employee extends Person {
  constructor(name, hours) {
    super(name);
    this.hours = hours;
  }
  toString() {
    return `${ super.toString() } I work ${ this.hours } hours.`;
  }
}

好处

主要好处是静态分析工具发现更容易针对此语法。对于其他来自基于类的语言的人来说,使用该语言作为多语言也更容易。

注意事项

警惕其当前的局限性。要获得私有属性,必须使用 Symbols 或 WeakMaps 。在将来的版本中,很可能会将类扩展为包括这些缺少的功能。

支持

浏览器支持是不是现在(通过 IE 除外几乎每个人都支持)很不错,但你可以像现在 transpiler 使用这些功能巴贝尔

资源