+ 前缀在此上下文中有什么作用

What does a + prefix do in this context?

本文关键字:什么 作用 上下文 前缀      更新时间:2023-09-26

这是下划线中的一行代码。 这一行中的加号前缀是什么?

if (obj.length === +obj.length) { // plus prefix?

添加+符号可以有效地将变量转换为数字,因此:

+"1" === 1;

但是,请注意

+"1" === "1"; // FALSE
+"1" ==  "1"; // TRUE

这是因为==会将其操作数转换为相同的类型,而===不会。

这意味着测试:

obj.length === +obj.length

本质上是试图测试obj.length是否是数字。

在 Underscore 中,此代码试图确定未知类型的变量是否具有名为 length 的属性以及它是否为数字。假设是,如果这两个都为真,你可以迭代变量,如果它是一个数组。

编辑

请注意,OP 的代码中有许多错误,其中最重要的是这种检测某些东西是否是数组(或类数组(的方法。以下对象会导致问题:

var footballField = {
    covering: "astroturf",
    condition: "muddy",
    length: 100
};

我不提倡上述方法...只是解释别人的。

加号前缀将变量转换为数字。基本上,obj.length === +obj.length是一个健全性检查,obj.length确实是一个数字。如果obj.length不是数字,例如字符串"foo",那么"foo" === +"foo"等同于假,因为+"foo"出来是NaN

这会强制obj.length的值为Number。 从本质上讲,这样做是为了确保类数组对象的length默认值未被覆盖,以便可以正确迭代它。

在这种情况下,breaker什么也不做,因为即使没有等价比较,与breaker相比,即使是另一个空对象{}也会评估为false

但是,breaker不会在该上下文中使用,因为它是在 .each 函数之外定义的,该函数看起来与您在此处显示的内容不同。 相反,它用于强制"中断"其他循环方法:

_.every = _.all = function(obj, iterator, context) {
  /* snip */
  if (!(result = result && iterator.call(context, value, index, list)))
      return breaker;

你可以看到,如果结果在"每"中不真实,我们希望立即打破。 _.every调用_.each,它将返回breaker与自身相比,这将是正确的,允许立即中断。

+ 前缀将值转换为数字。

如果对象没有length属性(是常规Object,而不是Array(,则调用obj.length将返回undefined。未定义的测试会更清晰,但实现者选择首先将其转换为数字(因此它将变为NaN(,然后将其与原始值进行比较(使用严格的比较,这将确保它将产生false(。

更新:正如其他人指出的那样,这段代码似乎不仅关注Array,还关注"类数组"对象(即具有数字length属性和数字索引的对象(。在这种情况下,对instanceof Array进行测试是不够的(仅测试undefined可能不是最佳选择,因为可能存在另一种类型的length(。