फॉर लूप्स में ऑब्जेक्ट्स का उपयोग करना


84

लूप के लिए ऑब्जेक्ट का उपयोग करना क्यों संभव नहीं है? या यह एक ब्राउज़र बग है? यह कोड Chrome 42 में काम नहीं करता है, यह कहना कि अपरिभाषित कोई कार्य नहीं है:

test = { first: "one"}

for(var item of test) {
  console.log(item)
}

एक सरणी या वस्तु का परीक्षण है?
किक बटवस्की

9
@KickButtowski, आप नहीं देख सकते हैं? यह निश्चित रूप से एक वस्तु है।
ग्रीन

4
के लिए (Object.keys (परीक्षण) की कुंजी दें) {...}
घड़ीसाज़

जवाबों:


69

For..of पाश केवल सरणियों की तरह iterable वस्तुओं का समर्थन करता है, नहीं वस्तुओं।

किसी ऑब्जेक्ट के मूल्यों पर पुनरावृति करने के लिए, उपयोग करें:

for (var key in test) {
    var item = test[key];
}

3
@DanielHerr एक .iterableसदस्य कार्य कर रहा है, जो कि वह जगह है जहाँ त्रुटि तब आती है जब आप इसे किसी ऑब्जेक्ट पर उपयोग करने का प्रयास करते हैं (जिसमें आपके पास नहीं है)। developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Overv

4
मेरा मतलब है, वस्तुओं में ऐसा क्यों नहीं है? इसे मूल रूप से जोड़ने में क्या समस्या होगी?
डेनियल हैर

3
@DanielHerr मेरे पास इसका जवाब नहीं है, आपको भाषा डिजाइन करने वाले लोगों से पूछना होगा।
ओवरव्यू

6
@DanielHerr यदि ऑब्जेक्ट "बेस क्लास" चलने योग्य थे, तो अन्य जटिलताओं के बीच कोई फ़ंक्शन / दिनांक / आदि "सबक्लास" होगा। हालाँकि आपके प्रश्न की अधिक गहन / सटीक चर्चा के लिए esdiscuss.org/topic/es6-iteration-over-object-values#content-5 देखें ।
natevw

5
इसके लिए ..in समाधान के साथ, क्या आपको अभी भी तकनीकी रूप से जांच नहीं करनी है if (test.hasOwnProperty(key)){ ... }? या कि जरूरत नहीं है?
टेनिस

40

आप इस सिंटैक्स का उपयोग कर सकते हैं:

let myObject = {first: "one"};

for(let [key, value] of Object.entries(myObject)) {
    console.log(key, value); // "first", "one"
}

तथापि, Object.entries अभी गरीब का समर्थन है IE में काम नहीं करता है या iOS सफारी। आप करेंगेशायद एक पॉलीफ़िल की आवश्यकता हो सकती है।


33

यदि आप कुंजी-मूल्य की दुकान में डेटा संग्रहीत कर रहे हैं, तो कृपयाMap इस उद्देश्य के लिए उपयोग करें।

यदि आपको किसी वस्तु का उपयोग करना है, तो ES2017 (ES8) आपको उपयोग करने की अनुमति देता है Object.values:

const foo = { a: 'foo', z: 'bar', m: 'baz' };
for (let value of Object.values(foo)) {
    console.log(value);
}

यदि वह अभी तक समर्थित नहीं है, तो एक पॉलीफ़िल का उपयोग करें: के लिए वैकल्पिक संस्करणObject.values()

और अंत में यदि आप एक पुराने वातावरण का समर्थन कर रहे हैं जो इस वाक्यविन्यास का समर्थन नहीं करता है, तो आपको उपयोग करने का सहारा लेना होगा forEachऔर Object.keys:

var obj = { a: 'foo', z: 'bar', m: 'baz' };
Object.keys(obj).forEach(function (prop) {
    var value = obj[prop];
    console.log(value);
});

ऑब्जेक्ट प्रोटोटाइप को इसका समर्थन करने के लिए नहीं बढ़ाया जा सकता है?
सोनिक सोल

1
@SonicSoul: तकनीकी रूप से हाँ, लेकिन यह आम तौर पर वस्तु प्रोटोटाइप का विस्तार करने की सलाह नहीं देता है (बहुत ज्यादा) सब कुछ इसमें से विरासत में मिला है।
कांटा 94 हेवी

1
Object.entriesप्रोटोटाइप को छूने के बिना polyfilled द्वारा कर सकते हैं।
एमपैन

5
वस्तुओं के बजाय मानचित्रों का उपयोग क्यों करें?
डैनियल हेर

1
क्या इन जटिल उदाहरणों को एक सरल से अधिक उपयोग करने का कोई फायदा है for-in?
1252748

18

ECMAScript 2015 / ES6 में Iterator, Iterable और for..of लूप

let tempArray = [1,2,3,4,5];

for(element of tempArray) {
  console.log(element);
}

