JavaScript: анализ строкового логического значения?

В JavaScript есть parseInt() и parseFloat(), но, насколько мне известно, в глобальной области нет методов parseBool или parseBoolean.

Мне нужен метод, который принимает строки со значениями типа «истина» или «ложь» и возвращает JavaScript Boolean.

Вот моя реализация:

function parseBool(value) {
    return (typeof value === "undefined") ? 
           false : 
           // trim using jQuery.trim()'s source 
           value.replace(/^\s+|\s+$/g, "").toLowerCase() === "true";
}

Это хорошая функция? Пожалуйста, дайте мне свой отзыв.

Спасибо!


person AgileMeansDoAsLittleAsPossible    schedule 07.03.2011    source источник
comment
и вы также можете разместить свой код на codereview.stackexchange.com, если вам нужны только обзоры кода ...   -  person peirix    schedule 07.03.2011
comment
см. stackoverflow.com/questions/263965/   -  person Alex Pacurar    schedule 07.03.2011


Ответы (14)


Я был бы склонен сделать однострочник с тройным if.

var bool_value = value == "true" ? true : false

Изменить: Еще быстрее было бы просто избежать использования логического оператора и вместо этого просто использовать само выражение:

var bool_value = value == 'true';

Это работает, потому что value == 'true' оценивается на основе того, является ли переменная value строкой 'true'. Если это так, все выражение становится true, а если нет, становится false, тогда этот результат присваивается bool_value после оценки.

person raddrick    schedule 18.01.2012
comment
Почему бы не сократить его еще немного? var bool_value = value == "true" делает то же самое :) - person Jakob; 08.04.2012
comment
Здесь может быть полезно тернарное выражение для обработки случая, когда вам передано значение null / undefined / empty: bool_value = value ? (value.toLowerCase() == "true") : false - person parsifal; 11.10.2012
comment
"true" ? true : false является троичным, но да, его можно расширить, чтобы проверить null/undefined/empty - person raddrick; 13.10.2012
comment
Я использую следующую троицу:! Value || значение === 'ложь'? ложь Правда; Он правильно перехватит следующее: false, true, false, true, 0, 1 и undefined. - person Matt James; 27.02.2014
comment
причина, по которой я бы не стал использовать тернарный оператор более короткого, для ясности :) - person thermite; 19.11.2014
comment
Более короткий путь: var bool = !!value - person Ifch0o1; 14.12.2014
comment
согласен с @ Ifch0o1 о том, что !! valuee лучше. и вы можете убедиться, что это работает следующим образом: !! value === true, однако, это расширит эту проверку, включив в нее другие достоверные значения, такие как 1, которые могут приветствоваться или не приветствоваться - person Sonic Soul; 14.06.2016
comment
@ Ifch0o1 Я бы не стал использовать var bool = !!value. Строка, содержащая false, является истинным значением, поэтому !!'false' === true - person Michael Lang; 27.09.2018
comment
@ Майкл Лэнг! Оператор переводит следующее значение в логическое значение true или false. Он не вернул строку, а вернул boleab. При двойном использовании возвращает revert bolean и снова revert bolean, которое является логическим значением переменной. - person Ifch0o1; 01.10.2018
comment
Обычно я ожидаю, что когда кто-то говорит, что хочет преобразовать строку в логическое значение, они имеют в виду, что они хотят сопоставить строку false с логическим значением false. Однако в javascript !! 'false' дает логическое значение true. Если вы мне не верите, откройте консоль javascript в своем любимом браузере или ответ nodeJS и попробуйте сами. Если исходный постер согласен с этим синтаксическим анализом, принимающим false в true, то я полагаю !! это нормально, но это определенно не то поведение, которого я ожидал бы от парсера. - person Michael Lang; 24.10.2018

Для этого вы можете использовать JSON.parse:

JSON.parse("true"); //returns boolean true
person F.Alves    schedule 11.07.2015
comment
Не обрабатывает смешанный регистр JSON.parse("True") или синтаксис, отличный от JSON, например. JSON.parse (x) - person AndrewL; 29.03.2018
comment
Это должен быть принятый ответ - person johnny peter; 18.06.2019
comment
@AndrewL вы потенциально можете сделать JSON.parse (True.toLowerCase ()), заменив True вашей переменной - person Jacques; 05.08.2020

Это зависит от того, как вы хотите, чтобы эта функция работала.

Если все, что вы хотите сделать, это проверить наличие слова «истина» внутри строки и определить любую строку (или не строку), в которой оно отсутствует, как ложь, возможно, самый простой способ:

function parseBoolean(str) {
  return /true/i.test(str);
}

Если вы хотите убедиться, что вся строка является словом true, вы можете сделать это:

