17

我不确定这个结构是什么意思,但我已经看过几次了。下面的示例来自另一个 Stack Overflow 问题。我不确定如何解释最初的“或”构造本身:

Object.keys = Object.keys || (function () {
  var hasOwnProperty = Object.prototype.hasOwnProperty,
      hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
      DontEnums = [ 
          'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
          'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
      ],
      DontEnumsLength = DontEnums.length;
  //etc...
});
4

4 回答 4

20

a = a || function(){...}是 Javascript 中非常常见的一个成语。它依赖于两个概念,虽然这不是 Javascript 独有的,但您可能还不熟悉。

1.操作员短路

运算符短路[wikipedia]是一种编译器优化,旨在防止不必要的评估。

为了证明这一点,让我们假设我们要确定一个人是否是青少年:即一个人的年龄是否在 13 到 19 岁之间。

var isTeenager = person.age >= 13 && person.age <= 19;

现在,让我们假设代码执行并且结果是这个人小于 13 岁。将评估第一个条件并将返回 false。由于程序现在知道运算符的左侧&&false,并且由于&&需要两边都是true才能计算到true,所以它知道计算右侧是没有意义的。

也就是说,程序看到这个人的年龄不超过13岁,就已经知道他不是青少年,不管他是否低于19岁。

同样的原则也适用于||运营商。假设我们想知道一个人是否可以免费乘坐公共汽车:也就是说,这个人是否超过 70 岁或是否有残障。

var canRideFree = person.age >= 70 || isHandicapped(person);

如果这个人超过 70 岁,程序已经知道他可以免费骑行。此时,程序不关心他是否有障碍,因此不会评估对isHandicapped函数的调用。另一方面,如果这个人小于 70 岁,那么canRideFree将被设置为任何isHandicapped返回值。

2.真值和假值

真值和假值[一些随机人的博客]是对象的布尔评估。在 Javascript 中,每个对象都将评估为“真实”或“虚假”值。

如果表达式的值是以下任何一种,则表达式是“假的”:

false, null, undefined, 0, "", NaN

其他一切都是真实的。

人们利用 null 或未定义变量的计算结果为false. 这意味着您可以很容易地检查变量是否存在:

if (a) { /* a exists and is not a falsy value */ }

结合我们所知道的

||运算符短路并返回它计算的最后一个表达式的值。在这个单一的陈述中,这一原则与真实性相结合:

Object.keys = Object.keys || function() {...}

如果Object.keys是真的,它将被评估并分配给它自己。否则,Object.keys将分配给该功能。这是 Javascript 中一个非常常见的习惯用法,用于检查一个值是否已经存在,如果不存在则将其分配给其他东西。

其他一些没有真实性的语言,例如 C#,有一个具有类似目的的空合并运算符[MSDN] 。

object Value = PossiblyNullValue ?? ValueIfNull;

在此代码中,Value将分配给PossiblyNullValue,除非它为空,在这种情况下,它将分配给ValueIfNull

tl;博士[维基百科]

如果您没有费心阅读我上面所说的任何内容,那么您只需要知道a = a || function() {...}基本上就是执行此代码的功能:

if (exists(Object.keys)) {
  Object.keys = Object.keys;
} else { 
  Object.keys = function() {...};
}

function exists(obj) {
  return typeof obj !== "undefined" && 
         obj !== null && 
         obj !== false &&
         obj !== 0 &&
         obj !== "" &&
         !isNaN(obj);
}
于 2011-08-15T18:56:50.280 回答
4

这对我来说看起来不完整,但它似乎是 Object.keys 的垫片。基本上,如果该属性不存在(例如在不符合标准的浏览器中),我们自己实现它。

仅当第一个操作数为假时,or运算符才会评估第二个操作数。像这样

alert(false || "Hello, world");

将提醒“你好,世界”。在这种情况下, Object.keys 将是undefined,其计算结果为false

于 2011-08-15T18:57:32.840 回答
3

基本||意思是:如果Object.keys没有定义,使用后面的表达式定义||

此行为基于 JavaScript 功能,任何未定义的变量都会计算为false. 如果变量是true,则不需要计算第二个表达式,如果是的false话。

于 2011-08-15T18:57:01.990 回答
2

据我所知,Object.keys如果该函数尚未定义(或者它为假),则该代码会尝试定义该函数。左边的||函数将成为函数Object.keys

我说“据我所知”的原因是您没有发布整个代码片段。请注意,||读取后的代码(function(){不仅仅是function(){. 有可能作者已将函数设置为自调用。

如果在函数定义之后看到})(),则函数的返回值存储在 中Object.keys。如果不是,则函数本身存储在那里。

于 2011-08-15T18:56:44.137 回答