所有当前模块加载器(如AMD,CommonJS,SystemJS
)使用变量定义将外部对象加载到当前模块范围
像:
var something = require('something');
或:
define('module',['something'],function(something){});
如果您不知道需要从外部模块导入什么,或者只需要导入所有内容,这就成了问题,因为无法在运行时定义变量。
我猜这是ES6翻译不使用
的主要原因import * from 'something';
语法,它们不包含在ES6规范中。
所以说动态模块范围我的意思是模块变量可以定义/加载运行时,这将允许将ES6语法扩展为某种东西 喜欢:
import * from 'something';
import Something.* from 'something';
import /regexp/ from 'something';
在我看来,这是定义导入的更佳方式,而不是列出所有名称,如:
import {
ONE,
TWO,
...
} from 'something';
现在我真正的问题:
为什么不使用
with
来实现这一目标?
以下是从ES6到ES5的简单示例翻译,可以解决问题:
file:modules / module-1.js
var localVar = 'VALUE';
function localFun(a,b){
return a +' and '+ b;
}
export {
localVar as module1Var
localFun as module1Fun
}
于:
(function(){
// define module named 'modules/module-1'
// and return related scope object
// containing 'execute_module' function predefined
with (define_module('modules/module-1')) {
// will register actual module execution
// which will be called after all imports
// initialized
execute_module(function(){
var localVar = 'VALUE';
function localFun(a,b){
return a +' and '+ b;
}
// returns value as current module exports
return {
module1Var : localVar,
module1Fun : localFun
// ...
};
});
}
})();
file:modules / module-1.js
import * from 'modules/module-1.js';
console.info(module1Fun(module1Var)); //prints: VALUE and VALUE
于:
(function(){
// define module named 'modules/module-2'
// after execute is called loader will do
// all imports and bind exports from modules
// to current module scope and then invoke callback
// after which imported variables will appear in with scope
// and will be visible in callback scope.
with (define_module('modules/module-2',{
'modules/module-1' : '*',
// also can filter exports by regexp
'modules/other' : /.*/
})) {
execute_module(function(){
console.info(module1Fun(module1Var)); //prints: VALUE and VALUE
});
}
})();
是否真的有必要避免
with
甚至在转发器/加载器中?
我将非常感谢您对这些人的看法,因为我正在考虑编写另一个ES6to5转换器和模块加载器。 :)
答案 0 :(得分:2)
所以有一些很好的理由不这样做......
......首先,简单来说,JS的不良做法是将全球或全球的工作环境付诸实践。变量,不知道那些变量是什么。
如果该导入的内容发生变化,并且我使用的是with
(这不是真正有效的ES5 ...... ...... ES5是严格模式子集,{{1留下来允许ES3代码在ES5浏览器中运行而不会爆炸),然后我要担心的不仅仅是尝试调用已更改的模块上的方法......
with
看起来很好,当然。没有任何伤害。
如果// some-module/v1.0/some-module.js
// ...
export { doA, doB, a, b }
// my-app/index.js
import * with "./some-module/v1.0/some-module";
const c = 1;
let doC = ( ) => doA( a ) + doB( b );
是NPM包,并且我处于开发模式,那么我希望在功能添加中不断更新some-module
,因为我知道某些功能会使当他们降落时,我的生活更轻松:
some-module
<强> BOOM! 强>
// some-module/v1.5/some-module.js
export { doA, doB, doC, a, b, c };
// my-app/index.js
import * with "./some-module/v1.5/some-module";
const c = 1;
/*
...
*/
let doC = ( ) => doA( a ) + doB( b );
。
如果您搜索所有已编译的导入库/模块/组件(假设您的应用程序的入口点中有8个)... ...并且您终于找到了源代码导入c is already defined
作为全局,并更新所有您的代码,将c
的名称替换为其他名称,然后替换所有对它的引用,以便他们不再爆炸,接下来会发生什么?
<强> BOOM! 强>
c
。
重复此过程并找到有问题的文件。
我们如何解决这些问题?
通常,这是通过命名空间。
我们已经在那些doC is already defined
语句中拥有命名空间,这些语句大部分工作正常(在ES7中进一步简化了进一步的提案)。
import
突然之间,您可以清楚地看到应用程序中的任何地方都存在 no 对方法/值冲突的恐惧,除非它是您自己的错误。
此外,如果您加载整个库并决定通过直接引用这些值/方法的某些来节省时间,则可以选择来执行此操作。< / p>
import someModule from "./some-module/v1.0/some-module";
let doC = ( ) => someModule.doA( someModule.a ) + someModule.doB( someModule.b );
仍有0%的歧义,但所有代码都保持尽可能小,这要归功于让消费者选择如何处理导入。
答案 1 :(得分:0)
@norguard, good catch on "strict mode" and module updates, but:
strict mode still can be used in actual execution callback
booms ! definitions of local execution scope will override(hide) definitions of with scope in current context, so there are no problem of redefinition.
// some-module/v1.5/some-module.js
export { doA, doB, doC, a, b, c };
// my-app/index.js
import * with "./some-module/v1.5/some-module";
const c = 1;
/*
...
*/
let doC = ( ) => doA( a ) + doB( b );
// translated to:
(function(){
// with scope contain { doA, doB, doC, a, b, c }
with (define_module('my-app/index.js',{
'some-module/v1.5/some-module.js':'*'
})) {
execute_module(function(){
"use struct"
// local var 'c' overrides definition 'c' of 'with scope'
// in current function context.
var c = 1;
// same for 'doC' function
var doC = function( ){return doA( a ) + doB( b )};
});
}
})();
So the everything above still will work.