【问题标题】:Importing old javascript with namespace from ES6从 ES6 导入带有命名空间的旧 javascript
【发布时间】:2019-05-26 12:29:50
【问题描述】:

我正在使用 babel 和 webpack 将旧的 javascript 转换为 ES6。 在多个文件中我有类似的东西

var BLOG = BLOG || {};
BLOG.myClass1 = ...

在另一个文件中

var BLOG = BLOG || {};
BLOG.myClass2 = ...

所以,我已经在这些文件中添加了export {BLOG},但是如何多次导入 BLOG?似乎不允许,而我想做类似的事情

import {BLOG} from 'file1.js'
import {BLOG} from 'file2.js'

并将 myClass1 和 myClass2 放入 BLOG。

有没有办法做到这一点?

【问题讨论】:

  • 你应该导出类,而不是命名空间。
  • 问题是我的代码使用了new BLOG.myClass1之类的类,所以我必须重写所有代码吗??
  • 是的,你知道。模块的重点是根本不使用命名空间。
  • @cdarwin - 公平地说,将BLOG.myClass1 更改为MyClass1(使用标准命名约定)是一个非常简单的搜索和替换。在任何 *nix 上,您都可以向它抛出 sed...

标签: javascript webpack ecmascript-6 namespaces


【解决方案1】:

所以,我已将export {BLOG} 添加到这些文件中,但如何多次导入BLOG

您必须为它们使用不同的导入绑定:

import {BLOG as BLOG1} from 'file1.js';
import {BLOG as BLOG2} from 'file2.js';

...然后使用BLOG1BLOG2。或者,如果这让您感到困扰,请添加

const BLOG = Object.assign({}, BLOG1, BLOG2);

导入后继续使用BLOG

如果您有循环依赖项,BLOG1BLOG2 可能不会立即被完全填充。使用真正的import/export,在这种情况下,您收到的对象将具有它们的属性,但这些属性还不会初始化。因此,使用真正的import/export 或良好的模拟,您可以使用访问器属性来处理它:

// In a true ES2015+ module environment, or a simulated one that
// creates the properties up-front like the real one does
const BLOG = (() => {
    const b = {};
    for (const blog of [BLOG1, BLOG2]) {
        for (const key of Object.keys(blog)) {
            Object.defineProperty(b, key, {
                get(name) {
                    return blog[name];
                }
            });
        }
    }
    return b;
})();

(显然,您会将其包装在一个函数中并重用它。)

在模拟模块环境中,它不像真实的那样预先创建属性,您可以使用代理(当然,如果您要在 ES2015 之前的环境中运行它,它不会有Proxy):

const BLOGS = [BLOG1, BLOG2];
const BLOG = new Proxy({}, {
  get(target, propName, receiver) {
    const b = BLOGS.find(b => propName in b) || target;
    return Reflect.get(b, propName, receiver);
  }
});

然后,添加到 BLOG1BLOG2 的属性在事后仍然得到正确解析。

为了避免接下来提到的搜索和替换,所有这些都非常麻烦


但是:不要导出BLOGas SLaks says,而是导出类并导入它们。当您使用适当的模块时,不需要“命名空间对象”。

export { myClass1 };

export { myClass2 };

然后

import { myClass1 } from "file1.js";
import { myClass2 } from "file2.js";

您甚至可以按照自己的定义导出类:

export function myClass1() { /* ... */ }

或者如果使用class 表示法:

export class myClass1 { /* ... */ }

在多个文件中将new BLOG.myClass1 更改为new MyClass1 是一个非常简单的搜索和替换。在 *nix 上,您可以向它抛出 sed 并创建整个目录树...


旁注:JavaScript 中的压倒性约定是构造函数(通常松散地称为“类”,例如,与new 一起使用的函数)以首字母大写字符编写。例如,MyClass1MyClass2

【讨论】:

  • Slaks 说我必须重写所有使用 new BLOG.myClass1 之类的调用的代码,你同意吗?
  • @cdarwin - 点击刷新。 :-) 你没有必须,但你可能想...
  • 对不起,我不明白。如果我将 BLOG 作为 BLOG1 导入,如何保持客户端代码不变?在我看来,我必须用新的 BLOG1.myClass1 替换我的代码,我错了吗?即使我在没有命名空间的情况下导出/导入类,我也无法执行 new BLOG.myClass1 之类的操作,但我必须执行 new myClass1(再次重写我的代码)
  • @cdarwin - 是的,您必须使用BLOG1.myClass1(或者当您在问题cmets 中提出关于必须更新您的代码的担忧时,我添加了const BLOG = Object.assign({}, BLOG1, BLOG2); 的东西)。但同样:使用任何合理的文本编辑器(或sed 或类似工具)更新该代码真的非常简单。你没有重写任何东西。您正在执行搜索和替换。
  • const BLOG = Object.assign({}, BLOG1, BLOG2);是一个很好的建议,我想我会用这个。不管你是对的,这是搜索和替换,但我担心我会弄得一团糟。
【解决方案2】:

您需要通过以下方式使用导入

{BLOG as variable name} from file

【讨论】:

    猜你喜欢
    • 2016-05-17
    • 2023-03-13
    • 2010-10-29
    • 1970-01-01
    • 2021-03-20
    • 2020-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多