开发者

Closure compiler treats definitions inside closures as redefinitions

I've been working with google closure, trying to get a large body of JavaScript to compile cleanly for minimization using the Google compiler. I came across a problem though:

goog.provide('test');
goog.provide('test2');

/**
 * @constructor
 */
test = function () {
    this.x = 10;
    this.y = 13;
};

(function () {
    /**
     * @constructor
     */
    test2 = function () {
        this.x = 10;
        this.y = 13;
    };
})();

The former is fine. The latter generates a constant-redefinition error:

JSC_CONSTANT_REASSIGNED_VALUE_ERROR. constant test2 assigned a value more than once at /home/hbrown/tmp/closure-test/foo.js line 16 : 10
BUILD FAILED: 1 error(s), 0 warning(s)

Is there some way to coerce plovr/closure compiler to allow this construct? I've looked around and found nothing.


Later: on a further point, why does closure/plovr consider test2 a constant? I suspect it has to do with plovr/closure's creation of a namespace for test2 when goog.provide is called. it would be nic开发者_运维技巧e to see the intermediate form that it is working with when it generates the error.


I'm typing this as an answer even though it's just a guess, because comments are terrible for code.

Have you tried something like this:

test2 = (function () {
    /**
     * @constructor
     */
    function inner_test2() {
        this.x = 10;
        this.y = 13;
    };

    // ...

    return inner_test2;
})();

I wouldn't suggest that that's a convenient refactoring, particularly if that anonymous function is big and complicated, but it'd be interesting (sort-of) to see what it is that's confusing the compiler.


Depending on why you need the anonymous function, you might try replace the the anonymous function with a goog.scope

http://closure-library.googlecode.com/svn/docs/closure_goog_base.js.html


Declare test 2 outside the function closure, without assigning it:

var test2;

(function() {
    test2 = function(...

I realize this isn't a Closure Compiler configuration change like you wanted, but it will both improve code readability and resolve Closure Compiler's objections.

A little bit of what you get with Closure Compiler is really Google internal Javascript code guidelines, because of its history. So for example you can't use the with statement because that's against policy, even though you as a public user just want to minify your code, and may have a policy that allows for the with statement at your company.

That said, I do think it's not the best practice to declare a global inside a function closure (even though it's legal Javascript). And it wouldn't be that hard to write a script that goes around looking for /(\w[\w\d-]+) = function/ and declaring it with var at the top of the offending files. And, it would probably result in all the files modified that way being easier to analyze by coders new to a given file.

Your remaining option is to modify the open source Closure Compiler code so it warns instead of errors about this violation of Google JS policy.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