有人可以解释一下John Resig的pretty.js JavaScript是如何工作的吗?

时间:2011-02-17 04:10:03

标签: 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中可以做的那些“奇怪”事情中的另一个还是我只是错过了什么?

编辑:我没有问他是如何返回一个值,我问他是如何返回一个字符串。

return day_diff == 0 && (....)以我曾经使用的任何语言返回布尔值。

10 个答案:

答案 0 :(得分:28)

在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

答案 1 :(得分:10)

它在那里说:return ...然后进入一个基本上是“内联ifs”的长嵌套列表。 ; - )

在Javascript中,布尔运算符返回其中一个操作数的,而不仅仅是truefalse。例如。 0 || 'foo'返回'foo'。该特性与操作员短路一起使用。 false && true不会评估true方并立即返回false,因为整个表达式必须为false

答案 2 :(得分:7)

你是一个Java人吗?因为如果是这样,你可能认为if(x)需要x是一个布尔值,而“x&amp;&amp; y”返回一个布尔值。它不适用于JavaScript和许多其他语言,如Perl。在许多弱类型语言中&amp;&amp;被称为保护运算符和||被称为默认运算符。他们返回了两个论点中的一个。

答案 3 :(得分:2)

return语句只是一个复杂的if / else级联,最终会在所有非错误情况下返回一个字符串。

E.g。

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

如果day_diff为零(意味着日期是今天),则它会进入检查以查看它是否小于60.如果该语句为真,那么它将短路评估整个事物的其余部分,并且返回表达式的值,这将是“刚才”。如果diff不小于60,它将使子表达短路,并继续进行diff < 120检查,依此类推。

表达式中的字符串始终为“true”,并且当该情况匹配时,它们也会成为评估表达式的结果。

这是功能性但相当混淆的代码。不是为了教学目的。 :)

答案 4 :(得分:1)

是的,这是奇怪的Javascript东西。字符串连接的计算结果为true,return底部的prettyDate()语句在条件语句中利用此加号short-circuiting

基本上,在第一种情况下,如果diff < 60 && "just now"确实小于60,diff将评估字符串“just now”,因为条件中的所有其他顶级项目都是OR'd因此,一旦第一个条件成立,Javascript评估者就不会关心它们。同样如此。

答案 5 :(得分:1)

正在玩依赖运算符优先级处理条件的危险游戏:

+胜过&&,胜过||

请参阅: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");

答案 6 :(得分:1)

该行的最后一个陈述的格式为

return boolExpression && otherBoolExpression

当javascript读取此内容时,会发生以下情况:

  1. 如果boolExpression如果为false,则返回boolExpression
  2. 否则返回otherBoolExpression
  3. 这是JavaScript执行短路逻辑的方式。

    在这种情况下,otherBoolExpression使用字符串连接,只要dayDiff不为0,函数就会返回字符串。

答案 7 :(得分:1)

基本上你只需知道

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

将返回lalalolo if day_diff == 0 ...因为运营商优先。

所以这只是一种较短的写作方式

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

答案 8 :(得分:0)

有两个变量:diff - 以秒为单位的差异,daydiff - 以天为单位的差异。 如果daydiff为零,则返回值基于diff,否则为天数。

将'return'作为'if'/'else'子句系列决定返回字符串。

答案 9 :(得分:0)

prettyDate() 函数的返回值取决于以下评估中使用的两个变量 day_diffdiff

<块引用>
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/else 语句,但如果 time 参数是超过 31 天前的日期,则不会返回任何字符串。

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

(并稍微更新了模板文字,强调返回的字符串顺式)

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