// 1
// 2
// 3
// 4
// 5

लेकिन अगर हम करते हैं

let tempObj = {a:1, b:2, c:3};

for(element of tempObj) {
   console.log(element);
}
// error

हमें त्रुटि मिलती है क्योंकि..ऑपर लूप केवल Iterables पर काम करता है , अर्थात, जिस वस्तु में @@ itter है जो Iterator प्रोटोकॉल का पालन ​​करता है , जिसका अर्थ है कि उसके पास अगली विधि के साथ कोई ऑब्जेक्ट होना चाहिए । अगली विधि में कोई तर्क नहीं है और इसे इन दो गुणों के साथ एक वस्तु वापस करनी चाहिए।

किया : संकेत है कि अनुक्रम समाप्त हो गया है जब सच है, और झूठ का मतलब है कि अधिक मूल्य हो सकते हैं : यह अनुक्रम में वर्तमान आइटम है

इसलिए, एक वस्तु को Iterable बनाने के लिए जिसे हम इसके साथ काम कर सकते हैं..यदि हम कर सकते हैं

1। एक वस्तु को Iterable का उपयोग करके उसे रहस्यमय @@ पुनरावृत् त करने के लिए कहा जाता है Symbol.iterator प्रॉपर्टी के माध्यम से itter गुण बताएं। यह कैसे है:

let tempObj = {a:1, b:2, c:3};

tempObj[Symbol.iterator]= () => ({
next: function next () {
return {
    done: Object.keys(this).length === 0,
    value: Object.keys(this).shift()
     }
    }
  })

for(key in tempObj){
 console.log(key)
}
// a
// b
// c

2.Use Object.entries , जो एक रिटर्न देता है Iterable :

let tempObj = {a:1, b:2, c:3};

for(let [key, value] of Object.entries(tempObj)) {
    console.log(key, value);
}
// a 1
// b 2
// c 3

3.Use यूज ऑब्जेक्ट.कीज , यहां बताया गया है:

let tempObj = {a:1, b:2, c:3};
for (let key of Object.keys(tempObj)) {
    console.log(key);
}

// a
// b
// c

उम्मीद है की यह मदद करेगा!!!!!!


16

मैंने इस कोड के साथ वस्तुओं को चलने योग्य बनाया:

Object.prototype[Symbol.iterator] = function*() {
 for(let key of Object.keys(this)) {
  yield([ key, this[key] ])
} }

उपयोग:

for(let [ key, value ] of {}) { }

Alternativly:

for(let [ key, value ] of Object.entries({})) { }

48
पता नहीं क्यों यह स्वीकृत उपाय है। प्रोटोटाइप को संशोधित करना जब तक कि एक पॉलीफ़िल हमेशा एक भयानक विचार न हो।
user1703761

2
@ user1703761 यह स्वीकृत समाधान है क्योंकि यह काम करता है। कृपया बताएं कि अगर यह बहुत भयानक है तो इससे क्या समस्याएं होंगी।
डैनियल हैर

9
सभी प्रकार के मुद्दे हैं, मुख्य रूप से संगतता वाले आगे। एक उदाहरण यह है कि Array.prototype.includes, जिसमें पहले नाम थे, लेकिन Moo टूल्स ने प्रोटोटाइप को बढ़ाया और कार्यान्वयन असंगत था, देखें Bugzilla.mozilla.org/show_bug.cgi?id=1075059 प्रोटोटाइप लाइब्रेरी डिसास्टर को देखें;)
user1703761

4
मेरा मानना ​​है कि इसमें आगे की संगतता के मुद्दे नहीं होंगे क्योंकि अगर एक इटरेटर को ऑब्जेक्ट्स में जोड़ा जाता है तो यह इसे अधिलेखित कर देगा और अगर एक इटरेटर को ऑब्जेक्ट उपप्रकार में जोड़ा गया था तो यह सबटाइप इटरेटर का उपयोग करेगा।
डैनियल हैर

4
हे दोस्तों, प्रोटोटाइप को संशोधित करना एक बुरा विचार है !!! चलो वास्तव में सवाल का जवाब देने के लिए ओपी को शर्मिंदा करते हैं!
NiCk न्यूमैन

12

क्योंकि ऑब्जेक्ट शाब्दिक के पास Symbol.iterator गुण नहीं है । विशिष्ट होने के लिए, आप केवल लूप के लिए स्ट्रिंग , एरे , मैप , सेट , तर्क , नॉडलिस्ट (व्यापक रूप से समर्थन नहीं) और जनरेटर के साथ पुनरावृति कर सकते हैं ।

वस्तु शाब्दिक पुनरावृत्ति से निपटने के लिए, आपके पास दो विकल्प हैं।

अंदर के लिए

for(let key in obj){
    console.log(obj[key]); 
}

Object.keys + forEach

Object.keys(obj).forEach(function(key){
    console.log(obj[key]);
});

3

