यह जाँचना कि क्या कुछ चलने योग्य है


104

MDN डॉक्स में: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

for...ofनिर्माण "iterable" वस्तुओं से अधिक पुनरावृति करने में सक्षम होना बताया गया है। लेकिन क्या यह तय करने का एक अच्छा तरीका है कि क्या कोई वस्तु चलने योग्य है?

मैंने सरणियों, पुनरावृत्तियों और जनरेटर के लिए सामान्य गुण खोजने की कोशिश की है, लेकिन ऐसा करने में असमर्थ रहा है।

एक तरफ एक करने के लिए for ... ofएक कोशिश ब्लॉक में और प्रकार त्रुटियों के लिए जाँच, वहाँ ऐसा करने का एक साफ तरीका है?


निश्चित रूप से, लेखक के रूप में, आप जानते हैं कि क्या आपकी वस्तु चलने योग्य है?
andrewb

5
ऑब्जेक्ट को एक तर्क के रूप में पारित किया जाता है, मैं निश्चित नहीं हूं।
सिमोनजैक

1
तर्क के टाइपोफ़ का परीक्षण क्यों नहीं किया गया?
जेम्स ब्रुकनर

2
@ andrew-buchan, जेम्स ब्रुकनर: प्रकारों के लिए जाँच काम कर सकती है, लेकिन यदि आप MDN डॉक्स पढ़ते हैं, तो आप देखेंगे कि यह "सरणी-जैसा" कहती है। मुझे नहीं पता कि इसका क्या मतलब है, बिल्कुल, इसलिए सवाल।
सिमोनजैक

1
wiki.ecmascript.org/doku.php?id=harmony:iterators बताता है कि " यदि कोई iterator()विधि है तो कोई वस्तु चलने योग्य है " फिर भी, चूंकि यह एक मसौदा है, केवल एक जाँच लागू-निर्भर हो सकती है। आप किस वातावरण का उपयोग करते हैं?
बेर्गी

जवाबों:


142

पुनरावृत्ति की जांच करने का उचित तरीका इस प्रकार है:

function isIterable(obj) {
  // checks for null and undefined
  if (obj == null) {
    return false;
  }
  return typeof obj[Symbol.iterator] === 'function';
}

यह क्यों काम करता है (गहराई में चलने योग्य प्रोटोकॉल): https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols

जब से हम .. के बारे में बात कर रहे हैं, मुझे लगता है, हम ES6 मानसिकता में हैं।

इसके अलावा, यह आश्चर्यचकित न करें कि trueयदि objयह स्ट्रिंग है, तो यह फ़ंक्शन वापस आ जाता है, क्योंकि स्ट्रिंग उनके वर्णों पर पुनरावृति करता है।


14
या Symbol.iterator in Object(obj)

14
संचालक: स्ट्रिंग में 'का उपयोग करने के लिए (कम से कम) एक अपवाद है। स्ट्रिंग iterable (for..of के संदर्भ में) है, लेकिन आप इस पर 'इन' का उपयोग नहीं कर सकते हैं। यदि इसके लिए नहीं, तो मैं 'का उपयोग करना पसंद करूंगा' यह निश्चित रूप से अच्छा लग रहा है।
टॉमस कुलिच

क्या यह नहीं होना चाहिए return typeof obj[Symbol.iterator] === 'function'? "चलने योग्य होने के लिए, एक वस्तु को @@ पुनरावृत्ति विधि को लागू करना चाहिए" - यह विधि निर्दिष्ट करता है
Callum

Obj के लिए कोई उचित शब्दार्थ नहीं है [Symbol.iterator] इसके अलावा (अपरिभाषित या) फ़ंक्शन के अलावा और कुछ भी नहीं है। यदि कोई भी उदाहरण के लिए स्ट्रिंग करता है, तो यह एक बुरी बात है और आईएमओ अच्छा है अगर कोड जल्द से जल्द विफल हो जाता है।
टॉमस कुलिच

