JavaScript String concatenation behavior with null or undefined values

后端 未结 6 432
无人及你
无人及你 2020-12-02 17:54

As you may know, in JavaScript \'\' + null = \"null\" and \'\' + undefined = \"undefined\" (in most browsers I can test: Firefox, Chrome and IE). I

6条回答
  •  情深已故
    2020-12-02 18:55

    The ECMA Specification

    Just to flesh out the reason it behaves this way in terms of the spec, this behavior has been present since version one. The definition there and in 5.1 are semantically equivalent, I'll show the 5.1 definitions.

    Section 11.6.1: The Addition operator ( + )

    The addition operator either performs string concatenation or numeric addition.

    The production AdditiveExpression : AdditiveExpression + MultiplicativeExpression is evaluated as follows:

    1. Let lref be the result of evaluating AdditiveExpression.
    2. Let lval be GetValue(lref).
    3. Let rref be the result of evaluating MultiplicativeExpression.
    4. Let rval be GetValue(rref).
    5. Let lprim be ToPrimitive(lval).
    6. Let rprim be ToPrimitive(rval).
    7. If Type(lprim) is String or Type(rprim) is String, then
      a. Return the String that is the result of concatenating ToString(lprim) followed by ToString(rprim)
    8. Return the result of applying the addition operation to ToNumber(lprim) and ToNumber(rprim). See the Note below 11.6.3.

    So, if either value ends up being a String, then ToString is used on both arguments (line 7) and those are concatenated (line 7a). ToPrimitive returns all non-object values unchanged, so null and undefined are untouched:

    Section 9.1 ToPrimitive

    The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type ... Conversion occurs according to Table 10:

    For all non-Object types, including both Null and Undefined, [t]he result equals the input argument (no conversion). So ToPrimitive does nothing here.

    Finally, Section 9.8 ToString

    The abstract operation ToString converts its argument to a value of type String according to Table 13:

    Table 13 gives "undefined" for the Undefined type and "null" for the Null type.

    Will it change? Is it even an "oddity"?

    As others have pointed out, this is very unlikely to change as it would break backward compatibility (and bring no real benefit), even more so given that this behavior is the same since the 1997 version of the spec. I would also not really consider it an oddity.

    If you were to change this behavior, would you change the definition of ToString for null and undefined or would you special-case the addition operator for these values? ToString is used many, many places throughout the spec and "null" seems like an uncontroversial choice for representing null. Just to give a couple of examples, in Java "" + null is the string "null" and in Python str(None) is the string "None".

    Workaround

    Others have given good workarounds, but I would add that I doubt you want to use entity || "" as your strategy since it resolves true to "true" but false to "". The array join in this answer has the more expected behavior, or you could change the implementation of this answer to check entity == null (both null == null and undefined == null are true).

提交回复
热议问题