Подтвердить что ты не робот

+!! оператора в выражении if

Я просмотрел код для angularjs factory, чтобы лучше понять, как он работает. Код содержит оператор if, который я не совсем понимаю.

В демо-версии plnkr автор написал следующее:

if ((+!!config.template) + (+!!config.templateUrl) !== 1) {
  throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`');
}

Он немного отличается в репозитории github:

if (!(!config.template ^ !config.templateUrl)) {
  throw new Error('Expected modal to have exactly one of either `template` or `templateUrl`');
}

Очевидно, что сообщение об ошибке проверяет наличие одного из двух. Я просто не знаю, как это получается. Я не смог найти информацию о ^ или +!

Мой вопрос: как это работает оператор if? (^ или +! или +!!)

4b9b3361

Ответ 1

!! преобразует значение в логическое (true или false). + затем преобразует логическое значение в число, либо 1 для true или 0 для false.

> +true
1
> +false
0

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

if (!config.template == !config.templateUrl) {
  throw ...
}

Явная и читабельность кода, судя по всему, проклята.

Ответ 2

+!! использует неявное преобразование для приведения значения как 0 или 1 в зависимости от его логического значения

По большей части это проверка на существование. Например, пустая строка имеет значение false (!!"" === false), и это означает undefined и ряд других. Это основные два, хотя

"Ложные" преобразования

+!!""        ===   0
+!!false     ===   0
+!!0         ===   0
+!!undefined ===   0
+!!null      ===   0
+!!NaN       ===   0

Преобразования "Truthy"

+!!1         ===   1
+!!true      ===   1
+!!"Foo"     ===   1
+!!3.14      ===   1
+!![]        ===   1
+!!{}        ===   1

if ((+!! config.template) + (+!! config.templateUrl)! == 1)

Надеюсь, это имеет смысл в этом вопросе. Объект config имеет два свойства, которые мы рассматриваем. .template и .templateUrl. Неявное преобразование в 0 или 1 с помощью +!! будет добавлено, а затем сравнивается, чтобы убедиться, что оно не равно 1 (что означает, что оно равно 0 или 2). Свойства могут быть либо включенными, либо выключенными, но не различными.

Таблица истинности выглядит следующим образом:

template    templateUrl    (+!!) + (+!!)     !==1
"foo"       "foo"              1 + 1         true
undefined   undefined          0 + 0         true
undefined   ""                 0 + 0         true
""          undefined          0 + 0         true
12          ""                 1 + 0         false
""          12                 0 + 1         false
undefined   "foo"              0 + 1         false
""          "foo"              0 + 1         false
"foo"       ""                 1 + 0         false
"foo"       undefined          1 + 0         false

Более простым методом для всего этого было бы просто использовать неявное булево преобразование

if (!config.template === !config.templateUrl)

Ответ 3

Это ужасно читаемый способ выписать логическое значение переменной, а затем преобразовать его с помощью унарного преобразования, чтобы дать результат 0/1.

Рассмотрим:

+!!true; //this converts true to false, then to true again, and true is 1 when converted
+!!0; //converts 0 (falsy) to true, then false, and then the numeric 0

Технически говоря, !! не является его собственным оператором, это просто оператор NOT (!) дважды.

Унарное преобразование: ECMA spec doc унарный плюс пытается преобразовать в целое число. Number() также будет правильным преобразованием.

Ответ 4

Между тем ^ - побитовый оператор XOR.

При работе с номерами меньше 2, ^ будет работать как логическое ИЛИ (||), если вы считаете 0= false и 1= true.

Ответ 5

! является логическим оператором. Это унарный оператор, который преобразует его операнд в логическое и затем отрицает его. !! - это просто этот оператор дважды, второй ! отменяет отрицание, поэтому конечным результатом является просто преобразование в логическое.

+ - это оператор унарного плюса, который преобразует его в число. В случае логического значения false становится 0, а true становится 1.

Итак, +!!(expression) оценивает 1, если выражение является правдивым и 0, если выражение является ложным.

Ответ 6

if ((+!!config.template) + (+!!config.templateUrl) !== 1) {

            0            +         0               !== 1  true
            0            +         1               !== 1  false
            1            +         0               !== 1  false
            1            +         1               !== 1  true

равно

if (!config.template === !config.templateUrl) {

несмотря на содержимое двух свойств.