Nota: no busco opiniones. Un solo ejemplo útil objetivo de un constructor primitivo satisfaría la pregunta.
¿Hay alguna buena razón para usar new Number(n) ? ¿Por qué existe este constructor?
Puedo pensar en varias razones para evitarlo, por ejemplo,
5 === 5 pero el new Number(5) !== new Number(5) ).typeof indica que es un número/str/etc en lugar de un objeto.new Number(0) nunca es falso. ( !!new Number(false) == true ).+false === 0 ).Para ser claros, entiendo que el objeto Number (o String u Object o Array) tiene métodos y propiedades útiles, mi pregunta es específicamente sobre el constructor .
También soy consciente de que los constructores se llaman implícitamente cuando se usan los métodos de estos tipos primitivos (por ejemplo, 123.45.toFixed(n) ), pero eso no explica por qué los constructores están expuestos al navegador, o cómo (o si ) los propios constructores son útiles.
Estoy usando Number como ejemplo, pero no entiendo por qué Javascript expone otros constructores donde los literales están disponibles (String, Object, Array, etc.).
¿Por qué existen y hay alguna buena razón para usarlos?
Al final, esa pregunta se responde con "porque está en la especificación", pero todavía hay una lógica intuitiva para tener un constructor de Number :
Como ya mencionó en la pregunta, hay un objeto prototipo (útil) para números, para que pueda llamar a métodos como .toFixed et al. Cada objeto de JavaScript con un prototipo no nulo tiene un constructor. Constructor y prototipo van de la mano; a menos que el código sobrescriba las propiedades involucradas, existe esta relación para cada objeto que tiene un prototipo no nulo:
instance.constructor.prototype === Object.getPrototypeOf(instance) Como esto es como una regla general, tiene sentido no desviarse de eso para números (envueltos en objetos), y tener un valor significativo para esa propiedad de constructor , es decir, un ... constructor. Y por definición de "constructor", se puede llamar con new .
Aquí realmente entramos en la zona gris de la opinión.
Solo una observación: las instancias de Number pueden tener propiedades personalizadas, pero incluso para ese propósito puede confiar en el ajuste automático:
let n = Object.assign(2, { isPrime: true }); console.log(n instanceof Number); // true console.log(n.isPrime); // true console.log(n*2); // 4Estos constructores crean un "objeto contenedor" alrededor del tipo primitivo, por lo tanto, el objeto devuelto es fundamentalmente diferente al propio primitivo.
var example = new String('abc')devolvería un objeto contenedor que contiene el valor "abs" y para acceder a él debe llamar a la función .valueOf()
example.valueOf() // returns abcLos primitivos también tienen acceso al prototipo del envoltorio, pero aún así son fundamentalmente diferentes. Las primitivas simplemente "toman prestados" los métodos en su prototipo de su envoltorio.
La razón de la existencia del envoltorio de la primitiva es meramente histórica, ya que este comportamiento existe en Java, del cual Javascript heredó la diferencia entre objetos y primitivas.
La única razón por la que puedo pensar en usarlo es agregar una propiedad en una primitiva como la siguiente:
Si haces esto:
var example = "Foo" ; example.bar = "Baz"; // The property "bar" only exist on this line and does not persist;Usando el envoltorio:
var example = new String("foo") ; example.bar = "baz" ; // Now you can access the property "baz" example.charAt(1); //You still can access the methods on the string prototypeEs una sintaxis muy incómoda pero funciona.
Gracias por la gran pregunta y espero ver todas las respuestas y diferentes discusiones para tratar de comprender la existencia detrás de algunos de los comportamientos muy extraños en Javascript.
¿Hay alguna buena razón para usar el nuevo número (n)?
Puedo pensar en una razón, pero podría no ser válida hoy. Es una exageración, pero creo que podría usarse por razones de rendimiento según la implementación.
La especificación dice esto sobre un caso en el que harías algo como:
1.2.toString()El objeto que se puede crear en el paso 4.a no es accesible fuera de la operación abstracta anterior y el método interno de objeto ordinario [[Obtener]]. Una implementación podría optar por evitar la creación real del objeto.
Entonces, técnicamente, alguien que está haciendo algo así podría beneficiarse un poco si creara de manera preventiva el objeto numérico y llamara al método allí. Eso es si la implementación no evita el contenedor de objetos.
Sin embargo, dadas las implementaciones actuales, probablemente obtendrá los resultados opuestos y obtendrá un peor rendimiento.
De todos modos, es un gran tramo.
¿Por qué existe este constructor?
Bueno, se me ocurren un par de razones, principalmente por la consistencia. En primer lugar, String , Number y Boolean se duplican como constructores y como funciones regulares. Cada uno puede convertir su entrada en sus respectivos tipos cuando se les llama sin new . En realidad, había muy pocas funciones en ese entonces que no fueran constructores (como eval o Function.prototype ). También tenía que pensar dónde colocar estos prototipos de objetos y un lugar bastante obvio para colocarlos habría sido en estas funciones, al igual que las otras funciones integradas.
Entonces, en general, es probable que no desee que estas funciones no sean constructoras porque no desearía imponer una carga innecesaria de recordar todos estos casos extremos a sus usuarios y aquellos que los implementarán. Hoy tendríamos preguntas como: "¿Por qué Number es una función y no un constructor cuando incluso tiene el prototipo Number en su propiedad .prototype ?"
Estoy usando Number como ejemplo, pero no entiendo por qué Javascript expone otros constructores donde los literales están disponibles (String, Object, Array, etc.).
Bueno, cada uno de estos también se puede extender a través class . Extending Array , por ejemplo, se buscó un poco antes de ES6. P.ej
class myArrayClass extends Array { myCustomMethod(){ } } También puede extender String y Number de una manera un tanto segura.