如何使用 javaScript 文件作为其他 JavaScript 文件的高阶包装器

Posted

技术标签:

【中文标题】如何使用 javaScript 文件作为其他 JavaScript 文件的高阶包装器【英文标题】:How to use javaScript file as Higher Order wrapper for other JavaScript File 【发布时间】:2020-08-13 20:35:14 【问题描述】:

我想问一下,因为在反应中我们有 HOC(高阶组件),我们传递修改它的组件,然后返回修改后的组件以供使用

我们可以在 javascript 中做同样的事情吗?

举例

// index1.js
// this is file where i am importing all the folder modules and exporting them

export  methodA, methodB  from './xyzAB'
export  methodC, methodD  from './xyzCD'

我正在将这个文件导入到另一个文件夹中

import * as allMethods from './modules'

// this allows me to use this syntax
allMethods.methodA()
allMethods.methodB()

这工作正常,但我正在寻找这种包装器

// index2.js 
// this is another file somewhere else where i want to use index1.js exported methods

import * as allMethods from './modules/xyz'
import anotherMethod from './somewhere/xyz'

// here i want customize some of `allMethods` functions and export them as new object
//which contains modifed version of default `index1.js` methods

allMethods.methodA = allMethods.methodA( anotherMethod ) // this is example of modified as HO Method


export default allMethods

我上面的例子可能看起来很混乱, 为什么我要寻找这样的解决方案,我有一组实用程序,我试图将它们作为库并在多个项目中使用它们,

现在一些实用程序依赖于与主要项目相关的东西,所以不要给我的实用程序硬编码引用它们的依赖项, 我想通过我的高阶方法或配置文件为不同的方法传递不同的依赖关系, 以便每个新项目从其配置或更高阶的包装文件中传递其依赖的实用程序,如上所示

我希望我能解决我的问题,

我尝试过的几件事, 我尝试将所有模块导入我算作包装文件的文件中 如果我尝试使用任何返回 webpack 错误的模块作为未定义的方法,由于方法直到几秒钟才完全加载,我尝试了 setTimeOut,它工作正常,但这不是管理事物的有效方式,

然后我尝试了一些异步方式,我使用了返回 promise 的动态 import(),我使用了 async/await 语法,还使用了 .then 语法但无法提取数据并将其保存为变量(我可能正在做某事在这一步出错,但我完全失败了)但这仅适用于承诺或异步等待范围,

还尝试了其他步骤,

我希望我能找到一些更简洁的语法,如下所示

import * as F from '../../core/lib/functions'
import  getModel  from '../entities'

F.getKeys = F.getKeys( getModel )


export default F

欢迎提出建议

【问题讨论】:

【参考方案1】:

我认为您正在寻找的是某种柯里化或类似工厂的模式。

没有高阶模块这样的东西,但由于 JavaScript 支持高阶函数,所以你应该使用它。

提醒一下,高阶组件是将一个组件作为参数并返回另一个组件的任何组件。类似地(简化),高阶函数是将函数作为参数并返回新函数的函数。 (实际上所有 React 组件或多或少都是函数,因此我们能够拥有更高阶的组件)。

关键是你需要调用一个高阶函数,而不仅仅是导入它(同样,没有高阶模块之类的东西)。但这与您对依赖注入的想法非常吻合。

我想,你想要的是在你的实用程序中是这样的:

function a(dependency1, arg1, arg2) 

function b(dependency2, arg1, arg2) 

function createUtils(dependency1, dependency2) 
  return 
       a: a.bind(null, dependency1), 
       b: b.bind(null, dependency2) 
   

这允许您自定义每个项目的依赖项 1 和 2 是什么以及它们如何工作的详细信息(使用一些通用接口)。使用绑定,您不必在每次调用函数时都传递该依赖项。

然后在您的一个项目中,您将设置它们如下:

import  createUtils from 'utils';
import  dependency1, dependency2  from 'somewhere' ;

const  a, b  = createUtils(dependency1, dependency2)

export  a, b ;

你并没有真正做任何高阶函数的事情,就像我说的那样,这更像是工厂/依赖注入的事情。虽然bind 是一个高阶函数(它接受调用它的函数并返回一个绑定了一些参数的新函数)。

您可以通过带有选项的另一个参数在 createUtils 中放置位置进行一般修改。或者,您可以为您希望能够修改的每个方法导出较小的“工厂”。

考虑到这一点,您可能只从 utils 导出原始函数,并在模块设置代码中使用 bind 来绑定依赖项。我认为bind 是您所缺少的。以及您必须创建要导出的新函数,而不是修改导入的函数。这也意味着您在其余代码中的导入将仅来自您自己的模块,而不是来自 utils 模块。

【讨论】:

感谢您的详细回答,实际上我的实用程序中有函数组合,这里是 config/ 或更高阶文件包装器中的组合 export function getKeys(callback) return entity => callback(entity).key 之一的示例,我将为每个方法设置回调方法并将它们分配给新变量,然后从中导出,是的,在这样做之后,我将在项目中使用我当前的包装文件来导出新修改的方法我希望这更清楚我的问题 在如何实现这一点上您还有什么不清楚的地方吗? 你能告诉我这可能吗?我会做这样的事情import * as F from '../../core/lib/functions' import createModelUtils from '../../core/lib/functions' import getModel from '../entities' const getKeys = createModelUtils(getModel) export default getKeys, ...F 我想使用同一个包装文件并将其导入整个项目,我可以使用 /core/lib/ 中的所有导出方法函数,请清楚你打算如何使用这个export a, ba(null, arg1, arg2) 或者在绑定依赖后如何使用它 在导出中使用价差不起作用,请参阅***.com/questions/43300618/…。你将如何使用aimport a from './module/utils/'; a(arg1, arg2);。在执行bind 时,我们将函数上下文(this)绑定为null,并且我们将“first”参数绑定到dependency1。该函数接受 3 个参数,因此您只需要提供最后 2 个。 谢谢 milton,我能够找到有关传播的信息,我读到他们提到它处于第 3 阶段,尚未实施等,如果您仔细查看,我也能够使用这些导出的方法当我使用 * 作为 F 导入时,它需要延迟和提示变量为未定义,如果我单独构造它,它工作正常你对此有什么想法吗?如果可能的话,我们可以进行几分钟的视频群聊吗?

以上是关于如何使用 javaScript 文件作为其他 JavaScript 文件的高阶包装器的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jQuery 或其他 js 框架将字符串作为文件上传

MVC 视图和 JavaScript 文件

加快JavaScript加载和执行效率

我如何仅使用HTML CSS和JAVASCRIPT将Square Payment Gateway嵌入网站中?没有框架&&没有其他语言

如何在javascript中获取一位随机数? [复制]

动态加载 JavaScript 文件