Может кто-нибудь объяснить, как работает JavaScript Джона Резига pretty.js? - PullRequest
12 голосов
/ 17 февраля 2011

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: я не спрашивал, как он возвращает значение, я спрашивал, как он возвращает строку.1008 *

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

Ответы [ 9 ]

28 голосов
/ 17 февраля 2011

В 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

10 голосов
/ 17 февраля 2011

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

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

7 голосов
/ 17 февраля 2011

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

2 голосов
/ 17 февраля 2011

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

Например,

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

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

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

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

1 голос
/ 17 февраля 2011

В основном вам просто нужно знать, что

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 "..."
   }
}
1 голос
/ 17 февраля 2011

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

return boolExpression && otherBoolExpression

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

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

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

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

1 голос
/ 17 февраля 2011

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

+ козыри &&, что козыри ||

См .: 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");
1 голос
/ 17 февраля 2011

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

Таким образом, в основном, в первом случае1007 * вычисляет строку «только сейчас», если diff действительно меньше 60, потому что все остальные элементы верхнего уровня в условном выражении объединены в OR, поэтому оценщик Javascript не заботится о них, когда выполняется это первое условиеправда.То же самое происходит и в дальнейшем.

0 голосов
/ 17 февраля 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...