ES6 模块和装饰器模式
ES6 modules and decorator pattern
我知道 import 语句向模块传递只读绑定,我想这取决于模块加载器,但是否可以使用 ES6 模块导入、修饰和重新导出?
例如,使用 rollup.js
时失败
test.plugin.js
import * as d3 from 'd3'
d3.ui = {test: 1};
export default d3;
index.js
import * as d3 from 'd3'
import './src/test.plugin'
汇总错误...
Illegal reassignment to import 'd3'
src\test.plugin.js (6:0)
4:
5: import * as d3 from 'd3'
6: d3.ui = {test: 1};
这也是...
test.plugin.js
export default (d3) => d3.ui = {test: 1};
index.js
import * as d3 from 'd3'
import test from './src/test.plugin'
test(d3);
第一个失败是因为导入是不可变的,第二个是因为模块解析是静态的。
是否可以在 ES6 模块中使用装饰器模式?
更新
问题是模块对象不可扩展。可扩展的是模块对象中的对象。
模块A
let mod = { a, b, c };
// Once exported the "mod" object cannot be extended from the outside
export mod;
index.js
// What you are saying here is
import * as mod from "moduleA.js"
// mod cannot be extended here
// mod.b can be extended though
mod.b.ui = {test: 1};
默认导出
当您执行默认导出时,您可以扩展它,因为 default
实际上是一个嵌套的 属性。
模块A
let mod = { a, b, c };
// Once exported as default
export default mod;
index.js
import mod from "moduleA.js"
// mod is effectively a prop of the module object, so it can be extended
mod.d = { ... };
对于您的情况,您可以执行以下操作:
test.plugin.js
// Import d3 as a composition of props
import * as d3 from 'd3';
// Create a new object using the Object.assign operator
// You can use the spread operator too
const d3plus = Object.assign({ui: () => 'test'}, d3);
// Now d3plus will be extendable!
export default d3plus;
index.js
import d3plus from 'test.plugin.js';
console.log(d3plus.ui);
旧的错误答案
这是我在阅读规范时弄错的答案。公平地说 some other module bundler got it wrong before hand, as es6 modules are pretty hard.
当你有模块 A
并且你想用新的 functions/things 装饰它时,你有两个选择:
- 包装模块
A
,然后仅在以后使用包装器
- 编写需要时应用的装饰器函数(如第二个示例)。
在前一种情况下你可以这样做:
test.plugin.js
import * as d3 from 'd3'
d3.ui = {test: 1};
export default d3;
index.js
// Note that using this wrapper makes sure you have the extra stuff all the time
import d3plus from './src/test.plugin';
console.log(d3plus.ui);
使用第二种方法,您必须获得装饰器操作的结果:
test.plugin.js
export default (d3) => {
d3.ui = {test: 1};
// Do not forget to return the new object
return d3;
};
index.js
import * as d3 from 'd3'
import pluginify from './src/test.plugin'
// Note that this change is local to this module only
const d3plus = pluginify(d3);
console.log(d3plus.ui);
您可以使用更多技巧来获得相同的结果,但我建议明确说明您应用到模块的丰富过程。
我知道 import 语句向模块传递只读绑定,我想这取决于模块加载器,但是否可以使用 ES6 模块导入、修饰和重新导出?
例如,使用 rollup.js
时失败test.plugin.js
import * as d3 from 'd3'
d3.ui = {test: 1};
export default d3;
index.js
import * as d3 from 'd3'
import './src/test.plugin'
汇总错误...
Illegal reassignment to import 'd3'
src\test.plugin.js (6:0)
4:
5: import * as d3 from 'd3'
6: d3.ui = {test: 1};
这也是...
test.plugin.js
export default (d3) => d3.ui = {test: 1};
index.js
import * as d3 from 'd3'
import test from './src/test.plugin'
test(d3);
第一个失败是因为导入是不可变的,第二个是因为模块解析是静态的。
是否可以在 ES6 模块中使用装饰器模式?
更新
问题是模块对象不可扩展。可扩展的是模块对象中的对象。
模块A
let mod = { a, b, c };
// Once exported the "mod" object cannot be extended from the outside
export mod;
index.js
// What you are saying here is
import * as mod from "moduleA.js"
// mod cannot be extended here
// mod.b can be extended though
mod.b.ui = {test: 1};
默认导出
当您执行默认导出时,您可以扩展它,因为 default
实际上是一个嵌套的 属性。
模块A
let mod = { a, b, c };
// Once exported as default
export default mod;
index.js
import mod from "moduleA.js"
// mod is effectively a prop of the module object, so it can be extended
mod.d = { ... };
对于您的情况,您可以执行以下操作:
test.plugin.js
// Import d3 as a composition of props
import * as d3 from 'd3';
// Create a new object using the Object.assign operator
// You can use the spread operator too
const d3plus = Object.assign({ui: () => 'test'}, d3);
// Now d3plus will be extendable!
export default d3plus;
index.js
import d3plus from 'test.plugin.js';
console.log(d3plus.ui);
旧的错误答案
这是我在阅读规范时弄错的答案。公平地说 some other module bundler got it wrong before hand, as es6 modules are pretty hard.
当你有模块 A
并且你想用新的 functions/things 装饰它时,你有两个选择:
- 包装模块
A
,然后仅在以后使用包装器 - 编写需要时应用的装饰器函数(如第二个示例)。
在前一种情况下你可以这样做:
test.plugin.js
import * as d3 from 'd3'
d3.ui = {test: 1};
export default d3;
index.js
// Note that using this wrapper makes sure you have the extra stuff all the time
import d3plus from './src/test.plugin';
console.log(d3plus.ui);
使用第二种方法,您必须获得装饰器操作的结果:
test.plugin.js
export default (d3) => {
d3.ui = {test: 1};
// Do not forget to return the new object
return d3;
};
index.js
import * as d3 from 'd3'
import pluginify from './src/test.plugin'
// Note that this change is local to this module only
const d3plus = pluginify(d3);
console.log(d3plus.ui);
您可以使用更多技巧来获得相同的结果,但我建议明确说明您应用到模块的丰富过程。