संपादित करें : इस उत्तर में सभी नीचे दिए गए उदाहरणों में @ सुपरसैन के अनुरोध के अनुसार इट्रेटर से प्राप्त एक नया पथ चर शामिल करने के लिए संपादित किया गया है । पथ चर स्ट्रिंग का एक सरणी है जहां सरणी में प्रत्येक स्ट्रिंग प्रत्येक कुंजी का प्रतिनिधित्व करता है जिसे मूल स्रोत ऑब्जेक्ट से परिणामी पुनरावृत्त मूल्य तक पहुंचने के लिए एक्सेस किया गया था। पथ चर को लॉश के गेट फ़ंक्शन / विधि में खिलाया जा सकता है । या आप अपना खुद का संस्करण लिख सकते हैं, जो कि केवल सरणियों को संभालता है जैसे:
function get (object, path) {
return path.reduce((obj, pathItem) => obj ? obj[pathItem] : undefined, object);
}
const example = {a: [1,2,3], b: 4, c: { d: ["foo"] }};
// these paths exist on the object
console.log(get(example, ["a", "0"]));
console.log(get(example, ["c", "d", "0"]));
console.log(get(example, ["b"]));
// these paths do not exist on the object
console.log(get(example, ["e", "f", "g"]));
console.log(get(example, ["b", "f", "g"]));
संपादित करें : यह संपादित उत्तर अनंत लूपिंग ट्रैवर्स को हल करता है।
पेसकी अनंत अनंत ट्रैवर्सल्स को रोकना
यह संपादित उत्तर अभी भी मेरे मूल उत्तर के अतिरिक्त लाभों में से एक प्रदान करता है जो आपको क्लीनर और सरल चलने योग्य इंटरफ़ेस का उपयोग करने के लिए प्रदान किए गए जनरेटर फ़ंक्शन का उपयोग करने की अनुमति देता है (लगता है कि for ofलूप का उपयोग करना for(var a of b)जहां bएक चलने योग्य है और पुनरावृत्त aका एक तत्व है) )। एक सरल एपीआई होने के साथ-साथ जनरेटर फ़ंक्शन का उपयोग करके यह कोड के पुन: उपयोग में मदद करता है ताकि आप इसे बना सकें, ताकि आपको हर जगह पुनरावृति तर्क को दोहराना न पड़े, जिसे आप किसी वस्तु के गुणों पर गहराई से पुनरावृत्त करना चाहते हैं और यह भी breakबाहर करना संभव बनाता है यदि आप पहले पुनरावृति को रोकना चाहते हैं तो लूप।
एक बात जो मैं नोटिस करता हूं, जिसे संबोधित नहीं किया गया है और वह मेरे मूल उत्तर में नहीं है, आपको सावधान रहना चाहिए कि वस्तुओं की मनमानी (यानी "किसी भी" यादृच्छिक "सेट) के कारण, क्योंकि जावास्क्रिप्ट ऑब्जेक्ट्स स्वयं संदर्भित हो सकते हैं। यह अनंत लूपिंग ट्रैवर्सल्स का अवसर पैदा करता है। अनमॉडिफाइड JSON डेटा हालांकि सेल्फ रेफरेंसिंग नहीं हो सकता है, इसलिए यदि आप JS ऑब्जेक्ट्स के इस विशेष सबसेट का उपयोग कर रहे हैं, तो आपको अनंत लूपिंग ट्रैवर्सल्स के बारे में चिंता करने की ज़रूरत नहीं है और आप मेरे मूल उत्तर या अन्य उत्तरों को संदर्भित कर सकते हैं। यहां एक गैर-समाप्ति ट्रैवर्सल का एक उदाहरण दिया गया है (ध्यान दें कि यह कोड का एक चलने योग्य टुकड़ा नहीं है, क्योंकि अन्यथा यह आपके ब्राउज़र टैब को क्रैश कर देगा)।
अपने संपादित उदाहरण में जनरेटर ऑब्जेक्ट में भी मैंने Object.keysइसके बजाय उपयोग करने का विकल्प चुना , for inजो ऑब्जेक्ट पर केवल गैर-प्रोटोटाइप कुंजी को पुनरावृत्त करता है। यदि आप प्रोटोटाइप कुंजी को शामिल करना चाहते हैं, तो आप इसे स्वयं स्वैप कर सकते हैं। के साथ दोनों कार्यान्वयन के लिए नीचे मेरा मूल उत्तर अनुभाग देखें Object.keysऔर for in।
इससे भी बदतर - यह आत्म-संदर्भित वस्तुओं पर अनंत लूप होगा:
//your object
var o = {
foo:"bar",
arr:[1,2,3],
subo: {
foo2:"bar2"
}
};
// this self-referential property assignment is the only edited line
// from the below original example which makes the traversal
// non-terminating (i.e. it makes it infinite loop)
o.o = o;
function* traverse(o, path=[]) {
for (var i of Object.keys(o)) {
const itemPath = path.concat(i);
yield [i,o[i],itemPath];
if (o[i] !== null && typeof(o[i])=="object") {
//going one step down in the object tree!!
yield* traverse(o[I], itemPath);
}
}
}
//that's all... no magic, no bloated framework
for(var [key, value, path] of traverse(o)) {
// do something here with each key and value
console.log(key, value, path);
}
इससे खुद को बचाने के लिए आप एक क्लोजर के भीतर एक सेट जोड़ सकते हैं, ताकि जब फ़ंक्शन को पहली बार कहा जाए तो यह उन वस्तुओं की एक मेमोरी का निर्माण करना शुरू कर देता है जिसे उसने देखा है और एक बार पहले से देखी गई वस्तु के पार होने पर पुनरावृत्ति जारी नहीं रखता है। नीचे दिया गया कोड स्निपेट ऐसा करता है और इस प्रकार अनंत लूपिंग मामलों को संभालता है।
बेहतर - यह आत्म-संदर्भित वस्तुओं पर अनंत लूप नहीं होगा:
//your object
var o = {
foo:"bar",
arr:[1,2,3],
subo: {
foo2:"bar2"
}
};
// this self-referential property assignment is the only edited line
// from the below original example which makes more naive traversals
// non-terminating (i.e. it makes it infinite loop)
o.o = o;
function* traverse(o) {
const memory = new Set();
function * innerTraversal (o, path=[]) {
if(memory.has(o)) {
// we've seen this object before don't iterate it
return;
}
// add the new object to our memory.
memory.add(o);
for (var i of Object.keys(o)) {
const itemPath = path.concat(i);
yield [i,o[i],itemPath];
if (o[i] !== null && typeof(o[i])=="object") {
//going one step down in the object tree!!
yield* innerTraversal(o[i], itemPath);
}
}
}
yield* innerTraversal(o);
}
console.log(o);
//that's all... no magic, no bloated framework
for(var [key, value, path] of traverse(o)) {
// do something here with each key and value
console.log(key, value, path);
}
मूल उत्तर
यदि आप IE को छोड़ने और मुख्य रूप से अधिक वर्तमान ब्राउज़रों का समर्थन करने की इच्छा नहीं रखते हैं, तो इसे करने के लिए एक नए तरीके के लिए ( संगतता के लिए kangax की es6 तालिका देखें )। आप इसके लिए es2015 जनरेटर का उपयोग कर सकते हैं । मैंने तदनुसार @ TheHippo का उत्तर अपडेट किया है। बेशक, यदि आप वास्तव में IE समर्थन चाहते हैं तो आप babel जावास्क्रिप्ट ट्रांसपिलर का उपयोग कर सकते हैं ।
//your object
var o = {
foo:"bar",
arr:[1,2,3],
subo: {
foo2:"bar2"
}
};
function* traverse(o, path=[]) {
for (var i in o) {
const itemPath = path.concat(i);
yield [i,o[i],itemPath];
if (o[i] !== null && typeof(o[i])=="object") {
//going one step down in the object tree!!
yield* traverse(o[i], itemPath);
}
}
}
//that's all... no magic, no bloated framework
for(var [key, value, path] of traverse(o)) {
// do something here with each key and value
console.log(key, value, path);
}
यदि आप केवल स्वयं के असंख्य गुण (मूल रूप से गैर-प्रोटोटाइप श्रृंखला गुण) चाहते हैं, तो आप इसका उपयोग करके इसे बदलने Object.keysऔर एक for...ofलूप में बदल सकते हैं :
//your object
var o = {
foo:"bar",
arr:[1,2,3],
subo: {
foo2:"bar2"
}
};
function* traverse(o,path=[]) {
for (var i of Object.keys(o)) {
const itemPath = path.concat(i);
yield [i,o[i],itemPath];
if (o[i] !== null && typeof(o[i])=="object") {
//going one step down in the object tree!!
yield* traverse(o[i],itemPath);
}
}
}
//that's all... no magic, no bloated framework
for(var [key, value, path] of traverse(o)) {
// do something here with each key and value
console.log(key, value, path);
}