domenica 13 maggio 2012

.js: che voglia dire Jet Set ?

Leggevo ieri un post sul mercato del libro informatico negli USA, in particolare come i vari linguaggi di programmazione si litigano lo share; domina Java, ma la dinamica anno su anno premia javascript.

Delphi: ZERO libri venduti. (zero, nada, nil). Pascal: qualche decina di unità. Ma anche Ruby sembra un linguaggio minore. Quindi bisogna studiarsi javascript in generale e nodejs in particolare. Il fatto che nodejs piaccia a Micro$oft un po' mi preoccupa, comunque approfittiamo di quello che mettono a disposizione per l'ambiente windows, poi si vedrà. L'accoppiata con mongoDB come strato di persistenza sembra quella che va per la maggiore.

Sto guardando in particolare locomotivejs che sembra un "js on rails": ci si ritrovano molte delle sue convenzioni, ma i "model" (la M del M-V-C) non li ho mica capiti bene ... si deve usare mongoose. Devo verificare in fretta come va su heroku.

Un'altra "locomotiva" ha nel frattempo catturato la mia attenzione: locomotivecms, un CMS per RoR tipo Refinery. Sembra meglio attrezzato di quest'ultimo: in particolare ha un editor a pagamento (23€) che promette grande produttività. Heroku e S3 sono elementi di primo piano. Da testare ASAP.

Back to js: è un linguaggio OO, espressivo e potente, ma l'impatto iniziale per me è "sgodevole". Sto leggendo alcuni post che vorrebbero privilegiare l'immediatezza intuitiva della raffigurazione visuale, ma quello che mi colpisce è l'apparente arbitrarietà di talune scelte sintattiche. C'è da soffrire, ma immaginare un unico linguaggio dal back-end alla pagina nel browser è estremamente attraente. L'hype in ambiente SW-dev sembra di nuovo allontanarsi dall'approccio native in favore di HTML5 + CSS3.

L'importante è trovare commesse.

P.S.: seguono alcune dolorose annotazioni su js.

Graffa, proprietà, due punti, valore, chiusa graffa. POF ! Questo è un oggetto. Non serve necessariamente una classe e un costruttore (invece in Delphi e in Ruby le Classi contengono i metodi e gli oggetti i valori, cioè le istanze dello stato). Esempio: { name: "ogiva" } ecco un oggetto con una sola proprietà (attualmente) di tipo string che contiene il valore "ogiva". La proprietà si chiama name. Un oggetto è una raccolta di (uno o più) puntatori ad altri oggetti o primitive (string, number, boolean or functions). L'oggetto di solito nasce "per" una variabile:

var obj = { name: "ogiva" } 

oppure viene istanziato a partire da un altro oggetto:


var ob2 = Object.create(obj)


ma può anche essere passato come parametro ad una funzione (oggetto creato al volo):


console.log(description.call({
  name: "Zed the Zetabyte"
}));

Ma sono io che ci vedo poco ???  Si fa fatica a distinguere una tonda da una graffa, specie se uno alla graffa non ci ha mai dato molta importanza, essendo relegata ai commenti in pascal. Non è un linguaggio per vecchi.

Il concetto di closure e l'uso di this mi è particolarmente indigesto. Mi sembra che faccia a pugni con il primo paradigma della OO, l'incapsulazione. Adesso mi leggo questi articoli sperando in maggiori lumi.

Lexical scope is 100% based on the physical location of the variables in the nesting in the code. Questo è rassicurante, nel senso che non c'è niente di nuovo:  variabili "inner" possono nascondere variabili "outer".


var Lui = { name: "Zed", ciao: function() { return "Ciao " + name}}
var name = "Dug"

Lui.ciao() dà sempre e comunque "Ciao Zed" a prescindere dall'esistenza e dal valore dalla var globale name.

This è invece il context object: lo puoi solo usare, non modificare; di volta in volta "vale" in base a "da dove" chiami la funzione che lo usa. Es.:

var Lui = { name: "Zed", ciao: function() { return "Ciao " + this.name}}

var name = "Dug"
var effe = Lui.ciao      // nota bene, senza parentesi, non voglio il risultato ma l'indirizzo della funzione


Lui.ciao() dà ancora "Ciao Zed" ma effe() dà invece "Ciao Dug" e se la variabile globale name non esiste va in errore (undef) !!! Capito cos'è il context object ? Non ci sono garanzie sul valore che potrà assumere this quando la funzione verrà invocata ... con ogni funzione puoi fare .call e passare un oggetto arbitrario che diventerà il this di quella esecuzione (vedi esempio sopra ... description.call( {... oggettino ...} )   ). C'è anche .apply( pThis, [ params ...] ) cambia solo il modo di passare i parametri.

Conclusion

There some universal rules that will go a long way to understanding scope in JavaScript:
  • The only way to create a new scope is through the function keyword. Nothing else, not even for ... in blocks create new scopes.
  • The var statement declares a variable as local to the current scope and the entire current scope, not just from the var statement onward. These local variables shadow any existing variables from outer scopes.
  • All variables except "this" and "arguments" follow lexical scope. Their meaning is defined by the physical location in the code.
  • The variables "this" and "arguments" change at every nesting level. If you want to preserve them in a closure, then you need to first create a reference to their value through another variable that follows lexical scope.
  • The value of "this" is defined by how the function is called. You can control this through use of apply and call.
(riepiloghino preso pari pari dall'articolo su this di Tim Caswell citato prima)





Nessun commento: