Как я могу разорвать цепочку пользовательских методов, все еще возвращая значение?

Я выполняю замену в поисковой переменной, превращая известные группы в имена групп.

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

Моя фактическая цепочка замен - 15 длинных, если я могу выйти из этого на первом или втором, это кажется уместным.

Итак, я думал, что напишу что-то вроде этого

String.prototype.abortreplace = function (m,r) {
    var toreturn;
    if (this.match(/\b\w\b/g).length > 0) {
        toreturn = this.replace(m,r); 
    } else {
        return;
    }
    return toreturn;
}

tx = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
tx2 = tx.abortreplace(/a,b,c/g,"first three letters").abortreplace(/d,e,f/g,"second three letters").abortreplace(/g,h,i/g,"third three letters").abortreplace(/j,k,l/g,"fourth three letters").abortreplace(/m,n,o/g,"fifth three letters").abortreplace(/p,q,r/g,"sixth three letters");
alert(tx2);

Это работает с этой конкретной строкой из-за p в конце строки и потому, что у меня есть length > 0, На практике длина будет length > 2, В этом случае он возвращает undefined и ломается. Мне интересно, как я могу вернуть строку и все же разорвать цепь. (Я тоже пробовал return false который возвращает false, а не undefined).

String.prototype.abortreplace = function (m,r) {
    var toreturn;
    if (this.match(/\b\w\b/g).length > 2) {
        toreturn = this.replace(m,r); 
    } else {
        return;
    }
    return toreturn;
}

tx = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
tx2 = tx.abortreplace(/a,b,c/g,"first three letters").abortreplace(/d,e,f/g,"second three letters").abortreplace(/g,h,i/g,"third three letters").abortreplace(/j,k,l/g,"fourth three letters").abortreplace(/m,n,o/g,"fifth three letters").abortreplace(/p,q,r/g,"sixth three letters");
alert(tx2);

Четкий обходной путь заключается в том, чтобы просто return this когда условие не совпадает, но, конечно, это не прерывает цепочку, оно просто сводит на нет каждый последующий шаг.

Я также знаю, что я мог бы так примерно так:

var groups = ["a,b,c","d,e,f"]
var gnames = ["first three letters","second three letters"]
function chainreplace(query,step) {
  if (this.match(/\b\w\b/g).length > 0) {
    query = query.replace(groups[step],gnames[step]);
    if (step < groups.length) {
      query = chainreplace(query,step+1);
    }
    return query;
  }
}
chainreplace("a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p",1);

Но я предпочитаю метод цепочки, если это возможно, проще для повторного использования (аналогично, но не идентично), без создания большего количества массивов объектов

1 ответ

Решение

Вместо того, чтобы ставить свои собственные методы на String Прототип (тьфу), вы можете придумать свою собственную структуру данных, чтобы делать то, что вы хотите.

Идея ниже состоит в том, что есть один тип объекта, который выполняет необходимую обработку и возвращает цепочечные объекты, и когда придет время, он может вернуть другой тип с тем же интерфейсом, который закорачивает последующие вызовы цепочки:

var replacer = (function() {
  function fixedReplacer(str) {
    var r = {
      abortreplace: function() {
        // this abortreplace just returns the object it was called on
        return r;
      },
      toString: function() {
        return str;
      }
    };
    return r;
  }

  function replacer(str) {
    return {
      abortreplace: function(m, r) {
        return (str.match(/\b\w\b/g)||[]).length > 2 
          ? replacer(str.replace(m, r)) 
          : fixedReplacer(str);
      },
      toString: function() {
        return str;
      }
    };
  }
  
  return replacer;
})();

tx = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p";
tx2 = replacer(tx)
  .abortreplace(/a,b,c/g, "first three letters")
  .abortreplace(/d,e,f/g, "second three letters")
  .abortreplace(/g,h,i/g, "third three letters")
  .abortreplace(/j,k,l/g, "fourth three letters")
  .abortreplace(/m,n,o/g, "fifth three letters")
  .abortreplace(/p,q,r/g, "sixth three letters")
  .toString();
console.log(tx2);

Конечно, это не препятствует выполнению всех 15 вызовов методов (как указали Феликс и Берги, это невозможно без исключения), но может значительно сократить объем выполняемых вычислений.

Другие вопросы по тегам