¿Cómo y por qué funciona 'a'['toUpperCase']() en JavaScript?

Resuelto Mahesha999 asked hace 11 años • 12 respuestas

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 toUpperCasees 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.

Mahesha999 avatar Mar 27 '13 20:03 Mahesha999
Aceptado

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']();
jAndy avatar Mar 27 '2013 13:03 jAndy

foo.bary 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 barsino 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 objcomo argumento. Cuando se ejecute esa función, llamará methoda ese objeto. Por lo tanto, el método dado sólo necesita existir en objsí mismo o en algún lugar de su cadena de prototipos.

En el caso de que toUpperCaseprovenga de ese método String.prototype.toUpperCase, sería bastante estúpido tener una copia separada del método para cada cadena que exista.

ThiefMaster avatar Mar 27 '2013 13:03 ThiefMaster

Puede acceder a los miembros de cualquier objeto con .propertyNamenotació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
    }
}
Artyom Neustroev avatar Mar 27 '2013 13:03 Artyom Neustroev

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']();
Nisk avatar Mar 27 '2013 13:03 Nisk