2016-06-15 16 views
8

Sto provando ad assegnare in modo profondo un valore in un oggetto. Per esempio:Assegnare in modo approfondito l'oggetto JavaScript letterale

const errors = {} 
if(errorOnSpecificField) { 
    // TypeError: Cannot read property 'subSubCategory' of undefined(…) 
    errors.subCategory.subSubCategory.fieldWithError = 'Error Message' 
} 

In questo momento, senza lodash, non posso fare:

const errors = {} 
if(errorOnSpecificField) { 
    errors.subCategory = errors.SubCategory || {} 
    errors.subCategory.subSubCategory = errors.SubCategory.subSubCategory || {} 
    errors.subCategory.subSubCategory.fieldWithError = 'Error Message' 
} 

Con lodash, posso fare questo:

const errors = {} 
if(errorOnSpecificField) { 
    _.set(errors, 'subCategory.subSubCategory.fieldWithError', 'Error Message'); 
} 

sto cercando di evitare l'uso di un terzo biblioteca di partito. Esiste una soluzione più elegante, specialmente ora che es2015 ha una destrutturazione degli oggetti. L'operazione inversa è semplice:

let {subCategory : {subSubCategory: {fieldWithError}}} = errors 

Qual è una soluzione elegante per l'assegnazione di oggetti profondi? Grazie!

+2

Object.assign()? - sostituisce tutte le proprietà anche se –

+0

Come si cita, poiché sovrascrive le altre proprietà già impostate, questo non funzionerà per il mio caso – aherriot

+0

si potrebbe quindi cercare alcune delle numerose implementazioni 'estese ' –

risposta

0

Ecco un modo abbastanza leggibile per assegnare in modo sicuro per l'oggetto in profondità:

(((errors||{}).subCategory||{}).subSubCategory||{}).fieldWithError = 'Error Message' 

Ciò non creareerrors.subCategory.subSubCategory se non esiste già, però.

+2

Questo in realtà non funziona per l'assegnazione. Per l'accesso, sì, ma non per la creazione di proprietà. – Bergi

+0

Hmm ... Non creerà 'errors.subCategory.subSubCategory', ma assegnerà sicuro ad esso se già esiste. –

0

Risposta breve, non v'è alcun modo pulito di fare questo senza scrivere un metodo per esso (TBH si potrebbe utilizzare il metodo da lodash senza importare l'intera libreria)

... però ...

ATTENZIONE Questo è solo per divertimento. Non provarlo in produzione (req es6).

Object.prototype.chainSet = function() { 
    let handler = { 
    get (target, name) { 
     if (!(name in target)) { 
     target[name] = new Proxy({}, handler) 
     } 
     return target[name] 
    } 
    } 

    return new Proxy(this, handler) 
} 

uso:

let a = {} 
a.chainSet().foo.bar.baz = 1 
a.foo.bar.baz // => 1 
0

Object.assign() funziona bene per quello che stai chiedendo.

let errors = { otherField: "value" }; 
let newobj = {subCategory : {subSubCategory: {fieldWithError: "Error goes here"}}}; 
Object.assign(errors, newobj); 

Questo produce:

{ 
    otherField:'value', 
    subCategory: { 
    subSubCategory: { 
     fieldWithError:'Error goes here' 
    } 
    } 
} 
+1

se 'errors = {sottocategoria: {x:" y "}}' e assegni 'newobj', quindi property' x' viene "rimosso" (l'intero oggetto 'subCategory' viene scambiato). OP sta cercando un modo per evitarlo. –

0

Si potrebbe provare qualcosa di simile di seguito:

function ErrorRegistry(obj) 
{ 
    this.errors = obj || {}; 
    this.addError = function(k, msg) 
    { 
     var keys = k.split('.'); 
     var o = this.errors; 
     for(var i = 0, l = keys.length, last = l-1; i<l; i++) 
     { 
      if(typeof o[keys[i]] === 'undefined') 
       o[keys[i]] = {}; 
      if(i == last) 
       o[keys[i]] = msg; 
      else 
       o = o[keys[i]]; 
     } 
    }; 
} 
var errors = {'subCategory1':{'fieldWithError1':'Error1'}}; 
var errorRegistry = new ErrorRegistry(errors); 
errorRegistry.addError('subCategory1.fieldWithError2', "Error2"); 
errorRegistry.addError('subCategory1.subSubCategory1.fieldWithError3', "Error3"); 
errorRegistry.addError('subCategory1.subSubCategory2.fieldWithError4', "Error4"); 
errors = errorRegistry.errors; 
console.log(errors); 
Problemi correlati