JavaScript中的原型OO [英] Prototypical OO in JavaScript

查看:112
本文介绍了JavaScript中的原型OO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

TL; DR:

我们是否需要原型OO中的工厂/构造函数?我们可以进行范例切换并将其完全删除吗?

Do we need factories/constructors in prototypical OO? Can we make a paradigm switch and drop them completely?

背景故事:

最近,我一直在用JavaScript进行原型OO,这发现用JavaScript完成的OO中有99%都在强迫使用经典的OO模式.

I've been toying with doing prototypical OO in JavaScript lately and find that 99% of OO done in JavaScript is forcing classical OO patterns into it.

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

My take on prototypical OO is that it involves two things. A static prototype of methods (and static data) and a data binding. We don't need factories or constructors.

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

In JavaScript these are Object literals containing functions and Object.create.

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

This would mean we can model everything as a static blueprint/prototype and a data binding abstraction that's preferably hooked straight into a document-style database. I.e. objects are taken out of the database and created by cloning a prototype with the data. This would mean there is no constructor logic, no factories, no 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是一个蓝图/原型.任何带有数据的实际对象都可以使用Object.create(Entity, {...})创建.

The particular code is verbose because ES5 is verbose. Entity above is a blueprint/prototype. Any actual object with data would be created by using Object.create(Entity, {...}).

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

The actual data (in this case the components) is directly loaded from a JSON store and injected directly into the Object.create call. Of course a similar pattern is applied to creating components and only properties that pass Object.hasOwnProperty are stored in the database.

首次创建实体时,会使用空的{}

When an entity is created for the first time it's created with an empty {}

实际问题:

现在我的实际问题是

  • JS原型OO的开源示例?
  • 这是个好主意吗?
  • 它与原型OOP背后的思想和观念一致吗?
  • 不使用任何构造函数/工厂功能会在某个地方把我咬伤吗?我们真的可以不使用构造函数而摆脱困境吗?使用上述方法是否有任何局限性,我们需要工厂来克服它们.
  • Open source examples of JS prototypical OO?
  • Is this a good idea?
  • Is it in-line with the ideas and concepts behind prototypical OOP?
  • Will not using any constructors/factory functions bite me in the ass somewhere? Can we really get away with not using constructors. Are there any limitations using the above methodology where we would need factories to overcome them.

推荐答案

根据您的评论,问题主要是构造函数知识是否必要?"我觉得是.

As per your comment that the question is mainly "is constructor knowledge necessary?" I feel it is.

一个玩具示例将存储 partial 数据.在内存中给定的数据集上,当持久化时,我只能选择存储某些元素(出于效率或数据一致性的目的,例如,持久化后这些值本质上是无用的).让我们进行一个会话,在该会话中存储用户名以及用户单击帮助按钮的次数(因为缺少更好的示例).当我在示例中坚持执行此操作时,单击数没有用,因为现在将其保存在内存中,并且下次加载数据时(下次用户登录或连接或进行其他操作),我将初始化从零开始的值(大概为0).这种特殊的用例非常适合构造函数逻辑.

A toy example would be storing partial data. On a given data set in memory, when persisting I may only choose to store certain elements (either for the sake of efficiency or for data consistency purposes, e.g. the values are inherently useless once persisted). Let's take a session where I store the user name and the number of times they've clicked on the help button (for lack of a better example). When I persist this in my example, I do have no use for the number of clicks, since I keep it in memory now, and next time I load the data (next time the user logs in or connects or whatever) I will initialise the value from scratch (presumably to 0). This particular use case is a good candidate for constructor logic.

Aahh,但您始终可以将其嵌入到静态原型中:Object.create({name:'Bob', clicks:0});当然,在这种情况下.但是,如果一开始的值并不总是为0,而是需要计算的话,该怎么办?假设用户的年龄以秒为单位(假设我们存储了名称和DOB).再次强调,很少使用的项目会持续存在,因为无论如何在检索时都需要重新计算该项目.那么,如何在静态原型中存储用户的年龄?

Aahh, but you could always just embed that in the static prototype: Object.create({name:'Bob', clicks:0}); Sure, in this case. But what if the value wasn't always 0 at first, but rather it was something that required computation. Uummmm, say, the users age in seconds (assuming we stored the name and the DOB). Again, an item that there is little use persisting, since it will need to be recalculated on retrieval anyway. So how do you store the user's age in the static prototype?

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

The obvious answer is constructor/initialiser logic.

还有更多场景,尽管我认为这个主意与js oop或任何特定语言无关.在我看到计算机系统为世界建模的方式中,实体创建 logic 的必要性是固有的.有时,我们存储的项目将是简单的检索并注入到原型外壳之类的蓝图中,有时值是动态的,并且需要进行初始化.

There are many more scenarios, although I don't feel the idea is much related to js oop or any language in particular. The necessity for entity creation logic is inherent in the way I see computer systems model the world. Sometimes the items we store will be a simple retrieval and injection into a blueprint like prototype shell, and sometimes the values are dynamic, and will need to be initialised.

更新

好的,我将尝试一个更真实的示例,为避免混淆,请假设我没有数据库,也不需要持久化任何数据.假设我要制作纸牌服务器.每个新游戏(自然)将是Game原型的新实例.对我来说很明显,这里(以及很多地方)需要使用它们的初始化逻辑:

OK, I'm going to try for a more real-world example, and to avoid confusion assume that I have no database and need not persist any data. Let's say I'm making a solitaire server. Each new game will be (naturally) a new instance of the Game prototype. It is clear to me that their is initialiser logic required here (and lots of it):

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

I will, for example, need on each game instance not just a static/hard-coded deck of cards, but a randomly shuffled deck. If it were static the user would play the same game every time, which is clearly not good.

如果玩家用完了,我可能还必须启动一个计时器来完成游戏.再说一遍,这不是静态的,因为我的游戏有一些要求:秒数与所连接的玩家迄今为止赢得的游戏数成反比(同样,没有保存的信息,仅此连接有多少个信息) ,并且与改组的难度成比例(有一种算法,根据改组结果可以确定游戏的难度).

I may also have to start a timer to finish the game if the player runs out. Again, not something that can be static, since my game has a few requirements: the number of seconds is inversely related to the number of games the connected player has won so far (again, no saved info, just how many for this connection), and proportional to the difficulty of the shuffle (there is an algorithm that according to the shuffle results can determine the degree of difficulty of the game).

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

How do you do that with a static Object.create()?

这篇关于JavaScript中的原型OO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