【问题标题】:node/js es6 "class" inherit prototype (chain) from functionnode/js es6“类”从函数继承原型(链)
【发布时间】:2021-04-28 08:55:24
【问题描述】:

是否可以从 es6 类定义中的函数 inerhit 原型链?

const { PassThrough } = require("stream");
const duplexer = require("duplexer3");


class Interface {

    constructor(obj, options) {

        options = Object.assign({
            decodeStrings: false,
            autoClose: false,
            objectMode: true
        }, options);

        let reader = new PassThrough(options);
        let writer = new PassThrough(options);


        // use duplex stream as prototype
        this = duplexer(options, reader, writer);



        Object.assign(this, obj);

    };

};


const iface = new Interface({
    _id: "60891a02256c0c7931395c48",
    settings: {
        port: 8080,
        host: "127.0.0.1"
    }
});
this = duplexer(options, reader, writer);

给我错误:

        this = duplexer(options, reader, writer);
        ^^^^

SyntaxError: Invalid left-hand side in assignment
    at Object.compileFunction (vm.js:344:18)
    at wrapSafe (internal/modules/cjs/loader.js:1048:15)
    at Module._compile (internal/modules/cjs/loader.js:1082:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1138:10)
    at Module.load (internal/modules/cjs/loader.js:982:32)
    at Function.Module._load (internal/modules/cjs/loader.js:875:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47

如果我使用extendssuper,它可以工作,但我在接口对象上有双工器流的属性,但我想“隐藏”它们,在原型链的上层。

class Interface extends duplexer {

    constructor(obj, options) {

        options = Object.assign({
            decodeStrings: false,
            autoClose: false,
            objectMode: true
        }, options);

        let reader = new PassThrough(options);
        let writer = new PassThrough(options);

        super(options, reader, writer)
        Object.assign(this, obj);

    };

};

不确定,如果这是可能的或者我理解正确,但是当我从其他类/对象中获取某些属性时,它们“停留”在其原始对象范围内,当我想访问它们时,引擎“看起来" 向上直到找到一个属性,如果没有,它的undefined

我的目标是拥有干净的“交互”对象实例,将属性传递给我的构造函数,并且仍然能够使用 node.js 流特定方法(读/写/等)

感谢您的帮助。

编辑:我找到了使用代理对象的解决方法:

class Root {
    constructor() {
        this.root = true;
    }
    rootMethod() {
        console.log("i am root");
    }
}


class Parent extends Root {
    constructor() {
        super();
        this.parent = true;
    }
    parentMethod() {
        console.log("i am parent");
    }
}

class Child extends Parent {
    constructor() {
        super();
        this.child = true;
    }
    childMethod() {
        console.log("i am child")
    }
}


class Interface {
    constructor() {
        this.settings = {
            host: "0.0.0.0",
            port: 8030
        }
    }
}

const root = new Root();
const parent = new Parent();
const child = new Child();
const iface = new Interface();


const proxy = new Proxy(child, {
    get: function (target, prop) {

        if (target[prop]) {
            return target[prop];
        } else {
            return iface[prop];
        }

    }
});


//console.log(root, root.rootMethod);
//console.log(parent, parent.parentMethod);
//console.log(child, child.childMethod);

console.log(proxy.settings, proxy.rootMethod)

这会检查代理对象上是否存在属性,如果不存在,则尝试访问隐藏对象上的属性。

【问题讨论】:

  • 更喜欢组合而不是继承 - 只是有一个 .#duplex 成员并将流接口委托给它? (或者更好 - 改用异步迭代器:D)
  • @BenjaminGruenbaum 感谢您的回复。你能给我一个“组合”的描述/链接/示例吗?第一次听说...这看起来很简单,但我想不通,这让我发疯了
  • 我理解这个概念,但我无法将代码放在一起解决我的问题。我所做的只是“接口”范围被父/双工器方法/属性污染。我不知道为什么...pastebin.com/raw/ihGvi1aX是我能做的最接近的,但这里是类名“流”显示在console.log,这不太好......我不明白,在普通的 js 对象中它也可以工作......
  • @BenjaminGruenbaum 您如何看待我的解决方法,使用代理对象?

标签: javascript class inheritance stream


【解决方案1】:

这是肯定的。你只需要修改子类的原型原型,就可以了。

查看代码:

class Interface {}
Object.setPrototypeOf(Interface.prototype, Duplex.prototype)
const instance = new Interface
// you are able to call method from Duplex
instance.someMethodFromDuplex()

【讨论】:

  • 你能给我一个“工作”的例子吗?我必须将参数传递给duplexer 函数。这不是来自 node.js 内部的“双工”流。我不了解您的代码 sn-p 足以按照我需要的方式扩展它。这里的原型链:medium.com/developers-arena/… 就是我所说的。我想要“继承 - ES5 方式”的结果,但使用我的 sn-p 中的双工器方法
  • 其实extends关键字完全符合你的需求。但我看到你想从 Duplexer 中“隐藏”属性,这个要求看起来有点不寻常。这样做的必要原因是什么?也许我们可以找到一些替代方法。
  • 接口实例(带有它的属性)应该通过 API 发送并显示在前端,当范围内充斥着来自超级/父类的属性时,它会变得凌乱且不干净。我的意思是,它也适用于标准的 js 对象/函数……看看这里:pastebin.com/raw/ihGvi1aX 这很接近,但正如你在console.log 中看到的那样,它说它是一个“流”对象,而不是我的“接口” " 对象,有没有办法“更改”正在显示的名称?
  • 根据您描述的情况,我认为更好的方法是您可以实现一个类的函数,该函数返回一个明确包含您要通过 API 发送的内容的对象,然后使用它函数的返回值,而不是将整个实例传递给您的 AJAX 方法。这种方式非常清晰和声明性。顺便说一句,在您的 sn-p console.log 中显示了一个 Interface 对象,这显然是正确的结果。
  • 在节点中显示一个“流”对象。在浏览器中,我没有看到类名。可以发截图吗?编辑:在 Chromium 中,它确实显示了一个“接口”对象/名称。这很有趣...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多