2016-06-15 6 views
8

Próbuję głęboko przypisać wartość w obiekcie. Na przykład:Głębokie przypisanie literału obiektu JavaScript

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

Teraz bez lodash mogę zrobić:

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

Z lodash, mogę to zrobić:

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

staram się unikać trzeci biblioteka imprezowa. Czy istnieje bardziej eleganckie rozwiązanie, zwłaszcza teraz, gdy es2015 ma destrukturyzację obiektu. Operacja odwrotna jest łatwa:

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

Co to jest eleganckie rozwiązanie do wykonywania głębokich obiektów? Dzięki!

+2

Object.assign()? - nadpisuje wszystkie właściwości przez: –

+0

Jak wspomniałeś, ponieważ przesłania inne ustawione już właściwości, to nie zadziała dla mojego przypadku: – aherriot

+0

możesz wtedy szukać niektórych z wielu implementacji 'extend'ów –

Odpowiedz

0

Oto dość czytelny sposób, aby bezpiecznie przypisać do głębokiego obiektu:

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

To nie stwarzaerrors.subCategory.subSubCategory jeśli nie istnieje, choć.

+2

To w rzeczywistości nie działa dla przypisania. Aby uzyskać dostęp, tak, ale nie do tworzenia właściwości. – Bergi

+0

Hmm ... Nie utworzy 'errors.subCategory.subSubCategory', ale bezpiecznie ją przypisze, jeśli już istnieje. –

0

Krótka odpowiedź, nie brak jest czysty sposób to zrobić bez pisania metodę It (TBH można po prostu użyć metody z lodash bez importowania całą bibliotekę)

... jednak ...

OSTRZEŻENIE To jest tylko zabawa. Nie próbuj tego w produkcji (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) 
} 

zastosowanie:

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

Object.assign() będzie działać dobrze na co pytasz.

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

Daje:

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

jeśli 'errors = {podkategoria: {x:" y "}}' i przypisujesz 'newobj', wówczas właściwość' x' zostaje "usunięta" (zamieniony zostaje cały obiekt 'subCategory'). OP szuka sposobu, aby tego uniknąć. –

0

Można spróbować coś jak poniżej:

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);