【问题标题】:Why does String(null) work?为什么 String(null) 有效?
【发布时间】:2012-04-28 09:05:50
【问题描述】:

nullundefined 没有 toStringvalueOf 方法。 Afaik 使用String 调用其参数的toString 方法(例如String({}) => [object Object])。

那为什么String(null)String(undefined 工作?它不会隐含地执行Object.prototype.toString.call(null)。因为计算结果为[object Null]

[编辑]:来自规范 ECMA-262/5th edition(第 48 页)。这并没有增加澄清,我想说:

/*
Table 13 — ToString Conversions  
-------------------------------------------------------------------------
Argument Type  | Result  
-------------------------------------------------------------------------
Undefined      | "undefined"
Null           | "null"  
Boolean        | If the argument is true, then the result is "true".
...            | ...
*/

【问题讨论】:

    标签: javascript string null tostring


    【解决方案1】:

    在查看了我之前的答案之后,似乎有必要对我之前的答案进行彻底检查。我把它复杂化了,因为简短的回答是这些是标准指定的特殊情况。

    String()specificationString 用作函数):

    15.5.1.1 字符串([值])

    返回由 ToString(value) 计算的字符串值(不是字符串对象)。如果未提供值,则为空 返回字符串“”。

    ToString 函数(存在于内部,不在用户空间中)定义如下(9.8):

    "抽象操作 ToString 根据表 13 将其参数转换为 String 类型的值"

    Argument Type | Result
    Null | "null"
    Undefined | "undefined"
    

    这意味着String(null)String(undefined) 进入这个特殊的类型表,只返回值"null""undefined" 的字符串值。

    用户级伪实现如下所示:

    function MyString(val) {
        if (arguments.length === 0) {
            return "";
        } else if (typeof val === "undefined") {
            return "undefined";
        } else if (val === null) {
            return "null";
        } else if (typeof val === "boolean") {
            return val ? "true" : "false";
        } else if (typeof val === "number") {
            // super complex rules
        } else if (typeof val === "string") {
            return val;
        } else {
            // return MyString(ToPrimitive(val, prefer string))
        }
    }
    

    (请注意,此示例忽略了构造函数案例 (new MyString()),并且它使用了用户域概念而不是引擎域。)


    我有点得意忘形,找到了一个示例实现(具体是 V8):

    string.js:

    // Set the String function and constructor.
    %SetCode($String, function(x) {
      var value = %_ArgumentsLength() == 0 ? '' : TO_STRING_INLINE(x);
      if (%_IsConstructCall()) {
        %_SetValueOf(this, value);
      } else {
        return value;
      }
    });
    

    macros.py:

    macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg));
    

    runtime.js:

    function NonStringToString(x) {
      if (IS_NUMBER(x)) return %_NumberToString(x);
      if (IS_BOOLEAN(x)) return x ? 'true' : 'false';
      if (IS_UNDEFINED(x)) return 'undefined';
      return (IS_NULL(x)) ? 'null' : %ToString(%DefaultString(x));
    }
    

    NonStringToString(本质上是我们感兴趣的)幸运地在 psuedo-JS-land 中定义。如您所见,确实存在 null/true/false/undefined 的特殊情况。

    【讨论】:

    • String() !== String(undefined) 是因为在 JavaScript 中,两个对象只有在内存中是同一个对象时才相等。调用 String() 时,您正在围绕字符串原语创建一个包装器对象,因此本质上比较的是两个不同的对象包装了相同的字符串原语。
    • @Buzzy 是的,对于正确的对象,因此对于像new String(x) === new String(y) 这样的东西,这是有道理的。 String(x) 被指定为等效于字符串值,而不是字符串对象。根据关于=== 运算符(11.9.6)的标准:“如果 x 和 y 是完全相同的字符序列(相同长度和对应位置的相同字符),则返回 true;否则返回 false。”跨度>
    • @Buzzy 很高兴您发表了评论。重读我的旧答案后,我意识到规范中非常明确的功能过于复杂了! :)
    • 使这项工作,这很奇怪:x={null:1}; x["null"];//1 x[null]; //1
    【解决方案2】:

    对于nullundefined 等特殊情况,可能只是一些额外的检查和处理。

    MDN says:

    可以使用 String 作为“更安全”的 toString 替代方案,因为尽管它通常仍会调用底层 toString,但它也适用于 null 和 undefined。

    【讨论】:

      【解决方案3】:

      String(null) 创建一个字符串对象并传递一个默认值 null。

      【讨论】:

        【解决方案4】:

        您可能有兴趣查看Annotated ES5(比 ECMAScript 5 PDF 更具可读性),它指出:new String([ value ]) http://es5.github.com/#x15.5.2.1 调用 [ToString] http://es5.github.com/#x9.8(有一个特殊的表转换情况)将传递给它的值转换为字符串。

        【讨论】:

        • 这与我链接的表格完全相同,除了斑点呈绿色。 (以及直接链接)
        猜你喜欢
        • 2023-03-24
        • 1970-01-01
        • 2012-11-14
        • 1970-01-01
        • 2021-09-20
        • 1970-01-01
        • 1970-01-01
        • 2010-12-23
        • 2018-11-24
        相关资源
        最近更新 更多