Эквивалентны ли эти строки кода JavaScript?


Я нашел эту строку в коде JavaScript.

var c = (a.b !== null) ? a.b : null;

это сокращение оператора if-else, однако значение null присваивается, если оно равно null. Разве это не всегда эквивалентно

var c = a.b

включая все случаи-исключения, null, undefined и т. д.?

другими словами, эти строки (всегда) эквивалентны?

var c = (a.b !== null) ? a.b : null;

-игры

var c = a.b
6 54

6 ответов:

нет, они НЕ ОБЯЗАТЕЛЬНО РАВНЫ всегда, если b-геттер, который обновляет переменную. Это плохая практика, чтобы кодировать таким образом, хотя

var log = 0;
var a = {
    get b() {
        log++;
        return log;
    }
}

var c = (a.b !== null) ? a.b : null;
// outputs 2
console.log(c);
var log = 0;
var a = {
    get b() {
        log++;
        return log;
    }
}

var c = a.b;
// outputs 1
console.log(c);

эти заявления логически эквивалентны.

Это было сказано, и как упоминалось в еще один ответ, если a.b имеет побочные эффекты, заявления не приведут в таком же положении программы.

Это может быть легко очевидно в виде var c имеющие различное значение в зависимости от того, какие из этих операторов выполняются, или более скрытые, если a.b изменяет что-то в другом месте программа.

рефакторинг

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

две возможные ситуации, как я вижу их:

  1. a.b не имеет никаких побочных эффектов, прямое рефакторинг безопасно
  2. a.b имеет скрытые побочные эффекты. Это представляет собой очень неясный, запутанный, и просто код. Она должна быть преобразована так, что все изменения, происходящие во время отчета понятно и очевидно в читатель (надеюсь, интуитивно так, а также поддерживается комментариями).

как уже указывал @potatopeelings, два возможных оператора не всегда эквивалентны, так как можно написать неясный код, который будет иметь разные результаты.

однако, если я вижу код, как

var c = (a.b !== null) ? a.b : null;

Я буду считать, что намерение кода

var c = a.b;

поэтому я изменю его, чтобы сделать код красивее. Если я буду негативно удивлен, то есть код не проходит фазы тестирования из-за этого изменения, то я постараюсь найти автор a.b с git виноват.

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

ну, на самом деле даже не

var c = (a !== null) ? a : null;

гарантированно будет эквивалентно

var c = a;

, когда a решается геттером или обработчиком прокси ES6 на глобальном объекте.

следовательно, например, это назначить c значение 0:

Object.defineProperty(self, 'a', { get: function() { return c ^= 1; } });
var c = (a !== null) ? a : null;
console.log(c);

в то время как это присваивает c значение 1:

Object.defineProperty(self, 'a', { get: function() { return c ^= 1; } });
var c = a;
console.log(c);

вы правы, var c = a.b точно так же, как var c = (a.b !== null) ? a.b : null;

Я думаю null в тернарном операторе должно было быть все, кроме null, значение по умолчанию, если хотите.

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

кроме того, Примечание: a.b может быть функцией.