Оператор switch для сопоставления строк в JavaScript

Как написать swtich для следующего условного?

Если url содержит "foo", тогда settings.base_url является "bar".

Следующее - это необходимый эффект, но я чувствую, что это будет более управляемым в коммутаторе:

var doc_location = document.location.href;
var url_strip = new RegExp("http:\/\/.*\/");
var base_url = url_strip.exec(doc_location)
var base_url_string = base_url[0];

//BASE URL CASES

// LOCAL
if (base_url_string.indexOf('xxx.local') > -1) {
    settings = {
        "base_url" : "http://xxx.local/"
    };
}

// DEV
if (base_url_string.indexOf('xxx.dev.yyy.com') > -1) {
    settings = {
        "base_url" : "http://xxx.dev.yyy.com/xxx/"
    };
}

Ответ 1

Вы не можете сделать это в switch, если не выполняете полное соответствие строк; что делает подстроку. (Это не совсем так, как отмечает Шон в комментариях. См. примечание в конце.)

Если вы счастливы, что ваше регулярное выражение наверху удаляет все, что вы не хотите сравнивать в своем матче, вам не нужно подстрочное совпадение и можно было бы сделать:

switch (base_url_string) {
    case "xxx.local":
        // Blah
        break;
    case "xxx.dev.yyy.com":
        // Blah
        break;
}

... но опять же, это работает только в том случае, если полная строка соответствует. Это не сработает, если base_url_string были, скажем, "yyy.xxx.local", тогда как ваш текущий код будет соответствовать этому в ветке "xxx.local".


Обновить. Хорошо, так что технически вы можете использовать switch для подстроки, но я бы не рекомендовал его в большинстве ситуаций. Вот как (живой пример):

function test(str) {
    switch (true) {
      case /xyz/.test(str):
        display("• Matched 'xyz' test");
        break;
      case /test/.test(str):
        display("• Matched 'test' test");
        break;
      case /ing/.test(str):
        display("• Matched 'ing' test");
        break;
      default:
        display("• Didn't match any test");
        break;
    }
}

Это работает из-за того, как работают JavaScript switch, в частности два ключевых аспекта: во-первых, что случаи рассматриваются в источнике текстовый порядок, а во-вторых, что выражения селектора (биты после ключевого слова case) являются выражениями, которые оцениваются по мере того, как этот случай оценивается (а не константы, как на некоторых других языках). Так как наше тестовое выражение true, первое выражение case, которое приводит к true, будет тем, которое будет использоваться.

Ответ 2

RegExp может использоваться во входной строке не только технически, но и практически с помощью метода match.

Поскольку вывод match() является массивом, нам нужно получить первый элемент массива результата. Когда совпадение не выполняется, функция возвращает null. Чтобы избежать ошибки исключения, мы добавим условный оператор || перед доступом к первому элементу массива и протестируем его с помощью свойства input который является статическим свойством регулярных выражения, которые содержат входную строку.

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

Другой подход заключается в использовании конструктора String() для преобразования результирующего массива, который должен иметь только 1 элемент (без групп захвата), а целая строка должна быть захвачена с помощью quanitifiers (.*) в строку. В случае сбоя объект null станет строкой "null". Не удобно.

str = 'haystack';
switch (str) {
  case String(str.match(/^hay.*/)):
    console.log("Matched a string that starts with 'hay'");
    break;
}

В любом случае более элегантным решением является использование метода /^find-this-in/.test(str) с switch (true), который просто возвращает логическое значение, и его легче искать без чувствительности к регистру.

Ответ 3

Просто используйте свойство location.host

switch (location.host) {
    case "xxx.local":
        settings = ...
        break;
    case "xxx.dev.yyy.com":
        settings = ...
        break;
}

Ответ 4

Другой вариант - использовать поле input в результат соответствия регулярного выражения:

str = 'XYZ test';
switch (str) {
  case (str.match(/^xyz/) || {}).input:
    console.log("Matched a string that starts with 'xyz'");
    break;
  case (str.match(/test/) || {}).input:
    console.log("Matched the 'test' substring");        
    break;
  default:
    console.log("Didn't match");
    break;
}

Ответ 5

var token = 'spo';

switch(token){
    case ( (token.match(/spo/) )? token : undefined ) :
       console.log('MATCHED')    
    break;;
    default:
       console.log('NO MATCH')
    break;;
}


→ Если совпадение выполнено, тернарное выражение возвращает исходный токен
---- > Исходный токен оценивается по случаю

- > Если совпадение не выполняется, тройной возвращает undefined
---- > Дело оценивает токен против undefined, который, надеюсь, не имеет токена.

Тройной тест может быть любым, например, в вашем случае

( !!~ base_url_string.indexOf('xxx.dev.yyy.com') )? xxx.dev.yyy.com : undefined 

===========================================

(token.match(/spo/) )? token : undefined ) 

является тройным выражением.

В этом случае тестом является токен .match(/spo/), который указывает совпадение строки, хранящейся в токене, с выражением regex/spo/(которое в данном случае является буквенной строкой).

Если выражение и строка соответствуют ему, это возвращает true и возвращает токен (который является строкой, на которой работает оператор switch).

Очевидно, токен === token, так что оператор switch согласован и оценивается случай

Легче понять, если вы посмотрите на него в слоях и поймете, что тест turnery оценивается "ПЕРЕД" командой switch, так что оператор switch видит результаты теста.

Ответ 6

Это может быть проще. Попробуйте подумать так:

  • сначала поймать строку между регулярными символами
  • после этого найдите "случай"

:

// 'www.dev.yyy.com'
// 'xxx.foo.pl'

var url = "xxx.foo.pl";

switch (url.match(/\..*.\./)[0]){
   case ".dev.yyy." :
          console.log("xxx.dev.yyy.com");break;

   case ".some.":
          console.log("xxx.foo.pl");break;
} //end switch