Javascript 何时使用原型(prototype)

标签 javascript performance prototype function-prototypes

我想了解什么时候适合在js中使用原型(prototype)方法。是否应该始终使用它们?或者是否存在不优选使用它们和/或导致性能损失的情况?

在本网站搜索 js 中命名空间的常用方法时,似乎大多数都使用基于非原型(prototype)的实现:简单地使用对象或函数对象来封装命名空间。

来自基于类的语言,很难不尝试进行相似之处并认为原型(prototype)就像“类”,而我提到的命名空间实现就像静态方法。

最佳答案

原型(prototype)是一种优化

jQuery 库是很好地使用它们的一个很好的例子。每次使用 $('.someClass') 获取 jQuery 对象时,该对象都有数十个“方法”。该库可以通过返回一个对象来实现这一点:

return {
   show: function() { ... },
   hide: function() { ... },
   css: function() { ... },
   animate: function() { ... },
   // etc...
};

但这意味着内存中的每个 jQuery 对象都会有数十个包含相同方法的命名槽,一遍又一遍。

相反,这些方法是在原型(prototype)上定义的,并且所有 jQuery 对象都“继承”该原型(prototype),以便以很少的运行时成本获得所有这些方法。

jQuery 如何正确实现这一点的一个至关重要的部分是,它对程序员是隐藏的。它纯粹被视为一种优化,而不是您在使用该库时必须担心的事情。

JavaScript 的问题在于,裸构造函数要求调用者记住在它们前面加上 new 前缀,否则它们通常无法工作。这没有充分的理由。 jQuery 通过将这些废话隐藏在普通函数 $ 后面来实现这一点,因此您不必关心对象是如何实现的。

为了方便您创建具有指定原型(prototype)的对象,ECMAScript 5 包含一个标准函数 Object.create。它的一个大大简化的版本如下所示:

Object.create = function(prototype) {
    var Type = function () {};
    Type.prototype = prototype;
    return new Type();
};

它只是解决了编写构造函数然后使用 new 调用它的痛苦。

什么时候你会避免使用原型(prototype)?

与流行的 OO 语言(例如 Java 和 C#)进行有用的比较。它们支持两种继承:

  • 接口(interface)继承,您在其中实现一个接口(interface),以便该类为该接口(interface)的每个成员提供自己独特的实现。<
  • 实现继承,您可以在其中扩展提供某些方法的默认实现的

在 JavaScript 中,原型(prototype)继承是一种实现继承。因此,在这些情况下(在 C# 或 Java 中),您将从基类派生以获得默认行为,然后通过覆盖对其进行少量修改,那么在 JavaScript 中,原型(prototype)继承就有意义了。

但是,如果您在 C# 或 Java 中使用接口(interface),那么您不需要 JavaScript 中的任何特定语言功能。无需显式声明表示接口(interface)的内容,也无需将对象标记为“实现”该接口(interface):

var duck = {
    quack: function() { ... }
};

duck.quack(); // we're satisfied it's a duck!

换句话说,如果对象的每个“类型”都有自己的“方法”定义,那么从原型(prototype)继承就没有任何值(value)。之后,这取决于您为每种类型分配的实例数量。但在许多模块化设计中,给定类型只有一个实例。

事实上,it has been suggested by many people that implementation inheritance is evil 。也就是说,如果某个类型有一些常见的操作,那么如果它们不放入基类/父类(super class)中,而是仅在某个模块中作为普通函数公开,并将对象传递给该模块,那么可能会更清楚您希望它们进行操作。

关于Javascript 何时使用原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31308283/

相关文章:

javascript - CKEditor 如何以允许 React 识别的方式与 React.js 一起使用?

performance - 即使设置了 PCE,用户模式下的 rdpmc 也不起作用

Android Listview 降低滚动速度

javascript - 为什么 JavaScript 的 `function.call` 必须显式调用?

javascript - 在 React 中调用 onClick 函数

javascript - MAC 地址正则表达式验证逗号分隔、冒号或破折号分隔值

javascript - 如何在react中使用带有useState钩子(Hook)的回调

sql - Postgres 最小函数性能

javascript - 将键和原型(prototype)方法转换为驼峰式

javascript - 继承类的对象可以访问父类的所有属性和方法