typeof Object(obj)[Symbol.iterator] === 'function'सभी मामलों में काम करेगा ?
क्रेग गिडनी

26

इतनी क्रिया क्यों?

const isIterable = object =>
  object != null && typeof object[Symbol.iterator] === 'function'

57
Readability > Clevernessहमेशा लौटता है true
jfmercer

27
हाहा, आम तौर पर मैं एक अपठनीय कोड के बारे में शिकायत करने वाला हूं, लेकिन वास्तव में मुझे लगता है कि यह बहुत पठनीय है। एक अंग्रेजी वाक्य की तरह: यदि ऑब्जेक्ट अशक्त नहीं है और प्रतीकात्मक पुनरावृत्ति गुण एक फ़ंक्शन है, तो यह चलने योग्य है। अगर यह आसान नहीं है, तो मुझे नहीं पता ... क्या है
adius

4
imo, "पठनीयता" का बिंदु यह समझना है कि वास्तविक पढ़ने के बिना क्या हो रहा है
दिमित्री Parzhitsky

2
@Alexander मिल्स आपके सुधार ने कोड को बदतर बना दिया। 1. जैसे @jfmercer ने कहा Readability > Cleverness, इसलिए किसी objectको oमदद करने के लिए चर को छोटा करना । 2. एक खाली स्ट्रिंग ''चलने योग्य है और इसलिए इसे वापस लौटना चाहिए true
adius

1
समझ गया, मुझे लगा कि एक कारण है कि इसका उपयोग क्यों किया जा रहा था!= null
अलेक्जेंडर मिल्स

22

सबसे सरल समाधान वास्तव में यह है:

function isIterable (value) {
  return Symbol.iterator in Object(value);
}

Objectऐसी किसी भी चीज़ को लपेटेंगे जो एक वस्तु नहीं है, inऑपरेटर को काम करने की अनुमति देता है, भले ही मूल मूल्य एक वस्तु न हो। nullऔर undefinedखाली वस्तुओं में बदल जाते हैं, इसलिए किनारे के मामले का पता लगाने की कोई आवश्यकता नहीं है, और स्ट्रिंग स्ट्रिंग वस्तुओं में लिपटे जाते हैं जो कि चलने योग्य हैं।


1
आपने गलत प्रतीक का उपयोग किया। यह बताया गया है: Symbol.iterator
गिल

@ तुम बिल्कुल सही हो, उफ़! मेरे पास एक पोस्ट में सीधे टाइप करने के बजाय कॉपी-पेस्ट किए गए परीक्षण कोड होने चाहिए।
डोमिनोज़

Objectइस प्रकार की जाँच के लिए एक नई वस्तु का निर्माण व्यर्थ है।
रूबेन वेरबर्ग

मैं यह नहीं कह सकता कि मुझे पता है कि Objectफ़ंक्शन कैसे लागू किया जाता है, लेकिन यह केवल एक नई वस्तु बनाता है अगर valueपहले से ही ऑब्जेक्ट नहीं है। मुझे उम्मीद है कि इसके संयोजन inऔर Object(...)कुछ ब्राउज़र इंजन आसानी से अनुकूलन कर सकते हैं, इसके विपरीत value !== undefined && value !== null && value[Symbol.iterator] && true। साथ ही, यह बेहद पठनीय है, जिसकी मुझे परवाह है।
डोमिनोज

9

एक sidenote के रूप, सावधान की परिभाषा के बारे में iterable । आप अन्य भाषाओं से आ रहे हैं आप उम्मीद करेंगे कि कुछ लोगों के साथ आप अधिक पुनरावृति कर सकते हैं कहते हैं, एक forपाश है iterable । मुझे डर है कि यहाँ ऐसा नहीं है जहाँ iterable का अर्थ है कि पुनरावृत्ति प्रोटोकॉल को लागू करता है

