问题
null
and undefined
don't have a toString
or valueOf
method. Afaik using String
calls the toString
method of its parameter (e.g. String({})
=> [object Object]
).
Why do String(null)
or String(undefined
work then? It doesn't implicitly do Object.prototype.toString.call(null)
. because that evaluates to [object Null]
.
[edit]: from the spec ECMA-262/5th edition (page 48). This doesn't add to clarification, I'd say:
/*
Table 13 — ToString Conversions
-------------------------------------------------------------------------
Argument Type | Result
-------------------------------------------------------------------------
Undefined | "undefined"
Null | "null"
Boolean | If the argument is true, then the result is "true".
... | ...
*/
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
String(null)
creates a string object and passes it a default value of null.
来源:https://stackoverflow.com/questions/10362114/why-does-stringnull-work