Можно ли использовать выражения, разделенные запятыми, как выражение в Javascript?

Я пытаюсь понять сценарий, в котором широко используются выражения, разделенные запятыми. Например:

popup_window != is_null && ("function" == typeof popup_window.close && popup_window.close(), popup_window = is_null);

Если верно, что разделение запятой означает «оценить все следующие выражения, а затем получить значение конечного выражения» (как в этот ответ SO), это еще одна форма оператора if?

Например:
"если popup_window не равен null, а popup_window.close является методом, вызовите этот метод и установите для popup_window значение null"

Во всяком случае, я не уверен, что понимаю синтаксис.

Вопрос:
Что означает это утверждение и что не так с разделением запятыми? Это должно быть оператором if?

Спасибо!


person frequent    schedule 10.02.2015    source источник
comment
Это просто умный (слишком умный) способ использования И для проверки ряда утверждений, и если они все правдивы, он доходит до конца, где запятая используется в качестве оператора, и если window.close() возвращает истину (он возвращает всплывающее окно, если один существует), переменная popup_window имеет значение is_null, что, вероятно, равно null, исходя из оператора.   -  person adeneo    schedule 11.02.2015
comment
Итак, а если в процессе выполнения оператора произойдет сбой, то окончательное выражение не будет выполнено?   -  person frequent    schedule 11.02.2015
comment
Точно, это как if ( truthy && falsy && truthy ), последний никогда не проверяется, так как второй ложный, и тут же дает сбой.   -  person adeneo    schedule 11.02.2015
comment
Действительно, слишком умно... Спасибо. Сделать это ответом?   -  person frequent    schedule 11.02.2015
comment
Это скомпилированный минимизированный скрипт. Получите исходный код, никто никогда не напишет это вручную.   -  person Bergi    schedule 11.02.2015
comment
когда вы пишете: if( a() && b() && c() ) {} a() будет проверено, если a() вернет true, будет проверено b(), если b() вернет true, c( ) будет проверяться при написании: if(a() && b() , c() ) {} a() будет проверяться, если a() возвращает true, b() будет проверяться, а c() будет всегда быть оцененным jsfiddle.net/try2d0rj   -  person Steven    schedule 11.02.2015
comment
Я знаю людей, которые пишут такой код, поэтому его не нужно генерировать с помощью минификаторов;)   -  person Florian Loch    schedule 11.02.2015


Ответы (1)


Это серия утверждений на самом деле

popup_window != is_null // if true, continue to the statement in the parenthesis
    && 
(
    "function" == typeof popup_window.close // if true continue to close the window
      && 
    popup_window.close()
    , popup_window = is_null // this is executed as long as "popup_window != is_null" 
);                           // is truthy, it doesn't depend on the other conditions

предполагая, что is_null на самом деле null, во-первых, popup_window не должно быть нулевым.
Во-вторых, мы можем предположить, что popup_window — это другое окно, открытое с помощью window.open, поскольку оно предположительно должно иметь функцию close, и это немного похоже на условие Йоды, но это также может быть написано

typeof popup_window.close === "function"

поэтому popup_window должен иметь метод close, чтобы перейти к следующему шагу. Последний шаг закрывает всплывающее окно, если оно не пустое и если оно имеет метод close.

popup_window.close()

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

А тут запятая. Из документов

Оператор запятой оценивает каждый из своих операндов (слева направо) и возвращает значение последнего операнда.

и у нас есть

("function" == typeof popup_window.close && popup_window.close(), popup_window = is_null);

давайте немного по другому напишем

(                          // ↓ must be thruthy .... ↓ for this to execute
   (typeof popup_window.close === "function" && popup_window.close())
   , popup_window = is_null
);      // ↑ unrelated, it's just another operand, seperated by comma

Хитрость здесь в том, что всегда выполняется последняя часть после запятой, так как оцениваются все операнды, разделенные запятой.

Это означает, что если popup_window не равно is_null, popup_window явно устанавливается равным is_null, независимо от второго условия.

Второе условие также выполняется только в том случае, если popup_window не является is_null, затем проверяется, есть ли метод close(), и закрывается окно, оператор после запятой не связан с результатом этого условия.

Чтобы написать это еще проще (так, как это должно было быть написано IMO)

if ( popup_window != is_null ) {

    if ( typeof popup_window.close === "function" ) {
        popup_window.close();
    }

    popup_window = is_null;

}
person adeneo    schedule 10.02.2015
comment
прекрасный ответ. Спасибо! - person frequent; 11.02.2015