a.b < 0,为什么在 a.b === undefined 时不会抛出错误?
a.b < 0, why does this not throw an error when a.b === undefined?
一个错字最终变成了
a.b > 0
a.b
未定义。根据 MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator),比较在操作数上调用 .valueOf()
。所以应该是
a.b.valueOf() > 0
但这实际上引发了一个似乎并没有发生的错误。相反,这似乎被评估了:
undefined > 0
我是不是误会了什么?
在我的例子中,这导致了 Node.js 代码中的静默错误。我当然希望抛出一个错误。
我可以在不显式检查操作数的情况下处理这个问题吗?
编辑:freeCodeCamp 似乎比 MDN 描述得更正确:
https://guide.freecodecamp.org/javascript/comparison-operators/
但我仍然想知道在不被简单的拼写错误困住的情况下处理这个问题的最简单方法。
参见 specification: what it does is:
- Let r be the result of performing Abstract Relational Comparison lval < rval.
哪个 does,它首先尝试将每一侧强制转换为原始:
a. Let px be ? ToPrimitive(x, hint Number).
b. Let py be ? ToPrimitive(y, hint Number).
undefined
已经是原始类型了——什么都不会抛出。然后,它会:
Let nx be ? ToNumeric(px).
Let ny be ? ToNumeric(py).
将 undefined
转换为数字也不会抛出,但 returns NaN
:
console.log(Number(undefined));
那么我们就到了
If Type(nx) is the same as Type(ny), return Type(nx)::lessThan(nx, ny).
其中 nx
是 NaN
并且 ny
是 0。 lessThan
returns undefined
当 nx
是 NaN
, 描述 here:
- If x is NaN, return undefined.
然后,回到答案开头 5.
之后的步骤:
- If r is undefined, return false. Otherwise, return r.
结果是 undefined
,所以返回 false
(没有抛出错误)。
So it should be
a.b.valueOf() > 0
只有对象会在<
评估过程中调用valueOf
(在上面的a. Let px be ? ToPrimitive(x, hint Number).
中)。 undefined
不是一个对象 - 它已经是一个基本类型,所以在那一步不会发生额外的转换。
I certainly wanted that an error was thrown instead.
Can I handle this without explicitly checking the operands?
不完全是,但这一点都不难 - 如果您不确定,只需先检查 a.b
是一个数字。 if (typeof a.b === 'number')
。没有错。
一个错字最终变成了
a.b > 0
a.b
未定义。根据 MDN (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Greater_than_operator),比较在操作数上调用 .valueOf()
。所以应该是
a.b.valueOf() > 0
但这实际上引发了一个似乎并没有发生的错误。相反,这似乎被评估了:
undefined > 0
我是不是误会了什么?
在我的例子中,这导致了 Node.js 代码中的静默错误。我当然希望抛出一个错误。
我可以在不显式检查操作数的情况下处理这个问题吗?
编辑:freeCodeCamp 似乎比 MDN 描述得更正确:
https://guide.freecodecamp.org/javascript/comparison-operators/
但我仍然想知道在不被简单的拼写错误困住的情况下处理这个问题的最简单方法。
参见 specification: what it does is:
- Let r be the result of performing Abstract Relational Comparison lval < rval.
哪个 does,它首先尝试将每一侧强制转换为原始:
a. Let px be ? ToPrimitive(x, hint Number).
b. Let py be ? ToPrimitive(y, hint Number).
undefined
已经是原始类型了——什么都不会抛出。然后,它会:
Let nx be ? ToNumeric(px).
Let ny be ? ToNumeric(py).
将 undefined
转换为数字也不会抛出,但 returns NaN
:
console.log(Number(undefined));
那么我们就到了
If Type(nx) is the same as Type(ny), return Type(nx)::lessThan(nx, ny).
其中 nx
是 NaN
并且 ny
是 0。 lessThan
returns undefined
当 nx
是 NaN
, 描述 here:
- If x is NaN, return undefined.
然后,回到答案开头 5.
之后的步骤:
- If r is undefined, return false. Otherwise, return r.
结果是 undefined
,所以返回 false
(没有抛出错误)。
So it should be
a.b.valueOf() > 0
只有对象会在<
评估过程中调用valueOf
(在上面的a. Let px be ? ToPrimitive(x, hint Number).
中)。 undefined
不是一个对象 - 它已经是一个基本类型,所以在那一步不会发生额外的转换。
I certainly wanted that an error was thrown instead.
Can I handle this without explicitly checking the operands?
不完全是,但这一点都不难 - 如果您不确定,只需先检查 a.b
是一个数字。 if (typeof a.b === 'number')
。没有错。