¿Por qué puedo agregar propiedades con nombre a una matriz como si fuera un objeto?
Los siguientes dos fragmentos de código diferentes me parecen equivalentes:
var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";
y
var myObject = {'A': 'Athens', 'B':'Berlin'};
porque ambos se comportan igual, y además typeof(myArray) == typeof(myObjects)
(ambos producen 'objeto').
¿Hay alguna diferencia entre estas variantes?
Prácticamente todo en javascript es un objeto, por lo que puedes "abusar" de un objeto Array estableciendo propiedades arbitrarias en él. Sin embargo , esto debería considerarse perjudicial . Las matrices son para datos indexados numéricamente; para claves no numéricas, use un Objeto.
Aquí hay un ejemplo más concreto de por qué las claves no numéricas no "encajan" en una matriz:
var myArray = Array();
myArray['A'] = "Athens";
myArray['B'] = "Berlin";
alert(myArray.length);
Esto no mostrará '2', sino '0'; efectivamente, no se han agregado elementos a la matriz, solo algunas propiedades nuevas agregadas al objeto de la matriz.
En JS, las matrices son objetos, ligeramente modificados (con algunas funciones más).
Funciones como:
concat
every
filer
forEach
join
indexOf
lastIndexOf
map
pop
push
reverse
shift
slice
some
sort
splice
toSource
toString
unshift
valueOf
Pienso yo demasiado metafórico y críptico con la respuesta anterior. Sigue una aclaración.
Una instancia de Matriz, Booleano, Fecha, Función, Número, RegExp, Cadena es un Objeto pero mejorado con métodos y propiedades específicas de cada tipo. Por ejemplo, una matriz tiene una length
propiedad predefinida, mientras que los objetos genéricos no.
javascript:alert([].length+'\n'+{}.length)
muestra
0 indefinido
Intrínsecamente, el intérprete de FF Gecko también distingue entre matrices y objetos genéricos con distintas diferencias al evaluar las construcciones del lenguaje.
javascript:
ra=[ "one", "two", "three"]; ra.a=4;
ob={0:"one", 1:"two", 2:"three"}; ob.a=4;
alert(
ra +"\n\n"+
ob +"\n\n"+
ra.toSource() +"\n\n"+
ra.a +"\t .toSource() forgot me! \n\n"+
ra.length +"\t and my length! \n\n"+
ob.toSource());
ps=""; for(i in ra)ps+=i+" "; alert(ps); /* NB .length is missing! */
ps=""; for(i in ob)ps+=i+" "; alert(ps);
mostrando
Uno, dos, tres [objeto Objeto] ["Uno, dos, tres"] 4 .toSource() ¡me olvidó! 3 y mi longitud! ({0:"uno", 1:"dos", 2:"tres", a:4})
y 0 1 2 a
y 0 1 2 a
.
Respecto a la afirmación de que todos los objetos son funciones:
No es sintáctica ni semánticamente correcto utilizar una instancia de objeto arbitrario como una función como 123()
o "abc"()
o []()
o {}()
donde obj()
es obj
de cualquier tipo distinto de Function
, por lo que una INSTANCIA de objeto arbitrario no es un Function
. Sin embargo, dado un objeto obj
y su tipo como Array, Boolean, Date, ...
, ¿cómo llegó obj
a serlo Array, Boolean, Date, ...
? Que es un Array, Boolean, Date, ...
?
javascript:
alert([Array, Boolean, Date, Function,
Number, Object, RegExp, String] . join('\n\n') );
muestra
function Array() {
[native code]
}
function Boolean() {
[native code]
}
function Date() {
[native code]
}
function Function() {
[native code]
}
function Number() {
[native code]
}
function Object() {
[native code]
}
function RegExp() {
[native code]
}
function String() {
[native code]
}
En todos los casos, sin lugar a dudas, el tipo de objeto se manifiesta como una function
definición, ¡de ahí la afirmación de que todos los objetos son funciones! (¡Lo irónico es que intencionalmente oscurecí y desdibujé la distinción de una instancia de objeto con la de su tipo! Aún así, esto muestra "no puedes tener uno sin el otro", ¡Objeto y Función! Las mayúsculas enfatizan el tipo como opuesto a instancia.)
Tanto el paradigma funcional como el de objetos parecen ser fundamentales para la programación e implementación de las primitivas integradas de bajo nivel del intérprete JS, como Math
y JSON
y true
.
javascript:alert([Math, JSON, true.toSource()].join("\n\n"));
muestra
[object Math]
[object JSON]
(new Boolean(true))
En el momento del desarrollo de Javascript, estaba de moda un estilo de programación centrado en objetos (OOP's - estilo de programación orientada a objetos - ¡la "'s" es mi propio juego de palabras!) y el intérprete fue bautizado de manera similar con Java para darle mayor credibilidad. . Las técnicas de programación funcional quedaron relegadas a exámenes más abstractos y esotéricos que estudiaban las teorías de autómatas, funciones recursivas, lenguajes formales, etc. y, como tales, no eran aceptables. Sin embargo, los puntos fuertes de estas consideraciones formales se manifiestan claramente en Javascript, particularmente tal como se implementa en el motor Gecko de FF (es decir, .toSource()
).
¡La definición de Objeto para Función es particularmente satisfactoria porque se define como una relación de recurrencia! definido usando su propia definición!
function Function() { [native code] }
y dado que una función es un objeto, el mismo sentimiento se aplica a
function Object() { [native code] }
.
La mayoría de las otras definiciones se mantienen inactivas en un valor terminal estático. Sin embargo, eval()
es una primitiva particularmente poderosa y, por lo tanto, una cadena también puede incorporar funciones arbitrarias.
Tenga en cuenta nuevamente que la lengua vernácula utilizada anteriormente oscurece la distinción entre el tipo de objeto y la instancia.
Todo en JavaScript es un objeto además de los tipos primitivos.
El código
var myArray = Array();
crea una instancia del objeto Array mientras
var myObject = {'A': 'Athens', 'B':'Berlin'};
crea una instancia del objeto Objeto.
Pruebe el siguiente código
alert(myArray.constructor)
alert(myObject.constructor)
Entonces verás que la diferencia está en el tipo de constructor de objetos.
La instancia del objeto Array contendrá todas las propiedades y métodos del prototipo Array.