Нет дополнительного логического приведения в JavaScript

В операторе if приведение к логическому значению через двойное отрицание (!!) не требуется, потому что эти операторы if, например, эквивалентны:

if (!!foo) {
    // ...
}

if (foo) {
    // ...
}

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

nameToSomething : function(someName){
            if (someName) {
                return !!this._var[someVar] ? this._var: undefined;
            }
            return undefined;
        },

!!this._mServicesByName[someName] здесь то же самое, что и this._mServicesByName[someName]? Почему?

Объяснение на простом английском, почему это отличается/одинаково, а также примеры, как обойти это правило в JavaScript, чтобы мой линтер не «увидел», будет очень признателен.

Спасибо заранее.


person Ilya Dachkovsky    schedule 27.04.2015    source источник
comment
Ну, это приводит к логическому значению, а возврат логического значения сильно отличается от возврата свойства объекта?   -  person dsgriffin    schedule 27.04.2015
comment
Это должно быть довольно очевидно, если вам нужно логическое значение, вы можете принудить его с помощью двойного логического оператора not. Если вам просто нужно ложное или истинное значение, вам не нужно ничего принуждать. Если вы хотите быть модным, вы можете вместо этого сделать побитовое ~~sServiceName   -  person adeneo    schedule 27.04.2015
comment
@adeneo Ну, для новичка это не так очевидно :-) Мне нужно логическое значение в операторе return. Но мой линтер считает это ошибкой. Итак, могу ли я вместо возврата !!this._mServicesByName[someName] сделать что-то вроде этого: var x = !!_mServicesByName, а затем вернуть this.x[somename]?   -  person Ilya Dachkovsky    schedule 27.04.2015
comment
@dsg Мое предположение не сильно отличается, но я не уверен. С момента вопроса :-)   -  person Ilya Dachkovsky    schedule 27.04.2015
comment
Ваш линтер на самом деле не так важен, нет причин, по которым !!func недействителен.   -  person adeneo    schedule 27.04.2015


Ответы (2)


Хорошо, я сам провел некоторое исследование с тех пор, как задал этот вопрос, и на самом деле наткнулся на несколько очень похожих вопросов (с ответами) на двойной отрицательный трюк в JavaScript. Здесь и здесь я нашел некоторое объяснение необходимости самого двойного логического отрицательного трюка. Короче говоря, это похоже на кастинг в Java. !! выражение используется, когда вам действительно нужно вернуть логическое значение без изменения истинного и ложного. Это не инвертированное логическое значение или, проще говоря, истинное логическое представление.

Например, это !true будет ложным, и наоборот !false будет истинным. Но, просто используя !!true и !!false, вы можете получить те же самые true и false без изменения результата и по-прежнему работать с логическими значениями. То же самое верно для !!0, являющегося false, и !!1, являющегося true.

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

Или, как вариант, изменить параметры линтера на правило «no-extra-boolean» в IDE будет гораздо лучшим решением) Потому что в JavaScript, как я понял, они используются часто и от этого никуда не деться. Это даже не плохая практика. Иногда, когда вам нужно настоящее логическое представление, это очень удобный способ написать код. И единственный.

person Ilya Dachkovsky    schedule 02.05.2015

Я не совсем понимаю, в чем заключается ваш вопрос, но в отношении ошибок линтера «no-extra-boolean-cast» он говорит вам, что !! не нужен в обоих ваших случаях.

Вы упоминаете, что !!this._mServicesByName[someName] в ответ совпадает с this._mServicesByName[someName], но в вашем коде: return !!this._var[someVar] ? this._var: undefined; это не то, что вы делаете. У вас есть тернарный оператор, первый параметр которого автоматически преобразуется в логическое значение, поэтому ваш линтер должен корректно выдавать ошибку.

Это ненужно:

`return !!this._var[someVar] ? this._var: undefined;`

А должно быть просто:

`return this._var[someVar] ? this._var: undefined;`

Так как они эквивалентны.

Это, однако, допустимое использование логического приведения:

`return !!this._var[someVar]; // Returns value cast as true/false

Потому что это совсем не то, что:

`return this._var[someVar]; // Returns unmodified value
person cyberwombat    schedule 05.08.2016