¿Cómo y por qué funciona 'a'['toUpperCase']() en JavaScript?
JavaScript sigue sorprendiéndome y este es otro ejemplo. Me encontré con un código que al principio no entendí. Entonces lo depuré y llegué a este hallazgo:
alert('a'['toUpperCase']()); //alerts 'A'
Ahora bien, esto debe ser obvio si toUpperCase()
se define como un miembro del tipo cadena, pero inicialmente no tenía sentido para mí.
De todos modos,
- ¿Funciona esto porque
toUpperCase
es miembro de 'a'? ¿O hay algo más detrás de escena? el código que estaba leyendo tiene una función de la siguiente manera:
function callMethod(method) { return function (obj) { return obj[method](); //**how can I be sure method will always be a member of obj** } } var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] // ignoring details of map() function which essentially calls methods on every // element of the array and forms another array of result and returns it
Es una función algo genérica llamar a CUALQUIER método en CUALQUIER objeto. ¿Pero eso significa que el método especificado ya será un miembro implícito del objeto especificado?
Estoy seguro de que me falta una comprensión seria del concepto básico de las funciones de JavaScript. Por favor ayúdame a entender esto.
Para descomponerlo.
.toUpperCase()
es un método deString.prototype
'a'
es un valor primitivo, pero se convierte en su representación de Objeto- Tenemos dos notaciones posibles para acceder a las propiedades/métodos del objeto, notación de puntos y corchetes.
Entonces
'a'['toUpperCase'];
es el acceso mediante notación entre corchetes a la propiedad toUpperCase
, desde String.prototype
. Dado que esta propiedad hace referencia a un método , podemos invocarlo adjuntando()
'a'['toUpperCase']();
foo.bar
y foo['bar']
son iguales, por lo que el código que publicaste es el mismo que
alert('a'.toUpperCase())
Cuando usa foo[bar]
(tenga en cuenta la falta de comillas), no usa el nombre literal bar
sino cualquier valor que contenga la variable bar
. Entonces, usar la foo[]
notación en lugar de foo.
le permite usar un nombre de propiedad dinámico.
Echemos un vistazo a callMethod
:
En primer lugar, devuelve una función que toma obj
como argumento. Cuando se ejecute esa función, llamará method
a ese objeto. Por lo tanto, el método dado sólo necesita existir en obj
sí mismo o en algún lugar de su cadena de prototipos.
En el caso de que toUpperCase
provenga de ese método String.prototype.toUpperCase
, sería bastante estúpido tener una copia separada del método para cada cadena que exista.
Puede acceder a los miembros de cualquier objeto con .propertyName
notación o ["propertyName"]
notación. Esa es la característica del lenguaje JavaScript. Para asegurarse de que ese miembro esté en el objeto, simplemente verifique si está definido:
function callMethod(method) {
return function (obj) {
if (typeof(obj[method]) == 'function') //in that case, check if it is a function
return obj[method](); //and then invoke it
}
}
Básicamente, JavaScript trata todo como un objeto, o más bien, cada objeto puede verse como un diccionario/matriz asociativa. Y las funciones/métodos se definen exactamente de la misma manera para el objeto: como una entrada en esta matriz asociativa.
Básicamente, estás haciendo referencia/llamando (observa ' () ' ) la propiedad 'toUpperCase', del objeto 'a' (que es un tipo de cadena, en este caso).
Aquí hay un código de la parte superior de mi cabeza:
function myObject(){
this.msg = "hey there! ;-)";
this.woop = function(){
alert(this.msg); //do whatever with member data
}
}
var obj = new myObject();
alert( obj.msg );
alert( obj['msg'] );
obj['woop']();