首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >继承JS (Map,EventTarget)中的两个(或更多)内置对象

继承JS (Map,EventTarget)中的两个(或更多)内置对象
EN

Stack Overflow用户
提问于 2019-03-30 19:39:00
回答 2查看 142关注 0票数 0

我不是JS中的Noob,我知道从技术上讲,从多个类继承没有正确的方法。所以我的问题很简单

有没有什么想法,我可以创建一个类,或仅仅是一个对象,作为它从JS Native object中的两个版本继承而来。尤其是EventTarget和另一个对象。

我试着:

代码语言:javascript
复制
var map = new Map();
var eventtarget = new EventTarget();
mix = Object.create({...Map.prototype, ...EventTarget.prototype});
Object.assign(mix, et , map);

这似乎不起作用,因为Map.prototype中的方法并不麻烦,也使用Object.assign({}, Map.prototype, ...EventTarget.prototype)作为相同的效果。

再试一次:

代码语言:javascript
复制
class Base5 extends Map{
 constructor(){
    super();
    var eventTarget = new EventTarget();
    Object.assign(this,eventTarget);
 }
}

Base5.prototype = Object.create(Base5.prototype)
Object.assign(Base5.prototype,EventTarget.prototype); 

//    that seem to work
const b5 = new Base5();
b5.set('foo','bar');
//    but... 
b4.addEventListener('fire', _=>_ )
// throw Uncaught TypeError: Illegal invocation at <anonymous>:1:4

这个有效,但它不是通用的

代码语言:javascript
复制
const wm = new WeakMap();

class Base6 extends Map{
 constructor(){
    super();
    wm.set(this, new EventTarget() )
 }
 addEventListener(){ 
    wm.get(this).addEventListener(...arguments)
 }
 dispatchEvent(){
    wm.get(this).dispatchEvent(...arguments)
 }
 removeEventListener(){
   wm.get(this).removeEventListener(...arguments)
 }
}

const b6 = new Base6();
b6.set('foo','bar'); // Map(1) {"foo" => "bar"}
b6.addEventListener('foo', e=>console.log(e) );
b6.dispatchEvent( new Event('foo') ) 

那么任何人都可以提出更好的方法吗?

也许Reflect.construct可以在这方面有所帮助

EN

回答 2

Stack Overflow用户

发布于 2019-03-30 22:20:47

您可以创建一个函数,该函数创建基类的私有实例,并返回一个代理,该代理将属性检索分派到其中一个对象。基类可以传递给构造函数以保持其泛型:

代码语言:javascript
复制
createMix(Map, EventTarget)

有几件事仍然会有问题。一个阻塞问题是方法调用通常需要将this设置为基本对象才能工作。一种变通办法可能是返回一个绑定的方法,知道这本身可能会产生不良的影响(例如,客户不能接受该方法并将其自己绑定到其他东西上--如果这是有意义的话)。

当然,这并不能解决所有潜在的问题,但它似乎在非常基本的用法中起作用:

代码语言:javascript
复制
function createMix(...classes) {
    const obj = {};
    const instances = [obj, ...classes.map(cls => new cls)];
    return new Proxy(obj, {
        get(obj, prop) {
            obj = instances.find(obj => prop in obj);
            const val = Object(obj)[prop];
            return typeof val === "function" ? val.bind(obj) : val;
        },
        has(obj, prop) { // Optional: if you care about the `in` operator
            return instances.some(obj => prop in obj);
        }
    });
}

// Tiny test
const obj = createMix(Map, EventTarget);
obj.set('foo','bar'); 
console.log("Map contains: ", Object.fromEntries(obj));
obj.addEventListener('foo', e => console.log("Event object type: ", e.type) );
obj.dispatchEvent( new Event('foo') );

由于该函数返回一个容器对象,因此它不会对传递给该函数的任何基类执行instanceof操作。

票数 1
EN

Stack Overflow用户

发布于 2019-03-30 21:21:24

现在,对于其他寻求解决这个问题的人,我提出了这个解决方案

代码语言:javascript
复制
const wm = new WeakMap();

function Emitter(Base) {
   return class extends Base {
    constructor() {
        super(...arguments);
        wm.set(this, new EventTarget())
    }

    addEventListener() {
        wm.get(this).addEventListener(...arguments)
    }

    dispatchEvent() {
        wm.get(this).dispatchEvent(...arguments)
    }

    removeEventListener() {
        wm.get(this).removeEventListener(...arguments)
    }
  }
}

// how to use
const EmitterableMap = Emitter(Map);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55431060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档