{"id":16847421,"url":"https://github.com/othree/20k-for-of","last_synced_at":"2026-06-29T08:31:22.609Z","repository":{"id":66786588,"uuid":"72804873","full_name":"othree/20k-for-of","owner":"othree","description":"for...of is a very useful new syntax of ECMAScript 2015","archived":false,"fork":false,"pushed_at":"2016-11-08T04:42:45.000Z","size":55,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-22T06:04:59.615Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/othree.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-04T02:01:15.000Z","updated_at":"2016-11-07T10:36:38.000Z","dependencies_parsed_at":"2023-07-31T09:46:05.490Z","dependency_job_id":null,"html_url":"https://github.com/othree/20k-for-of","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/othree/20k-for-of","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/othree%2F20k-for-of","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/othree%2F20k-for-of/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/othree%2F20k-for-of/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/othree%2F20k-for-of/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/othree","download_url":"https://codeload.github.com/othree/20k-for-of/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/othree%2F20k-for-of/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34919882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T13:07:52.749Z","updated_at":"2026-06-29T08:31:22.572Z","avatar_url":"https://github.com/othree.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"20K for...of\n============\n\n[`for...of`][forof] is a very useful new syntax of ES2015. In the past, to iterate an array is like:\n\n```javascript\nvar arr = [1, 2, 3];\nvar i, v;\n\nfor (i in arr) {\n    v = arr[i];\n    console.log(v);\n}\n```\n\nBut now its much easier:\n\n```javascript\nvar arr = [1, 2, 3];\n\nfor (let v of arr) {\n    console.log(v);\n}\n```\n\nIn propduction environment. There are still lots of user agent only supports ES5. \nSo use of transpiler like [Babel][] is very popular. By Babel, the code transforms to:\n\n```javascript\n\"use strict\";\n\nvar arr = [1, 2, 3];\n\nvar _iteratorNormalCompletion = true;\nvar _didIteratorError = false;\nvar _iteratorError = undefined;\n\ntry {\n    for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n        var v = _step.value;\n\n        console.log(v);\n    }\n} catch (err) {\n    _didIteratorError = true;\n    _iteratorError = err;\n} finally {\n    try {\n        if (!_iteratorNormalCompletion \u0026\u0026 _iterator.return) {\n            _iterator.return();\n        }\n    } finally {\n        if (_didIteratorError) {\n            throw _iteratorError;\n        }\n    }\n}\n```\n\nIt depends on the iterator defined in ECMAScript 2015.\nAnd Babel have [babel-polyfill][] to provide iterator.\nBut the size of babel-polyfill is very huge.\nNormal size is 228KB and minimized size is 95KB.\nSo how about only import what we really need?\nThere is a plugin called [transform-runtime][] can do this.\nThe code will now transform to:\n\n[babel-polyfill]:https://babeljs.io/docs/usage/polyfill/\n[transform-runtime]:https://babeljs.io/docs/plugins/transform-runtime/\n\n```javascript\nimport _getIterator from \"babel-runtime/core-js/get-iterator\";\nvar arr = [1, 2, 3];\n\nvar _iteratorNormalCompletion = true;\nvar _didIteratorError = false;\nvar _iteratorError = undefined;\n\ntry {\n  for (var _iterator = _getIterator(arr), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n    var v = _step.value;\n\n    console.log(v);\n  }\n} catch (err) {\n  _didIteratorError = true;\n  _iteratorError = err;\n} finally {\n  try {\n    if (!_iteratorNormalCompletion \u0026\u0026 _iterator.return) {\n      _iterator.return();\n    }\n  } finally {\n    if (_didIteratorError) {\n      throw _iteratorError;\n    }\n  }\n}\n```\n\nThere is an import statement on the top:\n\n```javascript\nimport _getIterator from \"babel-runtime/core-js/get-iterator\";\n```\n\nThen we use [rollup][] to do module bundle with two plugins:\n\n* [rollup-plugin-node-resolve][] to find module in `node_modules`\n* [rollup-plugin-commonjs][] to recognize CommonJS module (node style module)\n\nAnd following configure:\n\n```javascript\nbabel({\n  exclude: 'node_modules/**',\n  plugins: ['transform-runtime'],\n  presets: ['es2015-loose-rollup'],\n  runtimeHelpers: true\n}),\nnodeResolve({ jsnext: true }),\ncommonjs({\n  include: 'node_modules/**'\n})\n```\n\nWe will get a [20KB file][bundle-all]. Compare to the original code (72Bytes).\nThis is still too large. So, is ther any solution for this?\n\nYes, we have other options.\nFirst is [TypeScript][]. \nTypeScript transform for...of loop to for...in loop if the target language is *ES3* or *ES5*.\n\nThe second is [Bublé][buble].\nBublé is another transpiler transform ES2015 to ES5. Build by the author of Rollup, Rich Harris.\nThe philosophy of Bublé is only do simple, straight forward transform.\nSo for...of loop will transform to a simple for...in loop.\n\nOf course these two solution have their disadvantages.\nFor example, you can't use for...of on Map, Set...etc.\nBublé [don't support][buble-async] `async`, `await`.\nTypeScript only supports `async`, `await` when [target is ES6][ts-async] (but in [2.1 roadmap][ts-2.1]).\n\n\n[rollup]:http://rollupjs.org/\n[rollup-plugin-node-resolve]:https://github.com/rollup/rollup-plugin-node-resolve\n[rollup-plugin-commonjs]:https://github.com/rollup/rollup-plugin-commonjs\n\n[bundle-all]:https://github.com/othree/20k-for-of/blob/master/out/bundle-all.js\n\n[forof]:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of\n[Babel]:https://babeljs.io/\n\n[TypeScript]:https://www.typescriptlang.org/\n[ts-ite]:https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html#targeting-es5-and-es3\n\n[buble]:https://buble.surge.sh/\n[buble-async]:https://gitlab.com/Rich-Harris/buble/issues/71\n[ts-async]:https://www.typescriptlang.org/docs/release-notes/typescript-1.7.html\n[ts-2.1]:https://github.com/Microsoft/TypeScript/wiki/Roadmap#21-november-2016\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fothree%2F20k-for-of","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fothree%2F20k-for-of","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fothree%2F20k-for-of/lists"}