Может ли кто-нибудь объяснить, как работает Javas Resig pretty.js JavaScript?

http://ejohn.org/files/pretty.js

// Takes an ISO time and returns a string representing how
// long ago the date represents.
function prettyDate(time){
    var date = new Date((time || "").replace(/-/g,"/").replace(/[TZ]/g," ")),
        diff = (((new Date()).getTime() - date.getTime()) / 1000),
        day_diff = Math.floor(diff / 86400);

    if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 )
        return;

    return day_diff == 0 && (
            diff < 60 && "just now" ||
            diff < 120 && "1 minute ago" ||
            diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
            diff < 7200 && "1 hour ago" ||
            diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
        day_diff == 1 && "Yesterday" ||
        day_diff < 7 && day_diff + " days ago" ||
        day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
}

// If jQuery is included in the page, adds a jQuery plugin to handle it as well
if ( typeof jQuery != "undefined" )
    jQuery.fn.prettyDate = function(){
        return this.each(function(){
            var date = prettyDate(this.title);
            if ( date )
                jQuery(this).text( date );
        });
    };

Как именно метод prettyDate() возвращает строку? Это еще одна из тех "странных" вещей, которые вы можете сделать в JavaScript, или я просто что-то пропустил?

edit: я не спрашивал, как он возвращает значение, я спросил, как он возвращает строку.

return day_diff == 0 && (....) возвращает логическое значение на любом языке, который я когда-либо использовал.

Ответ 1

Он говорит прямо там: return ..., а затем переходит в длинный вложенный список в основном "inline ifs".; -)

В Javascript операторы boolean возвращают значение одного из операндов, а не только true или false. Например. 0 || 'foo' возвращает 'foo'. Эта характеристика используется в сочетании с короткозамкнутым оператором. false && true не будет оценивать сторону true и возвращать false немедленно, так как все выражение должно быть false.

Ответ 2

В JavaScript:

  • a || b эквивалентен a ? a : b
  • a && b эквивалентен a ? b : a
  • любая непустая строка в булевом выражении имеет значение true

Благодаря этим знаниям логика оператора return становится довольно простой.

Предположим, например, что day_diff = 5

Затем, шаг за шагом, сделав шаг сверху:

return day_diff == 0 && (
       diff < 60 && "just now" ||
       diff < 120 && "1 minute ago" ||
       diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
       diff < 7200 && "1 hour ago" ||
       diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
   day_diff == 1 && "Yesterday" ||
   day_diff < 7 && day_diff + " days ago" ||
   day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";

Сначала day_diff == 0 будет оцениваться как false и правая часть:

(diff < 60 && "just now" ||
 diff < 120 && "1 minute ago" ||
 diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" ||
 diff < 7200 && "1 hour ago" ||
 diff < 86400 && Math.floor( diff / 3600 ) + " hours ago")

... не оценивается. Обе стороны:

day_diff == 1 && "Yesterday"

... оцените значение false. Далее:

day_diff < 7 && day_diff + " days ago"

В этом выражении day_diff < 7 оценивается как true, поэтому его правая часть, которая является строкой, будет оценена и ее результат будет возвращен.

Дальнейшее чтение:

http://www.ejball.com/EdAtWork/2005/02/19/JavaScriptBooleanOperators.aspx

Ответ 3

Вы человек Java? Потому что, если это так, вы, вероятно, думаете, что if(x) требует, чтобы x было логическим, и что "x && y" возвращает логическое значение. Это не в JavaScript и во многих других языках, таких как Perl. Во многих слабо типизированных языках && называется охранным оператором и || называется оператором по умолчанию. Они возвращают один из двух аргументов.

Ответ 4

Оператор return - это просто сложный каскад if/else, который возвращает строку во всех случаях без ошибок.

например.

return day_diff == 0 && (
        diff < 60 && "just now" ||
        diff < 120 && "1 minute ago" || [...]

Если day_diff равен нулю (это означает, что дата сегодня), тогда он попадает в чек, чтобы увидеть, если он меньше 60. Если это утверждение истинно, тогда он будет короткозамкнуто оценивать остальную часть всего, и возвращает значение выражения, которое будет "только сейчас". Если diff не менее 60, он будет коротко закоротить суб-выражение и перейти к проверке diff < 120 и т.д.

Строки всегда являются "истинными" в выражениях, и они также становятся результатом оценки выражения, когда этот случай соответствует.

Это функциональный, но довольно запутанный код. Не для учебных целей.:)

Ответ 5

Да, это странный материал Javascript. Конкатенация строк оценивается как true, а оператор return внизу prettyDate() использует этот плюс short-circuiting в условных выражениях.

Итак, в первом случае diff < 60 && "just now" оценивает строку "только сейчас", если diff действительно меньше 60, потому что все остальные элементы верхнего уровня в условном выражении OR'd вместе, поэтому Javascript оценщик не заботится о них, как только это первое условие выполняется. То же самое происходит по линии.

Ответ 6

Он играет в опасную игру, полагаясь на приоритет оператора для обработки условных выражений:

+ trumps &&, который превосходит ||

Смотрите: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence

Вот как я его читаю:

(day_diff == 0 && (
            (diff < 60 && "just now") ||
            (diff < 120 && "1 minute ago") ||
            (diff < 3600 && Math.floor( diff / 60 ) + " minutes ago") ||
            (diff < 7200 && "1 hour ago") ||
            (diff < 86400 && Math.floor( diff / 3600 ) + " hours ago")
        )) ||
        (day_diff == 1 && "Yesterday") ||
        (day_diff < 7 && day_diff + " days ago") ||
        (day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago");

Ответ 7

Последний оператор строки имеет вид

return boolExpression && otherBoolExpression

Когда javascript читает это, происходит следующее:

  • if boolExpression если false, то он возвращает boolExpression
  • в противном случае он возвращает otherBoolExpression.

Это метод JavaScript для логики короткого замыкания.

Так как в этом случае otherBoolExpression использует конкатенацию строк, функция возвращает строку, пока dayDiff не равно 0.

Ответ 8

В принципе, вы просто должны знать, что

return day_diff == 0 && "lala" + "lolo"

вернет lalalolo, если day_diff == 0... из-за приоритета оператора.

Так что это всего лишь более короткий способ написать

if (day_diff == 0) {
   if (diff < 60) {
      return "just now"
   } else (...)
} else {
   if (day_diff == 1) {
     return "..."
   }
}

Ответ 9

Существуют две переменные: diff - разница в секундах, daydiff - разница в днях. Если daydiff равен нулю, возвращаемое значение основывается на diff, иначе это количество дней.

Прочитайте 'return' как серию предложений 'if'/'else', определяющих возвращаемую строку.