Search code examples
jqueryfunctioncompressiongoogle-closure-compileruglifyjs

closure compiler / uglifyjs - this.function name not shortened?


If I run this piece of code through closure compiler or uglifyjs, this.init is not shortened.. Can anyone tell me why that is?

function test() {
    var v = "abc";
    this.init = function() {
         alert('var = ' + v + ' and func = ' + f());
         f2();
    }
    function f() {
        return 'def';
    }
    function f2() {
        v = "ghi";
        alert('blabla');
        alert('filler');
    }
}

test();

uglifyjs turns this into :

function test(){function c(){a="ghi",alert("blabla"),alert("filler")}function b(){return"def"}var a="abc";this.init=function(){alert("var = "+a+" and func = "+b()),c()}}test()

Beautified that is:

function test() {
    function c() {
        a = "ghi", alert("blabla"), alert("filler")
    }
    function b() {
        return "def"
    }
    var a = "abc";
    this.init = function () {
        alert("var = " + a + " and func = " + b()), c()
    }
}

test()

So why is this.init() not changed as well to a shorter name?

Additionally, what exactly is the difference between doing:

 function init() {..}

and

 this.init = function() { .. }

Thanks, Wesley


Solution

  • init is not shortened for the same reason test is not shortened ... because it is part of the public API of your code.

    When you call var t = new test() you would create an object that looks like this:

    {
        init: function() { ... },
        prototype: test
    }
    

    and you can call t.init(). If the compiler did not respect those variables which are available from the global scope, you would have to inline all of your JavaScript code into one file before you minified it. Otherwise, every time you minified test.js the public function test's name would change. So this code:

    <script type="text/javascript" src="js/test.min.js"></script>
    <script type="text/javascript">
    var t = new test();
    t.init();
    </script>
    

    would break (because test would probably be changed to a by the minifier and init to some other letter.)

    As to the second part of your question, when you do this.init = function you are setting an attribute on an indeterminate object (it could be anything, since this is set at call time in JavaScript and you are declaring it inside of the function test). When you write function init(){} you are writing a function declaration, which will be hoisted to the top of the enclosing scope (meaning you can call it, inside of the scope in which it is defined, before you have defined it.) However, it will not be available outside of test.