Why does String(null) work?

人走茶凉 提交于 2019-12-01 02:12:52
Corbin

After reviewing my previous answer, it seems a complete overhaul of my previous answer is necessary. I was way over complicating it, as the short answer is that these are standards-specified special cases.

The specification for String() (String used as a function):

15.5.1.1 String ( [ value ] )

Returns a String value (not a String object) computed by ToString(value). If value is not supplied, the empty String "" is returned.

The ToString function (that exists internally, not in userland) is defined as follows (9.8):

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

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

This means that String(null) and String(undefined) go into this special table of types and just return the string values valued "null" and "undefined".

A user-land pseudo-implementation looks something like this:

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))
    }
}

(Note that this example ignores the constructor case (new MyString()) and that it uses user-land concepts rather than engine-land.)


I got a bit carried away and found an example implementation (V8 to be specific):

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));
}

The NonStringToString (which is essentially what is of interest), is luckily defined in psuedo-JS-land. As you can see, there is indeed a special case for null/true/false/undefined.

There is probably just some extra checks and handling for special cases like null and undefined.

MDN says:

It's possible to use String as a "safer" toString alternative, as although it still normally calls the underlying toString, it also works for null and undefined.

You might be interested in seeing the Annotated ES5 (which is much more readable than the ECMAScript 5 PDF) which states that: new String([ value ]) http://es5.github.com/#x15.5.2.1 calls [ToString] http://es5.github.com/#x9.8 (there is a table of the special convertion cases) to convert the value passed to it to a string.

String(null) creates a string object and passes it a default value of null.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!