function parseBoolean(str) {
  return /^true$/i.test(str);
}
person Martin Jespersen    schedule 07.03.2011
comment
То, как это работает изначально, абсолютно глупо. Логическая функция должна выполнять последний из ваших примеров. Если нужно проверить, содержит ли строка слово «истина» или «ложь», вы должны проверить, имеет ли индекс ›0. - person The Muffin Man; 22.05.2012
comment
Это имеет огромное количество накладных расходов, связанных с регулярным выражением, вместо простой проверки, содержит ли строка «истину» или нет. - person Soviut; 05.08.2013
comment
@Soviut: Совершенно верно, RGB-решение намного предпочтительнее - person Martin Jespersen; 06.08.2013

Вы можете попробовать следующее:

function parseBool(val)
{
    if ((typeof val === 'string' && (val.toLowerCase() === 'true' || val.toLowerCase() === 'yes')) || val === 1)
        return true;
    else if ((typeof val === 'string' && (val.toLowerCase() === 'false' || val.toLowerCase() === 'no')) || val === 0)
        return false;

    return null;
}

Если это допустимое значение, оно возвращает эквивалентное значение типа bool, в противном случае возвращает null.

person Paul Fleming    schedule 13.07.2012
comment
Это почти сработало, я немного изменил его, чтобы он работал правильно (одинарные кавычки вокруг 'string'): function parseBool(val) { if ((typeof val == 'string' && (val.toLowerCase() === 'true' || val.toLowerCase() === 'yes')) || val === 1) return true; else if ((typeof val === 'string' && (val.toLowerCase() === 'false' || val.toLowerCase() === 'no')) || val === 0) return false; return null; } - person delliottg; 11.07.2014
comment
@delliottg Обновлено с кавычками на строку. - person Paul Fleming; 14.07.2014

Вы можете использовать JSON.parse или jQuery.parseJSON и посмотреть, вернет ли он истину, используя что-то вроде этого:

function test (input) {
    try {
        return !!$.parseJSON(input.toLowerCase());
    } catch (e) { }
}
person rsp    schedule 07.03.2011
comment
Для меня это выглядит немного опасно. Например, test("\"false\"") вернет true, поскольку это непустая строка. Маловероятно, но очень неочевидный источник ошибок. - person RoToRa; 07.03.2011
comment
Если введен недопустимый JSON, эта функция вернет undefined. - person PleaseStand; 07.03.2011
comment
@idealmaschine: Мне кажется, это хорошо. Это то, что вы хотели сказать, или это была критика? - person RoToRa; 07.03.2011
comment
@RoToRa: Хороший момент. Но, не зная данных, трудно понять, должно ли \ false \ быть истинным или ложным - а как насчет \ not true \ или \ no \ или да? Одна из возможностей - вернуть undefined для всего, кроме явного истинного или ложного, или использовать обычную семантику JavaScript или JSON, или использовать некоторую настраиваемую логику, подходящую для данного приложения. Трудно сделать универсальное решение, если даже трудно найти два языка программирования, которые согласились бы в том, что истинно, а что ложно. - person rsp; 07.03.2011
comment
@idealmaschine: вы можете добавить return false; в блок catch, если хотите получить false для недопустимого JSON, но имейте в виду, что undefined также является ложным в JavaScript, поэтому это может не иметь большого значения, в зависимости от того, как вы его используете. - person rsp; 07.03.2011

Лично я думаю, что это нехорошо, что ваша функция «скрывает» недопустимые значения как false и - в зависимости от ваших вариантов использования - не возвращает true для "1".

Другая проблема может заключаться в том, что он блокирует все, что не является строкой.

Я бы использовал что-то вроде этого:

function parseBool(value) {
  if (typeof value === "string") {
     value = value.replace(/^\s+|\s+$/g, "").toLowerCase();
     if (value === "true" || value === "false")
       return value === "true";
  }
  return; // returns undefined
}

И в зависимости от вариантов использования расширьте его, чтобы различать "0" и "1".

(Может быть, есть способ сравнить только один раз с "true", но сейчас я ничего не мог придумать.)

person RoToRa    schedule 07.03.2011
comment
Извините, что копаю действительно старый код, но почему не просто return true;? почему return value === "true";? Я имею в виду, вы уже проверили, действительно ли это, верно? - person Metagrapher; 19.03.2015
comment
@Metagrapher Если я просто return true, он вернет истину, если значение тоже "false". - person RoToRa; 19.03.2015
comment
Я не знаю, что со мной было не так, когда я читал этот код. Прости. ха-ха, спасибо за ясность. - person Metagrapher; 22.03.2015

Вы можете добавить этот код:

function parseBool(str) {

  if (str.length == null) {
    return str == 1 ? true : false;
  } else {
    return str == "true" ? true : false;
  }

}

