javascript - JavaScript 中的原型(prototype) OO

标签 javascript oop node.js prototypal-inheritance ecmascript-5

TL;博士:

我们需要原型(prototype) OO 中的工厂/构造函数吗?我们可以进行范式转换并完全放弃它们吗?

背景故事:

我最近一直在玩弄 JavaScript 中的 OO 原型(prototype),发现 99% 的 JavaScript 中的 OO 都迫使经典的 OO 模式进入其中。

我对原型(prototype) OO 的看法是它涉及两件事。方法(和静态数据)的静态原型(prototype)和数据绑定(bind)。我们不需要工厂或构造函数。

在 JavaScript 中,这些是包含函数和 Object.create 的对象字面量。 .

这意味着我们可以将一切建模为静态蓝图/原型(prototype)和数据绑定(bind)抽象,最好直接连接到文档样​​式的数据库中。 IE。对象从数据库中取出并通过使用数据克隆原型(prototype)来创建。这意味着没有构造函数逻辑,没有工厂,没有 new .

示例代码:

一个伪示例是:

var Entity = Object.create(EventEmitter, {
    addComponent: {
        value: function _addComponent(component) {
            if (this[component.type] !== undefined) {
                this.removeComponent(this[component.type]);
            }

            _.each(_.functions(component), (function _bind(f) {
                component[f] = component[f].bind(this);
            }).bind(this));

            component.bindEvents();

            Object.defineProperty(this, component.type, {
                value: component,
                configurable: true
            });

            this.emit("component:add", this, component);
        }
    },
    removeComponent: {
        value: function _removeComponent(component) {
            component = component.type || component;

            delete this[component];

            this.emit("component:remove", this, component);
        }
    }
}

var entity = Object.create(Entity, toProperties(jsonStore.get(id)))

次要说明:

特定的代码很冗长,因为 ES5 很冗长。 Entity上面是一个蓝图/原型(prototype)。任何带有数据的实际对象都可以使用 Object.create(Entity, {...}) 创建。 .

实际数据(在本例中为组件)直接从 JSON 存储加载并直接注入(inject) Object.create称呼。当然,类似的模式适用于创建组件和仅通过 Object.hasOwnProperty 的属性。存储在数据库中。

当一个实体第一次被创建时,它是用空的 {} 创建的。

实际问题:

现在我的实际问题是
  • Open source examples of JS prototypical OO?
  • 这是一个好主意吗?
  • 它是否符合原型(prototype) OOP 背后的思想和概念?
  • 不使用任何构造函数/工厂函数会在某个地方咬我吗?我们真的可以不使用构造函数吗?使用上述方法是否有任何限制,我们需要工厂来克服它们。
  • 最佳答案

    根据您的评论,问题主要是“是否需要构造函数知识?”我觉得是。

    一个玩具示例是存储部分数据。在内存中的给定数据集上,当持久化时,我可能只选择存储某些元素(为了效率或数据一致性目的,例如,一旦持久化,这些值本质上是无用的)。让我们以一个 session 来存储用户名和他们点击帮助按钮的次数(因为没有更好的例子)。当我在我的示例中坚持这一点时,我确实没有使用点击次数,因为我现在将它保存在内存中,下次我加载数据时(下次用户登录或连接或其他时)我将初始化值从头开始(大概为 0)。这个特殊的用例是构造函数逻辑的一个很好的候选者。

    啊哈,但你总是可以将它嵌入到静态原型(prototype)中:Object.create({name:'Bob', clicks:0});当然,在这种情况下。但是,如果该值一开始并不总是 0,而是需要计算,该怎么办。嗯,比如说,用户的年龄以秒为单位(假设我们存储了姓名和 DOB)。同样,一个几乎没有用的项目持久化,因为无论如何它都需要在检索时重新计算。那么如何在静态原型(prototype)中存储用户的年龄呢?

    显而易见的答案是构造函数/初始化器逻辑。

    还有更多的场景,尽管我不觉得这个想法与 js oop 或任何语言特别相关。在我看待计算机系统建模世界的方式中,实体创建逻辑的必要性是内在的。有时我们存储的项目将是一个简单的检索和注入(inject)蓝图,如原型(prototype) shell ,有时值是动态的,需要初始化。

    更新

    好的,我将尝试一个更真实的例子,为了避免混淆,假设我没有数据库并且不需要保留任何数据。假设我正在制作一个纸牌服务器。每个新游戏都(自然地)是 Game 的一个新实例。原型(prototype)。我很清楚,这里(以及很多)需要他们的初始化逻辑:

    例如,我将在每个游戏实例上不仅需要一副静态/硬编码的纸牌,还需要一副随机洗牌的纸牌。如果它是静态的,用户每次都会玩同一个游戏,这显然是不好的。

    如果玩家用完,我可能还需要启动一个计时器来完成游戏。同样,不是静态的,因为我的游戏有一些要求:秒数与到目前为止连接的玩家赢得的游戏数量成反比(同样,没有保存的信息,只是这个连接有多少) , 和shuffle的难度成正比(有算法可以根据shuffle的结果判断游戏的难易程度)。

    你如何用静态 Object.create() 做到这一点?

    关于javascript - JavaScript 中的原型(prototype) OO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6526241/

    相关文章:

    php - 未从子类处理的查询字符串

    C# - CLR 在继承过程中如何组织内存/引用?

    java - 当对象初始化时调用方法

    javascript - React Horizo​​ntal Timeline distance of undefined 错误

    javascript - 获得顶点折线图的正确尺寸

    javascript - Angular 数据绑定(bind)不允许获取对象中的最新数据

    javascript - 使用 javascript/jquery 将 CSV 拆分为对象

    javascript - Node strip 产品列表返回空

    node.js - gruntjs 服务器任务的目的是什么?

    javascript - three.js-围绕球体旋转矩形 Sprite ,以保持最小接近度