演示与基于类的模型相关的Javascript继承优势 [英] Demonstrating Javascript Inheritance Benefits in Relation to a Class-Based Model

查看:124
本文介绍了演示与基于类的模型相关的Javascript继承优势的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以提供一个特定的例子来展示Javascript的原型继承,它展示了什么时候使用传统的基于类的(经典)模型是有益的吗?

Can anyone provide a specific example showing Javascript's prototypal inheritance that demonstrates when it's beneficial to use over a traditional class-based (classical) model?

我见过的其他问题(例如 Classical Vs原型继承为什么使用原型继承实现JavaScript?基于原型和基于类的继承)只提供高水平讨论,而不是一个具体的例子(最好是你在生产代码中使用的一个)。

Other questions I have seen (such as Classical Vs prototypal inheritance, Why was JavaScript implemented using prototypal inheritance?, prototype based vs. class based inheritance) only give a high level discussion, not a specific example (preferably one that you have used in production code).

推荐答案

我认为我们最大的原因是直接看不到更多的原型模式是Javascript中的默认语法是伪古典像差而不是更有利的Object.create。如果你想真正看到原型模式闪耀搜索使用此功能的地方。以下示例来自Dojo工具包:

I think the biggest reason that we don't see more of the prototypal pattern directly is that the default syntax in Javascript is that pseudo-classical aberration instead of the more favourable Object.create. If you want to really see the prototypal patter shining search for places where this function is used. The following example comes from the Dojo toolkit:

警告:我改变了主意关于这种代码在我最初编写这个答案时的表现有多好。虽然基本思想仍然存在,但你应该小心,你有方法可以改变实例(this)属性。这是因为如果通过委托者调用委托对象中的方法,那么最终可能会在委托者中而不是在委托中设置变量,如果其他人最终直接访问委托,则可能会破坏某些不变量。

Caveat: I kind of changed my mind about how good this kind of code is since back when I originally wrote this answer. While the basic idea still stands, you should be careful it you have methods that mutate instance ("this") properties. This is because if you invoke a method in the delegate object via the delegator then you might end up setting variables in the delegator instead of in the delegate and that might break some invariants if someone else ends up accessing the delegate directly latter on.

尽管你有不可变的对象,但整个想法是100%罚款。

The whole idea is 100% fine you you have immutable objects though.

Dojo定义了一般的商店界面(使用get()等方法,例如,add()等可用于从服务器抽象REST API。我们想创建一个缓存功能,接收任何数据存储并返回一个新版本,缓存对get()方法的任何调用(这允许我们将缓存与实现实际get()的特定于商店的行为分离)

Dojo defines a general store interface (with methods like get(), add(), etc) that can be used, for example, to abstract a REST API from the server. We would like to create a Cache function that receives any datastore and returns a new version that caches any calls to the get() method (this allows us to decouple the caching from the store-specific behaviour of implementing the actual get())

第一个想法是使用Javascript高度恐怖的事实来取代get方法:

A first idea would involve using the fact the Javascript is highly dinamic to replace the get method:

//not the actual implementation. Things get more complicated w/ async code.
var oldGet = store.get;
store.get = function(id){
    if(!cache[id]){ cache[id] = oldGet(id); }
    return cache[id];
}

然而,这会破坏原始对象,因此您无法访问原始方法不再需要并行添加其他修改。

However, this clobbers the original object so you can't access the original method anymore and also makes it trickier to add other modifications in parallel.

第二个想法是使用委托制作更强大的解决方案:

A second idea would be to make a more robust solution using delegation:

function Cache(obj){
    this.obj = obj;
}
Cache.prototype = {
    get: function(){
        //do things involving this.obj...
    }
};

这看起来很有希望,直到你记得生成的Cache对象需要实现商店界面。我们可以尝试手动添加所有方法:

This looks promising, until you remember that the resulting Cache object needs to implement the store interface. We could try adding all the methods by hand:

Cache.prototype = {
    //...
    put: function(){ return this.obj.apply(this, arguments); },
    //...
}

但不仅如此它很麻烦且容易出错(很容易忘记某些东西)它甚至不如对象修改解决方案那么强大,因为我们无法访问原始对象中不属于商店界面的方法。

but not only would that be cumbersome and error prone (its so easy to forget something) it would not even be as powerful as the object-modifying solution since we lose access to methods in that original object that aren´t from the store interface.

嗯,执行这种自动委托的方法是继承,但在这种情况下它最初似乎没用,因为你需要为每个可能的商店类创建一个新的缓存子类或者你需要某种花哨的多重继承mixin。输入原型继承以节省一天。我们可以轻松地创建一个新的obejct,为旧的添加功能而无需修改它或不得不使用类hieharchies

Well, the way to do this kind of "automatic delegation" is inheritance, but it would initialy seem useless in this case since you would need to create a new cache subclass for every possible store class or you would need some sort of fancy multiple-inheritance mixin. Enter prototypal inheritance to save the day. We can easily make a new obejct that adds functionality to an old one without modifying it or having to fiddle with the class hieharchies

dojo.store.Cache = function(masterStore, cachingStore, options){
    //...
    return dojo.delegate(masterStore, {
        //... 
        get: function(id, directives){
            //...
        }
        //...
    }
}

其中dojo.delegate是一个函数,它创建一个新对象,其中包含第二个参数中的所有属性,其原型将是是第一个参数。

Where dojo.delegate is a function that creates a new object with all the properties in the second argument and whose prototype will be the first argument.

非JS理论上的ramblings:原型继承在更多的委托方案中可以更加积极地使用像Self这样的语言允许多个原型,并且还可以在运行时直接访问和修改原型。例如,可以通过委派所有适用性来实现GoF中的State模式le方法到原型并在状态改变时改变原型。

Non JS theoretical ramblings: Prototypal inheritance can be used even more agressively in even more delegation scenarios in a language like Self that allows multiple prototypes and also direct access and modification of prototypes at runtime. For example, it is possible to implement the State pattern from the GoF by delegating all suitable methods to a prototype and changing the prototype whenever the state changes.

这篇关于演示与基于类的模型相关的Javascript继承优势的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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