इसका उत्तर यह है कि ऑब्जेक्ट के शाब्दिक शब्दों के लिए For..Of का उपयोग करना संभव नहीं है।

मैं ओवरव के साथ सहमत हूं कि For..Of केवल iterables के लिए है। मेरे पास बिल्कुल वही प्रश्न था क्योंकि मैं for..in के साथ कुंजियों और मूल्यों पर पुनरावृति करने के लिए वस्तुओं का उपयोग करता हूं। लेकिन मुझे सिर्फ एहसास हुआ कि यही ES6 MAPS और SETS हैं।

let test = new Map();
test.set('first', "one");
test.set('second', "two");

for(var item of test) {
  console.log(item); // "one" "two"
}

इसलिए यह for..In ( hasOwnProperty के साथ सत्यापन ) और Object.keys () का उपयोग नहीं करने के लिए उपयोग नहीं करने के लक्ष्य को प्राप्त करता है ।

इसके अतिरिक्त, आपकी कुंजी स्ट्रिंग्स तक सीमित नहीं हैं। आप संख्याओं, वस्तुओं या अन्य शाब्दिक का उपयोग कर सकते हैं।


2

ऑब्जेक्ट शाब्दिक में अंतर्निहित पुनरावृत्तियाँ नहीं होती हैं, जिन्हें for...ofलूप के साथ काम करना आवश्यक होता है। हालाँकि, यदि आप [Symbol.iterator]अपनी वस्तु को जोड़ने की परेशानी के कारण नहीं जाना चाहते हैं , तो आप बस Object.keys()विधि का उपयोग कर सकते हैं । यह विधि एक Arrayऑब्जेक्ट लौटाती है , जिसमें पहले से ही एक अंतर्निर्मित इट्रेटर है, इसलिए आप इसे for...ofइस तरह लूप के साथ उपयोग कर सकते हैं :

const myObject = {
    country: "Canada",
    province: "Quebec",
    city: "Montreal"
}

for (let i of Object.keys(myObject)) {
    console.log("Key:", i, "| Value:", myObject[i]);
}

//Key: country | Value: Canada
//Key: province | Value: Quebec
//Key: city | Value: Montreal

हर बार चाबियों का उपयोग करना एक बार पुनरावृत्ति जोड़ने की तुलना में अधिक परेशानी है। इसके अलावा, Object.keys () ES5 है।
डैनियल हेर

1

किसी भी वस्तु को देने के लिए एक पुनरावृत्त को परिभाषित करना संभव है, इस तरह आप प्रत्येक वस्तु के लिए अलग तर्क रख सकते हैं

var x = { a: 1, b: 2, c: 3 }
x[Symbol.iterator] = function* (){
    yield 1;
    yield 'foo';
    yield 'last'
}

फिर बस सीधे पुनरावृति x

for (let i in x){
    console.log(i);
}
//1
//foo
//last

Object.prototypeऑब्जेक्ट पर एक ही कार्य करना संभव है और सभी वस्तुओं के लिए एक सामान्य पुनरावृत्ति है

Object.prototype[Symbol.iterator] = function*() {
    for(let key of Object.keys(this)) {
         yield key 
    } 
 }

फिर अपनी वस्तु को इस तरह से व्यवस्थित करें

var t = {a :'foo', b : 'bar'}
for(let i of t){
    console.log(t[i]);
}

या इस तरह से

var it = t[Symbol.iterator](), p;
while(p = it.next().value){
    console.log(t[p])
}

1

मैंने अपना सामान आसानी से सांत्वना देने के लिए निम्नलिखित कार्य किया।

for (let key in obj) {
  if(obj.hasOwnProperty(key){
    console.log(`${key}: ${obj[key]}`);
  }
}


0

उपयोग करने के बारे में क्या

function* entries(obj) {
    for (let key of Object.keys(obj)) {
        yield [key, obj[key]];
    }
}

for ([key, value] of entries({a: "1", b: "2"})) {
    console.log(key + " " + value);
}

0

ES6 में आप जनरेटर के साथ जा सकते हैं:

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

function* entries(obj) {
  for (let key of Object.keys(obj)) {
    yield [key, obj[key]];
  }
}

let generator = entries(obj);

let step1 = generator.next();
let step2 = generator.next();
let step3 = generator.next();

console.log(JSON.stringify(step1)); // {"value":["1","a"],"done":false}
console.log(JSON.stringify(step2)); // {"value":["2","b"],"done":false}
console.log(JSON.stringify(step3)); // {"done":true}

यहाँ jsfiddle है। आउटपुट में आपको "value"और "done"कुंजियों के साथ एक ऑब्जेक्ट मिलेगा । "Value"इसमें वह सब कुछ शामिल है जो आप चाहते हैं और "done"बूल में पुनरावृत्ति की वर्तमान स्थिति है।


0

सरणी विनाश का उपयोग करके आप इसे निम्नानुसार पुनरावृत्त कर सकते हैं forEach

const obj = { a: 5, b: 7, c: 9 };

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.