Javascript 在具有属性的ES6模块上使用闭包编译器

Javascript 在具有属性的ES6模块上使用闭包编译器,javascript,ecmascript-6,gulp,google-closure-compiler,es6-modules,Javascript,Ecmascript 6,Gulp,Google Closure Compiler,Es6 Modules,因此,经过一天的测试,我几乎做到了:使用和缩小/编译基于ES6模块的“库” 只剩下一个问题了。如何调用导入模块的属性 我的测试用例由3个文件组成: gulpfile.js const gulp = require("gulp"); const compiler = require("google-closure-compiler-js").gulp(); const sourcemaps = require("gulp-sourcemaps"); gulp.task("default", fu

因此,经过一天的测试,我几乎做到了:使用和缩小/编译基于ES6模块的“库”

只剩下一个问题了。如何调用导入模块的属性

我的测试用例由3个文件组成:

gulpfile.js

const gulp = require("gulp");
const compiler = require("google-closure-compiler-js").gulp();
const sourcemaps = require("gulp-sourcemaps");

gulp.task("default", function() {
// wildcards don't seem to work yet with the js version
// files need to be in reverse order of dependency...
return gulp.src(["src/boilerplate/main.js", "src/app.js"])
    .pipe(sourcemaps.init())
    .pipe(compiler({
        jsOutputFile: "app.min.js",
        compilationLevel: "ADVANCED",
        warningLevel: "VERBOSE",
        createSourceMap: true
    }))
    .pipe(sourcemaps.write("/"))
    .pipe(gulp.dest("./dist"));
});
var mod = {};
export default mod;

var foo = "FOO";
var bar = "BAR";

function foobar(join) {
    join = (typeof join === "string") ? join : "";
    return foo + join + bar;
}
Object.defineProperty(mod, "foobar", {value: foobar});
import boilerplate from "./boilerplate/main.js";

console.log(boilerplate["foobar"]("+"));
console.log(boilerplate.foobar("+"));

src/boilerplate/main.js

const gulp = require("gulp");
const compiler = require("google-closure-compiler-js").gulp();
const sourcemaps = require("gulp-sourcemaps");

gulp.task("default", function() {
// wildcards don't seem to work yet with the js version
// files need to be in reverse order of dependency...
return gulp.src(["src/boilerplate/main.js", "src/app.js"])
    .pipe(sourcemaps.init())
    .pipe(compiler({
        jsOutputFile: "app.min.js",
        compilationLevel: "ADVANCED",
        warningLevel: "VERBOSE",
        createSourceMap: true
    }))
    .pipe(sourcemaps.write("/"))
    .pipe(gulp.dest("./dist"));
});
var mod = {};
export default mod;

var foo = "FOO";
var bar = "BAR";

function foobar(join) {
    join = (typeof join === "string") ? join : "";
    return foo + join + bar;
}
Object.defineProperty(mod, "foobar", {value: foobar});
import boilerplate from "./boilerplate/main.js";

console.log(boilerplate["foobar"]("+"));
console.log(boilerplate.foobar("+"));

src/app.js

const gulp = require("gulp");
const compiler = require("google-closure-compiler-js").gulp();
const sourcemaps = require("gulp-sourcemaps");

gulp.task("default", function() {
// wildcards don't seem to work yet with the js version
// files need to be in reverse order of dependency...
return gulp.src(["src/boilerplate/main.js", "src/app.js"])
    .pipe(sourcemaps.init())
    .pipe(compiler({
        jsOutputFile: "app.min.js",
        compilationLevel: "ADVANCED",
        warningLevel: "VERBOSE",
        createSourceMap: true
    }))
    .pipe(sourcemaps.write("/"))
    .pipe(gulp.dest("./dist"));
});
var mod = {};
export default mod;

var foo = "FOO";
var bar = "BAR";

function foobar(join) {
    join = (typeof join === "string") ? join : "";
    return foo + join + bar;
}
Object.defineProperty(mod, "foobar", {value: foobar});
import boilerplate from "./boilerplate/main.js";

console.log(boilerplate["foobar"]("+"));
console.log(boilerplate.foobar("+"));

如果您在这里记录
样板文件
,您会看到它具有属性“foobar”。符号完整无缺。太好了

因此app.js的第一个调用——括号符号[“foobar”]——工作得非常好。但是,点表示法并不适用。闭包编译器会缩小对导入模块属性的调用
您会收到经典的“嗨,我是高级模式新手”错误:
TypeError:a.a不是函数

我如何防止这种情况?(为了现实世界,我们假设直接导出foobar是不可行的。)

  • 我需要导出文件吗?我到底要怎么做?我在那个方向的第一次冒险并没有带我走多远。。。有什么特别的窍门吗

  • 在闭包编译器添加一个不会自动重命名对导入属性的调用的功能之前,是否存在允许点表示法的黑客行为

  • 这篇关于JS模块类型引用的文章建议我做什么?这就是我未能实现的答案吗

    /**@param{foo.foo}foo*/
    函数(Foo){}


对于高级模式兼容性,请使用
Object.defineProperties
避免使用带引号的字符串

Object.defineProperties(mod, {
  foobar: {value: foobar}
});

无论何时使用带引号的字符串,都需要使用括号(或其他技术),否则可能会违反一致的属性访问规则。

出于好奇,为什么要使用
mod
对象而不是仅使用命名导出?除其他外,这将防止树上攀爬。为什么需要
对象。defineProperty
?您可以这样轻松地定义模块:
var mod={foobar}@T.J.Crowder部分原因是为了防止爬树;如果我想创建一个以小型版本分发的库,那会是理想的吗?另一件事是,我想测试如何实际导出和访问一个对象。当然,这在这里毫无意义!,使用foobar函数。@Andy我绝对可以做到!它是ES5的遗物,在ES5中,以这种方式定义它会自动使其非枚举、非配置、不可写。使用不再需要的模块。好球。:)@不,爬树是你希望你的图书馆启用的一件好事。如果使用你的库的应用程序不需要函数X,那么树形搜索可以将函数X从捆绑包中删除。是的!神圣的烟。那是丢失的一块。非常感谢。