La cosa importante da notare qui è che, dal momento che Javascript è un linguaggio dinamico , ogni oggetto è, essenzialmente, solo una mappa hash glorificata ( con alcune eccezioni ). E tutto in un oggetto Javascript è accessibile in due modi: notazione parentesi e notazione punto.
Esaminerò rapidamente le due notazioni che rispondono alla prima parte della domanda e poi passerò alla seconda parte.
Notazione parentesi
Questa modalità è più simile all'accesso a hashmap e array in altri linguaggi di programmazione. Puoi accedere a qualsiasi componente (dati (inclusi altri oggetti) o funzione) utilizzando questa sintassi.
Questo è esattamente ciò che stai facendo nel tuo esempio. Hai 'a', che è una stringa (e non un carattere letterale, come sarebbe in un linguaggio come C ++).
Usando la notazione parentesi, si accede al suo toUpperCasemetodo. Ma accedervi non è ancora sufficiente; semplicemente digitando alert, ad esempio, in Javascript, non si chiama il metodo. È solo una semplice affermazione. Per chiamare la funzione, è necessario aggiungere la parentesi: alert()mostra una semplice finestra di dialogo contenente undefined, in quanto non ha ricevuto parametri. Ora possiamo usare questa conoscenza per decifrare il tuo codice, che diventa:
alert('a'.toUpperCase());
Che è molto più leggibile.
In realtà, un buon modo per capirlo un po 'meglio è eseguire il seguente Javascript:
alert(alert)
Questo chiama anche alertpassandogli un oggetto funzione, anche alertsenza eseguire il secondo avviso. Ciò che viene mostrato (almeno in Chrome 26) è il seguente:
function alert() { [native code] }
Calling:
alert(alert())
mostra due finestre di messaggio consecutive contenenti undefined. Questo è facile da spiegare: l'interno alert()viene eseguito per primo, mostra undefined(perché non aveva parametri) e non restituisce nulla. L'avviso esterno riceve il valore di ritorno dell'avviso interno, che è nulla e viene visualizzato anche undefinedin una finestra di messaggio.
Prova tutti i casi su jsFiddle!
Notazione a punti
Questo è l'approccio più standard, che consente l'accesso ai membri di un oggetto usando l' .operatore dot ( ). Ecco come apparirebbe il tuo codice nella notazione a punti:
alert('a'.toUpperCase())
Molto più leggibile. Quindi, quando dovremmo usare la notazione punto e quando dovremmo usare la notazione parentesi?
Confronto
La differenza principale tra i due metodi è semantica. Ci sono anche altri dettagli, ma li raggiungerò tra un secondo. La cosa più importante è ciò che realmente vuoi fare - una regola empirica è che usi la notazione a punti per campi e metodi ben definiti che un oggetto ha e la notazione a parentesi quadre per quando stai effettivamente usando il tuo oggetto come una mappa di hash .
Un ottimo esempio del motivo per cui questa regola è così importante può essere mostrato nel tuo esempio: poiché il codice utilizza la notazione tra parentesi in un punto in cui la notazione con punti sarebbe stata molto più sensata, rende il codice più difficile da leggere. E questa è una cosa negativa, perché il codice viene letto molte più volte di quanto non sia scritto .
In alcuni casi, è necessario utilizzare la notazione tra parentesi quadre anche se l'uso della notazione con punti era più sensato:
se un membro di un oggetto ha un nome contenente uno o più spazi o altri caratteri speciali, non puoi usare la notazione a punti: foo.some method()non funziona, ma foo["some method"]()funziona;
se devi accedere dinamicamente ai membri di un oggetto, sei anche bloccato usando la notazione parentesi;
Esempio:
for(var i = 0; i < 10; ++i) {
foo["method" + i]();
}
La linea di fondo è che dovresti usare la sintassi della parentesi quando usi l'oggetto come hash map ( foods["burger"].eat()) e la sintassi del punto quando lavori con campi e metodi "reali" ( enemy.kill()). Dato che Javascript è un linguaggio dinamico, la linea tra i campi "reali" e i metodi di un oggetto e "altri" dati memorizzati può diventare piuttosto sfocata. Ma finché non li mescoli in modi confusi, dovresti andare bene.
Ora, sul resto della tua domanda (finalmente!: P).
come posso essere sicuro che il metodo sarà sempre un membro di obj
Non puoi. Provalo. Prova a chiamare derpuna stringa. Verrà visualizzato un errore nelle righe di:
Uncaught TypeError: Object a has no method 'derp'
È una specie di funzione generica chiamare QUALSIASI metodo su QUALSIASI oggetto. Ciò significa che il metodo specificato sarà già un membro implicito dell'oggetto specificato?
Sì, nel tuo caso dovrebbe essere. Altrimenti si finisce con l'errore che ho menzionato sopra. Tuttavia, non è necessario utilizzare return obj[method]();nella callMethod()funzione. È possibile aggiungere la propria funzionalità che viene quindi utilizzata dalla funzione mappa. Ecco un metodo codificato che trasforma tutte le lettere in lettere maiuscole:
function makeCap()
{
return function(obj) {
return obj.toUpperCase();
}
}
var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C']
console.log(caps2)
Il codice nell'esercitazione a cui si è collegati utilizza funzioni parziali . Sono un concetto complicato da soli. Leggere di più su questo argomento dovrebbe aiutare a rendere le cose più chiare di quanto potrei mai farle.
Nota: questo è il codice della funzione mappa utilizzata dal codice nella domanda, fonte qui .
function map(arr, iterator) {
var narr = [];
for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
return narr;
}
arr[5]. Se i numeri in cui i nomi identificatore valido è possibile utilizzare la notazione del punto:arr.5.