2012-06-07 14 views
31

जावास्क्रिप्ट में इस वस्तु पर विचार करें,Convert स्ट्रिंग वस्तु संदर्भ

var obj = { a : { b: 1, c: 2 } }; 

स्ट्रिंग "obj.ab" मैं कैसे, वस्तु इस को संदर्भित करता है प्राप्त कर सकते हैं, ताकि मैं बदल सकता है दिया पाने के लिए अपने मूल्य? अर्थात मैं की तरह

obj.a.b = 5; 
obj.a.c = 10; 

जहां "obj.a.b" & "obj.a.c" कुछ करने के लिए सक्षम होना चाहते हैं तार (नहीं obj संदर्भ) कर रहे हैं। मैं this post पर आया जहां मुझे डॉट नोटेशन स्ट्रिंग का मूल्य ओबीजे का जिक्र कर रहा है, लेकिन मुझे जो चाहिए वह एक वस्तु है जिसे मैं ऑब्जेक्ट पर प्राप्त कर सकता हूं?

ऑब्जेक्ट का घोंसला भी इससे भी गहरा हो सकता है। "obj.a.b" आप . द्वारा इसे विभाजित करने के लिए है

window['obj']['a']['b'] = 5 

तो स्ट्रिंग दिया: यानी शायद

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } } 

उत्तर

70

मूल्य प्राप्त करने के लिए, इस पर विचार करें:

function ref(obj, str) { 
    str = str.split("."); 
    for (var i = 0; i < str.length; i++) 
     obj = obj[str[i]]; 
    return obj; 
} 

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } } 
str = 'a.c.d' 
ref(obj, str) // 3 

या एक अधिक फैंसी तरह से, reduce का उपयोग कर:

:

function ref(obj, str) { 
    return str.split(".").reduce(function(o, x) { return o[x] }, obj); 
} 

रिटर्निंग एक वस्तु सदस्य के लिए एक आबंटित संदर्भ जावास्क्रिप्ट में संभव नहीं है, तो आप निम्नलिखित की तरह एक समारोह का उपयोग करना होगा

function set(obj, str, val) { 
    str = str.split("."); 
    while (str.length > 1) 
     obj = obj[str.shift()]; 
    return obj[str.shift()] = val; 
} 

var obj = { a: { b: 1, c : { d : 3, e : 4}, f: 5 } } 
str = 'a.c.d' 
set(obj, str, 99) 
console.log(obj.a.c.d) // 99 

या ref ऊपर दिए गए का उपयोग युक्त वस्तु के संदर्भ में प्राप्त करने के लिए और फिर इसे करने के लिए [] ऑपरेटर लागू:

parts = str.split(/\.(?=[^.]+$)/) // Split "foo.bar.baz" into ["foo.bar", "baz"] 
ref(obj, parts[0])[parts[1]] = 99 
+0

धन्यवाद दूसरा भाग वह है जिसे मैं ढूंढ रहा था और ठीक काम करता प्रतीत होता है। –

+0

+1 पहले आपके 'कम' उदाहरण को नहीं देखा गया। –

+0

यदि आप 'सेट()' और 'विभाजन (/\.(?=[^.]+$)/)' उदाहरण पर कुछ और विस्तृत करेंगे तो मैं वास्तव में सराहना करता हूं। – Redsandro

1

एक ब्राउज़र में इस javascript रन तो आप वस्तु इस तरह का उपयोग कर सकते हैं

var s = "obj.a.b" 
var e = s.split(".") 
window[e[0]][e[1]][e[2]] = 5 
+1

यदि इसमें अधिक घोंसला वाले स्तर हैं तो क्या होगा? –

+0

क्या नेस्टेड स्तरों की संख्या अज्ञात है? – WojtekT

+3

हां। यदि यह अज्ञात है तो इसे संशोधित करने का तरीका क्या होगा? –

0
var obj = { a : { b: 1, c: 2 } }; 
walkObject(obj,"a.b"); // 1 