Работает так:

parseBool(1) //true
parseBool(0) //false
parseBool("true") //true
parseBool("false") //false
person CodeGems    schedule 02.01.2015
comment
Я вижу, что тернари используются очень часто, но они не нужны. Вы можете просто сделать return (str === 1) - person Hexodus; 25.06.2021

Почему бы не сделать это простым?

var parseBool = function(str) {
    if (typeof str === 'string' && str.toLowerCase() == 'true')
            return true;

    return (parseInt(str) > 0);
}
person MiniGod    schedule 28.09.2012

Wood-eye будьте осторожны. Посмотрев весь этот код, я чувствую себя обязанным опубликовать:

Начнем с самого короткого, но очень строгого способа:

var str = "true";
var mybool = JSON.parse(str);

И закончить правильным, более терпимым путем:

var parseBool = function(str) 
{
    // console.log(typeof str);
    // strict: JSON.parse(str)

    if(str == null)
        return false;

    if (typeof str === 'boolean')
    {
        if(str === true)
            return true;

        return false;
    } 

    if(typeof str === 'string')
    {
        if(str == "")
            return false;

        str = str.replace(/^\s+|\s+$/g, '');
        if(str.toLowerCase() == 'true' || str.toLowerCase() == 'yes')
            return true;

        str = str.replace(/,/g, '.');
        str = str.replace(/^\s*\-\s*/g, '-');
    }

    // var isNum = string.match(/^[0-9]+$/) != null;
    // var isNum = /^\d+$/.test(str);
    if(!isNaN(str))
        return (parseFloat(str) != 0);

    return false;
}

Тестирование:

var array_1 = new Array(true, 1, "1",-1, "-1", " - 1", "true", "TrUe", "  true  ", "  TrUe", 1/0, "1.5", "1,5", 1.5, 5, -3, -0.1, 0.1, " - 0.1", Infinity, "Infinity", -Infinity, "-Infinity"," - Infinity", " yEs");

var array_2 = new Array(null, "", false, "false", "   false   ", " f alse", "FaLsE", 0, "00", "1/0", 0.0, "0.0", "0,0", "100a", "1 00", " 0 ", 0.0, "0.0", -0.0, "-0.0", " -1a ", "abc");


for(var i =0; i < array_1.length;++i){ console.log("array_1["+i+"] ("+array_1[i]+"): " + parseBool(array_1[i]));}

for(var i =0; i < array_2.length;++i){ console.log("array_2["+i+"] ("+array_2[i]+"): " + parseBool(array_2[i]));}

for(var i =0; i < array_1.length;++i){ console.log(parseBool(array_1[i]));}
for(var i =0; i < array_2.length;++i){ console.log(parseBool(array_2[i]));}
person Stefan Steiger    schedule 06.03.2014

И последнее, но не менее важное: простой и эффективный способ сделать это со значением по умолчанию:

ES5

function parseBool(value, defaultValue) {
    return (value == 'true' || value == 'false' || value === true || value === false) && JSON.parse(value) || defaultValue;
}

ES6, более короткий лайнер

const parseBool = (value, defaultValue) => ['true', 'false', true, false].includes(value) && JSON.parse(value) || defaultValue

JSON.parse эффективен для анализа логических значений

person Sebastien H.    schedule 03.05.2018

Мне нравится решение, предоставленное RoToRa (попробуйте проанализировать данное значение, если оно имеет какое-либо логическое значение, в противном случае - нет). Тем не менее я хотел бы внести небольшую модификацию, чтобы она работала более или менее как Boolean.TryParse в C #, который поддерживает out параметры. В JavaScript это можно реализовать следующим образом:

var BoolHelpers = {
    tryParse: function (value) {
        if (typeof value == 'boolean' || value instanceof Boolean)
            return value;
        if (typeof value == 'string' || value instanceof String) {
            value = value.trim().toLowerCase();
            if (value === 'true' || value === 'false')
                return value === 'true';
        }
        return { error: true, msg: 'Parsing error. Given value has no boolean meaning.' }
    }
}

Использование:

var result = BoolHelpers.tryParse("false");
if (result.error) alert(result.msg);
person jwaliszko    schedule 08.04.2014

stringjs имеет метод toBoolean ():

http://stringjs.com/#methods/toboolean-tobool

S('true').toBoolean() //true
S('false').toBoolean() //false
S('hello').toBoolean() //false
S(true).toBoolean() //true
S('on').toBoolean() //true
S('yes').toBoolean() //true
S('TRUE').toBoolean() //true
S('TrUe').toBoolean() //true
S('YES').toBoolean() //true
S('ON').toBoolean() //true
S('').toBoolean() //false
S(undefined).toBoolean() //false
S('undefined').toBoolean() //false
S(null).toBoolean() //false
S(false).toBoolean() //false
S({}).toBoolean() //false
S(1).toBoolean() //true
S(-1).toBoolean() //false
S(0).toBoolean() //false
person prule    schedule 27.11.2014

