允许用户在上下文中修改导入的ES6模块功能

时间:2018-11-06 20:10:06

标签: javascript ecmascript-6 module es6-modules

对于是否有可能,我感到非常困惑。

我创建一个包含以下内容的模块:


@SmokeTests
  Scenario: Fetch financial plan
    Given header "A-banner" is ""
    When I get "/pos/some-service/version/finances/plans"
    Then the json structure is:
        """
    {
        "result": {
            "plans": [{
                "CFID": "",
                "DTFN": {"type": ["null", "string"]},
                "COEF": "",
                "TERM": "",
                "TYPC": "",
                "DESC": "",
                "BAN": "",
                "PLAN": "",
                "ECHE": "",
                "DTEF": "",
                "TYPF": ""
            }]
        }
    }

目的是让用户调用export function logText(){ console.log('some text'); } export class Example { constructor(){ logText(); } } 以启动模块逻辑。

new Example

最终用户是否可以修改logText?

有一种方法让用户可以执行类似的操作,否则他们将整个模块都放入自己的存储库中只是为了进行小的功能调整。

我经常看到带有很多导出功能的回购,这些回购是无用的,而用户不必手动重新制作几乎所有功能,这使得它变得毫无意义。一个很好的例子是this repo,甚至将导出的函数称为“ API”。在那个例子中,这些都是毫无意义的输出,更糟糕的是,如果有人尝试将它们与主要功能结合使用,就会引起问题。但是,如果您可以修改它们并使它们仍然运行,那么对我来说就很有意义。

2 个答案:

答案 0 :(得分:1)

为此:

import { logText, Example } from 'example';
  

最终用户是否可以修改logText?

由于您对“修改logText”的含义不是很明确,因此我将介绍几种选择:

  

您可以将其他功能重新分配给变量logText吗?

不。你不能这样做。当您使用import时,它将创建一个const且无法分配给它的变量。即使它不是const,它也只是一个本地符号,无论如何不会影响其他模块对logText()的使用。 import机制是专门为此设计的。您的模块的加载程序不应该能够替换未专门设计为要替换的模块内部实现部分。

  

您可以从包含它的模块外部修改logText函数内部的代码吗?

不,您不能。模块中的代码位于其自己的功能范围内,这使它具有隐私性。您无法从模块外部修改该模块中的代码。

  

您可以替换模块中的logText()函数,以使该类中的Example实现使用您的logText()函数吗?

否,您不能从模块外部执行此操作。您将必须实际上修改模块的代码本身,或者必须设计示例接口以具有示例对象使用的可替换或可修改的logText()函数。

例如,可以将logText()设为Example的方法,然后可以使用自己的实现覆盖它,这将导致Example的实现使用您的覆盖。

您未修改的模块中的代码:

export class Example {
    constructor(){
        this.logText();
    }
    logText() {
        console.log('some text');
    }
}

执行导入的代码:

import { Example } from 'example';

class MyExample extends Example {
    constructor() {
        super();
    }
    logText() {
        console.log("my own text");
    }
}

let o = new MyExample();    
  

您可以创建自己的logText版本并在本地使用吗?

当然可以。

function myLogText() {
    do your own thing
}

而且,您甚至不能导入logText,这样就可以在本地使用符号名称logText()。但这完全不会影响Example的功能。

  

有没有一些方法可以设计示例模块,以便可以轻松替换logText()

是的,有很多方法可以做到这一点。我在上面显示了一个使logText可以被覆盖的方法。也可以将其作为可选参数传递给Example构造函数。

甚至可能存在一个导出的对象,该对象允许调用者替换该对象上的属性。例如:

export const api = {
    logText: function logText(){
        console.log('some text');
    }
};

export class Example {
    constructor(){
        api.logText();
    }
}

然后,像这样使用它:

import { api, Example } from 'example';

api.logText = function() {
    console.log('my Text');
};

我一般不建议这样做,因为它会使您陷入同一模块的多个用户之间的使用冲突,因为每个用户都试图以相互冲突的方式对其进行全局修改。子类化模型(如上所述)使模块的每次使用都可以以自己的方式自定义,而不会与模块的其他用法冲突。

答案 1 :(得分:0)

  

最终用户是否可以修改logText?

不,那是不可能的,import绑定是不可变的,而函数对象基本上是不可变的,而其中包含的代码也是如此。

  

有一种方法让用户可以执行类似的操作,否则他们将整个模块都放入自己的存储库中只是为了进行小的功能调整。

为什么不使log函数成为构造函数中的可选参数?通常,当某些东西是可变的时,它就会成为参数。

export class Example {
    constructor(log=logText){
        log();
    }
}