javascript 不同的 OOP 方法标准

标签 javascript class oop methods

很长一段时间以来,我一直通过执行以下操作来编写 JavaScript 类

function MyClass(){
    this.v1;
    this.foo = function(){
        return true;
    }
};

然后我发现了 TypeScript,看起来它会将其类编译为

var MyClass = (function () {
    function MyClass(message) {
        this.v1 = message;
    }
    MyClass.prototype.foo = function () {
        return "Hello, " + this.v1;
    };
    return MyClass;
})();

我在网上找到的另一种方法是

var MyClass = {
    v1:1,
    foo: function(){
       return true;
    }
};

这对我来说看起来很难看,但也许我错过了这种方法的一些好处,因为它看起来是网络上大多数人在 javaScript 中处理对象的方式。

我能够从我创建的函数中继承的第一种方法。

Function.prototype.extends = function(parent){
    this.prototype = new parent();
    this.prototype.constructor = this;
};

我还看到了许多其他在 JavaScript 中创建类的方法。我想知道我的方法是否错误或者是否有进行OOP的最佳实践方法。我完成的所有项目都使用第一个示例。您可以在https://github.com/Patrick-W-McMahon上看到现在我了解了 JavaScript 编译器正在做什么,我开始质疑我的方法。我想知道其他 JavaScript 程序员建议的最佳方法是什么,以及这些方法之间是否存在差异。我有 C++/Java 背景,因此我编写 JavaScript 来匹配我的背景。

最佳答案

您在这里读到的内容称为幂构造函数,更多相关信息请参见:

Douglas Crockford about Inheritance

<小时/>

作为一种多范式语言,JavaScript 非常适合这些不同的考虑。事实是,它以您想象的方式在您的大脑中成型

换句话说,如果您可以用一种方式推理您的结构,那么就以这种方式使用它。

另一方面,如果您希望完全“摆脱”自己的约束,那么您应该完全放弃类中的推理,并拥抱原型(prototype)继承,而不使用任何类似于类的事物全部。鸭子类型是一个自然的结果,在极端情况下,你会在整个地方使用闭包。

我经常做的是这样的:

function myItemBuilder(p1)
{
  var s0, p0 = 0;

  // s0 is a shared private property (much like static in classes)
  // p0 is a shared private property but will be factorized (rendered non-shared)
  // p1 is a private instance property

  return (function (p0) { // factorize p0 if necessary

    return {
      publicProperty : 3,
      method1 : function (arg1) {
        // code here (may use publicProperty, arg1, s0, p0 (factorized) and p1)
      },
      method2 : function (arg2) {
        // code here (may use publicProperty, arg2, s0, p0 (factorized) and p1)
      }
    };
  }(p0++)); // on each invocation p0 will be different and method1/method2 will not interfere across invocations (while s0 is shared across invocations)
}

编辑:仅当您需要分解 p0 时才需要内部闭包(即每次调用时 p0 都有单独的独立值)。当然,如果不需要 p0 分解,请省略内部闭包。

The above example is intentionally more complex than required to illustrate various interesting cases.

调用像 myItemBuilder("hello") 这样的方法会构建一个具有这些特定功能的新项目,但实际上没有 class 构造本身.

当您想要放弃经典继承时,这是获取实例的一种特别强大的方法。例如,在 C++ 中,您可以从多个类继承,这称为混合。在 Java 和 C# 中,您只有单继承,但接口(interface)可以为您提供帮助。

这里,我上面展示的是装配线比喻,它可以将组件组装到实例中,结果是没有具体 (1)类、接口(interface)和混合之间的区别。它们都只是具有您可以通过元编程(鸭子类型、反射/检查)进行反射(reflection)的功能的实例。仍然存在逻辑 (2) 差异,因为:(1) 具体实例的行为相同,独立于它们的存在方式,但 (2) 从逻辑上讲,接口(interface)是契约,而实例是实现。

如果你真的懂SOLIDAssembly Line Metaphor这一切都是有道理的。否则我请您原谅这么长的答案:)

添加:

使用这种方法,您无法检查类型,但您也不需要这样做,因为鸭子类型允许您找到所需的方法,而无需查看类或接口(interface)契约。这类似于将每个方法放在单独的单一方法接口(interface)中。

关于javascript 不同的 OOP 方法标准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25003167/

相关文章:

java - 类对象和 JSP

c++ - 在 C++ 中使用 MinGW 工具包含多个类/.o 文件

java - 在Java中使用省略号(...)?

javascript - Vue 计算方法 - 在数组中查找值不起作用

javascript - JQuery if 语句未正确检测跨度复选框

javascript - 试图从 list2 中获取 "new markers"

java - 如何将匿名类(不是实例)作为参数传递给在 Java 中期望类型为类的方法

javascript - 穆工具 |打开/关闭弹出菜单和外部单击事件

java - 双向链表创建节点

python - python 中的属性错误。对象没有属性