Я беззастенчиво преобразовал Apache Common's toBoolean в JavaScript:

JSFiddle: https://jsfiddle.net/m2efvxLm/1/

Код:

function toBoolean(str) {
  if (str == "true") {
    return true;
  }
  if (!str) {
    return false;
  }
  switch (str.length) {
    case 1: {
      var ch0 = str.charAt(0);
      if (ch0 == 'y' || ch0 == 'Y' ||
          ch0 == 't' || ch0 == 'T' ||
          ch0 == '1') {
        return true;
      }
      if (ch0 == 'n' || ch0 == 'N' ||
          ch0 == 'f' || ch0 == 'F' ||
          ch0 == '0') {
        return false;
      }
      break;
    }
    case 2: {
      var ch0 = str.charAt(0);
      var ch1 = str.charAt(1);
      if ((ch0 == 'o' || ch0 == 'O') &&
          (ch1 == 'n' || ch1 == 'N') ) {
        return true;
      }
      if ((ch0 == 'n' || ch0 == 'N') &&
          (ch1 == 'o' || ch1 == 'O') ) {
        return false;
      }
      break;
    }
    case 3: {
      var ch0 = str.charAt(0);
      var ch1 = str.charAt(1);
      var ch2 = str.charAt(2);
      if ((ch0 == 'y' || ch0 == 'Y') &&
          (ch1 == 'e' || ch1 == 'E') &&
          (ch2 == 's' || ch2 == 'S') ) {
        return true;
      }
      if ((ch0 == 'o' || ch0 == 'O') &&
          (ch1 == 'f' || ch1 == 'F') &&
          (ch2 == 'f' || ch2 == 'F') ) {
        return false;
      }
      break;
    }
    case 4: {
      var ch0 = str.charAt(0);
      var ch1 = str.charAt(1);
      var ch2 = str.charAt(2);
      var ch3 = str.charAt(3);
      if ((ch0 == 't' || ch0 == 'T') &&
          (ch1 == 'r' || ch1 == 'R') &&
          (ch2 == 'u' || ch2 == 'U') &&
          (ch3 == 'e' || ch3 == 'E') ) {
        return true;
      }
      break;
    }
    case 5: {
      var ch0 = str.charAt(0);
      var ch1 = str.charAt(1);
      var ch2 = str.charAt(2);
      var ch3 = str.charAt(3);
      var ch4 = str.charAt(4);
      if ((ch0 == 'f' || ch0 == 'F') &&
          (ch1 == 'a' || ch1 == 'A') &&
          (ch2 == 'l' || ch2 == 'L') &&
          (ch3 == 's' || ch3 == 'S') &&
          (ch4 == 'e' || ch4 == 'E') ) {
        return false;
      }
      break;
    }
    default:
      break;
  }

  return false;
}
console.log(toBoolean("yEs")); // true
console.log(toBoolean("yES")); // true
console.log(toBoolean("no")); // false
console.log(toBoolean("NO")); // false
console.log(toBoolean("on")); // true
console.log(toBoolean("oFf")); // false
Inspect this element, and view the console output.

person Xaero Degreaz    schedule 19.08.2015
comment
Мне кажется абсурдным, почему они не включили аргумент для: typeof === 'boolean', на случай, если кто-то буквально пропустит true или false. - person Nicholas Hamilton; 12.02.2021
comment
В этом нет необходимости, поскольку Java - язык со строгой типизацией. - person Xaero Degreaz; 16.02.2021

Достаточно использовать функцию eval javascript для преобразования строки в логическое значение

eval('true')  
eval('false')
person MKD    schedule 02.05.2013
comment
Eval нарушает множество оптимизаций, приводит к медленному выполнению кода, его трудно отлаживать и плохо поддерживать. Если можете, никогда не используйте его - есть гораздо лучшие способы решить эту проблему, см. Другие ответы. - person Jens Erat; 03.05.2013
comment
При этом ни один из перечисленных вами не является критичным и применимым. - person MKD; 11.06.2013
comment
Йенс, все, что вы упомянули, не применимо в этом случае, но не упоминается действительно важная проблема с этим - безопасность. eval может привести к js-инъекции, поэтому не используйте его, если вы не можете доверять источнику ввода, а если вы используете браузер, вы вряд ли когда-либо можете этому доверять. JSON.parse - безопасный способ (не уверен, самый быстрый). - person Benja; 12.09.2013