Newsgroup: it.comp.lang.javascript
Titolo: costruttore di oggetti

ho bisogno di creare un costruttore di oggetti contenente una
proprietà 'data', una proprietà 'url' più qualunque eventuale altro
campo, a piacere.
 
desideravo generare l'oggetto con una chiamata come la seguente:
 
var nuovoOggetto = new
mioCostruttore("valoreCampoData","valoreCampoUrl",{ nuovaProprieta1:
valore1, nuovaProprieta2: valore2});
 
ho scritto il mio costruttore in due modi diversi. purtroppo, quello
che preferisco, basato sull'uso sistematico dell'operatore this, non
funziona e ho dovuto quindi optare per una versione che, a mio parere,
è ridondante.
il comportamento che ho osservato è uguale con firefox e con
googleChrome.
 
vorrei sapere se esiste una ragione specifica per questo o se si può
ritenere che il comportamento dipenda da una implementazione non
corretta del linguaggio javascript da parte del due browser.
 
la mia versione del costruttore (quella che non funziona) è la
seguente:
 
function mioCostruttoreCheNonFunziona(data,url) {
  this.data= data;
  this.url=url;
  if (typeof(arguments[2]) == 'object') {
    parametroEsterno = arguments[2];
    var vettore=Object.keys(parametroEsterno);
    vettore.forEach(function(element,index,vec) {
      this[element]= parametroEsterno[element];
    });
    }
}
 
la versione che funziona, invece, è questa:
 
function mioCostruttoreCheFunziona(data,url) {
  var questoOggetto=this
  this.data= data;
  this.url=url;
  if (typeof(arguments[2]) == 'object') {
    parametroEsterno = arguments[2];
    var vettore=Object.keys(parametroEsterno);
    vettore.forEach(function(element,index,vec) {
      questoOggetto[element]= parametroEsterno[element];
    });
    }
  return questoOggetto;
}


 
In pratica il "this" di _mioCostruttoreCheNonFunziona_ e' diverso dal 
"this" del forEach, che nella fattispecie punta a window.
Si puo' risolvere in vari modi, uno dei quali consiste nel memorizzarsi 
il valore di this in una variabile locale (come hai fatto nel secondo 
esempio) e usare quella negli assegnamenti (il return finale e' superfluo).
 


 
Quindi il tuo codice può benissimo essere riscritto passando `this` a
`forEach`:
 
    function mioCostruttoreCheNonFunziona(data,url) {
        this.data= data;
        this.url=url;
 
        // senza dichiarazione è considerata variabile globale
        var parametroEsterno = arguments[2];
 
        // typeof null è "object", quindi controlliamo che non
        // sia `null`
        if (parametroEsterno !== null && typeof parametroEsterno ===
"object") {
            var vettore = Object.keys(parametroEsterno);
 
            vettore.forEach(function (element, index, vec) {
                this[element] = parametroEsterno[element];
            }, this);
        }
    }
 
In realtà potresti anche far a meno del `keys` e `forEach` e di
callback, usando una tecnica da vecchia scuola:
 
    if (parametroEsterno !== null && typeof parametroEsterno === "object") {
        for (var key in parametroEsterno) {
            if (parametroEsterno.hasOwnProperty(key)) {
                this[element] = parametroEsterno[element];
            }
        }
    }
 
Se preferisci invece usare i metodi di ES5, allora ti suggerirei di
copiare i descrittori delle proprietà per fare un lavoro migliore:
 
    if (parametroEsterno !== null && typeof parametroEsterno === "object") {
        var des = Object.keys(parametroEsterno).reduce(function(p, c){
            p[c] = Object.getOwnPropertyDescriptor(parametroEsterno, c);
            return p;
        }, {});
 
        Object.defineProperties(this, des);
    }
 
Oppure anche:
 
    Object.keys(parametroEsterno).forEach(function(key) {
        var des = Object.getOwnPropertyDescriptor(obj, key);
        Object.defineProperty(this, key, des);
    }, this);
 
Hope it helps.