è¿ä»£åè®®å¹¶ä¸æ¯æ°çå ç½®å®ç°æè¯æ³ï¼èæ¯åè®®ãè¿äºåè®®å¯ä»¥è¢«ä»»ä½éµå¾ªæäºçº¦å®ç对象æ¥å®ç°ã
è¿ä»£åè®®å ·ä½å为两个åè®®ï¼å¯è¿ä»£åè®®åè¿ä»£å¨åè®®ã
å¯è¿ä»£åè®®å¯è¿ä»£åè®®å
许 JavaScript 对象å®ä¹æå®å¶å®ä»¬çè¿ä»£è¡ä¸ºï¼ä¾å¦ï¼å¨ä¸ä¸ª for..of
ç»æä¸ï¼åªäºå¼å¯ä»¥è¢«éåå°ãä¸äºå
置类ååæ¶æ¯å
ç½®çå¯è¿ä»£å¯¹è±¡ï¼å¹¶ä¸æé»è®¤çè¿ä»£è¡ä¸ºï¼æ¯å¦ Array
æè
Map
ï¼èå
¶ä»å
置类åå䏿¯ï¼æ¯å¦ Object
ï¼ã
è¦æä¸ºå¯è¿ä»£å¯¹è±¡ï¼è¯¥å¯¹è±¡å¿
é¡»å®ç° [Symbol.iterator]()
æ¹æ³ï¼è¿æå³çå¯¹è±¡ï¼æè
å®ååé¾ä¸çæä¸ªå¯¹è±¡ï¼å¿
é¡»æä¸ä¸ªé®ä¸º [Symbol.iterator]
ç屿§ï¼å¯éè¿å¸¸é Symbol.iterator
访é®è¯¥å±æ§ï¼
[Symbol.iterator]
ä¸ä¸ªæ åæ°ç彿°ï¼å ¶è¿åå¼ä¸ºä¸ä¸ªç¬¦åè¿ä»£å¨åè®®ç对象ã
å½ä¸ä¸ªå¯¹è±¡éè¦è¢«è¿ä»£çæ¶åï¼æ¯å¦è¢«ç½®å
¥ä¸ä¸ª for...of
å¾ªç¯æ¶ï¼ï¼é¦å
ï¼ä¼ä¸å¸¦åæ°è°ç¨å®ç [Symbol.iterator]()
æ¹æ³ï¼ç¶åä½¿ç¨æ¤æ¹æ³è¿åçè¿ä»£å¨è·å¾è¦è¿ä»£çå¼ã
å¼å¾æ³¨æçæ¯è°ç¨æ¤æ 忰彿°æ¶ï¼å®å°ä½ä¸ºå¯¹å¯è¿ä»£å¯¹è±¡çæ¹æ³è¿è¡è°ç¨ãå æ¤ï¼å¨å½æ°å
é¨ï¼this
å
³é®åå¯ç¨äºè®¿é®å¯è¿ä»£å¯¹è±¡ç屿§ï¼ä»¥å³å®å¨è¿ä»£è¿ç¨ä¸æä¾ä»ä¹ã
æ¤å½æ°å¯ä»¥æ¯æ®é彿°ï¼ä¹å¯ä»¥æ¯çæå¨å½æ°ï¼ä»¥ä¾¿å¨è°ç¨æ¶è¿åè¿ä»£å¨å¯¹è±¡ã卿¤çæå¨å½æ°çå
é¨ï¼å¯ä»¥ä½¿ç¨ yield
æä¾æ¯ä¸ªæ¡ç®ã
è¿ä»£å¨åè®®å®ä¹äºäº§çä¸ç³»åå¼ï¼æ è®ºæ¯æéä¸ªè¿æ¯æ é个ï¼çæ åæ¹å¼ï¼å½å¼ä¸ºæé个æ¶ï¼ææçå¼é½è¢«è¿ä»£å®æ¯åï¼åä¼è¿åä¸ä¸ªé»è®¤è¿åå¼ã
åªæå®ç°äºä¸ä¸ªæ¥æä»¥ä¸è¯ä¹ï¼semanticï¼ç next()
æ¹æ³ï¼ä¸ä¸ªå¯¹è±¡æè½æä¸ºè¿ä»£å¨ï¼
next()
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å符å 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)
å¯é
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å符å IteratorResult
æ¥å£ç对象ï¼å
¶ value
é常çä»·äºä¼ éç value
ï¼å¹¶ä¸ done
çäº true
ãè°ç¨è¿ä¸ªæ¹æ³è¡¨æè¿ä»£å¨çè°ç¨è
䏿ç®è°ç¨æ´å¤ç next()
ï¼å¹¶ä¸å¯ä»¥è¿è¡æ¸
çå·¥ä½ã
throw(exception)
å¯é
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å符å IteratorResult
æ¥å£ç对象ï¼é常 done
çäº true
ãè°ç¨è¿ä¸ªæ¹æ³è¡¨æè¿ä»£å¨çè°ç¨è
çæµå°é误çç¶åµï¼å¹¶ä¸ exception
é常æ¯ä¸ä¸ª Error
å®ä¾ã
夿³¨ï¼ æ æ³éè¿åå°çæ¹æ³ç¡®å®ï¼ä¾å¦ï¼æ²¡æå®é
è°ç¨ next()
å¹¶éªè¯è¿åçç»æï¼ä¸ä¸ªç¹å®ç对象æ¯å¦å®ç°äºè¿ä»£å¨åè®®ã
å¾å®¹æä½¿ä¸ä¸ªè¿ä»£å¨ä¹å¯è¿ä»£ï¼åªéå®ç° [Symbol.iterator]()
æ¹æ³ï¼å¹¶è¿åå®ç this
ã
// Satisfies both the Iterator Protocol and Iterable
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]() æ¹æ³è¿åèªèº«ï¼ä¸ä¸ªè¿ä»£å¨ï¼ï¼æä»¥å®æ¯ä¸ä¸ªå¯è¿ä»£çè¿ä»£å¨
ç¶èï¼å¯è½çæ
åµä¸ï¼iterable[Symbol.iterator]
æå¥½è¿åæ»æ¯ä»å¤´å¼å§çä¸åçè¿ä»£å¨ï¼å Set.prototype[Symbol.iterator]()
åç飿 ·ã
è¿æä¸å¯¹ç¨äºå¼æ¥è¿ä»£çåè®®ï¼å½åä¸ºå¼æ¥è¿ä»£å¨å弿¥å¯è¿ä»£åè®®ãå®ä»¬ä¸å¯è¿ä»£åè¿ä»£å¨åè®®æçéå¸¸ç±»ä¼¼çæ¥å£ï¼åªæ¯ä»è°ç¨è¿ä»£å¨æ¹æ³çæ¯ä¸ªè¿åå¼é½å è£ å¨ä¸ä¸ª promise ä¸ã
å½å¯¹è±¡å®ç°ä»¥ä¸æ¹æ³æ¶ï¼å®ä¼å®ç°å¼æ¥å¯è¿ä»£åè®®ï¼
[Symbol.asyncIterator]
è¿åå¯¹è±¡çæ åæ°å½æ°ï¼å¹¶ä¸ç¬¦å弿¥è¿ä»£å¨åè®®ã
å½å¯¹è±¡å®ç°ä»¥ä¸æ¹æ³æ¶ï¼å®ä¼å®ç°å¼æ¥è¿ä»£å¨åè®®ï¼
next()
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å promiseãpromise å
ç°ä¸ºä¸ä¸ªå¯¹è±¡ï¼è¯¥å¯¹è±¡ç¬¦å IteratorResult
æ¥å£ï¼å¹¶ä¸è¿äºå±æ§ä¸åæ¥è¿ä»£å¨æçç¸åçè¯ä¹ã
return(value)
å¯é
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å promiseãpromise å
ç°ä¸ºä¸ä¸ªå¯¹è±¡ï¼è¯¥å¯¹è±¡ç¬¦å IteratorResult
æ¥å£ï¼å¹¶ä¸è¿äºå±æ§ä¸åæ¥è¿ä»£å¨æçç¸åçè¯ä¹ã
throw(exception)
å¯é
æ åæ°æè
æ¥åä¸ä¸ªåæ°ç彿°ï¼å¹¶è¿å promiseãpromise å
ç°ä¸ºä¸ä¸ªå¯¹è±¡ï¼è¯¥å¯¹è±¡ç¬¦å IteratorResult
æ¥å£ï¼å¹¶ä¸è¿äºå±æ§ä¸åæ¥è¿ä»£å¨æçç¸åçè¯ä¹ã
JavaScript è¯è¨æå®äºäº§çæä½¿ç¨å¯è¿ä»£å¯¹è±¡åè¿ä»£å¨ç APIã
å ç½®çå¯è¿ä»£å¯¹è±¡String
ãArray
ãTypedArray
ãMap
ãSet
以å Intl.Segments
齿¯å
ç½®çå¯è¿ä»£å¯¹è±¡ï¼å 为å®ä»¬çæ¯ä¸ª prototype
对象é½å®ç°äº [Symbol.iterator]()
æ¹æ³ãæ¤å¤ï¼arguments
对象åä¸äº DOM éåç±»åï¼å¦ NodeList
乿¯å¯è¿ä»£çãç®åï¼æ²¡æå
ç½®ç弿¥å¯è¿ä»£å¯¹è±¡ã
çæå¨å½æ°è¿åçæå¨å¯¹è±¡ï¼å®ä»¬æ¯å¯è¿ä»£çè¿ä»£å¨ã弿¥çæå¨å½æ°è¿å弿¥çæå¨å¯¹è±¡ï¼å®ä»¬æ¯å¼æ¥å¯è¿ä»£çè¿ä»£å¨ã
ä»å
ç½®è¿ä»£è¿åçè¿ä»£å¨å®é
ä¸é½ç»§æ¿äºä¸ä¸ªå
Œ
±ç±»ï¼ç®åå°æªæ´é²ï¼ï¼è¯¥ç±»å®ç°äºä¸è¿° [Symbol.iterator]() { return this; }
æ¹æ³ï¼ä½¿å®ä»¬é½æ¯å¯è¿ä»£çè¿ä»£å¨ãå°æ¥ï¼é¤äºè¿ä»£å¨åè®®è¦æ±ç next()
æ¹æ³å¤ï¼è¿äºå
ç½®è¿ä»£å¨å¯è½è¿æå
¶ä»è¾
婿¹æ³ãä½ å¯ä»¥éè¿å¨å¾å½¢æ§å¶å°ä¸è®°å½è¿ä»£å¨çåå龿¥æ£æ¥å®ã
console.log([][Symbol.iterator]()); Array Iterator {} [[Prototype]]: Array Iterator ==> This is the prototype shared by all array iterators next: Æ next() Symbol(Symbol.toStringTag): "Array Iterator" [[Prototype]]: Object ==> This is the prototype shared by all built-in iterators Symbol(Symbol.iterator): Æ [Symbol.iterator]() [[Prototype]]: Object ==> This is 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"
å½å
ç½®è¯æ³è¿ä»£è¿ä»£å¨ï¼å¹¶ä¸æåçç»æä¸ 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 [b] = obj;
// Returning 1
// Closing
const [a, b, c] = obj;
// Returning 1
// Returning 2
// Returning 3
// Already reached the end (the last call returned `done: true`),
// so `return` is not called
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]()
æ¹æ³ä¸è½è¿åè¿ä»£å¨å¯¹è±¡ï¼é£ä¹å¯ä»¥è®¤ä¸ºå®æ¯ä¸ä¸ªä¸ç¬¦åæ åçï¼Non-well-formedï¼å¯è¿ä»£å¯¹è±¡ã
使ç¨è¿æ ·çå¯è¿ä»£å¯¹è±¡å¾å¯è½ä¼å¯¼è´å¦ä¸çè¿è¡æ¶å¼å¸¸ï¼æè ä¸å¯é¢æç表ç°ï¼
const nonWellFormedIterable = {};
nonWellFormedIterable[Symbol.iterator] = () => 1;
[...nonWellFormedIterable]; // TypeError: [Symbol.iterator]() returned a non-object value
ç¤ºä¾ èªå®ä¹å¯è¿ä»£å¯¹è±¡
ä½ å¯ä»¥åè¿æ ·å建èªå·±çå¯è¿ä»£å¯¹è±¡ï¼
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* makeSimpleGenerator(array) {
let nextIndex = 0;
while (nextIndex < array.length) {
yield array[nextIndex++];
}
}
const gen = makeSimpleGenerator(["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]() {
// Use a new index for each iterator. This makes multiple
// iterations over the iterable safe for non-trivial cases,
// such as use of break or nested looping over the same iterable.
let index = 0;
return {
// Note: using an arrow function allows `this` to point to the
// one of `[Symbol.iterator]()` instead of `next()`
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
çé»è®¤è¿ä»£å¨ä¼é个å°è¿åå符串ç代ç ç¹ï¼
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]()
éæ°å®ä¹è¿ä»£è¡ä¸ºï¼
// need to construct a String object explicitly to avoid auto-boxing
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"
åè§
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