gpt4 book ai didi

javascript - JavaScript 中的多重继承/原型(prototype)

转载 作者:IT王子 更新时间:2023-10-29 02:38:47 24 4
gpt4 key购买 nike

我已经到了需要在 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)迭代,依此类推。一旦一个属性被迭代,我将它存储在一个哈希表中以避免再次迭代它。
    警告 :这个陷阱已经在 ES7 草案中移除,并且在浏览器中被弃用。
  • 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/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com