2012-04-28 16 views
19

null y undefined no tienen un método toString o valueOf. Afaik utilizando String llama al método toString de su parámetro (por ejemplo, String({}) =>[object Object]).¿Por qué funciona String (null)?

¿Por qué String(null) o String(undefined funcionan entonces? No hace implícitamente Object.prototype.toString.call(null). porque eso evalúa a [object Null].

[edit]: de la especificación ECMA-262/5th edition (página 48). Esto no quiere añadir a la clarificación, diría:

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

Respuesta

22

Después de revisar mi respuesta anterior, parece una revisión completa de mi respuesta anterior es necesario. Me estaba complicando demasiado, ya que la respuesta corta es que estos son casos especiales especificados en estándares.

El specification para String() (String utilizado como una función):

15.5.1.1 String ([valor])

Devuelve un valor String (no un objeto String) calculada por ToString (valor) Si el valor no se> proporciona, se devuelve la cadena vacía "".

La función ToString (que existe internamente, no en espacio de usuario) se define como sigue (9,8):

"El ToString operación abstracta convierte su argumento a un valor de tipo String acuerdo con la Tabla 13"

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

esto significa que String(null) y String(undefined) entran en esta tabla especial de tipos y simplemente volver a los valores de la cadena de valor "null" y "undefined".

Un pseudo-aplicación fácil de la tierra es como la siguiente: (. Tenga en cuenta que este ejemplo ignora el caso constructor (new MyString()) y que utiliza los conceptos de zona de usuario en lugar de motor de la tierra)

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


me llevar un poco y encontré un ejemplo de implementación (V8 para ser específicos):

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

El NonStringToString (que es esencialmente lo que es de interés), se define por suerte en psuedo-JS-tierra. Como puede ver, de hecho hay un caso especial para null/true/false/undefined.

+0

Gracias por su respuesta Corbin, está claro. – KooiInc

+0

@Kooilnc No hay problema. – Corbin

+0

String()! == String (undefined) es porque en JavaScript dos objetos son iguales solo si son el mismo objeto en la memoria. Cuando se llama a String(), se está creando un objeto envoltorio alrededor de la primitiva de cadena, por lo que esencialmente la comparación es de dos objetos diferentes que envuelven la misma primitiva de cadena. – Buzzy

2

Es probable que haya algunos controles adicionales y manejo para casos especiales como null y undefined.

MDN says:

Es posible utilizar String como una alternativa toString "más seguro", ya que aunque todavía normalmente llama al método toString subyacente, sino que también trabaja para nula e indefinido.

0

String(null) crea un objeto de cadena y le pasa un valor predeterminado de nulo.

1

Usted podría estar interesado en ver el Annotated ES5 (que es mucho más fácil de leer que el ECMAScript 5 PDF) que establece que: new String([ value ])http://es5.github.com/#x15.5.2.1 llamadas [ToString]http://es5.github.com/#x9.8 (no es una tabla de los casos especiales convertion) para convertir el valor pasado a a una cuerda.

+1

Es la misma tabla a la que me he vinculado, a excepción de las manchas de color verde. (Y un enlace directo) – Corbin

Cuestiones relacionadas