- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我已经到了需要在 JavaScript 中进行某种基本多重继承的地步。 (我不是来讨论这是否是一个好主意,所以请把这些评论留给自己。)
我只想知道是否有人尝试过(或没有)成功,以及他们是如何做到的。
归根结底,我真正需要的是能够拥有一个能够从多个原型(prototype)链继承属性的对象(即每个原型(prototype)可以有自己的适当链),但以给定的优先级顺序(它将搜索链以找到第一个定义)。
为了证明这在理论上是如何可能的,可以通过将辅助链附加到主链的末端来实现,但这会影响任何先前原型(prototype)的所有实例,这不是我想要的。
想法?
最佳答案
在 ECMAScript 6 中可以使用 Proxy objects 实现多重继承。 .
执行
function getDesc (obj, prop) {
var desc = Object.getOwnPropertyDescriptor(obj, prop);
return desc || (obj=Object.getPrototypeOf(obj) ? getDesc(obj, prop) : void 0);
}
function multiInherit (...protos) {
return Object.create(new Proxy(Object.create(null), {
has: (target, prop) => protos.some(obj => prop in obj),
get (target, prop, receiver) {
var obj = protos.find(obj => prop in obj);
return obj ? Reflect.get(obj, prop, receiver) : void 0;
},
set (target, prop, value, receiver) {
var obj = protos.find(obj => prop in obj);
return Reflect.set(obj || Object.create(null), prop, value, receiver);
},
*enumerate (target) { yield* this.ownKeys(target); },
ownKeys(target) {
var hash = Object.create(null);
for(var obj of protos) for(var p in obj) if(!hash[p]) hash[p] = true;
return Object.getOwnPropertyNames(hash);
},
getOwnPropertyDescriptor(target, prop) {
var obj = protos.find(obj => prop in obj);
var desc = obj ? getDesc(obj, prop) : void 0;
if(desc) desc.configurable = true;
return desc;
},
preventExtensions: (target) => false,
defineProperty: (target, prop, desc) => false,
}));
}
Object.create(obj)
.但在这种情况下,我们想要多重继承,而不是
obj
我使用代理将基本操作重定向到适当的对象。
has
trap是 in
operator 的陷阱.我用 some
检查是否至少一个原型(prototype)包含该属性。 get
trap是获取属性值的陷阱。我用 find
找到包含该属性的第一个原型(prototype),然后返回该值,或者在适当的接收器上调用 getter。这由 Reflect.get
处理.如果没有原型(prototype)包含该属性,我返回 undefined
. set
trap是设置属性值的陷阱。我用 find
找到包含该属性的第一个原型(prototype),然后在适当的接收器上调用它的 setter。如果没有 setter 或没有原型(prototype)包含该属性,则在适当的接收器上定义该值。这由 Reflect.set
处理. enumerate
trap是 for...in
loops 的陷阱.我从第一个原型(prototype)迭代可枚举属性,然后从第二个原型(prototype)迭代,依此类推。一旦一个属性被迭代,我将它存储在一个哈希表中以避免再次迭代它。ownKeys
trap是 Object.getOwnPropertyNames()
的陷阱.从 ES7 开始,for...in
循环不断调用 [[GetPrototypeOf]] 并获取每个属性的属性。所以为了让它迭代所有原型(prototype)的属性,我使用这个陷阱让所有可枚举的继承属性看起来像自己的属性。 getOwnPropertyDescriptor
trap是 Object.getOwnPropertyDescriptor()
的陷阱.使所有可枚举属性在 ownKeys
中看起来像自己的属性陷阱还不够,for...in
循环将获取描述符以检查它们是否可枚举。所以我使用 find
找到包含该属性的第一个原型(prototype),然后迭代其原型(prototype)链,直到找到属性所有者,然后返回其描述符。如果没有原型(prototype)包含该属性,我返回 undefined
.修改描述符以使其可配置,否则我们可能会破坏一些代理不变量。 preventExtensions
和 defineProperty
包含陷阱只是为了防止这些操作修改代理目标。否则我们最终可能会破坏一些代理不变量。 getPrototypeOf
trap可以添加,但没有正确的方法返回多个原型(prototype)。这意味着 instanceof
也行不通。因此,我让它获取目标的原型(prototype),该原型(prototype)最初为空。 setPrototypeOf
trap可以添加并接受一个对象数组,这些对象将替换原型(prototype)。这留给读者作为练习。这里我只是让它修改了目标的原型(prototype),没有多大用处,因为没有陷阱使用目标。 deleteProperty
trap是删除自己属性的陷阱。代理代表继承,所以这没有多大意义。我让它尝试删除目标,无论如何它应该没有属性。 isExtensible
trap是获取可扩展性的陷阱。没有多大用处,因为不变量迫使它返回与目标相同的可扩展性。所以我只是让它将操作重定向到目标,这将是可扩展的。 apply
和 construct
陷阱是用于调用或实例化的陷阱。它们仅在目标是函数或构造函数时才有用。 // Creating objects
var o1, o2, o3,
obj = multiInherit(o1={a:1}, o2={b:2}, o3={a:3, b:3});
// Checking property existences
'a' in obj; // true (inherited from o1)
'b' in obj; // true (inherited from o2)
'c' in obj; // false (not found)
// Setting properties
obj.c = 3;
// Reading properties
obj.a; // 1 (inherited from o1)
obj.b; // 2 (inherited from o2)
obj.c; // 3 (own property)
obj.d; // undefined (not found)
// The inheritance is "live"
obj.a; // 1 (inherited from o1)
delete o1.a;
obj.a; // 3 (inherited from o3)
// Property enumeration
for(var p in obj) p; // "c", "b", "a"
关于javascript - JavaScript 中的多重继承/原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9163341/
好吧,我怀疑这是一个独特的情况,所以要么有人这样做了,要么有人认为这是不可能的,至少以我所要求的方式。 我有 2 个原型(prototype)变量(函数),一个是父变量,另一个是助手。我想做的是从助手
这是 JavaScript 大师的问题。我正在尝试更优雅地使用 JavaScript 原型(prototype)模型。这是我的实用程序代码(它提供了真实的原型(prototype)链并正确使用 ins
我们知道在 JavaScript 中有一个用于数组的 .forEach() 方法。但是字符串没有内置该方法。 那么,下面的代码片段有没有问题:String.prototype.forEach = Ar
我们知道在 JavaScript 中有一个用于数组的 .forEach() 方法。但是字符串没有内置该方法。 那么,下面的代码片段有没有问题:String.prototype.forEach = Ar
我看到了两种不同的模式和解释。来自 DailyJS 和许多其他人的一篇:矩形.prototype = new Shape(); 然后是 Crockford 的 here 这意味着只是 矩形.proto
尝试在 Object.prototype 以及 String.prototype 和 Number.prototype 上定义一个 hashCode 方法>。我正在使用以下方法定义原型(prototy
在本教程中,您将借助示例了解 JavaScript 中的原型。 在学习原型之前,请务必查看以下教程: JavaScript 对象 JavaScript 构造函数 如您所知,您可以使用对象构造函
当构造新对象时,该对象被设置为委托(delegate)任何尚未显式设置为其构造函数原型(prototype)的属性。这意味着我们可以稍后更改原型(prototype),并且仍然可以看到实例中的更改。
我正在努力获得更好的 JavaScript 实用知识。所以,我买了 Douglas Crockford 的书“JavaScript the good parts”。 我现在很难掌握原型(prototy
我的理解是相同类型的所有对象将共享相同的原型(prototype)。因此对原型(prototype)的更改将反射(reflect)在每个对象上。但是值类型的属性似乎不是这样。这种属性是如何存储的? f
这个问题在这里已经有了答案: 关闭 12 年前。 Possible Duplicate: JavaScript: Class.method vs. Class.prototype.method 创建
为什么在 MDN 函数中 polyfills 使用“if (!Array.prototype.filter)”? if (!Array.prototype.filter) { Array.prot
这个问题已经有答案了: Assigning prototype methods *inside* the constructor function - why not? (6 个回答) 已关闭 7 年
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
面向对象有一个特征是继承,即重用某个已有类的代码,在其基础上建立新的类,而无需重新编写对应的属性和方法,继承之后拿来即用; 。 在其他的面向对象编程语言比如Java中,通常是指,子类继承父类的属性和
OOP 中原型(prototype)设计模式最重要的部分之一是我们不会从头开始创建新对象,我们只是使用 clone() 函数从现有对象克隆它们。 那么clone()函数是深拷贝还是浅拷贝? 如果它是一
在进行原型(prototype)设计时,您在多大程度上放弃了最佳实践来支持代码和修复黑客攻击?当然,代码并不打算在完整的生产环境中保留。 补充:我正在研究一个用 Python 制作的相当大的半工作原型
我开始学习设计模式。我知道原型(prototype)是用来制作我已经拥有的对象的精确副本,而享元是用来制作类似的对象。 我已经编写了 2D 平台游戏,例如马里奥(Java)。有很多相同的敌人,唯一的区
我正在使用 Maven 生成原型(prototype)。我能够使原型(prototype)生成正常,并且它生成的项目模板按预期工作。唯一的问题是在我的 shell 脚本中。脚本中注释掉的任何内容都会被
我想用 primefaces 配置一个 Java EE 项目。我在某处读到可以使用 mvn arechetype:generate 创建项目结构。当我使用它时,我只看到了 41 个选项,而在该教程中,
我是一名优秀的程序员,十分优秀!