允许用户在上下文中修改导入的 ES6 模块函数
Allowing users to modify imported ES6 module functions in context
我对某些事情是否可行感到很困惑。
我创建了一个包含以下内容的模块:
export function logText(){
console.log('some text');
}
export class Example {
constructor(){
logText();
}
}
目的是让用户调用 new Example
来启动模块逻辑。
import { logText, Example } from 'example';
// Do some magic here to modify the functionality of logText
new Example();
最终用户是否可以修改logText?
如果用户有一种方法可以做这样的事情,那将是有意义的,否则他们必须将整个模块放入他们自己的存储库中,只是为了进行一些小的功能调整。
我经常看到 repos 中导出了许多无用的功能,用户无需手动重新制作几乎所有功能,这使得这样做毫无意义。一个很好的例子是 this repo,他们甚至将导出函数称为 'API'。在那个例子中,这些都是毫无意义的出口,更糟糕的是,如果有人试图将它们与主要功能结合使用,只会导致问题。但是,如果您可以修改它们并让它们保持不变 运行,那对我来说就有意义了。
Is it possible for the end user to modify logText?
不,那不可能,import
绑定是不可变的,函数对象基本上是不可变的,它们包含的代码。
It would make sense for there to be a way for users to do something like this, or they'd have to take the entire module into their own repo just to make small functionality tweaks.
为什么不让日志函数成为构造函数中的可选参数?通常,当某些东西是可变的时,它就变成了参数。
export class Example {
constructor(log=logText){
log();
}
}
鉴于此:
import { logText, Example } from 'example';
Is it possible for the end user to modify logText?
由于您对 "modify logText" 的含义不是很明确,我将介绍几种选择:
Can you reassign some other function to the variable logText
?
没有。你不能这样做。当您使用 import
时,它会创建一个 const
且无法分配给的变量。即使它不是 const,它也只是一个本地符号,无论如何都不会影响其他模块对其 logText()
的使用。 import
机制就是故意这样设计的。你的模块的加载器不应该能够替换模块的内部实现部分,这些部分不是专门设计用来替换的。
Can you modify the code inside of the logText
function from outside of the module that contains it?
不,你不能。模块中的代码存在于它自己的函数范围内,这赋予了它隐私。您不能从模块外部修改该模块内的代码。
Can you replace the logText()
function inside the module such that the implementation of Example
inside that class will use your logText()
function?
不,您不能从模块外部执行此操作。您实际上必须修改模块的代码本身,或者有人必须设计 Example 接口以具有 Example 对象使用的可替换或可修改的 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();
Can you create your own version of logText
and use it locally?
当然可以。
function myLogText() {
do your own thing
}
而且,您甚至可以不导入 logText,这样您就可以根据需要在本地使用符号名称 logText()
。但是,这根本不会影响 Example 的功能。
Are there ways to design the example module so that that logText()
can be easily replaced.
是的,有很多方法可以做到这一点。我在上面展示了一个使 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');
};
我通常不推荐这样做,因为它会让您在同一模块的多个用户之间发生使用冲突,每个用户都试图以相互冲突的方式全局修改它。子类化模型(上面提到的)允许模块的每次使用都以自己的方式自定义,而不会与模块的其他使用冲突。
我对某些事情是否可行感到很困惑。
我创建了一个包含以下内容的模块:
export function logText(){
console.log('some text');
}
export class Example {
constructor(){
logText();
}
}
目的是让用户调用 new Example
来启动模块逻辑。
import { logText, Example } from 'example';
// Do some magic here to modify the functionality of logText
new Example();
最终用户是否可以修改logText?
如果用户有一种方法可以做这样的事情,那将是有意义的,否则他们必须将整个模块放入他们自己的存储库中,只是为了进行一些小的功能调整。
我经常看到 repos 中导出了许多无用的功能,用户无需手动重新制作几乎所有功能,这使得这样做毫无意义。一个很好的例子是 this repo,他们甚至将导出函数称为 'API'。在那个例子中,这些都是毫无意义的出口,更糟糕的是,如果有人试图将它们与主要功能结合使用,只会导致问题。但是,如果您可以修改它们并让它们保持不变 运行,那对我来说就有意义了。
Is it possible for the end user to modify logText?
不,那不可能,import
绑定是不可变的,函数对象基本上是不可变的,它们包含的代码。
It would make sense for there to be a way for users to do something like this, or they'd have to take the entire module into their own repo just to make small functionality tweaks.
为什么不让日志函数成为构造函数中的可选参数?通常,当某些东西是可变的时,它就变成了参数。
export class Example {
constructor(log=logText){
log();
}
}
鉴于此:
import { logText, Example } from 'example';
Is it possible for the end user to modify logText?
由于您对 "modify logText" 的含义不是很明确,我将介绍几种选择:
Can you reassign some other function to the variable
logText
?
没有。你不能这样做。当您使用 import
时,它会创建一个 const
且无法分配给的变量。即使它不是 const,它也只是一个本地符号,无论如何都不会影响其他模块对其 logText()
的使用。 import
机制就是故意这样设计的。你的模块的加载器不应该能够替换模块的内部实现部分,这些部分不是专门设计用来替换的。
Can you modify the code inside of the
logText
function from outside of the module that contains it?
不,你不能。模块中的代码存在于它自己的函数范围内,这赋予了它隐私。您不能从模块外部修改该模块内的代码。
Can you replace the
logText()
function inside the module such that the implementation ofExample
inside that class will use yourlogText()
function?
不,您不能从模块外部执行此操作。您实际上必须修改模块的代码本身,或者有人必须设计 Example 接口以具有 Example 对象使用的可替换或可修改的 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();
Can you create your own version of
logText
and use it locally?
当然可以。
function myLogText() {
do your own thing
}
而且,您甚至可以不导入 logText,这样您就可以根据需要在本地使用符号名称 logText()
。但是,这根本不会影响 Example 的功能。
Are there ways to design the example module so that that
logText()
can be easily replaced.
是的,有很多方法可以做到这一点。我在上面展示了一个使 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');
};
我通常不推荐这样做,因为它会让您在同一模块的多个用户之间发生使用冲突,每个用户都试图以相互冲突的方式全局修改它。子类化模型(上面提到的)允许模块的每次使用都以自己的方式自定义,而不会与模块的其他使用冲突。