चीजों को स्पष्ट करने के लिए उपरोक्त सभी उदाहरण falseइस वस्तु पर वापस आते हैं {a: 1, b: 2}क्योंकि यह वस्तु पुनरावृत्ति प्रोटोकॉल को लागू नहीं करती है। तो आप एक for...of BUT के साथ उस पर पुनरावृति नहीं कर पाएंगे जो आप अभी भी कर सकते हैं for...in

इसलिए यदि आप दर्दनाक गलतियों से बचना चाहते हैं तो नीचे दिखाए गए तरीके से अपना नाम बदलकर अपना कोड और अधिक विशिष्ट बनाएं:

/**
 * @param variable
 * @returns {boolean}
 */
const hasIterationProtocol = variable =>
    variable !== null && Symbol.iterator in Object(variable);

आप कोई मतलब नहीं बना रहे हैं। आपको क्यों लगता है कि यह टूट जाएगा undefined?
adius

@ मुझे लगता है कि मैंने गलत तरीके से मान लिया है कि आप object !== nullअपने उत्तर में कर रहे थे लेकिन आप ऐसा कर रहे हैं, object != nullयह undefinedउस विशिष्ट मामले में नहीं है। मैंने उसी के अनुसार अपना उत्तर अपडेट किया है।
फ्रांसेस्को कासुला

ठीक है मैं समझा। Btw: आपका कोड गलत है। hasIterationProtocol('')वापस लौटना चाहिए true! कैसे आप अपने कोड को हटाते हैं और बस पुनरावृत्ति विवरण अनुभाग को छोड़ते हैं, जो केवल एक चीज है जो आपके उत्तर में वास्तविक मूल्य / कुछ नया जोड़ता है।
adius

1
यह वापसी करता है true, पुराने उत्तर के हिस्से को हटाकर मैंने दोनों कार्यों को मिला दिया और सख्त तुलना के बारे में भूल गया। अब मैंने मूल उत्तर वापस रख दिया जो ठीक काम कर रहा था।
फ्रांसेस्को कैसुला

1
मैंने कभी इस्तेमाल करने के बारे में नहीं सोचा होगा Object(...), अच्छी पकड़। लेकिन उस मामले में अशक्त जांच की जरूरत नहीं है।
डोमिनोज़

2

आजकल, जैसा कि पहले ही कहा गया है, परीक्षण करने के लिए कि क्या objयह चलने योग्य है

obj != null && typeof obj[Symbol.iterator] === 'function' 

ऐतिहासिक उत्तर (अधिक वैध नहीं)

for..ofनिर्माण ECMAScript 6 संस्करण भाषा विशिष्टता ड्राफ्ट का हिस्सा है। इसलिए यह अंतिम संस्करण से पहले बदल सकता है।

इस मसौदे में, चलने योग्य वस्तुओं का कार्य होना चाहिएiterator संपत्ति के रूप ।

आप जाँच सकते हैं कि क्या कोई वस्तु इस तरह से चलने योग्य है:

function isIterable(obj){
   if(obj === undefined || obj === null){
      return false;
   }
   return obj.iterator !== undefined;
}

7
पुनरावृत्त संपत्ति एक अस्थायी फ़ायरफ़ॉक्स चीज़ थी। यह ES6 अनुरूप नहीं है। देखें: developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
आमिर अराद

2

के लिए async iterators आप 'Symbol.iterator' के स्थान पर 'Symbol.asyncIterator' के लिए जाँच करनी चाहिए:

async function* doSomething(i) {
    yield 1;
    yield 2;
}

let obj = doSomething();

console.log(typeof obj[Symbol.iterator] === 'function');      // false
console.log(typeof obj[Symbol.asyncIterator] === 'function'); // true

1

यदि आप वास्तव में जांचना चाहते हैं कि क्या चर एक वस्तु ( {key: value}) या एक सरणी ( [value, value]) है, तो आप ऐसा कर सकते हैं:

const isArray = function (a) {
    return Array.isArray(a);
};

const isObject = function (o) {
    return o === Object(o) && !isArray(o) && typeof o !== 'function';
};

function isIterable(variable) {
    return isArray(variable) || isObject(variable);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.