function walkObject(obj, path){ 
    var parts = path.split("."), i=0, part; 
    while (obj && (part=parts[i++])) obj=obj[part]; 
    return obj; 
} 

या आप संक्षिप्त अपने कोड की तरह अगर:

function walkObject(o, path){ 
    for (var a,p=path.split('.'),i=0; o&&(a=p[i++]); o=o[a]); 
    return o; 
} 
+0

क्या यह मुझे डॉट-नोटेशन स्ट्रिंग का मान नहीं देता है? और ऑब्जेक्ट स्वयं नहीं जिसे मैं संशोधित कर सकता हूं? –

+0

@ source.rar यह आपको दूसरी पंक्ति पर दिखाए गए अनुसार श्रृंखला के अंत में मूल्य देता है। यदि वह मान एक ऑब्जेक्ट है, तो आपको ऑब्जेक्ट वापस मिल जाएगा (उदा। 'WalkObject (obj,' a ') // {b: 1, c: 2} ')। – Phrogz

9

thg435 के जवाब की तरह, लेकिन तर्क के चेक के साथ और समर्थन करता है, घोंसला स्तरों जहां पूर्वज स्तरों में से एक अभी तक परिभाषित नहीं है या नहीं एक वस्तु।

setObjByString = function(obj, str, val) { 
    var keys, key; 
    //make sure str is a string with length 
    if (!str || !str.length || Object.prototype.toString.call(str) !== "[object String]") { 
     return false; 
    } 
    if (obj !== Object(obj)) { 
     //if it's not an object, make it one 
     obj = {}; 
    } 
    keys = str.split("."); 
    while (keys.length > 1) { 
     key = keys.shift(); 
     if (obj !== Object(obj)) { 
      //if it's not an object, make it one 
      obj = {}; 
     } 
     if (!(key in obj)) { 
      //if obj doesn't contain the key, add it and set it to an empty object 
      obj[key] = {}; 
     } 
     obj = obj[key]; 
    } 
    return obj[keys[0]] = val; 
}; 

उपयोग:

var obj; 
setObjByString(obj, "a.b.c.d.e.f", "hello"); 
+0

उत्कृष्ट होगा यदि आप अनिर्धारित गुण लिखने का कोई तरीका समझ सकें, बिना किसी पूर्व-परिभाषित गुणों को ओवरराइट किए – scniro

0

एक वस्तु सदस्य के लिए एक आबंटित संदर्भ रिटर्निंग जावास्क्रिप्ट में संभव नहीं है। आप इस तरह के कोड की एक पंक्ति के साथ डॉट नोटेशन द्वारा गहरे ऑब्जेक्ट सदस्य को मान असाइन कर सकते हैं।

new Function('_', 'val', '_.' + path + ' = val')(obj, value); 

आप में मामला:

var obj = { a : { b: 1, c: 2 } }; 

new Function('_', 'val', '_.a.b' + ' = val')(obj, 5); // Now obj.a.b will be equal to 5 
1

नीचे एक साधारण क्लास आवरण के आसपास dict है:

class Dots(dict): 
    def __init__(self, *args, **kargs): 
      super(Dots, self).__init__(*args, **kargs) 

    def __getitem__(self, key): 
      try: 
        item = super(Dots, self).__getitem__(key) 
      except KeyError: 
        item = Dots() 
        self.__setitem__(key, item) 

      return Dots(item) if type(item) == dict else item 

    def __setitem__(self, key, value): 
      if type(value) == dict: value = Dots(value) 
      super(Dots, self).__setitem__(key, value) 

    __getattr__ = __getitem__ 
    __setattr__ = __setitem__ 

उदाहरण:

>>> a = Dots() 
>>> a.b.c = 123 
>>> a.b.c 
123 
>>> a.b 
{'c': 123} 
>>> a 
{'b': {'c': 123}} 

गुम कुंजी मक्खी पर बनाई गई हैं खालीके रूप में:

>>> if a.Missing: print "Exists" 
... 
>>> a 
{'Missing': {}, 'b': {'c': 123}} 
संबंधित मुद्दे