Google Closure Compiler - Как создать Extern для переменной (имя переменной не может измениться, как в Eval)

Я использую Google Closure Compiler в режиме SIMPLE_OPTIMIZATIONS. JavaScript использует оператор «Eval» с переменной «_u», встроенной в строку. Когда Google Closure Compiler запутывает код, имя переменной изменяется на «a», и я получаю сообщение об ошибке, что «_u» не определено в консоли. Насколько я понимаю, Extern решит эту проблему, но я не уверен, как это написать. Мысли?

Фрагмент кода:

var FuncName = (function(){

  var ht=escape(_w.location.href)

  function _fC(_u){
    _aT=_sp+',\\/,\\.,-,_,'+_rp+',%2F,%2E,%2D,%5F';
    _aA=_aT.split(',');
    for(i=0;i<5;i++){
      eval('_u=_u.replace(/'+_aA[i]+'/g,_aA[i+5])')
    }
    return _u
  };

  return {
  O_LC:function(){ 
    _w.open('https://someurl?referer='+_fC(_ht))
  }
};
})();

После того, как Google Closure Compiler изменит код:

var FuncName = function() {
  function a(a) {
    _aT = _sp + ",\\/,\\.,-,_," + _rp + ",%2F,%2E,%2D,%5F";
    _aA = _aT.split(",");
    for (i = 0;5 > i;i++) {
      eval("_u=_u.replace(/" + _aA[i] + "/g,_aA[i+5])");
    }
    return a;
  }
  escape(_w.location.href);
  return {O_LC:function() {
    _w.open("https://someurl?referer=" + a(_ht));
  }};
}();

person satoukum    schedule 14.10.2015    source источник


Ответы (2)


Вы можете предотвратить переименование глобальных переменных или свойств только с помощью внешних переменных. Местные жители всегда будут переименованы. Вы можете изменить код несколькими способами, чтобы исправить это, в том числе с помощью конструктора функций:

new Function("_u", "... function body ...")

Но я бы переписал код, чтобы избежать использования eval для создания регулярного выражения. Это будет работать:

_u=_u.replace(new RegExp(_aA[i], "g"), _aA[i+5]);

Вам также может быть интересно:

Escape-строка для использования в регулярном выражении Javascript

Общая документация по ограничениям Closure Compiler находится здесь:

https://developers.google.com/closure/compiler/docs/limitations

person John    schedule 15.10.2015
comment
Обратите внимание, что вы также можете изменить компилятор для специального случая _u. Один такой случай уже есть: github.com/google/closure-compiler/blob/ Или предложите патч, чтобы сделать это настраиваемым. - person John; 15.10.2015
comment
Я использую плагин, который использует компилятор закрытия Google, поэтому я думаю, что я ограничен только передачей таких параметров, как '--externs=./lib/gcc-externs.js' - person satoukum; 15.10.2015

Это довольно легко. Вам просто нужен отдельный файл externs:

образецextern.js

/** @externs */

var _u;

Экстерны являются действительным javascript. См. http://blogs.missouristate.edu/web/2013/09/12/how-to-write-closure-compiler-extern-files-part-1-the-basics/

person Chad Killingsworth    schedule 15.10.2015
comment
Чад, это не решит их проблему. Они не будут переименовывать свой параметр _u. Компилятор не поддерживает это напрямую. - person John; 15.10.2015
comment
@John Я предположил, что, поскольку _u не был определен в области видимости, компилятор предположил бы, что он глобальный, и поэтому вернется к использованию определения extern. - person Chad Killingsworth; 15.10.2015
comment
Да, похоже, это не работает. Другие варианты могут заключаться в том, чтобы переписать оператор без eval или изменить JavaScript, но это сторонний код, и мне не рекомендуется его редактировать. На данный момент наша команда использует WHITESPACE_ONLY. - person satoukum; 15.10.2015
comment
_u — это параметр функции, он находится в области видимости. - person John; 15.10.2015
comment
@satoukum Я бы изменил его и отправил патч оригинальному автору. - person John; 15.10.2015