Search code examples
javascriptgulpuglifyjs

Minifying javascript makes function un-callable


I'm using gulp to build an asset pipeline for my project. I'm currently using gulp-uglify to minify javascript.

When Uglify processes my JS, it changes the function name, which makes it un-callable. Does anyone know how to prevent this from happening?

(function() { "use strict";

  function Ajax(params, url, callbackFunction) {
    this.params = params,
    this.url = url,
    this.callback = callbackFunction
  }

  Ajax.prototype.call = function() {
    $.ajax({
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      type: "post",
      data: this.params,
      success: this.callback,
      error: this.callback
    });
  }
})();

becomes

!function(){"use strict";function t(t,a,s){this.params=t,this.url=a,this.callback=s}t.prototype.call=function(){$.ajax({contentType:"application/json; charset=utf-8",dataType:"json",type:"post",data:this.params,success:this.callback,error:this.callback})}}();

This changes the Ajax function to be called "t" and when I want to instantiate a new Ajax object, I get an Uncaught ReferenceError: Ajax is not defined

My calling code is

$(document).ready(function() {
  var ajaxTest = new Ajax("google.com", {}, printTest);
  console.log(ajaxTest);
  Ajax.call();

  function printTest() {
    console.log("Hello");
  }
});

which gets minified to

$(document).ready(function(){function o(){console.log("Hello")}var l=new Ajax("google.com",{},o);console.log(l),Ajax.call()});

Solution

  • There is nothing wrong with the minifying process. The Ajax identifier is local to the scope, so it's not reachable outside the scope anyway. Any code inside that scope that would use the Ajax identifier would be minified to use the t identifier.

    If you want to use the Ajax identifier outside the scope, you can return it from the function wrapper:

    var Ajax = (function() { "use strict";
    
      function Ajax(params, url, callbackFunction) {
        this.params = params,
        this.url = url,
        this.callback = callbackFunction
      }
    
      Ajax.prototype.call = function() {
        $.ajax({
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          type: "post",
          data: this.params,
          success: this.callback,
          error: this.callback
        });
      };
    
      return Ajax;
    })();
    

    Now you can use the Ajax identifier in your other code. If the Ajax identifier that is outside the scope is changed by minifying the code, the code using it will also use that new identifier.