当前位置: 首页 > 面试题库 >

JavaScript中的原型OO

公冶智刚
2023-03-14
问题内容

TL; DR:

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

背景故事:

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

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

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

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

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

首次创建实体时,将其创建为空 {}

实际问题:

现在我的实际问题是

  • JS原型OO的开源示例?
  • 这是一个好主意吗?
  • 它与典型的OOP背后的思想和观念一致吗?
  • 会不会使用任何构造函数/工厂 函数 在某个地方咬我屁股?我们真的可以不使用构造函数而摆脱困境吗?使用上述方法是否有任何局限性,我们需要工厂来克服它们。

问题答案:

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

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

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

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

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

更新

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

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

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

如何使用静态方法Object.create()呢?



 类似资料:
  • 问题内容: 该图再次显示每个对象都有一个原型。构造函数Foo也具有其自己的Function.prototype,而Foo又通过其属性再次引用Object.prototype。因此,重复一遍,Foo.prototype只是Foo的显式属性,它引用b和c对象的原型。 和之间有什么区别? 问题答案: 是在查找链中用于解析方法的实际对象,等等。 prototype是使用以下命令创建对象时用于构建的对象:

  • 问题内容: 我是JavaScript OOP的新手。您能否解释以下代码块之间的区别?我测试了两个模块。什么是最佳做法,为什么? 第一块: 第二块: 为什么笔者添加和使用方法,并没有宣布他们的内部方法类和在类? 为什么需要重新设置为?是当覆盖的属性设置?我注释了这一行,没有任何改变。 为什么叫在构造函数?当我这样做时,不会被“继承”的属性和方法 问题答案: 这两个块的不同之处在于,在第一个示例中该实

  • 问题内容: 以下两个JavaScript原型之间的功能区别是什么?选择一个与另一个原型有什么好处? 选项1: 选项2: 我是否假设 选项2 导致废弃某些隐式绑定到原型的函数是否正确? 问题答案: 我是否假设选项2导致废弃某些隐式绑定到原型的函数是否正确? 对,就是这样。尽管唯一隐式绑定的属性是您很少需要的属性。 功能上有什么区别? 选项1只是扩展现有的原型。如果已经有从原型对象继承的实例,则它们也

  • 本文向大家介绍深入学习JavaScript中的原型prototype,包括了深入学习JavaScript中的原型prototype的使用技巧和注意事项,需要的朋友参考一下 javascript 是一种 prototype based programming 的语言, 而与我们通常的 class based programming 有很大 的区别,我列举重要的几点如下: 1.函数是first cla

  • 问题内容: 我试图将一个bean 注入一个bean中,以便对单例bean方法的每个新调用都具有原型bean的新实例。 考虑如下的单例豆: 我希望每次调用该方法时,都会使用一个新实例。 下面是原型bean: 似乎正在发生的事情是,Spring急于在该方法中交付PrototypeBean的新实例。也就是说,该方法中的两行代码将在每一行中创建一个prototypeBean的新实例。 因此,在第二行中,输

  • 本文向大家介绍JavaScript原型继承和原型链原理详解,包括了JavaScript原型继承和原型链原理详解的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了JavaScript原型继承和原型链原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组