å復å¦çãããã³ã«ã¯ãæ°ããçµã¿è¾¼ã¿ãªãã¸ã§ã¯ããæ§æã§ã¯ãªããããã³ã«ã§ãããããã®ãããã³ã«ã¯ä»¥ä¸ã®ãããªåç´ãªç´æäºã«ãã£ã¦ããã¹ã¦ã®ãªãã¸ã§ã¯ãã§å®è£ ãããã¨ãã§ãã¾ãã
ãããã³ã«ã¯ 2 ã¤ããã¾ããå復å¯è½ãããã³ã«ã¨ã¤ãã¬ã¼ã¿ã¼ãããã³ã«ã§ãã
å復å¯è½ãããã³ã«å復å¯è½ãããã³ã« (iterable protocol) ã«ãã£ã¦ã JavaScript ã®ãªãã¸ã§ã¯ãã¯å復åä½ãå®ç¾©ã¾ãã¯ã«ã¹ã¿ãã¤ãºãããã¨ãã§ãã¾ããä¾ãã°ã for...of
æ§é ã®ä¸ã§ã©ã®å¤ãã«ã¼ãã«ä½¿ããããã§ããä¸é¨ã®çµã¿è¾¼ã¿åã¯æ¢å®ã®å復åä½ãæã¤çµã¿è¾¼ã¿å復å¯è½ãªãã¸ã§ã¯ãã§ãããã«ã¯ Array
ã Map
ãããã¾ãããä»ã®å (Object
ãªã©) ã¯ããã§ã¯ããã¾ããã
å復å¯è½ã§ããããã«ããªãã¸ã§ã¯ã㯠[Symbol.iterator]()
ã¡ã½ãããå®è£
ããå¿
è¦ãããã¾ããããã¯ã¤ã¾ãããªãã¸ã§ã¯ãï¼ã¾ãã¯ããããã¿ã¤ããã§ã¼ã³ä¸ã®ãªãã¸ã§ã¯ãã®ä¸ã¤ï¼ã [Symbol.iterator]
ãã¼ï¼Symbol.iterator
宿°ã«ã¦å©ç¨å¯ï¼ã®ããããã£ãæã¤å¿
è¦ãããã¾ãã
[Symbol.iterator]()
ã¤ãã¬ã¼ã¿ã¼ãããã³ã«ã«æºæ ãããªãã¸ã§ã¯ããè¿ãã弿°ãªãã®é¢æ°ã
ï¼for...of
ã«ã¼ãã®å§ã¾ãã®ããã«ï¼ãªãã¸ã§ã¯ããå復ãããå¿
è¦ãããã¨ãã¯ãã¤ã§ãããã® [Symbol.iterator]()
ã¡ã½ããã弿°ãªãã§å¼ã°ãã¾ããããã¦ãè¿ãããã¤ãã¬ã¼ã¿ã¼ã¯ãå復ãããå¤ãåå¾ããããã«ä½¿ç¨ããã¾ãã
ãªãããã®å¼æ°ãªãã®é¢æ°ãå¼ã³åºãããã¨ãå復å¯è½ãªãã¸ã§ã¯ãä¸ã®ã¡ã½ããã¨ãã¦å¼ã³åºããã¾ããå¾ã£ã¦é¢æ°ã®ä¸ã§ã¯ã this
ãã¼ã¯ã¼ããå復å¯è½ãªãã¸ã§ã¯ãã®ããããã£ã«ã¢ã¯ã»ã¹ããããã«ä½¿ç¨ãã¦ãå復ã®éã«ä½ãæä¾ããããæ±ºãããã¨ãã§ãã¾ãã
ãã®é¢æ°ã¯æ®éã®é¢æ°ãã¾ãã¯ã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã«ãããã¨ãã§ãããã®ããå¼ã³åºãããã¨ãã¤ãã¬ã¼ã¿ã¼ãªãã¸ã§ã¯ããè¿ããã¾ãããã®ã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã®ä¸ã§ã¯ yield
ã使ç¨ãã¦ããããã®é
ç®ãæä¾ãããã¨ãã§ãã¾ãã
ã¤ãã¬ã¼ã¿ã¼ï¼å復åï¼ãããã³ã« (The iterator protocol) ã¯ãå¤ã®ä¸¦ã³ï¼æéã§ãç¡éã§ãï¼ãçæããããã®æ¨æºçãªæ¹æ³ã¨ããã¹ã¦ã®å¤ãçæãããå ´åã®è¿å¤ãå®ç¾©ãã¾ãã
以ä¸ã®æå³ã§ next()
ã¡ã½ãããå®è£
ãã¦ããã°ããªãã¸ã§ã¯ãã¯ã¤ãã¬ã¼ã¿ã¼ã«ãªãã¾ãã
next()
0 åã¾ã㯠1 åã®å¼æ°ãåãå
¥ããIteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ï¼ä¸è¨åç
§ï¼ã«é©åãããªãã¸ã§ã¯ããè¿ã颿°ã§ããçµã¿è¾¼ã¿è¨èªæ©è½ï¼for...of
ãªã©ï¼ãã¤ãã¬ã¼ã¿ã¼ã使ç¨ãã¦ããã¨ãã«ããªãã¸ã§ã¯ã以å¤ã®å¤ï¼false
ã undefined
ãªã©ï¼ãè¿ããå ´åãTypeError
("iterator.next() returned a non-object value"
) ãçºçãã¾ãã
ã¤ãã¬ã¼ã¿ã¼ãããã³ã«ã®ãã¹ã¦ã®ã¡ã½ããï¼next()
ãreturn()
ãthrow()
ï¼ã¯ãIteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ãå®è£
ãããªãã¸ã§ã¯ããè¿ããã¨ãæå¾
ããã¦ãã¾ãããã®ãªãã¸ã§ã¯ãã¯ä»¥ä¸ã®ããããã£ãæã¤å¿
è¦ãããã¾ãã
done
çç¥å¯
ã¤ãã¬ã¼ã¿ã¼ãã·ã¼ã±ã³ã¹å
ã®æ¬¡ã®å¤ãçæã§ããã¨ã false
ã®å¤ã«ãªãã¾ããï¼ãã㯠done
ããããã£ãæå®ããã¦ããªãå ´åãåãã§ããï¼
ã¤ãã¬ã¼ã¿ã¼ãå復ã·ã¼ã±ã³ã¹ãçµäºããå ´åãtrue
ã®å¤ã«ãªãã¾ãããã®å ´åãvalue
ã¯ä»»æã§ã¤ãã¬ã¼ã¿ã¼ã®è¿å¤ãæå®ãã¾ãã
value
çç¥å¯
ã¤ãã¬ã¼ã¿ã¼ã«ãã£ã¦è¿ãããä»»æã® JavaScript å¤ãdone
ã true
ã®ã¨ãã¯çç¥ãããã¨ãã§ãã¾ãã
å®éã«ã¯ãã©ã¡ãã®ããããã£ãå³å¯ã«ã¯å¿
è¦ããã¾ãããã©ã¡ãã®ããããã£ãæããªããªãã¸ã§ã¯ããè¿ããå ´åãããã¯äºå®ä¸ { done: false, value: undefined }
ã¨åãã§ãã
ã¤ãã¬ã¼ã¿ã¼ã done: true
ã®çµæãè¿ããå ´åããã以éã« next()
ãå¼ã³åºãã¨ãåæ§ã« done: true
ãè¿ããã¨ãæå¾
ããã¾ãããããã¯è¨èªã¬ãã«ã§ã¯å¼·å¶ããããã®ã§ã¯ããã¾ããã
next
ã¡ã½ããã¯ãã¡ã½ããæ¬ä½ãå©ç¨ã§ããããã«ãªãå¤ãåãåããã¨ãã§ãã¾ããçµã¿è¾¼ã¿ã®è¨èªæ©è½ã§ã¯ãå¤ã渡ããã¨ã¯ããã¾ãããã¸ã§ãã¬ã¼ã¿ã¼ã® next
ã¡ã½ããã«æ¸¡ãããå¤ã¯ã対å¿ãã yield
å¼ã®å¤ã«ãªãã
ãªãã·ã§ã³ã¨ãã¦ãã¤ãã¬ã¼ã¿ã¼ã¯ return(value)
㨠throw(exception)
ã¡ã½ãããå®è£
ãããã¨ãã§ãã¾ãããããã®ã¡ã½ããã¯ãå¼ã³åºãããã¨ãå¼ã³åºãå´ãã¤ãã¬ã¼ã¿ã¼ã®å復å¦çãçµäºããï¼ãã¼ã¿ãã¼ã¹æ¥ç¶ãéãããªã©ã®ï¼å¿
è¦ãªã¯ãªã¼ã³ã¢ãããå®è¡ã§ãããã¨ãã¤ãã¬ã¼ã¿ã¼ã«æç¤ºãã¾ãã
return(value)
çç¥å¯
0 ã¾ã㯠1 ã¤ã®å¼æ°ãåãå
¥ããIteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«é©åãããªãã¸ã§ã¯ããè¿ã颿°ã§ãé常 value
ã¯æ¸¡ããã value
ã¨çãããdone
㯠true
ã¨çãããªãã¾ãããã®ã¡ã½ãããå¼ã³åºãã¨ãå¼ã³åºãå´ãããä»¥ä¸ next()
ãå¼ã³åºããªããã¨ãã¤ãã¬ã¼ã¿ã¼ã«æç¤ºããä»»æã®ã¯ãªã¼ã³ã¢ããå¦çãå®è¡ãããã¨ãã§ãã¾ããçµã¿è¾¼ã¿ã®è¨èªæ©è½ãã¯ãªã¼ã³ã¢ããã®ããã« return()
ãå¼ã³åºãã¨ã value
ã¯å¸¸ã« undefined
ã¨ãªãã¾ãã
throw(exception)
çç¥å¯
0 åã¾ã㯠1 åã®å¼æ°ãåãå
¥ããIteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«é©åãããªãã¸ã§ã¯ããè¿ã颿°ã§ãããé常 done
㯠true
ã«çãããªãã¾ãããã®ã¡ã½ãããå¼ã³åºãã¨ãå¼ã³åºãå´ãã¨ã©ã¼ç¶æ
ãæ¤åºãããã¨ãã¤ãã¬ã¼ã¿ã¼ã«æç¤ºããexception
ã¯é常 Error
ã¤ã³ã¹ã¿ã³ã¹ã¨ãªãã¾ããè¨èªæ©è½ã«çµã¿è¾¼ã¾ãããã®ã§ã¯ãªããããã¯ãªã¼ã³ã¢ããã®ç®çã§ throw()
ãå¼ã³åºããã¨ã¯ã§ãã¾ãããããã¯ãreturn
/throw
ã®å¯¾ç§°æ§ã®ããã«ã¸ã§ãã¬ã¼ã¿ã«ç¹å¥ã«ç¨æãããæ©è½ã§ãã
ã¡ã¢: ç¹å®ã®ãªãã¸ã§ã¯ããã¤ãã¬ã¼ã¿ã¼ãããã³ã«ãå®è£
ãã¦ãããã©ãããåå°çã«ï¼ã¤ã¾ããå®éã« next()
ãå¼ã³åºãã¦ãè¿ãããçµæãæ¤è¨¼ãããã¨ãªãï¼ç¥ããã¨ã¯ä¸å¯è½ã§ãã
ã¤ãã¬ã¼ã¿ã¼ã¯ã¨ã¦ãç°¡åã«å復å¯è½ãªãã¸ã§ã¯ãã«ãããã¨ãã§ãã¾ãã[Symbol.iterator]()
ã¡ã½ãããå®è£
ã㦠this
ãè¿ãã ãã§ãã
// ã¤ãã¬ã¼ã¿ã¼ã¨å復å¯è½ã®ä¸¡ãããã³ã«ãæºãã
const myIterator = {
next() {
// ...
},
[Symbol.iterator]() {
return this;
},
};
ãã®ãããªãªãã¸ã§ã¯ãã¯å復å¯è½ã¤ãã¬ã¼ã¿ã¼ã¨å¼ã°ãã¾ãããã®ããã«å®è£ ãããã¨ã§ãå復å¯è½ãªãã¸ã§ã¯ããæå¾ ããæ§ã ãªæ§æã§ã¤ãã¬ã¼ã¿ã¼ãå©ç¨ã§ããããã«ãªãã¾ãããããã£ã¦ãå復å¯è½ãããã³ã«ãå®è£ ããã«ã¤ãã¬ã¼ã¿ã¼ãããã³ã«ãå®è£ ãããã¨ã¯ãã»ã¨ãã©æçã§ã¯ããã¾ãããï¼å®éãã»ã¨ãã©ãã¹ã¦ã®æ§æã¨ API ã¯ã¤ãã¬ã¼ã¿ã¼ã§ã¯ãªãå復å¯è½ãæå¾ ãã¦ãã¾ããï¼ã¸ã§ãã¬ã¼ã¿ã¼ãªãã¸ã§ã¯ãããã®ä¾ã§ãã
const aGeneratorObject = (function* () {
yield 1;
yield 2;
yield 3;
})();
console.log(typeof aGeneratorObject.next);
// "function" â ï¼æ£ããçµæãè¿ãï¼next ã¡ã½ãããæã£ã¦ããã®ã§ã¤ãã¬ã¼ã¿ã¼
console.log(typeof aGeneratorObject[Symbol.iterator]);
// "function" â ï¼æ£ããã¤ãã¬ã¼ã¿ã¼ãè¿ãï¼[Symbol.iterator] ã¡ã½ãããæã£ã¦ããã®ã§å復å¯è½ãªãã¸ã§ã¯ã
console.log(aGeneratorObject[Symbol.iterator]() === aGeneratorObject);
// true â Symbol.iterator ã¡ã½ããã¯èªåèªèº«ï¼ã¤ãã¬ã¼ã¿ã¼ï¼ãè¿ãã®ã§ãå復å¯è½ãªã¤ãã¬ã¼ã¿ã¼
çµã¿è¾¼ã¿ã®ã¤ãã¬ã¼ã¿ã¼ã¯ãã¹ã¦ Iterator.prototype
ãç¶æ¿ãã¦ããã [Symbol.iterator]()
ã¡ã½ãã㯠this
ãè¿ããã®ã¨ãã¦å®è£
ããã¦ããã®ã§ãçµã¿è¾¼ã¿ã¤ãã¬ã¼ã¿ã¼ãå復å¯è½ãªãã®ã¨ãªã£ã¦ãã¾ãã
ããããå¯è½ã§ããã° iterable[Symbol.iterator]
ã Set.prototype[Symbol.iterator]()
ãè¡ãããã«ã常ã«å
é ããå§ã¾ãå¥ã®ã¤ãã¬ã¼ã¿ã¼ãè¿ãã»ããè¯ãã§ãããã
éåæã®å復å¦çã«ç¨ãããããã³ã«ã«ã¯ãéåæã¤ãã¬ã¼ã¿ã¼ã¨éåæå復å¯è½ãªãã¸ã§ã¯ãã¨ããååã®å¥ã®çµãããã¾ãããããã¯å復å¯è½ãªãã¸ã§ã¯ãã¨ã¤ãã¬ã¼ã¿ã¼ãããã³ã«ã«æ¯ã¹ã¦é常ã«ããä¼¼ãã¤ã³ã¿ã¼ãã§ã¤ã¹ãæã£ã¦ãã¾ãããã¤ãã¬ã¼ã¿ã¼ã¡ã½ããã®å¼ã³åºãããã®è¿å¤ããããããããã¹ã§ã©ããããã¦ããç¹ãç°ãªãã¾ãã
ãªãã¸ã§ã¯ããéåæã¤ãã¬ã¼ã¿ã¼ãããã³ã«ãå®è£ ããã®ã¯ã以ä¸ã®ã¡ã½ãããå®è£ ãã¦ããå ´åã§ãã
[Symbol.asyncIterator]()
éåæã¤ãã¬ã¼ã¿ã¼ãããã³ã«ã«æºæ ãããªãã¸ã§ã¯ããè¿ã弿°ã¼ãã®é¢æ°ã§ãã
ãªãã¸ã§ã¯ããéåæã¤ãã¬ã¼ã¿ã¼ãããã³ã«ãå®è£ ããã®ã¯ã以ä¸ã®ã¡ã½ãããå®è£ ãã¦ããå ´åã§ãã
next()
0 åã¾ã㯠1 åã®å¼æ°ãåãå
¥ãããããã¹ãè¿ã颿°ã§ãããããã¹ã¯ IteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«æºæ ãããªãã¸ã§ã¯ãã«å±¥è¡ãããããããã£ã¯åæã¤ãã¬ã¼ã¿ã¼ã®ãã®ã¨åãæå³ã¥ããæã¡ã¾ãã
return(value)
çç¥å¯
0 åã¾ã㯠1 åã®å¼æ°ãåãå
¥ãããããã¹ãè¿ã颿°ã§ãããããã¹ã¯ IteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«æºæ ãããªãã¸ã§ã¯ãã«å±¥è¡ãããããããã£ã¯åæã¤ãã¬ã¼ã¿ã¼ã®ãã®ã¨åãæå³ã¥ããæã¡ã¾ãã
throw(exception)
çç¥å¯
0 åã¾ã㯠1 åã®å¼æ°ãåãå
¥ãããããã¹ãè¿ã颿°ã§ãããããã¹ã¯ IteratorResult
ã¤ã³ã¿ã¼ãã§ã¤ã¹ã«æºæ ãããªãã¸ã§ã¯ãã«å±¥è¡ãããããããã£ã¯åæã¤ãã¬ã¼ã¿ã¼ã®ãã®ã¨åãæå³ã¥ããæã¡ã¾ãã
ãã®è¨èªã§ã¯ãå復å¯è½ãªãã¸ã§ã¯ãã¨ã¤ãã¬ã¼ã¿ã¼ãçæã¾ãã¯ä½¿ç¨ãã API ãè¦å®ãã¦ãã¾ãã
çµã¿è¾¼ã¿å復å¯è½ãªãã¸ã§ã¯ãString
ãArray
ãTypedArray
ãMap
ãSet
ãSegments
ï¼Intl.Segmenter.prototype.segment()
ã§è¿ãããï¼ã¯ããã¹ã¦çµã¿è¾¼ã¿å復å¯è½ãªãã¸ã§ã¯ãã§ãããããã® prototype
ãªãã¸ã§ã¯ãã¯ãããã [Symbol.iterator]()
ã¡ã½ãããå®è£
ãã¦ãã¾ããã¾ããarguments
ãªãã¸ã§ã¯ãã NodeList
ãªã©ã®ä¸é¨ã® DOM ã³ã¬ã¯ã·ã§ã³åãå復å¯è½ã§ãã JavaScript ã®ã³ã¢è¨èªã«ã¯ãéåæå復å¯è½ãªãã¸ã§ã¯ãã¯ããã¾ãããReadableStream
ãªã©ã®ä¸é¨ã®ã¦ã§ã API ã¯ãSymbol.asyncIterator
ã¡ã½ãããæ¢å®ã§è¨å®ããã¦ãã¾ãã
ã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã¯ãå復å¯è½ãªã¤ãã¬ã¼ã¿ã¼ã§ããã¸ã§ãã¬ã¼ã¿ã¼ãªãã¸ã§ã¯ããè¿ãã¾ããéåæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã¯ãéåæå復å¯è½ãªã¤ãã¬ã¼ã¿ã¼ã§ããéåæ ã¸ã§ãã¬ã¼ã¿ã¼ãªãã¸ã§ã¯ããè¿ãã¾ãã
çµã¿è¾¼ã¿å復å¯è½ãªãã¸ã§ã¯ãããè¿ãããã¤ãã¬ã¼ã¿ã¼ã¯ãå®éã«ã¯ãã¹ã¦å
±éã®ã¯ã©ã¹ Iterator
ãç¶æ¿ãã¦ãããåè¿°ã® [Symbol.iterator]() { return this; }
ã¡ã½ãããå®è£
ãã¦ããã®ã§ããã¹ã¦å復å¯è½ã¤ãã¬ã¼ã¿ã¼ã¨ãªã£ã¦ãã¾ãã Iterator
ã¯ã©ã¹ã¯ãã¤ãã¬ã¼ã¿ã¼ãããã³ã«ãè¦æ±ãã next()
ã¡ã½ããã«å ãã¦ã追å ã®ãã«ãã¼ã¡ã½ãããæä¾ãã¦ãã¾ããã¤ãã¬ã¼ã¿ã¼ã®ãããã¿ã¤ããã§ã¼ã³ã¯ãã°ã©ãã£ã«ã«ã³ã³ã½ã¼ã«ã«ãã°åºåãããã¨ã§æ¤æ»ãããã¨ãã§ãã¾ãã
console.log([][Symbol.iterator]()); Array Iterator {} [[Prototype]]: Array Iterator ==> é åã®ã¤ãã¬ã¼ã¿ã¼ã«å ±éãããããã¿ã¤ã next: Æ next() Symbol(Symbol.toStringTag): "Array Iterator" [[Prototype]]: Object ==> ãã¹ã¦ã®çµã¿è¾¼ã¿ã¤ãã¬ã¼ã¿ã¼ã«å ±éãããããã¿ã¤ã Symbol(Symbol.iterator): Æ [Symbol.iterator]() [[Prototype]]: Object ==> ãã㯠Object.prototypeå復å¯è½ãªãã¸ã§ã¯ããåãå ¥ããçµã¿è¾¼ã¿ API
å復å¯è½ãªãã¸ã§ã¯ããåãå ¥ãã API ã¯ããããããã¾ãã以ä¸ã¯ãã®ä¾ã§ãã
Map()
WeakMap()
Set()
WeakSet()
Promise.all()
Promise.allSettled()
Promise.race()
Promise.any()
Array.from()
Object.groupBy()
Map.groupBy()
const myObj = {};
new WeakSet(
(function* () {
yield {};
yield myObj;
yield {};
})(),
).has(myObj); // true
å復å¯è½ãªãã¸ã§ã¯ããæå¾
ããæ§æ
ä¸é¨ã®æãå¼ã¯å復å¯è½ãªãã¸ã§ã¯ããæå¾
ãã¾ããä¾ãã°ã for...of
ã«ã¼ããé
åã¨å¼æ°ã®ã¹ãã¬ãããyield*
ãé
åã®æ§é åè§£ãªã©ã§ãã
for (const value of ["a", "b", "c"]) {
console.log(value);
}
// "a"
// "b"
// "c"
console.log([..."abc"]); // ["a", "b", "c"]
function* gen() {
yield* ["a", "b", "c"];
}
console.log(gen().next()); // { value: "a", done: false }
[a, b, c] = new Set(["a", "b", "c"]);
console.log(a); // "a"
çµã¿è¾¼ã¿ API ãã¤ãã¬ã¼ã¿ã¼ãå復å¦çãã¦ãã¦ãæå¾ã®çµæã® done
ã false
ï¼ã¤ãã¬ã¼ã¿ã¼ãããã«å¤ãçæã§ããç¶æ
ï¼ã ãããã以ä¸ã®å¤ã¯å¿
è¦ãªãå ´åãreturn
ã¡ã½ãããåå¨ããã°ããããå¼ã³åºããã¾ãããã¯ä¾ãã°ãfor...of
ã«ã¼ãã®ä¸ã§ break
ã return
ã«ééããå ´åããé
åã®æ§é åè§£ã§ãã¹ã¦ã®èå¥åãæ¢ã«çµåããã¦ããå ´åãªã©ã«çºçãã¾ãã
const obj = {
[Symbol.iterator]() {
let i = 0;
return {
next() {
i++;
console.log("Returning", i);
if (i === 3) return { done: true, value: i };
return { done: false, value: i };
},
return() {
console.log("Closing");
return { done: true };
},
};
},
};
const [a] = obj;
// Returning 1
// Closing
const [b, c, d] = obj;
// Returning 1
// Returning 2
// Returning 3
// Already reached the end (the last call returned `done: true`),
// so `return` is not called
console.log([b, c, d]); // [1, 2, undefined]; the value associated with `done: true` is not reachable
for (const b of obj) {
break;
}
// Returning 1
// Closing
éåæå復å¯è½ãªãã¸ã§ã¯ãã¨å¯¾è©±ããå¯ä¸ã®æ¹æ³ã¯ãfor await...of
ã«ã¼ãã¨ãéåæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã§ã® yield*
ï¼ãã ãåæã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã§ã¯ããã¾ããï¼ã§ããéåæå復å¯è½ãªãã¸ã§ã¯ãã§ããããåæå復å¯è½ã§ã¯ãªãï¼ã¤ã¾ã [Symbol.asyncIterator]()
ã¯ããã [Symbol.iterator]()
ã¯ãªãï¼ãã®ã« for...of
ãé
åã®å±éãªã©ã使ç¨ããã¨ã TypeError: x is not iterable ä¾å¤ãçºçãã¾ãã
å復å¦çã§ã¯ãã¤ãã¬ã¼ã¿ã¼ã¨ã³ã³ã·ã¥ã¼ãã¼ã®éã§å¶å¾¡ãç§»è²ããããããã¨ã©ã¼å¦çã¯ã©ã¡ãã®æ¹åã«ãç¾ãã¾ããã¤ã¾ããã³ã³ã·ã¥ã¼ãã¼ãã¤ãã¬ã¼ã¿ã¼ããçºçããã¨ã©ã¼ãå¦çããæ¹æ³ã¨ãã¤ãã¬ã¼ã¿ã¼ãã³ã³ã·ã¥ã¼ãã¼ããçºçããã¨ã©ã¼ãå¦çããæ¹æ³ã§ããçµã¿è¾¼ã¿ã®å復å¦çã®æ¹æ³ã使ç¨ãã¦ãå復å¯è½ãªãã¸ã§ã¯ããç¹å®ã®ä¸å¤æ¡ä»¶ãç ´ã£ãããã«ã¨ã©ã¼ãçºçããå ´åãããã¾ãã çµã¿è¾¼ã¿æ§æãã¨ã©ã¼ãçæããå¦çããæ¹æ³ã説æãã¾ããããã¯ãã¤ãã¬ã¼ã¿ã¼ã段éçã«æåã§å¦çããå ´åã«ãèªåèªèº«ã§ã³ã¼ãã使ããéã®ã¬ã¤ãã©ã¤ã³ã¨ãã¦ä½¿ç¨ãããã¨ãã§ãã¾ãã
鿣è¦å½¢å復å¯è½ãªãã¸ã§ã¯ãå復å¯è½ãªãã¸ã§ã¯ãããã¤ãã¬ã¼ã¿ã¼ãåå¾ããéã«ã¨ã©ã¼ãç¾ããå¯è½æ§ãããã¾ããããã§è¦æ±ãããè¨èªã®ä¸å¤æ¡ä»¶ã¯ãå復å¯è½ãªãã¸ã§ã¯ãã¯æå¹ãªã¤ãã¬ã¼ã¿ã¼ãçæããªããã°ãªããªãã¨ãããã¨ã§ãã
[Symbol.iterator]()
ã¡ã½ãããæã£ã¦ãããã¨ã[Symbol.iterator]()
ã¡ã½ããããªãã¸ã§ã¯ããè¿ããã¨ã[Symbol.iterator]()
ããè¿ããããªãã¸ã§ã¯ãã«å¼ã³åºãå¯è½ãª next()
ã¡ã½ããããããã¨ãçµã¿è¾¼ã¿æ§æã使ç¨ãã¦ãæ£ããå½¢æããã¦ããªãå復å¯è½ãªãã¸ã§ã¯ãã®å復å¦çãéå§ããã¨ã TypeError ãçºçãã¾ãã
const nonWellFormedIterable = { [Symbol.iterator]: 1 };
[...nonWellFormedIterable]; // TypeError: nonWellFormedIterable is not iterable
nonWellFormedIterable[Symbol.iterator] = () => 1;
[...nonWellFormedIterable]; // TypeError: [Symbol.iterator]() returned a non-object value
nonWellFormedIterable[Symbol.iterator] = () => ({});
[...nonWellFormedIterable]; // TypeError: nonWellFormedIterable[Symbol.iterator]().next is not a function
éåæå復å¯è½ãªãã¸ã§ã¯ãã®å ´åã [Symbol.asyncIterator]()
ããããã£ã®å¤ã undefined
ã¾ã㯠null
ã§ããå ´åã JavaScript ã¯ä»£ããã« [Symbol.iterator]
ããããã£ã使ç¨ãã¾ãï¼ããã¦ãã¡ã½ããã転éãããã¨ã§ãçµæã¨ãã¦å¾ãããã¤ãã¬ã¼ã¿ã¼ãéåæã¤ãã¬ã¼ã¿ã¼ã«ã©ãããã¾ãï¼ã ãã以å¤ã®å ´åã¯ã [Symbol.asyncIterator]
ããããã£ãä¸è¨ä¸å¤æ¡ä»¶ã«é©åããå¿
è¦ãããã¾ãã
ãã®ç¨®é¡ã®ã¨ã©ã¼ã¯ãå復å¦çã試ã¿ãåã«æåã®å復å¯è½ãªãã¸ã§ã¯ããæ¤è¨¼ãããã¨ã§é²ããã¨ãã§ãã¾ããããããé常ã¯å復å¦çãããªãã¸ã§ã¯ãã®åãããã£ã¦ããããããã®ãããªã¨ã©ã¼ã¯çºçãããã¨ã¯ã»ã¨ãã©ããã¾ããããããä»ã«ãã³ã¼ãããå復å¯è½ãªãã¸ã§ã¯ããåãåã£ã¦ããå ´åã¯ã䏿£ãªå ¥åãæå®ããããã¨ãå¼ã³åºãå´ã«ç¥ãããããã«ãã¨ã©ã¼ãå¼ã³åºãå´ã«ä¼æãããã¹ãã§ãã
å復å¦çä¸ã®ã¨ã©ã¼ã»ã¨ãã©ã®ã¨ã©ã¼ã¯ãã¤ãã¬ã¼ã¿ã¼ã®é²è¡ï¼next()
ã®å¼ã³åºãï¼ã§çºçãã¾ããããã§å¼·å¶ãããè¨èªã®ä¸å¤æ¡ä»¶ã¯ã next()
ã¡ã½ããã¯ãªãã¸ã§ã¯ãï¼éåæã¤ãã¬ã¼ã¿ã¼ã®å ´åã¯ãå¾
æ©å¾ã®ãªãã¸ã§ã¯ãï¼ãè¿ããªããã°ãªããªãã¨ãããã¨ã§ããããã§ãªãå ´åã¯ã TypeError ãçºçãã¾ãã
ä¸å¤æ¡ä»¶ãç ´ãããå ´åãã¾ã㯠next()
ã¡ã½ããã§ã¨ã©ã¼ãçºçããå ´åï¼éåæã¤ãã¬ã¼ã¿ã¼ã®å ´åã¯ãæå¦ããããããã¹ãè¿ãå ´åãããã¾ãï¼ãã¨ã©ã¼ã¯å¼ã³åºãå´ã«ä¼æããã¾ããçµã¿è¾¼ã¿ã®æ§æã®å ´åãé²è¡ä¸ã®å復å¦çã¯å試è¡ãã¯ãªã¼ã³ã¢ãããªãã§ä¸æ¢ããã¾ãï¼next()
ã¡ã½ãããã¨ã©ã¼ãçºçãããå ´åããã§ã«ã¯ãªã¼ã³ã¢ãããå®äºãã¦ããã¨ããåæã§ï¼ãæåã§ next()
ãå¼ãã§ããå ´åã¯ãã¨ã©ã¼ãææã㦠next()
ã®å¼ã³åºããå試è¡ãããã¨ãã§ãã¾ãããä¸è¬çã«ã¯ã¤ãã¬ã¼ã¿ã¼ã¯ãã§ã«éããããã¨æ³å®ãã¹ãã§ãã
å¼ã³åºãå´ããåã®æ®µè½ã§è¿°ã¹ãã¨ã©ã¼ä»¥å¤ã®çç±ã§å復å¦çãçµäºããå ´åãä¾ãã°èªèº«ã®ã³ã¼ãã§ã¨ã©ã¼ç¶æ
ã«ãªã£ãå ´åï¼ä¾ãã°ãã¤ãã¬ã¼ã¿ã¼ã«ãã£ã¦çæããã䏿£ãªå¤ãå¦çãã¦ããå ´åãªã©ï¼ãã¤ãã¬ã¼ã¿ã¼ã« return()
ã¡ã½ãããåå¨ããå ´åã¯ããã®ã¡ã½ãããå¼ã³åºãå¿
è¦ãããã¾ããããã«ãããã¤ãã¬ã¼ã¿ã¼ãã¯ãªã¼ã³ã¢ããå¦çãå®è¡ã§ããããã«ãªãã¾ãã return()
ã¡ã½ããã¯ãæ©æçµäºã®å ´åã®ã¿ã«å¼ã³åºããã¾ãã next()
ã done: true
ãè¿ããå ´åãã¤ãã¬ã¼ã¿ã¼ããã§ã«ã¯ãªã¼ã³ã¢ããæ¸ã¿ã§ããã¨ããåæã®ãã¨ã return()
ã¡ã½ããã¯å¼ã³åºããã¾ããã
return()
ã¡ã½ããã䏿£ã«ãªãå¯è½æ§ãããã¾ããè¨èªã§ã¯ã return()
ã¡ã½ããã¯ãªãã¸ã§ã¯ããè¿ããªããã°ãªãããããã§ãªãå ´å㯠TypeError ãçºçãã¾ãã return()
ã¡ã½ããã§ã¨ã©ã¼ãçºçããå ´åããã®ã¨ã©ã¼ã¯å¼ã³åºãå´ã«ä¼æãã¾ãã ãã ããå¼ã³åºãå´ãèªåèªèº«ã§ã³ã¼ãã«ã¨ã©ã¼ãçºçããããã« return()
ã¡ã½ãããå¼ã°ããå ´åããã®ã¨ã©ã¼ã¯ return()
ã¡ã½ãããçºçããã¨ã©ã¼ã䏿¸ããã¾ãã
é常ãå¼ã³åºãå´ã§ã¯ãã¨ã©ã¼å¦çãæ¬¡ã®ããã«å®è£ ãã¾ãã
try {
for (const value of iterable) {
// ...
}
} catch (e) {
// Handle the error
}
catch
ã¯ãiterable
ãæå¹ãªå復å¯è½ãªãã¸ã§ã¯ãã§ãªãå ´åãnext()
ãã¨ã©ã¼ãçºçããå ´åãreturn()
ãã¨ã©ã¼ãçºçããå ´åï¼for
ã«ã¼ããæ©æã«çµäºããå ´åï¼ãããã³ for
ã«ã¼ãæ¬ä½ã§ã¨ã©ã¼ãçºçããå ´åã«çºçããã¨ã©ã¼ãææãããã¨ãã§ãã¾ãã
ã»ã¨ãã©ã®ã¤ãã¬ã¼ã¿ã¼ã¯ã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã§å®è£ ããã¦ãããããã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ãé常ã©ã®ããã«ã¨ã©ã¼ãå¦çããã®ããç´¹ä»ãã¾ãã
function* gen() {
try {
yield doSomething();
yield doSomethingElse();
} finally {
cleanup();
}
}
ããã§ catch
ãåå¨ããªããããdoSomething()
ã¾ã㯠doSomethingElse()
ã§çºçããã¨ã©ã¼ã gen
ã®å¼ã³åºãå´ã«ä¼æãã¦ãã¾ãã¾ãã ãããã®ã¨ã©ã¼ãã¸ã§ãã¬ã¼ã¿ã¼é¢æ°å
ã§ææãããå ´åï¼åæ§ã«æ¨å¥¨ããã¾ãï¼ãã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã¯å¤ã®çæãç¶ããããã¾ãã¯æ©æã«çµäºããããæ±ºå®ãããã¨ãã§ãã¾ãã ãããããªã½ã¼ã¹ãéããã¾ã¾ã«ããã¸ã§ãã¬ã¼ã¿ã¼ã§ã¯ã finally
ãããã¯ãå¿
è¦ã§ãã finally
ãããã¯ã¯ãæå¾ã® next()
ãå¼ã³åºããããã return()
ãå¼ã³åºããããã®ããããã®ã¿ã¤ãã³ã°ã§å®è¡ãããã¨ãä¿è¨¼ããã¦ãã¾ãã
çµã¿è¾¼ã¿ã®æ§æã®ä¸ã«ã¯ãã¤ãã¬ã¼ã¿ã¼ãå¥ã®ã¤ãã¬ã¼ã¿ã¼ã§ã©ãããããã®ãããã¾ããããã«ã¯ã Iterator.from()
ã§çæãããã¤ãã¬ã¼ã¿ã¼ãã¤ãã¬ã¼ã¿ã¼ãã«ãã¼ã¡ã½ãã (map()
, filter()
, take()
, drop()
, flatMap()
)ãyield*
ãããã³åæã¤ãã¬ã¼ã¿ã¼ã§éåæå復å¦ç (for await...of
, Array.fromAsync
) ã使ç¨ããå ´åã®é ãã©ããã¼ãããã¾ããã©ãããããã¤ãã¬ã¼ã¿ã¼ã¯ãå
é¨ã¤ãã¬ã¼ã¿ã¼ã¨å¼ã³åºãå´ã®éã§ã¨ã©ã¼ã転éããå½¹å²ãæ
ãã¾ãã
next()
ã¡ã½ãããããã®è¿å¤ã¨çºçããã¨ã©ã¼ãå«ãã¦ç´æ¥è»¢éãã¾ããreturn()
ã¡ã½ãããç´æ¥è»¢éãã¾ããå
é¨ã¤ãã¬ã¼ã¿ã¼ã« return()
ã¡ã½ãããåå¨ããªãå ´åã¯ã代ããã« { done: true, value: undefined }
ãè¿ãã¾ããã¤ãã¬ã¼ã¿ã¼ãã«ãã¼ã®å ´åã§ãã¤ãã¬ã¼ã¿ã¼ãã«ãã¼ã® next()
ã¡ã½ãããã¾ã ä¸åº¦ãå¼ã³åºããã¦ããªãå ´åãå
é¨ã¤ãã¬ã¼ã¿ã¼ã® return()
ãå¼ã³åºããã¨ããå¾ãç¾å¨ã®ã¤ãã¬ã¼ã¿ã¼ã¯å¸¸ã« { done: true, value: undefined }
ãè¿ãã¾ããããã¯ãã¾ã yield*
å¼ãå®è¡ããã¦ããªãã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã¨åãã§ããyield*
ã¯ãå
å´ã®ã¤ãã¬ã¼ã¿ã¼ã® throw()
ã¡ã½ããã転éããå¯ä¸ã®çµã¿è¾¼ã¿æ§æã§ãã yield*
ã return()
ããã³ throw()
ã¡ã½ããã転éããæ¹æ³ã«é¢ããæ
å ±ã¯ãèªåèªèº«ã§åç
§ãã¦ãã ãããæ¬¡ã®ããã«ãã¦ãç¬èªã®å復å¯è½ãªãã¸ã§ã¯ããä½ããã¨ãã§ãã¾ãã
const myIterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
},
};
console.log([...myIterable]); // [1, 2, 3]
åºæ¬çãªã¤ãã¬ã¼ã¿ã¼
ã¤ãã¬ã¼ã¿ã¼ã¯ãã¨ãã¨ã¹ãã¼ããã«ãªãã®ã§ããã¸ã§ãã¬ã¼ã¿ã¼é¢æ°ã¨ãã¦å®ç¾©ãã¦ããªãå ´åï¼ä¸ã®ä¾ã示ãããã«ï¼ãã¯ãã¼ã¸ã£ã§ç¶æ ãã«ãã»ã«åãããã¨æããã¨ã§ãããã
function makeIterator(array) {
let nextIndex = 0;
return {
next() {
return nextIndex < array.length
? {
value: array[nextIndex++],
done: false,
}
: {
done: true,
};
},
};
}
const it = makeIterator(["yo", "ya"]);
console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done); // true
ç¡éã®ã¤ãã¬ã¼ã¿ã¼
function idMaker() {
let index = 0;
return {
next() {
return {
value: index++,
done: false,
};
},
};
}
const it = idMaker();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 2
// ...
ã¸ã§ãã¬ã¼ã¿ã¼ã§å復å¯è½ãããã³ã«ãå®ç¾©
function* makeGenerator(array) {
let nextIndex = 0;
while (nextIndex < array.length) {
yield array[nextIndex++];
}
}
const gen = makeGenerator(["yo", "ya"]);
console.log(gen.next().value); // 'yo'
console.log(gen.next().value); // 'ya'
console.log(gen.next().done); // true
function* idMaker() {
let index = 0;
while (true) {
yield index++;
}
}
const it = idMaker();
console.log(it.next().value); // 0
console.log(it.next().value); // 1
console.log(it.next().value); // 2
// ...
ã¯ã©ã¹ã§å復å¯è½ãããã³ã«ãå®ç¾©
ç¶æ ã®ã«ãã»ã«åã¯ããã©ã¤ãã¼ããã£ã¼ã«ãã§ãè¡ããã¨ãã§ãã¾ãã
class SimpleClass {
#data;
constructor(data) {
this.#data = data;
}
[Symbol.iterator]() {
// ããããã®ã¤ãã¬ã¼ã¿ã¼ã«æ°ããã¤ã³ããã¯ã¹ã使ç¨ãã¾ããããã«ãã
// break ã®ä½¿ç¨ãåãå復å¯è½ãªãã¸ã§ã¯ãã«å¯¾ããå
¥ãåã«ã¼ããªã©ãèªæã§ãªãç¨éã§ã
// å復å¯è½ãªãã¸ã§ã¯ãã«å¯¾ããè¤æ°ã®å復å¦çãå®å
¨ã«è¡ããã¨ãã§ãã¾ãã
let index = 0;
return {
// 注: ã¢ãã¼é¢æ°ã使ç¨ããã¨ã`next()` ã®ä»£ããã« `[Symbol.iterator]()` ã®æ¹ã `this` ãæãããã«ãªãã¾ãã
next: () => {
if (index < this.#data.length) {
return { value: this.#data[index++], done: false };
} else {
return { done: true };
}
},
};
}
}
const simple = new SimpleClass([1, 2, 3, 4, 5]);
for (const val of simple) {
console.log(val); // 1 2 3 4 5
}
çµã¿è¾¼ã¿å復å¯è½ãªãã¸ã§ã¯ãã®ãªã¼ãã¼ã©ã¤ã
ä¾ãã°ãString
ã¯ãçµã¿è¾¼ã¿ã®ã¤ãã¬ã¼ã¿ã¼ãªãã¸ã§ã¯ãã§ãã
const someString = "hi";
console.log(typeof someString[Symbol.iterator]); // "function"
String
ã®æ¢å®ã®ã¤ãã¬ã¼ã¿ã¼ã¯ãæååã®ã³ã¼ããã¤ã³ãã 1 ã¤ãã¤è¿ãã¾ãã
const iterator = someString[Symbol.iterator]();
console.log(`${iterator}`); // "[object String Iterator]"
console.log(iterator.next()); // { value: "h", done: false }
console.log(iterator.next()); // { value: "i", done: false }
console.log(iterator.next()); // { value: undefined, done: true }
èªåèªèº«ã§ [Symbol.iterator]()
ãç¨æãããã¨ã§ãå復å¦çã®åä½ãåå®ç¾©ãããã¨ãã§ãã¾ãã
// èªåããã¯ã¹åãé¿ãããããæååãªãã¸ã§ã¯ããæç¤ºçã«æ§ç¯ããå¿
è¦ãããã¾ãã
const someString = new String("hi");
someString[Symbol.iterator] = function () {
return {
// this is the iterator object, returning a single element (the string "bye")
next() {
return this._first
? { value: "bye", done: (this._first = false) }
: { done: true };
},
_first: true,
};
};
[Symbol.iterator]()
ã®åå®ç¾©ããå復å¦çã使ç¨ããçµã¿è¾¼ã¿ã®æ§æè¦ç´ ã®åä½ã«ã©ã®ãããªå½±é¿ãä¸ãããã«æ³¨ç®ãã¦ãã ããã
console.log([...someString]); // ["bye"]
console.log(`${someString}`); // "hi"
å復å¦çæã®åæé²è¡ã®å¤æ´
ã»ã¨ãã©ãã¹ã¦ã®å復å¯è½ãªãã¸ã§ã¯ãã¯ãåãåºæ¬çãªæå³ãæã£ã¦ãã¾ããå復å¦çãéå§ãããæç¹ã§ãã¼ã¿ãã³ãã¼ããããã¨ã¯ãªãããã¤ã³ã¿ã¼ãä¿æããããããç§»åãã¾ãããã®ãããéåãå復å¦çããªãããã®éåå ã®è¦ç´ ã追å ãåé¤ãã¾ãã¯å¤æ´ããã¨ãéåå ã®ä»ã«ã夿´ããã¦ããªãè¦ç´ ã訪åããããã©ãããããã£ãã夿´ãã¦ãã¾ãå¯è½æ§ãããã¾ããããã¯å復å¯è½ãªé åã¡ã½ããã®åãã¨ã¨ã¦ãããä¼¼ã¦ãã¾ãã
URLSearchParams
ã使ç¨ããæ¬¡ã®ãããªã±ã¼ã¹ããã£ãã¨ãã¾ãã
const searchParams = new URLSearchParams(
"deleteme1=value1&key2=value2&key3=value3",
);
// Delete unwanted keys
for (const [key, value] of searchParams) {
console.log(key);
if (key.startsWith("deleteme")) {
searchParams.delete(key);
}
}
// åºå:
// deleteme1
// key3
key2
ãã¾ã£ãããã°ã«è¨é²ããã¦ããªããã¨ã«æ³¨æãã¦ãã ãããããã¯ãURLSearchParams
ãæ ¹åºã§ã¯ãã¼ã¨å¤ã®çµã®ãªã¹ãã§ããããã§ãã deleteme1
ãå¦çããåé¤ãããã¨ãä»ã®é
ç®ããã¹ã¦å·¦ã« 1 ã¤ãã¤ç§»åãã key2
ã deleteme1
ã以åã«ãã£ãä½ç½®ãå ãããã¨ã«ãªãããã¤ã³ã¿ã¼ã次ã®ãã¼ã«ç§»åããã¨ã key3
ã«ç§»åãã¾ãã
å復å¦çå¯è½ãªãªãã¸ã§ã¯ãã®å®è£
ã§ã¯ãæ®ãã®å¤ãã·ããããªãããã«ãå¢ç³ãå¤ãè¨å®ãããã¨ã§ããã®åé¡ãé¿ãããã¨ãã§ãã¾ãã Map
ã使ç¨ããé¡ä¼¼ã®ã³ã¼ããèãã¦ã¿ã¾ãããã
const myMap = new Map([
["deleteme1", "value1"],
["key2", "value2"],
["key3", "value3"],
]);
for (const [key, value] of myMap) {
console.log(key);
if (key.startsWith("deleteme")) {
myMap.delete(key);
}
}
// åºå:
// deleteme1
// key2
// key3
ãã¹ã¦ã®ãã¼ããã°åºåãã¦ãããã¨ã«æ³¨æãã¦ãã ãããããã¯ãMap
ããã¼ãåé¤ããéã«æ®ãã®ãã¼ãã·ããããªãããã§ããåæ§ã®å®è£
ãè¡ãããå ´åã以ä¸ã®ãããªå½¢ã«ãªãã§ãããã
const tombstone = Symbol("tombstone");
class MyIterable {
#data;
constructor(data) {
this.#data = data;
}
delete(deletedKey) {
for (let i = 0; i < this.#data.length; i++) {
if (this.#data[i][0] === deletedKey) {
this.#data[i] = tombstone;
return true;
}
}
return false;
}
*[Symbol.iterator]() {
for (let i = 0; i < this.#data.length; i++) {
if (this.#data[i] !== tombstone) {
yield this.#data[i];
}
}
}
}
const myIterable = new MyIterable([
["deleteme1", "value1"],
["key2", "value2"],
["key3", "value3"],
]);
for (const [key, value] of myIterable) {
console.log(key);
if (key.startsWith("deleteme")) {
myIterable.delete(key);
}
}
è¦å: ä¸è¬çã«ãåæé²è¡ã®å¤æ´ã¯ãã°ãçºçãããããæ··ä¹±ãæãããããã®ã§ããå復å¯è½ãªãã¸ã§ã¯ããã©ã®ããã«å®è£ ããã¦ããããæ£ç¢ºã«ææ¡ãã¦ããªãéãããã®éåãå復å¦çãã¦ããéã¯å¤æ´ããªãæ¹ãè¯ãã§ãããã
仿§æ¸ é¢é£æ å ±RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4