2016-06-15 3 views
8

मैं किसी ऑब्जेक्ट में एक मूल्य को गहराई से असाइन करने का प्रयास कर रहा हूं। उदाहरण के लिए:गहराई से जावास्क्रिप्ट ऑब्जेक्ट शाब्दिक

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

अभी, lodash बिना, मैं कर सकते हैं: एक तिहाई का उपयोग कर से बचने के लिए

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

मैं कोशिश कर रहा हूँ:

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

, मैं यह कर सकता पार्टी लाइब्रेरी क्या एक और अधिक सुरुचिपूर्ण समाधान है, विशेष रूप से अब es2015 ऑब्जेक्ट विनाशकारी है। व्यस्त ऑपरेशन आसान है:

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

गहरी ऑब्जेक्ट असाइनमेंट का एक सुरुचिपूर्ण समाधान क्या है? धन्यवाद!

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

कि हालांकिerrors.subCategory.subSubCategory नहीं बना करता है तो यह पहले से ही मौजूद नहीं है,:

+2

Object.assign()? - यह सभी गुणों को ओवरराइड करता है हालांकि –

+0

जैसा कि आप उल्लेख करते हैं, क्योंकि यह पहले से सेट की गई अन्य संपत्तियों को ओवरराइड करता है, यह मेरे मामले – aherriot

+0

के लिए काम नहीं करेगा, फिर आप कई 'विस्तार' कार्यान्वयन –

उत्तर

0

यहाँ एक काफी पठनीय रास्ता सुरक्षित रूप से गहरी वस्तु के लिए आवंटित करने के लिए है।

+2

ओवरराइट कर देगा, यह वास्तव में असाइनमेंट के लिए काम नहीं करता है। एक्सेस करने के लिए, हां, लेकिन गुण बनाने के लिए नहीं। – Bergi

+0

हम्म ... यह 'error.subCategory.subSubCategory' नहीं बनाएगा, लेकिन अगर यह पहले से मौजूद है तो यह सुरक्षित रूप से असाइन करेगा। –

0

लघु जवाब, नहीं इसके लिए एक विधि (tbh तुम सिर्फ पूरे पुस्तकालय आयात किए बिना lodash से विधि का उपयोग कर सकते हैं)

लेखन के बिना ऐसा करने का कोई साफ रास्ता है ... लेकिन ...

चेतावनी यह केवल मजेदार है। उत्पादन में कोशिश मत करो (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) 
} 

उपयोग:

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

Object.assign() आप क्या कह रहे हैं के लिए ठीक से काम करेगा।

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

यह पैदावार:

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

यदि 'त्रुटियां = {उपश्रेणी: {x:" y "}} 'और आप' newobj' असाइन करते हैं, तो संपत्ति 'x'" हटा दी जाती है "(संपूर्ण' subCategory' ऑब्जेक्ट को बदल दिया जाता है)। ओपी इससे बचने के लिए एक रास्ता तलाश रहा है। –

0

आप नीचे दिए गए की तरह कुछ की कोशिश कर सकते:

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); 
संबंधित मुद्दे