-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.json
1 lines (1 loc) · 343 KB
/
db.json
1
{"meta":{"version":1,"warehouse":"4.0.0"},"models":{"Asset":[{"_id":"themes/hexo-theme-matery/source/favicon.png","path":"favicon.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/css/bb.css","path":"css/bb.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/css/gitment.css","path":"css/gitment.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/css/matery.css","path":"css/matery.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/css/my-gitalk.css","path":"css/my-gitalk.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/css/my.css","path":"css/my.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/js/matery.js","path":"js/matery.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/js/search.js","path":"js/search.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/avatar.jpg","path":"medias/avatar.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/comment_bg.png","path":"medias/comment_bg.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/cover.jpg","path":"medias/cover.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/icp.png","path":"medias/icp.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/logo.png","path":"medias/logo.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/animate/animate.min.css","path":"libs/animate/animate.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/aos/aos.css","path":"libs/aos/aos.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/aos/aos.js","path":"libs/aos/aos.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/aplayer/APlayer.min.js","path":"libs/aplayer/APlayer.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/aplayer/APlayer.min.css","path":"libs/aplayer/APlayer.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/background/canvas-nest.js","path":"libs/background/canvas-nest.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon-dynamic.js","path":"libs/background/ribbon-dynamic.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon.min.js","path":"libs/background/ribbon.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon-refresh.min.js","path":"libs/background/ribbon-refresh.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeBlockFuction.js","path":"libs/codeBlock/codeBlockFuction.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeLang.js","path":"libs/codeBlock/codeLang.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeCopy.js","path":"libs/codeBlock/codeCopy.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeShrink.js","path":"libs/codeBlock/codeShrink.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/cryptojs/crypto-js.min.js","path":"libs/cryptojs/crypto-js.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/dplayer/DPlayer.min.css","path":"libs/dplayer/DPlayer.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/dplayer/DPlayer.min.js","path":"libs/dplayer/DPlayer.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/echarts/echarts.min.js","path":"libs/echarts/echarts.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/gitalk/gitalk.css","path":"libs/gitalk/gitalk.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/gitalk/gitalk.min.js","path":"libs/gitalk/gitalk.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/gitment/gitment-default.css","path":"libs/gitment/gitment-default.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/gitment/gitment.js","path":"libs/gitment/gitment.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/jqcloud/jqcloud-1.0.4.min.js","path":"libs/jqcloud/jqcloud-1.0.4.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/instantpage/instantpage.js","path":"libs/instantpage/instantpage.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/jqcloud/jqcloud.css","path":"libs/jqcloud/jqcloud.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/jquery/jquery.min.js","path":"libs/jquery/jquery.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/masonry/masonry.pkgd.min.js","path":"libs/masonry/masonry.pkgd.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/materialize/materialize.min.js","path":"libs/materialize/materialize.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/materialize/materialize.min.css","path":"libs/materialize/materialize.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/minivaline/MiniValine.js","path":"libs/minivaline/MiniValine.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/others/clicklove.js","path":"libs/others/clicklove.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/others/busuanzi.pure.mini.js","path":"libs/others/busuanzi.pure.mini.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/prism/prism.css","path":"libs/prism/prism.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/scrollprogress/scrollProgress.min.js","path":"libs/scrollprogress/scrollProgress.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/tocbot/tocbot.css","path":"libs/tocbot/tocbot.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/tocbot/tocbot.min.js","path":"libs/tocbot/tocbot.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/twikoo/twikoo.all.min.js","path":"libs/twikoo/twikoo.all.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/valine/Valine.min.js","path":"libs/valine/Valine.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/twikoo/twikoo.all.min.js.LICENSE.txt","path":"libs/twikoo/twikoo.all.min.js.LICENSE.txt","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/valine/av-min.js","path":"libs/valine/av-min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/0.jpg","path":"medias/banner/0.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/1.jpg","path":"medias/banner/1.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/2.jpg","path":"medias/banner/2.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/3.jpg","path":"medias/banner/3.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/4.jpg","path":"medias/banner/4.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/5.jpg","path":"medias/banner/5.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/6.jpg","path":"medias/banner/6.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/banner/back.jpeg","path":"medias/banner/back.jpeg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/0.jpg","path":"medias/featureimages/0.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/1.jpg","path":"medias/featureimages/1.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/10.jpg","path":"medias/featureimages/10.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/12.jpg","path":"medias/featureimages/12.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/11.jpg","path":"medias/featureimages/11.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/13.jpg","path":"medias/featureimages/13.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/14.jpg","path":"medias/featureimages/14.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/15.jpg","path":"medias/featureimages/15.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/16.jpg","path":"medias/featureimages/16.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/17.jpg","path":"medias/featureimages/17.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/18.jpg","path":"medias/featureimages/18.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/19.jpg","path":"medias/featureimages/19.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/2.jpg","path":"medias/featureimages/2.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/20.jpg","path":"medias/featureimages/20.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/21.jpg","path":"medias/featureimages/21.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/22.jpg","path":"medias/featureimages/22.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/23.jpg","path":"medias/featureimages/23.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/3.jpg","path":"medias/featureimages/3.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/4.jpg","path":"medias/featureimages/4.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/5.jpg","path":"medias/featureimages/5.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/6.jpg","path":"medias/featureimages/6.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/7.jpg","path":"medias/featureimages/7.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/8.jpg","path":"medias/featureimages/8.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/9.jpg","path":"medias/featureimages/9.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/reward/alipay.jpg","path":"medias/reward/alipay.jpg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/medias/reward/wechat.png","path":"medias/reward/wechat.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.svg","path":"libs/awesome/webfonts/fa-brands-400.svg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.eot","path":"libs/awesome/webfonts/fa-brands-400.eot","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.ttf","path":"libs/awesome/webfonts/fa-brands-400.ttf","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.woff","path":"libs/awesome/webfonts/fa-brands-400.woff","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.woff2","path":"libs/awesome/webfonts/fa-brands-400.woff2","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.eot","path":"libs/awesome/webfonts/fa-regular-400.eot","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.svg","path":"libs/awesome/webfonts/fa-regular-400.svg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.ttf","path":"libs/awesome/webfonts/fa-regular-400.ttf","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.woff","path":"libs/awesome/webfonts/fa-regular-400.woff","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.woff2","path":"libs/awesome/webfonts/fa-regular-400.woff2","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.eot","path":"libs/awesome/webfonts/fa-solid-900.eot","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.svg","path":"libs/awesome/webfonts/fa-solid-900.svg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.ttf","path":"libs/awesome/webfonts/fa-solid-900.ttf","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.woff","path":"libs/awesome/webfonts/fa-solid-900.woff","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.woff2","path":"libs/awesome/webfonts/fa-solid-900.woff2","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/awesome/css/all.css","path":"libs/awesome/css/all.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/css/lightgallery.min.css","path":"libs/lightGallery/css/lightgallery.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.eot","path":"libs/lightGallery/fonts/lg.eot","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.svg","path":"libs/lightGallery/fonts/lg.svg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.ttf","path":"libs/lightGallery/fonts/lg.ttf","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.woff","path":"libs/lightGallery/fonts/lg.woff","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/loading.gif","path":"libs/lightGallery/img/loading.gif","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/video-play.png","path":"libs/lightGallery/img/video-play.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/vimeo-play.png","path":"libs/lightGallery/img/vimeo-play.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/youtube-play.png","path":"libs/lightGallery/img/youtube-play.png","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/js/lightgallery-all.min.js","path":"libs/lightGallery/js/lightgallery-all.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/css/share.min.css","path":"libs/share/css/share.min.css","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.eot","path":"libs/share/fonts/iconfont.eot","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.svg","path":"libs/share/fonts/iconfont.svg","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.ttf","path":"libs/share/fonts/iconfont.ttf","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.woff","path":"libs/share/fonts/iconfont.woff","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/js/jquery.share.min.js","path":"libs/share/js/jquery.share.min.js","modified":0,"renderable":1},{"_id":"themes/hexo-theme-matery/source/libs/share/js/social-share.min.js","path":"libs/share/js/social-share.min.js","modified":0,"renderable":1}],"Cache":[{"_id":"source/about/index.md","hash":"1502da56df4298f84bbb6f6df081909123fdaa83","modified":1614658526924},{"_id":"source/categories/index-1.md","hash":"771569e6ded71d11a6cb0a527a3ac0dba9f89112","modified":1614658493713},{"_id":"source/_posts/hello-world.md","hash":"67443df10896f957c584971c882998736873c17a","modified":1614339695134},{"_id":"source/categories/index.md","hash":"25c2d9229b269315c28bc2c1900e9343c2d2e44f","modified":1614658396385},{"_id":"source/tags/index.md","hash":"e6cfaec36f35e7f1ebf3a2df0df754f21cfed5a5","modified":1614658514027},{"_id":"source/_posts/lodash.md","hash":"55f24fb566e293bd8a65ac6662d87db1890bed75","modified":1614339199417},{"_id":"source/_posts/basic/02-http&https.md","hash":"4f0e429e58c22e794f394a433c48650654f9dc87","modified":1615293449522},{"_id":"source/_posts/es6/01-let&const.md","hash":"b3c2eb52f9cf37e6148a61f2088eab0d794dcdb6","modified":1616641138010},{"_id":"source/_posts/es6/02-Destructuring.md","hash":"658815bb542ce24680aba47a67df7ed88cc5d604","modified":1616655482819},{"_id":"source/_posts/js_basic/01-basic-info.md","hash":"78371ba97bac345bab31d63fc80e83b4de106521","modified":1615520198809},{"_id":"source/_posts/js_basic/02-js-copy.md","hash":"29d06c7c64a260810054a81b979b074bab346bd3","modified":1614666772630},{"_id":"source/_posts/nodejs/01-Node简介.md","hash":"21f58c7578c43fd67735d5a606fb0f681ce8aa6a","modified":1614666772633},{"_id":"source/_posts/js_basic/03-js-gc.md","hash":"915a0e1d16d5c14d0e1ab3f3c18aca23dc56d5f3","modified":1614925255155},{"_id":"themes/hexo-theme-matery/CHANGELOG.md","hash":"084ec8b110a20170d08a0aa5fd8accf601051835","modified":1614657196041},{"_id":"themes/hexo-theme-matery/.gitignore","hash":"727607929a51db7ea10968f547c26041eee9cfff","modified":1614657196041},{"_id":"themes/hexo-theme-matery/LICENSE","hash":"7df059597099bb7dcf25d2a9aedfaf4465f72d8d","modified":1614657196041},{"_id":"themes/hexo-theme-matery/README.md","hash":"0366f3d50b18d095b0581e7b5974e3283d693884","modified":1614657196042},{"_id":"themes/hexo-theme-matery/README_CN.md","hash":"a1e060bb4cf2ccca5cad12d02cc3c37f8028fdfb","modified":1614657196042},{"_id":"themes/hexo-theme-matery/languages/default.yml","hash":"54ccc01b097c5bf6820f0edfcece1a87b78ab32d","modified":1614657196042},{"_id":"source/_posts/basic/img.png","hash":"3c7b80b0235bdaa41984dccc6e54bded88601eca","modified":1615293290676},{"_id":"themes/hexo-theme-matery/languages/zh-HK.yml","hash":"ae34ac0e175c3037675722e436637efbceea32f0","modified":1614657196043},{"_id":"themes/hexo-theme-matery/languages/zh-CN.yml","hash":"a957b05f70265a86a87d922e18488571809d2472","modified":1614657196043},{"_id":"themes/hexo-theme-matery/_config.yml","hash":"9325eabccc0343414e2b05f1a6518fa11c32cd26","modified":1616674576810},{"_id":"themes/hexo-theme-matery/layout/404.ejs","hash":"9c8ca67377211e5d60fdde272a975faa9a91a22a","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/about.ejs","hash":"99a74316aed478efb0db823c4460ee2e660f101c","modified":1614657196050},{"_id":"themes/hexo-theme-matery/layout/archive.ejs","hash":"cdac701de8370f9f3794a0eed4165983993a1ca7","modified":1614657196050},{"_id":"themes/hexo-theme-matery/layout/bb.ejs","hash":"21959d702f17a3d98b716daf44c8b5eecd59c7c5","modified":1614657196050},{"_id":"themes/hexo-theme-matery/layout/categories.ejs","hash":"8e54665cc25d7c333da7d9f312987190be6215da","modified":1614657196050},{"_id":"themes/hexo-theme-matery/layout/contact.ejs","hash":"cff60f87f69155707f3a33731c7fac945cf7cd93","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/friends.ejs","hash":"51e5369ec6b017cc702a8d957fc052c59dd4c3d7","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/category.ejs","hash":"00019bca11fb46477f22017cb1f5ad8444da0580","modified":1614657196050},{"_id":"themes/hexo-theme-matery/layout/index.ejs","hash":"4dc6f08e7709cc04e886be72dbf0d06469f0effc","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/layout.ejs","hash":"4bfb9e946a90724fc8a902efe404c7b20549a38c","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/post.ejs","hash":"90b5a4c1f70e4756db569c15a7c6cad0c77c4500","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/tag.ejs","hash":"85a4b05bd8a6ad0f17ff2e97dae56949b379c204","modified":1614657196051},{"_id":"themes/hexo-theme-matery/layout/tags.ejs","hash":"cf9517aa6a0111355121f44615d6923e312283c7","modified":1614657196052},{"_id":"themes/hexo-theme-matery/source/favicon.png","hash":"774fee8c6d0be9dbb010b20f36c06848d06e3da0","modified":1614657196053},{"_id":"themes/hexo-theme-matery/layout/_partial/back-top.ejs","hash":"47ee36a042bb6d52bbe1d0f329637e8ffcf1d0aa","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/_partial/background.ejs","hash":"aef6edeeb11209831a11d8c7f5d59992e2573335","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/_partial/baidu-analytics.ejs","hash":"3bbcdb474ca1dcad514bdc4b7763e17c55df04fd","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/_partial/bg-cover-content.ejs","hash":"a8d171a8f075695e4816eb8f4dfe2cd35bf2cb48","modified":1616673736760},{"_id":"themes/hexo-theme-matery/layout/_partial/baidu-push.ejs","hash":"2cebcc5ea3614d7f76ec36670e68050cbe611202","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/_partial/bg-cover.ejs","hash":"02191109712f61c0e487b8f0b8466597181a9004","modified":1614657196043},{"_id":"themes/hexo-theme-matery/layout/_partial/changyan.ejs","hash":"cd919d31564e118c2ee8d5cbfb7d51ee6da15d82","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/disqus.ejs","hash":"b2dc2c8b5ed56815e55cc2ea54a6dc4eeba2375d","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/footer.ejs","hash":"3be24e4c370671eda53bdfd99fb748f4a22948ba","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/github-link.ejs","hash":"3aeb581bd78ab8e15b858e4c44c03bcf92f20b9e","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/gitalk.ejs","hash":"2aa8fbb04b046fa7679092a48372d7e036835dff","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/gitment.ejs","hash":"90f6218512ef2eab63ada7ad2fc766ae635a2297","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/google-analytics.ejs","hash":"5f4992205617da5f8cc5863c62b5ec46e414e2fb","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/head.ejs","hash":"f8438ac80df005934a330b029de292d26f0b6ecb","modified":1614657196044},{"_id":"themes/hexo-theme-matery/layout/_partial/header.ejs","hash":"59e38c70f3d8e7165e686e5e84a627835f4321b0","modified":1614657196045},{"_id":"themes/hexo-theme-matery/layout/_partial/livere.ejs","hash":"9c3401b42ea7f26410a5593bae93ada7e57b43be","modified":1614657196045},{"_id":"themes/hexo-theme-matery/layout/_partial/index-cover.ejs","hash":"58d0a48335e90804e648cc45114728d5744f68c5","modified":1616750528110},{"_id":"themes/hexo-theme-matery/layout/_partial/minivaline.ejs","hash":"738b83cd90fe1b26971d803fc89c56193323da1e","modified":1614657196045},{"_id":"themes/hexo-theme-matery/layout/_partial/mobile-nav.ejs","hash":"cb0cb452be1cd1857ba600f04025b506f3b6fc79","modified":1614657196045},{"_id":"themes/hexo-theme-matery/layout/_partial/navigation.ejs","hash":"78b70ff24b3039c871331ebec114b936c1756cc8","modified":1614657196045},{"_id":"themes/hexo-theme-matery/layout/_partial/paging.ejs","hash":"e2df12cf92a82b1a7a7add2eac1db1d954bc5511","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/post-cover.ejs","hash":"d1c873c5de54498c722e155aadb8c0ec39485dfa","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/post-detail-toc.ejs","hash":"3ff94aff01936242a9f4e1f31adb9b43bfab8d53","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/post-detail.ejs","hash":"7933979c2092654a9c1038ff30495505d7d88f2d","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/post-statis.ejs","hash":"04889f9031743c6b081d02fa4027b0dbfcc45ecf","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/prev-next.ejs","hash":"c76b78782ea82340104fccc089417572e0adece4","modified":1614657196046},{"_id":"themes/hexo-theme-matery/layout/_partial/reprint-statement.ejs","hash":"0ce3f9361f558b99cc2f059c5e50b0e2a152ae38","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/reward.ejs","hash":"ffc55bc7e73bc698bfc58d8e3780c336b83282cf","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/share.ejs","hash":"c941730a2471d6aab367cbb6e09ed08b56c83143","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/search.ejs","hash":"150529c9fb9aa8ddb42ec3e02645d301faa2503b","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/social-link.ejs","hash":"6f871bd3a70f720e4e451f1f4f625cbc6d8994a4","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/twikoo.ejs","hash":"f9cb8c82b9d2a7cdb644e10718f1cdeb9400414c","modified":1614657196047},{"_id":"themes/hexo-theme-matery/layout/_partial/valine.ejs","hash":"045f3aaade1dc6749a1f824b0405b5fdb9e041e4","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/artitalk.ejs","hash":"b14e486f12b9ac42a273b80e4d785fcb94cf04b2","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/category-cloud.ejs","hash":"1b3df1009234c0112424b497b18b4ad8240b3bc7","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/category-radar.ejs","hash":"1d8747fda89a0b2ca3c7008867cbfeecad0578a6","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/dream.ejs","hash":"9a472ad5591100cdb65d0df9d01034163bd6dd9d","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/music.ejs","hash":"e9e3e327d5de9d7aeadbde32e1d558652d9e9195","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/my-gallery.ejs","hash":"65a2d2f9722f84c7fd98f6bdf79087a14848ebd8","modified":1614657196048},{"_id":"themes/hexo-theme-matery/layout/_widget/my-projects.ejs","hash":"ef60b64021fa349b0048425d858dfcf6c906fede","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/my-skills.ejs","hash":"89a0092df72d23093128f2fbbdc8ca7f83ebcfd9","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/post-calendar.ejs","hash":"48821e644bc73553d7c5c56d2e8ee111a70cd776","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/post-charts.ejs","hash":"ab5f986f428215941aeaa0c88aefd440c47d3bcf","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/recommend.ejs","hash":"8551137e94ca4e2e3b8b63d5626255884cb60cb5","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/tag-cloud.ejs","hash":"fc42b72cddc231f7485cdc1fd6852b66be6add26","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/tag-wordcloud.ejs","hash":"487aacb2454d6bf0d21cdb07ddd1fd5ddbca9038","modified":1614657196049},{"_id":"themes/hexo-theme-matery/layout/_widget/video.ejs","hash":"a0e002377af2a7f7e4da6d9a644de97adb035925","modified":1614657196050},{"_id":"themes/hexo-theme-matery/source/css/bb.css","hash":"aa15633888c7cf9baea8bb48d796c68b57cf14bf","modified":1616750225192},{"_id":"themes/hexo-theme-matery/source/css/gitment.css","hash":"2bd15cc17dca35ac3ecc0acf167a23a1dd362acd","modified":1614657196052},{"_id":"themes/hexo-theme-matery/source/css/matery.css","hash":"7230bdfb88d2c2c22091ff6da704d073129ca09e","modified":1616674459548},{"_id":"themes/hexo-theme-matery/source/css/my-gitalk.css","hash":"af18dd29e58642c18bab9b89541767b494c468dd","modified":1614657196053},{"_id":"themes/hexo-theme-matery/source/js/matery.js","hash":"b86de5fe3e9766b7ff80df12ea41c3a9e30825f7","modified":1614657196053},{"_id":"themes/hexo-theme-matery/source/css/my.css","hash":"497e50351f7838f8546cac76850a42e7e380a110","modified":1614657196053},{"_id":"themes/hexo-theme-matery/source/js/search.js","hash":"e1482406c58ea2a0eb178d7e4efb2c879cdddc80","modified":1614657196053},{"_id":"themes/hexo-theme-matery/source/medias/avatar.jpg","hash":"2a6287308628881ce27b9a7de53ba15c2be00d02","modified":1614657196099},{"_id":"themes/hexo-theme-matery/source/medias/comment_bg.png","hash":"dfc93d24081884fbc58cab0f8fd19e77d31d6123","modified":1614657196105},{"_id":"themes/hexo-theme-matery/source/medias/icp.png","hash":"27a96f31f7d0413c6ade6f40e06f021f501151c7","modified":1614657196115},{"_id":"themes/hexo-theme-matery/source/medias/logo.png","hash":"d9095f5ea8719374d9d1ff020279426f5b2a1396","modified":1614657196115},{"_id":"themes/hexo-theme-matery/source/libs/animate/animate.min.css","hash":"97afa151569f046b2e01f27c1871646e9cd87caf","modified":1614657196054},{"_id":"themes/hexo-theme-matery/source/libs/aos/aos.css","hash":"191a3705a8f63e589a50a0ff2f2c5559f1a1b6b2","modified":1614657196054},{"_id":"themes/hexo-theme-matery/source/libs/aos/aos.js","hash":"02bfb40b0c4b6e9b0b4081218357145cbb327d74","modified":1614657196054},{"_id":"themes/hexo-theme-matery/source/libs/aplayer/APlayer.min.js","hash":"22caa28ff6b41a16ff40f15d38f1739e22359478","modified":1614657196055},{"_id":"themes/hexo-theme-matery/source/libs/aplayer/APlayer.min.css","hash":"07372a2ba507388d0fed166d761b1c2c2a659dce","modified":1614657196055},{"_id":"themes/hexo-theme-matery/source/libs/background/canvas-nest.js","hash":"65333d0dbb9c1173a1b13031b230161fc42c8b2f","modified":1614657196074},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon-dynamic.js","hash":"052b80c29e6bc585aa28d4504b743bdbac220a88","modified":1614657196075},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon.min.js","hash":"6a99d494c030388f96f6086a7aaa0f03f3fe532e","modified":1614657196075},{"_id":"themes/hexo-theme-matery/source/libs/background/ribbon-refresh.min.js","hash":"6d98692b2cad8c746a562db18b170b35c24402f4","modified":1614657196075},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeBlockFuction.js","hash":"c7ab06d27a525b15b1eb69027135269e9b9132fb","modified":1614657196075},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeLang.js","hash":"bac88b4d4e3679732d29bd037c34f089cf27cf05","modified":1614657196076},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeCopy.js","hash":"6d39a766af62e625f177c4d5cf3adc35eed71e61","modified":1614657196075},{"_id":"themes/hexo-theme-matery/source/libs/codeBlock/codeShrink.js","hash":"201e8cd761b4be557247bdaf1ebc7c11c83194f6","modified":1614657196076},{"_id":"themes/hexo-theme-matery/source/libs/cryptojs/crypto-js.min.js","hash":"5989527a378b55011a59522f41eeb3981518325c","modified":1614657196076},{"_id":"themes/hexo-theme-matery/source/libs/dplayer/DPlayer.min.css","hash":"f7d19655f873b813ffba5d1a17145c91f82631b8","modified":1614657196076},{"_id":"themes/hexo-theme-matery/source/libs/gitalk/gitalk.css","hash":"940ded3ea12c2fe1ab0820d2831ec405f3f1fe9f","modified":1614657196082},{"_id":"themes/hexo-theme-matery/source/libs/gitment/gitment-default.css","hash":"2903c59ee06b965bef32e937bd69f5b0b2190717","modified":1614657196083},{"_id":"themes/hexo-theme-matery/source/libs/jqcloud/jqcloud-1.0.4.min.js","hash":"257eaae3020599e4939f50d5008a743827f25b8c","modified":1614657196084},{"_id":"themes/hexo-theme-matery/source/libs/instantpage/instantpage.js","hash":"83ce8919b1a69b2f1809ffaf99b52a8627e650e9","modified":1614657196084},{"_id":"themes/hexo-theme-matery/source/libs/jqcloud/jqcloud.css","hash":"20d9f11a19d95c70e27cb922e0d6dccbec4eae89","modified":1614657196085},{"_id":"themes/hexo-theme-matery/source/libs/masonry/masonry.pkgd.min.js","hash":"ff940b4ea68368ca0e4d5560cbb79fb147dfc3c5","modified":1614657196088},{"_id":"themes/hexo-theme-matery/source/libs/minivaline/MiniValine.js","hash":"f7f6cdc1b22297e02334e304444e9a8351acb455","modified":1614657196091},{"_id":"themes/hexo-theme-matery/source/libs/others/clicklove.js","hash":"6a39b8c683ba5dcd92f70c6ab45d1cfac3213e8e","modified":1614657196091},{"_id":"themes/hexo-theme-matery/source/libs/others/busuanzi.pure.mini.js","hash":"6e41f31100ae7eb3a6f23f2c168f6dd56e7f7a9a","modified":1614657196091},{"_id":"themes/hexo-theme-matery/source/libs/prism/prism.css","hash":"62e5474893dece076534352f564ceabd6e088a5a","modified":1614657196091},{"_id":"themes/hexo-theme-matery/source/libs/scrollprogress/scrollProgress.min.js","hash":"777ffe5d07e85a14fbe97d846f45ffc0087251cc","modified":1614657196092},{"_id":"themes/hexo-theme-matery/source/libs/tocbot/tocbot.css","hash":"9ab8ef576c9a57115194152e79cca79b0a41dd70","modified":1614657196094},{"_id":"themes/hexo-theme-matery/source/libs/tocbot/tocbot.min.js","hash":"5ec27317f0270b8cf6b884c6f12025700b9a565c","modified":1614657196094},{"_id":"themes/hexo-theme-matery/source/libs/twikoo/twikoo.all.min.js.LICENSE.txt","hash":"1e286a31ef472fb864fe2b9502e87df9242df56b","modified":1614657196097},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/10.jpg","hash":"98e7f6fd9c97d4de9044b6871ca08ebf14db11b9","modified":1614657196106},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/13.jpg","hash":"35a320174f8e316e3eadaec658024276b651c6e9","modified":1614657196108},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/15.jpg","hash":"da0fbee3b7bde1607eace377ddf834c0be99edfe","modified":1614657196108},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/16.jpg","hash":"97a829c4bc94f9d2929b20a1a9b798c57b9f7205","modified":1614657196109},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/2.jpg","hash":"4bba691cf71a517ecaeaf42afd3e8f8b31e346c1","modified":1614657196110},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/21.jpg","hash":"b26edb128bb0bf58b23fd2f014e9555e89a2ca3b","modified":1614657196111},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/22.jpg","hash":"754579747a3e99747d890fca3162f370b96a7941","modified":1614657196112},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/23.jpg","hash":"7d7f37da3fa7128343adac23866449eb2c6a549a","modified":1614657196112},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/3.jpg","hash":"6ec646c2a70f5f11edacf225c1477f2200a37a96","modified":1614657196112},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/5.jpg","hash":"41ca20129a37fedc573eec28dd7d7b9e5b09228a","modified":1614657196113},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/7.jpg","hash":"7975141cd64e875122c0ea33daaca1a06bf00b8e","modified":1614657196114},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/8.jpg","hash":"8e4b7186352085483ca1174c7c0800114c48df8b","modified":1614657196114},{"_id":"themes/hexo-theme-matery/source/medias/reward/alipay.jpg","hash":"1abc719b95d1b26f1f898e6b0a9b7609146e332f","modified":1614657196115},{"_id":"themes/hexo-theme-matery/source/medias/reward/wechat.png","hash":"fe93385aa92fe328e01c8221a80b039be9e4e140","modified":1614657196116},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.eot","hash":"439c8afd3373acb4a73135a34e220464a89cd5e2","modified":1614657196064},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.ttf","hash":"0f4bd02942a54a6b3200d9078adff88c2812e751","modified":1614657196065},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.woff","hash":"59439d3ad31d856d78ec3e2bd9f1eafa2c7a581c","modified":1614657196065},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.woff2","hash":"f6f653b4ea8fc487bdb590d39d5a726258a55f40","modified":1614657196066},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/css/lightgallery.min.css","hash":"1b7227237f9785c66062a4811508916518e4132c","modified":1614657196086},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.eot","hash":"54caf05a81e33d7bf04f2e420736ce6f1de5f936","modified":1614657196086},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.svg","hash":"9c6632aeec67d3e84a1434884aa801514ff8103b","modified":1614657196086},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.ttf","hash":"f6421c0c397311ae09f9257aa58bcd5e9720f493","modified":1614657196086},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/fonts/lg.woff","hash":"3048de344dd5cad4624e0127e58eaae4b576f574","modified":1614657196086},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/loading.gif","hash":"15a76af2739482d8de7354abc6d8dc4fca8d145e","modified":1614657196087},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/video-play.png","hash":"2962e03ddbe04d7e201a5acccac531a2bbccddfc","modified":1614657196087},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/vimeo-play.png","hash":"9b72fc0f86a01467ed0b68c9cc4d604ec316d517","modified":1614657196087},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/img/youtube-play.png","hash":"f8d11384d33b7a79ee2ba8d522844f14d5067a80","modified":1614657196087},{"_id":"themes/hexo-theme-matery/source/libs/lightGallery/js/lightgallery-all.min.js","hash":"9f5ef4bc8a0a3c746ca4f3c3e6d64493b1a977d8","modified":1614657196088},{"_id":"themes/hexo-theme-matery/source/libs/share/css/share.min.css","hash":"8a778a86f3ce9a042df6be63a9f1039631e351a5","modified":1614657196092},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.eot","hash":"00ff749c8e202401190cc98d56087cdda716abe4","modified":1614657196092},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.svg","hash":"1d56c9d5db0273f07c43cc1397e440f98ba7827a","modified":1614657196092},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.ttf","hash":"afd898f59d363887418669520b24d175f966a083","modified":1614657196093},{"_id":"themes/hexo-theme-matery/source/libs/share/fonts/iconfont.woff","hash":"2e3fce1dcfbd6e2114e7bfbeaf72d3c62e15a1bd","modified":1614657196093},{"_id":"themes/hexo-theme-matery/source/libs/share/js/jquery.share.min.js","hash":"41367dcb857e02e3c417ebe68a554ce1d4430806","modified":1614657196093},{"_id":"themes/hexo-theme-matery/source/libs/share/js/social-share.min.js","hash":"a3090a02786dcd4efc6355c1c1dc978add8d6827","modified":1614657196094},{"_id":"themes/hexo-theme-matery/source/libs/dplayer/DPlayer.min.js","hash":"c3bad7b265574fab0ae4d45867422ea1cb9d6599","modified":1614657196077},{"_id":"themes/hexo-theme-matery/source/libs/gitment/gitment.js","hash":"28c02c45ce568e084cd1041dc493f83f9c6c88c6","modified":1614657196084},{"_id":"themes/hexo-theme-matery/source/libs/jquery/jquery.min.js","hash":"2115753ca5fb7032aec498db7bb5dca624dbe6be","modified":1614657196085},{"_id":"themes/hexo-theme-matery/source/libs/valine/Valine.min.js","hash":"6cbdbf91e1f046dd41267a5ff0691a1fccba99df","modified":1614657196098},{"_id":"themes/hexo-theme-matery/source/medias/banner/0.jpg","hash":"69ec96cd9b4bc3aa631adc9da61353f50c39f031","modified":1614657196100},{"_id":"themes/hexo-theme-matery/source/medias/banner/2.jpg","hash":"39fb2535460ce66cc0b34e07ffb9411db1405f09","modified":1614657196101},{"_id":"themes/hexo-theme-matery/source/medias/banner/3.jpg","hash":"4ac047e92d0363b1a61ab756aca6dac13fb77494","modified":1614657196102},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/0.jpg","hash":"1c3300f029fc85d6dda6fa4f1d699551034cdaf7","modified":1614657196106},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/1.jpg","hash":"684ae89de8cb7acefae19f5aee6c612037c46393","modified":1614657196106},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/12.jpg","hash":"8a4b2e7d92ae95c3b0c921db23c35aa9a41a7d58","modified":1614657196107},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/11.jpg","hash":"f55972ce7175684f2b11c3c9fc2b5b14bccbfae8","modified":1614657196107},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/14.jpg","hash":"38e11221406785bcd93aa9cd23e568e164630ef1","modified":1614657196108},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/17.jpg","hash":"42d47903551ee81885c1386022982cae165841c5","modified":1614657196109},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/18.jpg","hash":"64829272ec85bb819d55ff89e5b5fd6f64aa436b","modified":1614657196110},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/19.jpg","hash":"eb250906fdbc0c408f42ae9933725bc1a05d79fb","modified":1614657196110},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/20.jpg","hash":"3b11f9b461168d907073f793190865fe621a8573","modified":1614657196111},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/4.jpg","hash":"e06c47de27619984be9d5d02947f8370a432dfea","modified":1614657196113},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/6.jpg","hash":"c8f2aa4bbb041158b4e73733a341e6a77c8583f7","modified":1614657196113},{"_id":"themes/hexo-theme-matery/source/medias/featureimages/9.jpg","hash":"b956a2291a04b2132366b53666cf34858b8bdb1f","modified":1614657196115},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.eot","hash":"22f9e7d5226408eb2d0a11e118257a3ca22b8670","modified":1614657196057},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.ttf","hash":"91cbeeaceb644a971241c08362898599d6d968ce","modified":1614657196063},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.woff","hash":"18838f5260317da3c5ed29bf844ac8a4f7ad0529","modified":1614657196063},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.woff2","hash":"a46bd47ff0a90b812aafafda587d095cdb844271","modified":1614657196063},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.woff","hash":"92803b8753ceda573c6906774677c5a7081d2fbb","modified":1614657196074},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.woff2","hash":"9c081b88b106c6c04ecb895ba7ba7d3dcb3b55ac","modified":1614657196074},{"_id":"themes/hexo-theme-matery/source/libs/awesome/css/all.css","hash":"ecc41e32ad2696877a1656749841f3b5543bbe3d","modified":1614657196056},{"_id":"themes/hexo-theme-matery/source/medias/cover.jpg","hash":"d4957ff7cc5e88555cd840f2956ab0561e6f1ccf","modified":1614657196105},{"_id":"themes/hexo-theme-matery/source/libs/gitalk/gitalk.min.js","hash":"8fefe38f28804f90116bdcb74a0875c9de9f3b7d","modified":1614657196083},{"_id":"themes/hexo-theme-matery/source/libs/materialize/materialize.min.js","hash":"c8b4c65651921d888cf5f27430dfe2ad190d35bf","modified":1614657196091},{"_id":"themes/hexo-theme-matery/source/libs/materialize/materialize.min.css","hash":"a69d456e3345e7f59cd0d47d1b3e70fd4a496a05","modified":1614657196089},{"_id":"themes/hexo-theme-matery/source/libs/valine/av-min.js","hash":"541efb9edc1ce425cbe3897cfc25803211fe6a05","modified":1614657196099},{"_id":"themes/hexo-theme-matery/source/medias/banner/1.jpg","hash":"ab122a36998a4f62a61e61a4fc5e00248113413b","modified":1614657196101},{"_id":"themes/hexo-theme-matery/source/medias/banner/5.jpg","hash":"852418f4f09e796e12bc3bab7a1488d3f37d6486","modified":1614657196104},{"_id":"themes/hexo-theme-matery/source/medias/banner/6.jpg","hash":"ed7282cc129c4ff9f322d2f2897fb4aac5c48589","modified":1614657196104},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-regular-400.svg","hash":"3d3a49445343d80f3b553e3e3425b9a7bd49acaf","modified":1614657196065},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.eot","hash":"cab8e84ae5682d1d556e234df9c790985888def8","modified":1614657196067},{"_id":"themes/hexo-theme-matery/source/medias/banner/4.jpg","hash":"e5ac5033678afa9d69edffe9a61004f836cb5734","modified":1614657196103},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.ttf","hash":"9521ed12274c2cbc910cea77657116fcf6545da3","modified":1614657196074},{"_id":"themes/hexo-theme-matery/source/libs/twikoo/twikoo.all.min.js","hash":"c3f5f0a69b7864e7ef5bbf99fc774bec37947d7c","modified":1614657196097},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-brands-400.svg","hash":"5e2d2a159294576bea69cc3360efb5ffe110ab2d","modified":1614657196061},{"_id":"themes/hexo-theme-matery/source/libs/echarts/echarts.min.js","hash":"9496f386a0da4601cad22c479cc5543913a4d67f","modified":1614657196081},{"_id":"themes/hexo-theme-matery/source/libs/awesome/webfonts/fa-solid-900.svg","hash":"7da88b19e1486f8c968d3cf5ab3f194f01ea17fd","modified":1614657196072},{"_id":"themes/hexo-theme-matery/source/medias/banner/back.jpeg","hash":"e42935957575702a44dcc0330d4521be4456cba0","modified":1616673629604},{"_id":"themes/hexo-theme-matery/.DS_Store","hash":"a991695ab42ec2cbe35032abdae9005f0689587b","modified":1616674803418},{"_id":"themes/hexo-theme-matery/source/.DS_Store","hash":"b6b76c4bbb15085df05f82cb2c423fcd7b9bcda9","modified":1616676163530},{"_id":"themes/hexo-theme-matery/source/medias/.DS_Store","hash":"4e193a35a4f1826327c280d634604954383aeaa8","modified":1616676163642}],"Category":[],"Data":[],"Page":[{"title":"about","date":"2021-03-02T04:15:26.000Z","_content":"","source":"about/index.md","raw":"---\ntitle: about\ndate: 2021-03-02 12:15:26\n---\n","updated":"2021-03-02T04:15:26.924Z","path":"about/index.html","comments":1,"layout":"page","_id":"ckmotuk0t0000f1vperui25fc","content":"","site":{"data":{}},"excerpt":"","more":""},{"title":"categories","date":"2021-03-02T04:14:53.000Z","_content":"","source":"categories/index-1.md","raw":"---\ntitle: categories\ndate: 2021-03-02 12:14:53\n---\n","updated":"2021-03-02T04:14:53.713Z","path":"categories/index-1.html","comments":1,"layout":"page","_id":"ckmotuk0x0002f1vphz0o510o","content":"","site":{"data":{}},"excerpt":"","more":""},{"title":"categories","date":"2021-03-02T04:13:16.000Z","_content":"","source":"categories/index.md","raw":"---\ntitle: categories\ndate: 2021-03-02 12:13:16\n---\n","updated":"2021-03-02T04:13:16.385Z","path":"categories/index.html","comments":1,"layout":"page","_id":"ckmotuk0z0004f1vp0nit48zu","content":"","site":{"data":{}},"excerpt":"","more":""},{"title":"tags","date":"2021-03-02T04:15:14.000Z","_content":"","source":"tags/index.md","raw":"---\ntitle: tags\ndate: 2021-03-02 12:15:14\n---\n","updated":"2021-03-02T04:15:14.027Z","path":"tags/index.html","comments":1,"layout":"page","_id":"ckmotuk100006f1vpci0xh3m0","content":"","site":{"data":{}},"excerpt":"","more":""}],"Post":[{"title":"Hello World","_content":"### hello world\n\n","source":"_posts/hello-world.md","raw":"---\ntitle: Hello World\n---\n### hello world\n\n","slug":"hello-world","published":1,"date":"2021-02-23T12:41:33.294Z","updated":"2021-02-26T11:41:35.134Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk0v0001f1vpam3n8f3m","content":"<h3><span id=\"hello-world\">hello world</span></h3>","site":{"data":{}},"excerpt":"","more":"<h3 id=\"hello-world\"><a href=\"#hello-world\" class=\"headerlink\" title=\"hello world\"></a>hello world</h3>"},{"title":"lodash","_content":"\n敬请期待\n\n","source":"_posts/lodash.md","raw":"---\ntitle: lodash\n---\n\n敬请期待\n\n","slug":"lodash","published":1,"date":"2021-02-24T03:22:30.831Z","updated":"2021-02-26T11:33:19.417Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk0y0003f1vpevaag6nr","content":"<p>敬请期待</p>\n","site":{"data":{}},"excerpt":"","more":"<p>敬请期待</p>\n"},{"title":"HTTP与HTTPS","_content":"### HTTP\nHTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。\nHTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。\nHTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。\n一次访问网址经历DNS解析服务器IP,三次握手,发送请求,响应请求四个步骤。\n三次握手是client端先发送SYN,svr发送ACK+SYN,client端在发送ACK。\nHTTP的特点:\n1. http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。\n2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。\n3. 灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。\n4. 无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫做Cookie,一个叫做Session。\n5. 无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。\n\n### HTTPS\nHTTP存在以下问题:\n请求信息明文传输,容易被窃听截取。\n数据的完整性未校验,容易被篡改\n没有验证对方身份,存在冒充危险\n\nHTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。\nSSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。\nTLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)\n由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。\n##### 浏览器在使用HTTPS传输数据的流程是什么?\n\n1. 首先客户端通过URL访问服务器建立SSL连接。\n2. 服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。\n3. 客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。\n4. 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。\n5. 服务器利用自己的私钥解密出会话密钥。\n6. 服务器利用会话密钥加密与客户端之间的通信。\n\nHTTPS的缺点:\n1. HTTPS协议多次握手,导致页面的加载时间延长近50%;\n2. HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;\n3. 申请SSL证书需要钱,功能越强大的证书费用越高。\n4. SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。\n","source":"_posts/basic/02-http&https.md","raw":"---\ntitle: HTTP与HTTPS\n---\n### HTTP\nHTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。\nHTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。\nHTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。\n一次访问网址经历DNS解析服务器IP,三次握手,发送请求,响应请求四个步骤。\n三次握手是client端先发送SYN,svr发送ACK+SYN,client端在发送ACK。\nHTTP的特点:\n1. http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。\n2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。\n3. 灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。\n4. 无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫做Cookie,一个叫做Session。\n5. 无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。\n\n### HTTPS\nHTTP存在以下问题:\n请求信息明文传输,容易被窃听截取。\n数据的完整性未校验,容易被篡改\n没有验证对方身份,存在冒充危险\n\nHTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。\nSSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。\nTLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)\n由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。\n##### 浏览器在使用HTTPS传输数据的流程是什么?\n\n1. 首先客户端通过URL访问服务器建立SSL连接。\n2. 服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。\n3. 客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。\n4. 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。\n5. 服务器利用自己的私钥解密出会话密钥。\n6. 服务器利用会话密钥加密与客户端之间的通信。\n\nHTTPS的缺点:\n1. HTTPS协议多次握手,导致页面的加载时间延长近50%;\n2. HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;\n3. 申请SSL证书需要钱,功能越强大的证书费用越高。\n4. SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。\n","slug":"basic/02-http&https","published":1,"date":"2021-03-09T12:26:49.342Z","updated":"2021-03-09T12:37:29.522Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk0z0005f1vp2k04g8zp","content":"<h3><span id=\"http\">HTTP</span></h3><p>HTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。<br>HTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。<br>HTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。<br>一次访问网址经历DNS解析服务器IP,三次握手,发送请求,响应请求四个步骤。<br>三次握手是client端先发送SYN,svr发送ACK+SYN,client端在发送ACK。<br>HTTP的特点:</p>\n<ol>\n<li>http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。</li>\n<li>简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。</li>\n<li>灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。</li>\n<li>无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫做Cookie,一个叫做Session。</li>\n<li>无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。</li>\n</ol>\n<h3><span id=\"https\">HTTPS</span></h3><p>HTTP存在以下问题:<br>请求信息明文传输,容易被窃听截取。<br>数据的完整性未校验,容易被篡改<br>没有验证对方身份,存在冒充危险</p>\n<p>HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。<br>SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。<br>TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)<br>由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。</p>\n<h5><span id=\"浏览器在使用https传输数据的流程是什么\">浏览器在使用HTTPS传输数据的流程是什么?</span></h5><p><img src=\"img.png\" alt=\"img.png\"></p>\n<ol>\n<li>首先客户端通过URL访问服务器建立SSL连接。</li>\n<li>服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。</li>\n<li>客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。</li>\n<li>客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。</li>\n<li>服务器利用自己的私钥解密出会话密钥。</li>\n<li>服务器利用会话密钥加密与客户端之间的通信。</li>\n</ol>\n<p>HTTPS的缺点:</p>\n<ol>\n<li>HTTPS协议多次握手,导致页面的加载时间延长近50%;</li>\n<li>HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;</li>\n<li>申请SSL证书需要钱,功能越强大的证书费用越高。</li>\n<li>SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。</li>\n</ol>\n","site":{"data":{}},"excerpt":"","more":"<h3 id=\"HTTP\"><a href=\"#HTTP\" class=\"headerlink\" title=\"HTTP\"></a>HTTP</h3><p>HTTP协议是超文本传输协议的缩写,英文是Hyper Text Transfer Protocol。它是从WEB服务器传输超文本标记语言(HTML)到本地浏览器的传送协议。<br>HTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML 文件,、图片文件, 查询结果等。<br>HTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。<br>一次访问网址经历DNS解析服务器IP,三次握手,发送请求,响应请求四个步骤。<br>三次握手是client端先发送SYN,svr发送ACK+SYN,client端在发送ACK。<br>HTTP的特点:</p>\n<ol>\n<li>http协议支持客户端/服务端模式,也是一种请求/响应模式的协议。</li>\n<li>简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。</li>\n<li>灵活:HTTP允许传输任意类型的数据对象。传输的类型由Content-Type加以标记。</li>\n<li>无连接:限制每次连接只处理一个请求。服务器处理完请求,并收到客户的应答后,即断开连接,但是却不利于客户端与服务器保持会话连接,为了弥补这种不足,产生了两项记录http状态的技术,一个叫做Cookie,一个叫做Session。</li>\n<li>无状态:无状态是指协议对于事务处理没有记忆,后续处理需要前面的信息,则必须重传。</li>\n</ol>\n<h3 id=\"HTTPS\"><a href=\"#HTTPS\" class=\"headerlink\" title=\"HTTPS\"></a>HTTPS</h3><p>HTTP存在以下问题:<br>请求信息明文传输,容易被窃听截取。<br>数据的完整性未校验,容易被篡改<br>没有验证对方身份,存在冒充危险</p>\n<p>HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):一般理解为HTTP+SSL/TLS,通过 SSL证书来验证服务器的身份,并为浏览器和服务器之间的通信进行加密。<br>SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持。<br>TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)<br>由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。</p>\n<h5 id=\"浏览器在使用HTTPS传输数据的流程是什么?\"><a href=\"#浏览器在使用HTTPS传输数据的流程是什么?\" class=\"headerlink\" title=\"浏览器在使用HTTPS传输数据的流程是什么?\"></a>浏览器在使用HTTPS传输数据的流程是什么?</h5><p><img src=\"img.png\" alt=\"img.png\"></p>\n<ol>\n<li>首先客户端通过URL访问服务器建立SSL连接。</li>\n<li>服务端收到客户端请求后,会将网站支持的证书信息(证书中包含公钥)传送一份给客户端。</li>\n<li>客户端的服务器开始协商SSL连接的安全等级,也就是信息加密的等级。</li>\n<li>客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。</li>\n<li>服务器利用自己的私钥解密出会话密钥。</li>\n<li>服务器利用会话密钥加密与客户端之间的通信。</li>\n</ol>\n<p>HTTPS的缺点:</p>\n<ol>\n<li>HTTPS协议多次握手,导致页面的加载时间延长近50%;</li>\n<li>HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗;</li>\n<li>申请SSL证书需要钱,功能越强大的证书费用越高。</li>\n<li>SSL涉及到的安全算法会消耗 CPU 资源,对服务器资源消耗较大。</li>\n</ol>\n"},{"title":"let 和const 命令","_content":"## 1. let和var的区别\n1. let声明的变量只在它所在的代码块有效。\n2. 循环内定义的变量,只在循环体内有效,循环体外引用会报错\n```javascript\nvar a = [];\nfor (var i = 0; i < 10; i++) {\n a[i] = function () {\n console.log(i);\n };\n}\na[6](); // 10\n```\nvar命名的变量是全局有效的,每次循环都会改变i的值,循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。\n\n```javascript\nvar a = [];\nfor (let i = 0; i < 10; i++) {\n a[i] = function () {\n console.log(i);\n };\n}\na[6](); // 6\n```\n变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。\n3. for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。\n```javascript\nfor (let i = 0; i < 3; i++) {\n let i = 'abc';\n console.log(i);\n}\n// abc\n// abc\n// abc\n```\n4. 不存在变量提升现象\n5. 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。\n6. “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。\n```javascript\ntypeof x; // ReferenceError\nlet x;\n```\n```javascript\ntypeof undeclared_variable // \"undefined\"\n```\n7. let不允许在相同作用域内,重复声明同一个变量。\n\n## 2. 块级作用域\nES5 只有全局作用域和函数作用域,没有块级作用域,这样会导致一些问题\n问题1: 内层变量可能会覆盖外层变量\n```javascript\nvar tmp = new Date();\n\nfunction f() {\n console.log(tmp);\n if (false) {\n var tmp = 'hello world';\n }\n}\n\nf(); // undefined\n```\n本意f是希望输出全局变量tmp的,但是在函数内部又定义了tmp,var方式定义会导致变量提升,这里实际输出的是未定义的内部tmp\n问题2:计数的循环变量泄露未全局变量\n```javascript\nvar s = 'hello';\n\nfor (var i = 0; i < s.length; i++) {\n console.log(s[i]);\n}\n\nconsole.log(i); // 5\n```\ni本来只用于控制循环,但是在循环结束后并未消失\nlet命令为JavaScript新增了块级作用域。\n```javascript\nfunction f1() {\n let n = 5;\n if (true) {\n let n = 10;\n }\n console.log(n); // 5\n}\n```\nES6允许块级作用域任意嵌套。\n块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。\n```javascript\n// IIFE 写法\n(function () {\n var tmp = ...;\n ...\n}());\n\n// 块级作用域写法\n{\n let tmp = ...;\n ...\n}\n```\nES5规定函数只能做顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是浏览器为了兼容旧代码,也支持。\n考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。\n```javascript\n// 块级作用域内部的函数声明语句,建议不要使用\n{\n let a = 'secret';\n function f() {\n return a;\n }\n}\n\n// 块级作用域内部,优先使用函数表达式\n{\n let a = 'secret';\n let f = function () {\n return a;\n };\n}\n```\nES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。\n```javascript\n// 第一种写法,报错\nif (true) let x = 1;\n\n// 第二种写法,不报错\nif (true) {\n let x = 1;\n}\n```\n第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。\n\n## 3. const 命令\n1. const 声明一个只读常量,一旦声明,常量的值就不会改变。\n2. const 的作用域与let命令相同:只在声明所在的块级作用域内有效。\n3. const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。\n4. const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。\n```javascript\nconst foo = {};\n\n// 为 foo 添加一个属性,可以成功\nfoo.prop = 123;\nfoo.prop // 123\n\n// 将 foo 指向另一个对象,就会报错\nfoo = {}; // TypeError: \"foo\" is read-only\n```\n如果真的想将对象冻结,应该使用Object.freeze方法。\n```javascript\nconst foo = Object.freeze({});\n\n// 常规模式时,下面一行不起作用;\n// 严格模式时,该行会报错\nfoo.prop = 123;\n```\n5. ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有import命令和class命令。因此ES6一共有6种声明变量的方式。\n\n## 4. 顶层对象的属性\n顶层对象,在浏览器中指的是window对象,在Node中指的是global对象。ES5中,顶层对象的属性与全局变量等价。\n顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。\n这样的设计带来了几个很大的问题:\n1、没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);\n2、程序员很容易不知不觉地就创建了全局变量(比如打字出错);\n3、顶层对象的属性是到处可以读写的,这非常不利于模块化编程。\n4、window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。\nES6规定var和function命令声明的全局变量,依旧是顶层对象的属性。let、const和class命令声明的全局变量,不属于顶层对象的属性\n\n## globalThis对象\nJavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。\n- 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。\n- 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。\n- Node 里面,顶层对象是global,但其他环境都不支持。\n- 全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。\n- 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。\n```javascript\nvar getGlobal = function () {\n if (typeof self !== 'undefined') { return self; }\n if (typeof window !== 'undefined') { return window; }\n if (typeof global !== 'undefined') { return global; }\n throw new Error('unable to locate global object');\n};\n```","source":"_posts/es6/01-let&const.md","raw":"---\ntitle: let 和const 命令\n---\n## 1. let和var的区别\n1. let声明的变量只在它所在的代码块有效。\n2. 循环内定义的变量,只在循环体内有效,循环体外引用会报错\n```javascript\nvar a = [];\nfor (var i = 0; i < 10; i++) {\n a[i] = function () {\n console.log(i);\n };\n}\na[6](); // 10\n```\nvar命名的变量是全局有效的,每次循环都会改变i的值,循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。\n\n```javascript\nvar a = [];\nfor (let i = 0; i < 10; i++) {\n a[i] = function () {\n console.log(i);\n };\n}\na[6](); // 6\n```\n变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。\n3. for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。\n```javascript\nfor (let i = 0; i < 3; i++) {\n let i = 'abc';\n console.log(i);\n}\n// abc\n// abc\n// abc\n```\n4. 不存在变量提升现象\n5. 在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。\n6. “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。\n```javascript\ntypeof x; // ReferenceError\nlet x;\n```\n```javascript\ntypeof undeclared_variable // \"undefined\"\n```\n7. let不允许在相同作用域内,重复声明同一个变量。\n\n## 2. 块级作用域\nES5 只有全局作用域和函数作用域,没有块级作用域,这样会导致一些问题\n问题1: 内层变量可能会覆盖外层变量\n```javascript\nvar tmp = new Date();\n\nfunction f() {\n console.log(tmp);\n if (false) {\n var tmp = 'hello world';\n }\n}\n\nf(); // undefined\n```\n本意f是希望输出全局变量tmp的,但是在函数内部又定义了tmp,var方式定义会导致变量提升,这里实际输出的是未定义的内部tmp\n问题2:计数的循环变量泄露未全局变量\n```javascript\nvar s = 'hello';\n\nfor (var i = 0; i < s.length; i++) {\n console.log(s[i]);\n}\n\nconsole.log(i); // 5\n```\ni本来只用于控制循环,但是在循环结束后并未消失\nlet命令为JavaScript新增了块级作用域。\n```javascript\nfunction f1() {\n let n = 5;\n if (true) {\n let n = 10;\n }\n console.log(n); // 5\n}\n```\nES6允许块级作用域任意嵌套。\n块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。\n```javascript\n// IIFE 写法\n(function () {\n var tmp = ...;\n ...\n}());\n\n// 块级作用域写法\n{\n let tmp = ...;\n ...\n}\n```\nES5规定函数只能做顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是浏览器为了兼容旧代码,也支持。\n考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。\n```javascript\n// 块级作用域内部的函数声明语句,建议不要使用\n{\n let a = 'secret';\n function f() {\n return a;\n }\n}\n\n// 块级作用域内部,优先使用函数表达式\n{\n let a = 'secret';\n let f = function () {\n return a;\n };\n}\n```\nES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。\n```javascript\n// 第一种写法,报错\nif (true) let x = 1;\n\n// 第二种写法,不报错\nif (true) {\n let x = 1;\n}\n```\n第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。\n\n## 3. const 命令\n1. const 声明一个只读常量,一旦声明,常量的值就不会改变。\n2. const 的作用域与let命令相同:只在声明所在的块级作用域内有效。\n3. const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。\n4. const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。\n```javascript\nconst foo = {};\n\n// 为 foo 添加一个属性,可以成功\nfoo.prop = 123;\nfoo.prop // 123\n\n// 将 foo 指向另一个对象,就会报错\nfoo = {}; // TypeError: \"foo\" is read-only\n```\n如果真的想将对象冻结,应该使用Object.freeze方法。\n```javascript\nconst foo = Object.freeze({});\n\n// 常规模式时,下面一行不起作用;\n// 严格模式时,该行会报错\nfoo.prop = 123;\n```\n5. ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有import命令和class命令。因此ES6一共有6种声明变量的方式。\n\n## 4. 顶层对象的属性\n顶层对象,在浏览器中指的是window对象,在Node中指的是global对象。ES5中,顶层对象的属性与全局变量等价。\n顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。\n这样的设计带来了几个很大的问题:\n1、没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);\n2、程序员很容易不知不觉地就创建了全局变量(比如打字出错);\n3、顶层对象的属性是到处可以读写的,这非常不利于模块化编程。\n4、window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。\nES6规定var和function命令声明的全局变量,依旧是顶层对象的属性。let、const和class命令声明的全局变量,不属于顶层对象的属性\n\n## globalThis对象\nJavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。\n- 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。\n- 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。\n- Node 里面,顶层对象是global,但其他环境都不支持。\n- 全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。\n- 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。\n```javascript\nvar getGlobal = function () {\n if (typeof self !== 'undefined') { return self; }\n if (typeof window !== 'undefined') { return window; }\n if (typeof global !== 'undefined') { return global; }\n throw new Error('unable to locate global object');\n};\n```","slug":"es6/01-let&const","published":1,"date":"2021-03-11T07:07:11.265Z","updated":"2021-03-25T02:58:58.010Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk100007f1vp93r2d40d","content":"<h2><span id=\"1-let和var的区别\">1. let和var的区别</span></h2><ol>\n<li>let声明的变量只在它所在的代码块有效。</li>\n<li>循环内定义的变量,只在循环体内有效,循环体外引用会报错<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n a<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\na<span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 10</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\nvar命名的变量是全局有效的,每次循环都会改变i的值,循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。</li>\n</ol>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n a<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\na<span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 6</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。<br>3. for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token string\">'abc'</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// abc</span>\n<span class=\"token comment\">// abc</span>\n<span class=\"token comment\">// abc</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<ol start=\"4\">\n<li>不存在变量提升现象</li>\n<li>在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。</li>\n<li>“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">typeof</span> x<span class=\"token punctuation\">;</span> <span class=\"token comment\">// ReferenceError</span>\n<span class=\"token keyword\">let</span> x<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">typeof</span> undeclared_variable <span class=\"token comment\">// \"undefined\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre></li>\n<li>let不允许在相同作用域内,重复声明同一个变量。</li>\n</ol>\n<h2><span id=\"2-块级作用域\">2. 块级作用域</span></h2><p>ES5 只有全局作用域和函数作用域,没有块级作用域,这样会导致一些问题<br>问题1: 内层变量可能会覆盖外层变量</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>tmp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token string\">'hello world'</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>本意f是希望输出全局变量tmp的,但是在函数内部又定义了tmp,var方式定义会导致变量提升,这里实际输出的是未定义的内部tmp<br>问题2:计数的循环变量泄露未全局变量</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> s <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> s<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>i本来只用于控制循环,但是在循环结束后并未消失<br>let命令为JavaScript新增了块级作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> n <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> n <span class=\"token operator\">=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6允许块级作用域任意嵌套。<br>块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// IIFE 写法</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">;</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 块级作用域写法</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> tmp <span class=\"token operator\">=</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">;</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES5规定函数只能做顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是浏览器为了兼容旧代码,也支持。<br>考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 块级作用域内部的函数声明语句,建议不要使用</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token string\">'secret'</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 块级作用域内部,优先使用函数表达式</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token string\">'secret'</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> <span class=\"token function-variable function\">f</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 第一种写法,报错</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 第二种写法,不报错</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。</p>\n<h2><span id=\"3-const-命令\">3. const 命令</span></h2><ol>\n<li>const 声明一个只读常量,一旦声明,常量的值就不会改变。</li>\n<li>const 的作用域与let命令相同:只在声明所在的块级作用域内有效。</li>\n<li>const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。</li>\n<li>const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> foo <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 为 foo 添加一个属性,可以成功</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token comment\">// 123</span>\n\n<span class=\"token comment\">// 将 foo 指向另一个对象,就会报错</span>\nfoo <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// TypeError: \"foo\" is read-only</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n如果真的想将对象冻结,应该使用Object.freeze方法。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> foo <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 常规模式时,下面一行不起作用;</span>\n<span class=\"token comment\">// 严格模式时,该行会报错</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n<li>ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有import命令和class命令。因此ES6一共有6种声明变量的方式。</li>\n</ol>\n<h2><span id=\"4-顶层对象的属性\">4. 顶层对象的属性</span></h2><p>顶层对象,在浏览器中指的是window对象,在Node中指的是global对象。ES5中,顶层对象的属性与全局变量等价。<br>顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。<br>这样的设计带来了几个很大的问题:<br>1、没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);<br>2、程序员很容易不知不觉地就创建了全局变量(比如打字出错);<br>3、顶层对象的属性是到处可以读写的,这非常不利于模块化编程。<br>4、window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。<br>ES6规定var和function命令声明的全局变量,依旧是顶层对象的属性。let、const和class命令声明的全局变量,不属于顶层对象的属性</p>\n<h2><span id=\"globalthis对象\">globalThis对象</span></h2><p>JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。</p>\n<ul>\n<li>浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。</li>\n<li>浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。</li>\n<li>Node 里面,顶层对象是global,但其他环境都不支持。</li>\n<li>全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。</li>\n<li>函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> <span class=\"token function-variable function\">getGlobal</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> self <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> window <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> window<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> global <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> global<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'unable to locate global object'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"1-let和var的区别\"><a href=\"#1-let和var的区别\" class=\"headerlink\" title=\"1. let和var的区别\"></a>1. let和var的区别</h2><ol>\n<li>let声明的变量只在它所在的代码块有效。</li>\n<li>循环内定义的变量,只在循环体内有效,循环体外引用会报错<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n a<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\na<span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 10</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\nvar命名的变量是全局有效的,每次循环都会改变i的值,循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,所有数组a的成员里面的i,指向的都是同一个i,导致运行时输出的是最后一轮的i的值,也就是 10。</li>\n</ol>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> a <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n a<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\na<span class=\"token punctuation\">[</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 6</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。<br>3. for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> <span class=\"token number\">3</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> i <span class=\"token operator\">=</span> <span class=\"token string\">'abc'</span><span class=\"token punctuation\">;</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// abc</span>\n<span class=\"token comment\">// abc</span>\n<span class=\"token comment\">// abc</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<ol start=\"4\">\n<li>不存在变量提升现象</li>\n<li>在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。</li>\n<li>“暂时性死区”也意味着typeof不再是一个百分之百安全的操作。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">typeof</span> x<span class=\"token punctuation\">;</span> <span class=\"token comment\">// ReferenceError</span>\n<span class=\"token keyword\">let</span> x<span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">typeof</span> undeclared_variable <span class=\"token comment\">// \"undefined\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre></li>\n<li>let不允许在相同作用域内,重复声明同一个变量。</li>\n</ol>\n<h2 id=\"2-块级作用域\"><a href=\"#2-块级作用域\" class=\"headerlink\" title=\"2. 块级作用域\"></a>2. 块级作用域</h2><p>ES5 只有全局作用域和函数作用域,没有块级作用域,这样会导致一些问题<br>问题1: 内层变量可能会覆盖外层变量</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>tmp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token string\">'hello world'</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>本意f是希望输出全局变量tmp的,但是在函数内部又定义了tmp,var方式定义会导致变量提升,这里实际输出的是未定义的内部tmp<br>问题2:计数的循环变量泄露未全局变量</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> s <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><</span> s<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>s<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>i本来只用于控制循环,但是在循环结束后并未消失<br>let命令为JavaScript新增了块级作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">f1</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> n <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> n <span class=\"token operator\">=</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6允许块级作用域任意嵌套。<br>块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// IIFE 写法</span>\n<span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">var</span> tmp <span class=\"token operator\">=</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">;</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 块级作用域写法</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> tmp <span class=\"token operator\">=</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">;</span>\n <span class=\"token operator\">...</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES5规定函数只能做顶层作用域和函数作用域之中声明,不能在块级作用域声明。但是浏览器为了兼容旧代码,也支持。<br>考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 块级作用域内部的函数声明语句,建议不要使用</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token string\">'secret'</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">f</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// 块级作用域内部,优先使用函数表达式</span>\n<span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token string\">'secret'</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> <span class=\"token function-variable function\">f</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// 第一种写法,报错</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 第二种写法,不报错</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> x <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。</p>\n<h2 id=\"3-const-命令\"><a href=\"#3-const-命令\" class=\"headerlink\" title=\"3. const 命令\"></a>3. const 命令</h2><ol>\n<li>const 声明一个只读常量,一旦声明,常量的值就不会改变。</li>\n<li>const 的作用域与let命令相同:只在声明所在的块级作用域内有效。</li>\n<li>const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。</li>\n<li>const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> foo <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 为 foo 添加一个属性,可以成功</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token comment\">// 123</span>\n\n<span class=\"token comment\">// 将 foo 指向另一个对象,就会报错</span>\nfoo <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// TypeError: \"foo\" is read-only</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n如果真的想将对象冻结,应该使用Object.freeze方法。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> foo <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">freeze</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// 常规模式时,下面一行不起作用;</span>\n<span class=\"token comment\">// 严格模式时,该行会报错</span>\nfoo<span class=\"token punctuation\">.</span>prop <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n<li>ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加let和const命令,还有import命令和class命令。因此ES6一共有6种声明变量的方式。</li>\n</ol>\n<h2 id=\"4-顶层对象的属性\"><a href=\"#4-顶层对象的属性\" class=\"headerlink\" title=\"4. 顶层对象的属性\"></a>4. 顶层对象的属性</h2><p>顶层对象,在浏览器中指的是window对象,在Node中指的是global对象。ES5中,顶层对象的属性与全局变量等价。<br>顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。<br>这样的设计带来了几个很大的问题:<br>1、没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);<br>2、程序员很容易不知不觉地就创建了全局变量(比如打字出错);<br>3、顶层对象的属性是到处可以读写的,这非常不利于模块化编程。<br>4、window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。<br>ES6规定var和function命令声明的全局变量,依旧是顶层对象的属性。let、const和class命令声明的全局变量,不属于顶层对象的属性</p>\n<h2 id=\"globalThis对象\"><a href=\"#globalThis对象\" class=\"headerlink\" title=\"globalThis对象\"></a>globalThis对象</h2><p>JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。但是,顶层对象在各种实现里面是不统一的。</p>\n<ul>\n<li>浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。</li>\n<li>浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。</li>\n<li>Node 里面,顶层对象是global,但其他环境都不支持。</li>\n<li>全局环境中,this会返回顶层对象。但是,Node.js 模块中this返回的是当前模块,ES6 模块中this返回的是undefined。</li>\n<li>函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this会指向顶层对象。但是,严格模式下,这时this会返回undefined。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> <span class=\"token function-variable function\">getGlobal</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> self <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> self<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> window <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> window<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> global <span class=\"token operator\">!==</span> <span class=\"token string\">'undefined'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> global<span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'unable to locate global object'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n</ul>\n"},{"title":"变量的解构赋值","_content":"## 1. 数组解构赋值\nES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。\n```javascript\nlet [a, b, c] = [1, 2, 3];\n```\n这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。\n如果解构不成功,变量的值就等于undefined。\n```javascript\nlet [foo] = []; // foo 为undefined\nlet [bar, foo] = [1]; // foo 为undefined\n```\n也可以进行不完全解构\n如果等号右边不是可遍历解构,就会报错。\n只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值\n```javascript\nfunction* fibs() {\n let a = 0;\n let b = 1;\n while (true) {\n yield a;\n [a, b] = [b, a + b];\n }\n}\n\nlet [first, second, third, fourth, fifth, sixth] = fibs();\nsixth // 5\n```\n解构允许指定默认值\n```javascript\nlet [foo = true] = [];\nfoo // true\nlet [x, y = 'b'] = ['a']; // x='a', y='b'\nlet [x, y = 'b'] = ['a', undefined]; // x='a', y='b'\n```\nES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。\n\n## 2. 对象解构赋值\n数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。\n如果解构失败,变量的值为undefined\n对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。\n如果变量名与属性名不一致,必须这么写\n```javascript\nlet { foo: baz } = { foo: 'aaa', bar: 'bbb' };\nbaz // \"aaa\"\n\nlet obj = { first: 'hello', last: 'world' };\nlet { first: f, last: l } = obj;\nf // 'hello'\nl // 'world'\n```\n实际上,对象的解构赋值是下面形式的简写\n```javascript\nlet { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };\n```\n解构也适用于嵌套结果的对象\n```javascript\nconst node = {\n loc: {\n start: {\n line: 1,\n column: 5\n }\n }\n};\n\nlet { loc, loc: { start }, loc: { start: { line }} } = node;\nline // 1\nloc // Object {start: Object}\nstart // Object {line: 1, column: 5}\n```\n三次解构赋值,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。\n对象的解构赋值可以取到继承的属性\n```javascript\nconst obj1 = {};\nconst obj2 = { foo: 'bar' };\nObject.setPrototypeOf(obj1, obj2);\n\nconst { foo } = obj1;\nfoo // \"bar\"\n```\n\n## 3. 对象的解构赋值\n可以解构出各个字符,例如\n```javascript\nconst [a, b, c, d, e] = 'hello';\nlet {length : len} = 'hello';\nlen // 5\n```\n\n## 4. 数值和布尔值的解构赋值\n解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。\n```javascript\nlet {toString: s} = 123;\ns === Number.prototype.toString // true\n\nlet {toString: s} = true;\ns === Boolean.prototype.toString // true\n```\n解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。\n\n## 5. 函数参数的解构赋值\n函数的参数也可以使用解构赋值。\n```javascript\nfunction move({x, y} = { x: 0, y: 0 }) {\n return [x, y];\n}\n\nmove({x: 3, y: 8}); // [3, 8]\nmove({x: 3}); // [3, undefined]\nmove({}); // [undefined, undefined]\nmove(); // [0, 0]\n```\n\n## 6. 解构的用途\n1. 交换变量的值\n2. 从函数处返回多个值\n3. 函数参数的定义\n4. 提取JSON数据\n5. 函数参数的默认值\n6. 遍历map结构\n7. 输入模块的指定方法","source":"_posts/es6/02-Destructuring.md","raw":"---\ntitle: 变量的解构赋值\n---\n## 1. 数组解构赋值\nES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。\n```javascript\nlet [a, b, c] = [1, 2, 3];\n```\n这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。\n如果解构不成功,变量的值就等于undefined。\n```javascript\nlet [foo] = []; // foo 为undefined\nlet [bar, foo] = [1]; // foo 为undefined\n```\n也可以进行不完全解构\n如果等号右边不是可遍历解构,就会报错。\n只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值\n```javascript\nfunction* fibs() {\n let a = 0;\n let b = 1;\n while (true) {\n yield a;\n [a, b] = [b, a + b];\n }\n}\n\nlet [first, second, third, fourth, fifth, sixth] = fibs();\nsixth // 5\n```\n解构允许指定默认值\n```javascript\nlet [foo = true] = [];\nfoo // true\nlet [x, y = 'b'] = ['a']; // x='a', y='b'\nlet [x, y = 'b'] = ['a', undefined]; // x='a', y='b'\n```\nES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。\n\n## 2. 对象解构赋值\n数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。\n如果解构失败,变量的值为undefined\n对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。\n如果变量名与属性名不一致,必须这么写\n```javascript\nlet { foo: baz } = { foo: 'aaa', bar: 'bbb' };\nbaz // \"aaa\"\n\nlet obj = { first: 'hello', last: 'world' };\nlet { first: f, last: l } = obj;\nf // 'hello'\nl // 'world'\n```\n实际上,对象的解构赋值是下面形式的简写\n```javascript\nlet { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };\n```\n解构也适用于嵌套结果的对象\n```javascript\nconst node = {\n loc: {\n start: {\n line: 1,\n column: 5\n }\n }\n};\n\nlet { loc, loc: { start }, loc: { start: { line }} } = node;\nline // 1\nloc // Object {start: Object}\nstart // Object {line: 1, column: 5}\n```\n三次解构赋值,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。\n对象的解构赋值可以取到继承的属性\n```javascript\nconst obj1 = {};\nconst obj2 = { foo: 'bar' };\nObject.setPrototypeOf(obj1, obj2);\n\nconst { foo } = obj1;\nfoo // \"bar\"\n```\n\n## 3. 对象的解构赋值\n可以解构出各个字符,例如\n```javascript\nconst [a, b, c, d, e] = 'hello';\nlet {length : len} = 'hello';\nlen // 5\n```\n\n## 4. 数值和布尔值的解构赋值\n解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。\n```javascript\nlet {toString: s} = 123;\ns === Number.prototype.toString // true\n\nlet {toString: s} = true;\ns === Boolean.prototype.toString // true\n```\n解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。\n\n## 5. 函数参数的解构赋值\n函数的参数也可以使用解构赋值。\n```javascript\nfunction move({x, y} = { x: 0, y: 0 }) {\n return [x, y];\n}\n\nmove({x: 3, y: 8}); // [3, 8]\nmove({x: 3}); // [3, undefined]\nmove({}); // [undefined, undefined]\nmove(); // [0, 0]\n```\n\n## 6. 解构的用途\n1. 交换变量的值\n2. 从函数处返回多个值\n3. 函数参数的定义\n4. 提取JSON数据\n5. 函数参数的默认值\n6. 遍历map结构\n7. 输入模块的指定方法","slug":"es6/02-Destructuring","published":1,"date":"2021-03-25T03:01:50.591Z","updated":"2021-03-25T06:58:02.819Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk110008f1vp6glc123x","content":"<h2><span id=\"1-数组解构赋值\">1. 数组解构赋值</span></h2><p>ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<p>这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。<br>如果解构不成功,变量的值就等于undefined。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>foo<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// foo 为undefined</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>bar<span class=\"token punctuation\">,</span> foo<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// foo 为undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n<p>也可以进行不完全解构<br>如果等号右边不是可遍历解构,就会报错。<br>只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token function\">fibs</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> b <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">yield</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>b<span class=\"token punctuation\">,</span> a <span class=\"token operator\">+</span> b<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>first<span class=\"token punctuation\">,</span> second<span class=\"token punctuation\">,</span> third<span class=\"token punctuation\">,</span> fourth<span class=\"token punctuation\">,</span> fifth<span class=\"token punctuation\">,</span> sixth<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">fibs</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nsixth <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>解构允许指定默认值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>foo <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\nfoo <span class=\"token comment\">// true</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y <span class=\"token operator\">=</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// x='a', y='b'</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y <span class=\"token operator\">=</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// x='a', y='b'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。</p>\n<h2><span id=\"2-对象解构赋值\">2. 对象解构赋值</span></h2><p>数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。<br>如果解构失败,变量的值为undefined<br>对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。<br>如果变量名与属性名不一致,必须这么写</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> baz <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'aaa'</span><span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> <span class=\"token string\">'bbb'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nbaz <span class=\"token comment\">// \"aaa\"</span>\n\n<span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> first<span class=\"token operator\">:</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">,</span> last<span class=\"token operator\">:</span> <span class=\"token string\">'world'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> first<span class=\"token operator\">:</span> f<span class=\"token punctuation\">,</span> last<span class=\"token operator\">:</span> l <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">;</span>\nf <span class=\"token comment\">// 'hello'</span>\nl <span class=\"token comment\">// 'world'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>实际上,对象的解构赋值是下面形式的简写</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> foo<span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> bar <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'aaa'</span><span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> <span class=\"token string\">'bbb'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<p>解构也适用于嵌套结果的对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> node <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n start<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n line<span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n column<span class=\"token operator\">:</span> <span class=\"token number\">5</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> loc<span class=\"token punctuation\">,</span> loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> start <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> start<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> line <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span>\nline <span class=\"token comment\">// 1</span>\nloc <span class=\"token comment\">// Object {start: Object}</span>\nstart <span class=\"token comment\">// Object {line: 1, column: 5}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>三次解构赋值,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。<br>对象的解构赋值可以取到继承的属性</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> obj2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'bar'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">setPrototypeOf</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">,</span> obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> foo <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> obj1<span class=\"token punctuation\">;</span>\nfoo <span class=\"token comment\">// \"bar\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2><span id=\"3-对象的解构赋值\">3. 对象的解构赋值</span></h2><p>可以解构出各个字符,例如</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">,</span> d<span class=\"token punctuation\">,</span> e<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>length <span class=\"token operator\">:</span> len<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\nlen <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2><span id=\"4-数值和布尔值的解构赋值\">4. 数值和布尔值的解构赋值</span></h2><p>解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>toString<span class=\"token operator\">:</span> s<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span>\ns <span class=\"token operator\">===</span> <span class=\"token class-name\">Number</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>toString <span class=\"token comment\">// true</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>toString<span class=\"token operator\">:</span> s<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\ns <span class=\"token operator\">===</span> <span class=\"token class-name\">Boolean</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>toString <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。</p>\n<h2><span id=\"5-函数参数的解构赋值\">5. 函数参数的解构赋值</span></h2><p>函数的参数也可以使用解构赋值。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> x<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> y<span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>x<span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> y<span class=\"token operator\">:</span> <span class=\"token number\">8</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [3, 8]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>x<span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [3, undefined]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [undefined, undefined]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [0, 0]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2><span id=\"6-解构的用途\">6. 解构的用途</span></h2><ol>\n<li>交换变量的值</li>\n<li>从函数处返回多个值</li>\n<li>函数参数的定义</li>\n<li>提取JSON数据</li>\n<li>函数参数的默认值</li>\n<li>遍历map结构</li>\n<li>输入模块的指定方法</li>\n</ol>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"1-数组解构赋值\"><a href=\"#1-数组解构赋值\" class=\"headerlink\" title=\"1. 数组解构赋值\"></a>1. 数组解构赋值</h2><p>ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<p>这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。<br>如果解构不成功,变量的值就等于undefined。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>foo<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// foo 为undefined</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>bar<span class=\"token punctuation\">,</span> foo<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// foo 为undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span></span></code></pre>\n<p>也可以进行不完全解构<br>如果等号右边不是可遍历解构,就会报错。<br>只要某种数据结构具有Iterator接口,都可以采用数组形式的解构赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token function\">fibs</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">let</span> a <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">let</span> b <span class=\"token operator\">=</span> <span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">while</span> <span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">yield</span> a<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>b<span class=\"token punctuation\">,</span> a <span class=\"token operator\">+</span> b<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>first<span class=\"token punctuation\">,</span> second<span class=\"token punctuation\">,</span> third<span class=\"token punctuation\">,</span> fourth<span class=\"token punctuation\">,</span> fifth<span class=\"token punctuation\">,</span> sixth<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">fibs</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nsixth <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>解构允许指定默认值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>foo <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\nfoo <span class=\"token comment\">// true</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y <span class=\"token operator\">=</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// x='a', y='b'</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y <span class=\"token operator\">=</span> <span class=\"token string\">'b'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'a'</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// x='a', y='b'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。</p>\n<h2 id=\"2-对象解构赋值\"><a href=\"#2-对象解构赋值\" class=\"headerlink\" title=\"2. 对象解构赋值\"></a>2. 对象解构赋值</h2><p>数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。<br>如果解构失败,变量的值为undefined<br>对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。<br>如果变量名与属性名不一致,必须这么写</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> baz <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'aaa'</span><span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> <span class=\"token string\">'bbb'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nbaz <span class=\"token comment\">// \"aaa\"</span>\n\n<span class=\"token keyword\">let</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> first<span class=\"token operator\">:</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">,</span> last<span class=\"token operator\">:</span> <span class=\"token string\">'world'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> first<span class=\"token operator\">:</span> f<span class=\"token punctuation\">,</span> last<span class=\"token operator\">:</span> l <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">;</span>\nf <span class=\"token comment\">// 'hello'</span>\nl <span class=\"token comment\">// 'world'</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>实际上,对象的解构赋值是下面形式的简写</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> foo<span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> bar <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'aaa'</span><span class=\"token punctuation\">,</span> bar<span class=\"token operator\">:</span> <span class=\"token string\">'bbb'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre>\n<p>解构也适用于嵌套结果的对象</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> node <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n start<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n line<span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n column<span class=\"token operator\">:</span> <span class=\"token number\">5</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span> loc<span class=\"token punctuation\">,</span> loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> start <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> loc<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> start<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> line <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> node<span class=\"token punctuation\">;</span>\nline <span class=\"token comment\">// 1</span>\nloc <span class=\"token comment\">// Object {start: Object}</span>\nstart <span class=\"token comment\">// Object {line: 1, column: 5}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>三次解构赋值,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。<br>对象的解构赋值可以取到继承的属性</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> obj2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> foo<span class=\"token operator\">:</span> <span class=\"token string\">'bar'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nObject<span class=\"token punctuation\">.</span><span class=\"token function\">setPrototypeOf</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">,</span> obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> foo <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> obj1<span class=\"token punctuation\">;</span>\nfoo <span class=\"token comment\">// \"bar\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"3-对象的解构赋值\"><a href=\"#3-对象的解构赋值\" class=\"headerlink\" title=\"3. 对象的解构赋值\"></a>3. 对象的解构赋值</h2><p>可以解构出各个字符,例如</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">,</span> c<span class=\"token punctuation\">,</span> d<span class=\"token punctuation\">,</span> e<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>length <span class=\"token operator\">:</span> len<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token string\">'hello'</span><span class=\"token punctuation\">;</span>\nlen <span class=\"token comment\">// 5</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"4-数值和布尔值的解构赋值\"><a href=\"#4-数值和布尔值的解构赋值\" class=\"headerlink\" title=\"4. 数值和布尔值的解构赋值\"></a>4. 数值和布尔值的解构赋值</h2><p>解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>toString<span class=\"token operator\">:</span> s<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token number\">123</span><span class=\"token punctuation\">;</span>\ns <span class=\"token operator\">===</span> <span class=\"token class-name\">Number</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>toString <span class=\"token comment\">// true</span>\n\n<span class=\"token keyword\">let</span> <span class=\"token punctuation\">{</span>toString<span class=\"token operator\">:</span> s<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\ns <span class=\"token operator\">===</span> <span class=\"token class-name\">Boolean</span><span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">.</span>toString <span class=\"token comment\">// true</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。</p>\n<h2 id=\"5-函数参数的解构赋值\"><a href=\"#5-函数参数的解构赋值\" class=\"headerlink\" title=\"5. 函数参数的解构赋值\"></a>5. 函数参数的解构赋值</h2><p>函数的参数也可以使用解构赋值。</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> x<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> y<span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> <span class=\"token punctuation\">[</span>x<span class=\"token punctuation\">,</span> y<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>x<span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> y<span class=\"token operator\">:</span> <span class=\"token number\">8</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [3, 8]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>x<span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [3, undefined]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [undefined, undefined]</span>\n<span class=\"token function\">move</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [0, 0]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n\n<h2 id=\"6-解构的用途\"><a href=\"#6-解构的用途\" class=\"headerlink\" title=\"6. 解构的用途\"></a>6. 解构的用途</h2><ol>\n<li>交换变量的值</li>\n<li>从函数处返回多个值</li>\n<li>函数参数的定义</li>\n<li>提取JSON数据</li>\n<li>函数参数的默认值</li>\n<li>遍历map结构</li>\n<li>输入模块的指定方法</li>\n</ol>\n"},{"title":"基础知识","_content":"\n## 1、0.1+0.2为什么不等于0.3\nJavaScript使用Number类型表示数字(整数和浮点数),遵循 IEEE 754 标准,通过64位来表示一个数字。\nJS中1位符号位,11位的指数e,剩余52位是尾数。\njs最大安全数是 Number.MAX_SAFE_INTEGER == Math.pow(2,53) - 1。本来应该是Math.pow(2,52)-1,但是二进制表示的有效数字总是1.xxx。\n计算机无法计算10进制,因此会先按照IEEE 754转换成二进制进行运算。\n浮点数运算的五个步骤:对阶、尾数运算、规格化、舍入处理、溢出判断\n1、0.1和0.2在转化为二进制后,都是无限循环小数,只能保留52位,会有精度损失\n2、在运算时,需要对阶,一般是小阶对大阶,这一步也可能丢失进度,\n3、对阶后进行尾数运算,相加后得到可结果,如果结果的整数部分超过1,需要进行规格化\n4、规格化之后如果小数部分超出52位,需要再次摄入处理\n5、0.1+0.2不涉及溢出判断,直接将结果转为10进制\n\n## 2、[1]==[1]为什么为false\n引用类型的比较,是数组堆内存的地址的比较,两个数组在堆内存中地址是不同的。\n\n## 3、如何将值类型的变量以引用的方式传递\n```javascript\nvar str = \"abcd\"; //基本类型\nvar obj = {\"str\":str}; //引用类型\nvar boj2 = obj; //复制引用地址\nconsole.log(boj2.str); //abcd\nobj.str = \"bcd\";\nconsole.log(boj2.str); //bcd\n```\n## 4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义\nconst定义的Array中间元素可以被修改,const定义的变量保存的是Array的地址,这个变量本身不可以修改,而存在于堆内存的Array本身是可以修改的。\n对于const声明,只是它的赋值操作被冻结了,而值不会因为const而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。\n## 5、null与undefined的区别\nnull表示\"没有对象\",此处不该有值\n\n典型用法\n - 作为函数的参数,表示该函数的参数不是对象\n - 作为对象原型链的终点\n\nundefined表示\"缺少值\",此处该有值,但是还未定义\n - 变量被声明了,但是没有赋值,就是undefined\n - 调用函数时,应该提供的参数没有提供,该参数等于undefined\n - 对象没有赋值的属性,该属性的值为undefined\n - 函数没有返回值时,默认返回undefined \n\n要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,它们就是相等的,在ECMAScript规范中也是这样定义的。\n## 6. ==和===的操作流程\n这两个操作符都会先转换操作,再比较它们的相等性\n转化基本规则\n1. 如果有一个操作数是布尔值,则在比较相等性之前现将其转换为数值-false转换为0,true转换为1\n2. 如果有一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值\n3. 如果一个操作数是对象,另一个操作数不是,则调用对象valueOf( )方法,用得到的基本类型值按照前面的规则进行比较\n4. 如果一个操作数是布尔值,另一个操作数是字符串,会把双方转换为数字,再进行比较\n\n比较时遵循规则:\n1. null和undefined相等\n2. 比较相等性之前,不能把null和undefined转换成任何其他值\n3. 如果有一个操作数是NaN,一定返回false,包括NaN==NaN\n4. 如果两个操作数都是对象,则比较它们是不是同一个对象\n\n## 7. JavaScript中不同类型以及不同环境下变量的内存都是何时释放\n引用类型是在没有引用之后,通过V8的GC自动回收。\n值类型如果处于闭包的情况下,要等闭包没有引用才会被GC回收,非闭包的情况下,等待V8的新生代(new space)切换的时候回收。\n如何爆掉JS的内存\n数组循环赋值\n```javascript\nlet arr = [];\nwhile(true) {\n arr.push(1);\n}\n```\n随着死循环会查出数组的最大长度,报错。\nFATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory\n\n数组循环赋空值\n```javascript\nlet arr = [];\nwhile(true){\n arr.push();\n}\n```\n死循环,不会爆掉V8内存,但是导致进程阻塞。\n\npush Buffer类型\n```javascript\nlet arr = [];\nwhile(true){\n arr.push(new Buffer(1000));\n}\n```\n内存泄露的速度比直接push Number类型的慢很多。\n因为ES定义的Number类型,实质上是遵循IEEE-2008的64位存储,也就是说,Number类型的1与buffer类型的1,完全不一样,前者在编译器中是00000000000000000000000000(63个0)1,占了64位;但是后者就只是1,只占了1位。当push buffer崩溃时,也会崩溃,只不过比Number类型的慢一些。\n当push buffer崩溃时...不存在的,push buffer不会崩溃,当内存顶到爆,也就是即将到达100%时,会自动垃圾回收,直观地讲,就是会瞬间降低内存,push工作继续,很是神奇。\n\n## 8. JS中typeof的类型有哪些\n```javascript\n console.log(typeof undefined); //undefined\n console.log(typeof 123); //number\n console.log(typeof '123'); //string\n console.log(typeof true); //boolean\n console.log(typeof [1,2,3]); //object\n console.log(typeof {\"id\": 11}); //object\n console.log(typeof null); //object\n console.log(typeof console.log); //function\n```\n## 9. koa 的中间件机制\n1. app.use函数,在application中将调用use的参数都添加到this.middleware数组中\n2. 在push时,对generator语法进行兼容,调用convert函数将其转换为async/await语法\n3. 源码中,通过 compose() 这个方法,就能将我们传入的中间件数组转换并级联执行,最后 callback() 返回this.handleRequest()的执行结果。\ncompose的函数源码\n```javascript\nfunction compose (middleware) {\n if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')\n for (const fn of middleware) {\n if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')\n }\n\n /**\n * @param {Object} context\n * @return {Promise}\n * @api public\n */\n\n return function (context, next) {\n // last called middleware #\n let index = -1\n return dispatch(0)\n function dispatch (i) {\n if (i <= index) return Promise.reject(new Error('next() called multiple times'))\n index = i\n let fn = middleware[i]\n if (i === middleware.length) fn = next\n if (!fn) return Promise.resolve()\n try {\n return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));\n } catch (err) {\n return Promise.reject(err)\n }\n }\n }\n}\n```\n1. compose()返回一个匿名函数的结果,匿名函数自执行了dispatch() 这个函数,并传入了0作为参数。\n2. 上面的代码执行了中间件 fn(context, next),并传递了 context 和 next 函数两个参数。context 就是 koa 中的上下文对象 context。至于 next 函数则是返回一个 dispatch(i+1) 的执行结果。值得一提的是 i+1 这个参数,传递这个参数就相当于执行了下一个中间件,从而形成递归调用。\n3. 只有执行了 next 函数,才能正确得执行下一个中间件。\n 所以当我们用 async 的语法写中间件的时候,执行流程大致如下:\n\n 1. 先执行第一个中间件(因为compose 会默认执行 dispatch(0)),该中间件返回 Promise,然后被 Koa 监听,执行对应的逻辑(成功或失败)\n 2. 在执行第一个中间件的逻辑时,遇到 await next()时,会继续执行 dispatch(i+1),也就是执行 dispatch(1),会手动触发执行第二个中间件。这时候,第一个中间件 await next() 后面的代码就会被 pending,等待 await next() 返回 Promise,才会继续执行第一个中间件 await next() 后面的代码。\n 3. 同样的在执行第二个中间件的时候,遇到 await next() 的时候,会手动执行第三个中间件,await next() 后面的代码依然被 pending,等待 await 下一个中间件的 Promise.resolve。只有在接收到第三个中间件的 resolve 后才会执行后面的代码,然后第二个中间会返回 Promise,被第一个中间件的 await 捕获,这时候才会执行第一个中间件的后续代码,然后再返回 Promise\n 4. 以此类推,如果有多个中间件的时候,会依照上面的逻辑不断执行,先执行第一个中间件,在 await next() 出 pending,继续执行第二个中间件,继续在 await next() 出 pending,继续执行第三个中间,直到最后一个中间件执行完,然后返回 Promise,然后倒数第二个中间件才执行后续的代码并返回Promise,然后是倒数第三个中间件,接着一直以这种方式执行直到第一个中间件执行完,并返回 Promise,从而实现文章开头那张图的执行顺序。\n","source":"_posts/js_basic/01-basic-info.md","raw":"---\ntitle: 基础知识\n---\n\n## 1、0.1+0.2为什么不等于0.3\nJavaScript使用Number类型表示数字(整数和浮点数),遵循 IEEE 754 标准,通过64位来表示一个数字。\nJS中1位符号位,11位的指数e,剩余52位是尾数。\njs最大安全数是 Number.MAX_SAFE_INTEGER == Math.pow(2,53) - 1。本来应该是Math.pow(2,52)-1,但是二进制表示的有效数字总是1.xxx。\n计算机无法计算10进制,因此会先按照IEEE 754转换成二进制进行运算。\n浮点数运算的五个步骤:对阶、尾数运算、规格化、舍入处理、溢出判断\n1、0.1和0.2在转化为二进制后,都是无限循环小数,只能保留52位,会有精度损失\n2、在运算时,需要对阶,一般是小阶对大阶,这一步也可能丢失进度,\n3、对阶后进行尾数运算,相加后得到可结果,如果结果的整数部分超过1,需要进行规格化\n4、规格化之后如果小数部分超出52位,需要再次摄入处理\n5、0.1+0.2不涉及溢出判断,直接将结果转为10进制\n\n## 2、[1]==[1]为什么为false\n引用类型的比较,是数组堆内存的地址的比较,两个数组在堆内存中地址是不同的。\n\n## 3、如何将值类型的变量以引用的方式传递\n```javascript\nvar str = \"abcd\"; //基本类型\nvar obj = {\"str\":str}; //引用类型\nvar boj2 = obj; //复制引用地址\nconsole.log(boj2.str); //abcd\nobj.str = \"bcd\";\nconsole.log(boj2.str); //bcd\n```\n## 4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义\nconst定义的Array中间元素可以被修改,const定义的变量保存的是Array的地址,这个变量本身不可以修改,而存在于堆内存的Array本身是可以修改的。\n对于const声明,只是它的赋值操作被冻结了,而值不会因为const而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。\n## 5、null与undefined的区别\nnull表示\"没有对象\",此处不该有值\n\n典型用法\n - 作为函数的参数,表示该函数的参数不是对象\n - 作为对象原型链的终点\n\nundefined表示\"缺少值\",此处该有值,但是还未定义\n - 变量被声明了,但是没有赋值,就是undefined\n - 调用函数时,应该提供的参数没有提供,该参数等于undefined\n - 对象没有赋值的属性,该属性的值为undefined\n - 函数没有返回值时,默认返回undefined \n\n要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,它们就是相等的,在ECMAScript规范中也是这样定义的。\n## 6. ==和===的操作流程\n这两个操作符都会先转换操作,再比较它们的相等性\n转化基本规则\n1. 如果有一个操作数是布尔值,则在比较相等性之前现将其转换为数值-false转换为0,true转换为1\n2. 如果有一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值\n3. 如果一个操作数是对象,另一个操作数不是,则调用对象valueOf( )方法,用得到的基本类型值按照前面的规则进行比较\n4. 如果一个操作数是布尔值,另一个操作数是字符串,会把双方转换为数字,再进行比较\n\n比较时遵循规则:\n1. null和undefined相等\n2. 比较相等性之前,不能把null和undefined转换成任何其他值\n3. 如果有一个操作数是NaN,一定返回false,包括NaN==NaN\n4. 如果两个操作数都是对象,则比较它们是不是同一个对象\n\n## 7. JavaScript中不同类型以及不同环境下变量的内存都是何时释放\n引用类型是在没有引用之后,通过V8的GC自动回收。\n值类型如果处于闭包的情况下,要等闭包没有引用才会被GC回收,非闭包的情况下,等待V8的新生代(new space)切换的时候回收。\n如何爆掉JS的内存\n数组循环赋值\n```javascript\nlet arr = [];\nwhile(true) {\n arr.push(1);\n}\n```\n随着死循环会查出数组的最大长度,报错。\nFATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory\n\n数组循环赋空值\n```javascript\nlet arr = [];\nwhile(true){\n arr.push();\n}\n```\n死循环,不会爆掉V8内存,但是导致进程阻塞。\n\npush Buffer类型\n```javascript\nlet arr = [];\nwhile(true){\n arr.push(new Buffer(1000));\n}\n```\n内存泄露的速度比直接push Number类型的慢很多。\n因为ES定义的Number类型,实质上是遵循IEEE-2008的64位存储,也就是说,Number类型的1与buffer类型的1,完全不一样,前者在编译器中是00000000000000000000000000(63个0)1,占了64位;但是后者就只是1,只占了1位。当push buffer崩溃时,也会崩溃,只不过比Number类型的慢一些。\n当push buffer崩溃时...不存在的,push buffer不会崩溃,当内存顶到爆,也就是即将到达100%时,会自动垃圾回收,直观地讲,就是会瞬间降低内存,push工作继续,很是神奇。\n\n## 8. JS中typeof的类型有哪些\n```javascript\n console.log(typeof undefined); //undefined\n console.log(typeof 123); //number\n console.log(typeof '123'); //string\n console.log(typeof true); //boolean\n console.log(typeof [1,2,3]); //object\n console.log(typeof {\"id\": 11}); //object\n console.log(typeof null); //object\n console.log(typeof console.log); //function\n```\n## 9. koa 的中间件机制\n1. app.use函数,在application中将调用use的参数都添加到this.middleware数组中\n2. 在push时,对generator语法进行兼容,调用convert函数将其转换为async/await语法\n3. 源码中,通过 compose() 这个方法,就能将我们传入的中间件数组转换并级联执行,最后 callback() 返回this.handleRequest()的执行结果。\ncompose的函数源码\n```javascript\nfunction compose (middleware) {\n if (!Array.isArray(middleware)) throw new TypeError('Middleware stack must be an array!')\n for (const fn of middleware) {\n if (typeof fn !== 'function') throw new TypeError('Middleware must be composed of functions!')\n }\n\n /**\n * @param {Object} context\n * @return {Promise}\n * @api public\n */\n\n return function (context, next) {\n // last called middleware #\n let index = -1\n return dispatch(0)\n function dispatch (i) {\n if (i <= index) return Promise.reject(new Error('next() called multiple times'))\n index = i\n let fn = middleware[i]\n if (i === middleware.length) fn = next\n if (!fn) return Promise.resolve()\n try {\n return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));\n } catch (err) {\n return Promise.reject(err)\n }\n }\n }\n}\n```\n1. compose()返回一个匿名函数的结果,匿名函数自执行了dispatch() 这个函数,并传入了0作为参数。\n2. 上面的代码执行了中间件 fn(context, next),并传递了 context 和 next 函数两个参数。context 就是 koa 中的上下文对象 context。至于 next 函数则是返回一个 dispatch(i+1) 的执行结果。值得一提的是 i+1 这个参数,传递这个参数就相当于执行了下一个中间件,从而形成递归调用。\n3. 只有执行了 next 函数,才能正确得执行下一个中间件。\n 所以当我们用 async 的语法写中间件的时候,执行流程大致如下:\n\n 1. 先执行第一个中间件(因为compose 会默认执行 dispatch(0)),该中间件返回 Promise,然后被 Koa 监听,执行对应的逻辑(成功或失败)\n 2. 在执行第一个中间件的逻辑时,遇到 await next()时,会继续执行 dispatch(i+1),也就是执行 dispatch(1),会手动触发执行第二个中间件。这时候,第一个中间件 await next() 后面的代码就会被 pending,等待 await next() 返回 Promise,才会继续执行第一个中间件 await next() 后面的代码。\n 3. 同样的在执行第二个中间件的时候,遇到 await next() 的时候,会手动执行第三个中间件,await next() 后面的代码依然被 pending,等待 await 下一个中间件的 Promise.resolve。只有在接收到第三个中间件的 resolve 后才会执行后面的代码,然后第二个中间会返回 Promise,被第一个中间件的 await 捕获,这时候才会执行第一个中间件的后续代码,然后再返回 Promise\n 4. 以此类推,如果有多个中间件的时候,会依照上面的逻辑不断执行,先执行第一个中间件,在 await next() 出 pending,继续执行第二个中间件,继续在 await next() 出 pending,继续执行第三个中间,直到最后一个中间件执行完,然后返回 Promise,然后倒数第二个中间件才执行后续的代码并返回Promise,然后是倒数第三个中间件,接着一直以这种方式执行直到第一个中间件执行完,并返回 Promise,从而实现文章开头那张图的执行顺序。\n","slug":"js_basic/01-basic-info","published":1,"date":"2021-03-01T08:10:55.197Z","updated":"2021-03-12T03:36:38.809Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk110009f1vph47h7zqk","content":"<h2><span id=\"1-0102为什么不等于03\">1、0.1+0.2为什么不等于0.3</span></h2><p>JavaScript使用Number类型表示数字(整数和浮点数),遵循 IEEE 754 标准,通过64位来表示一个数字。<br>JS中1位符号位,11位的指数e,剩余52位是尾数。<br>js最大安全数是 Number.MAX_SAFE_INTEGER == Math.pow(2,53) - 1。本来应该是Math.pow(2,52)-1,但是二进制表示的有效数字总是1.xxx。<br>计算机无法计算10进制,因此会先按照IEEE 754转换成二进制进行运算。<br>浮点数运算的五个步骤:对阶、尾数运算、规格化、舍入处理、溢出判断<br>1、0.1和0.2在转化为二进制后,都是无限循环小数,只能保留52位,会有精度损失<br>2、在运算时,需要对阶,一般是小阶对大阶,这一步也可能丢失进度,<br>3、对阶后进行尾数运算,相加后得到可结果,如果结果的整数部分超过1,需要进行规格化<br>4、规格化之后如果小数部分超出52位,需要再次摄入处理<br>5、0.1+0.2不涉及溢出判断,直接将结果转为10进制</p>\n<h2><span id=\"2-11为什么为false\">2、[1]==[1]为什么为false</span></h2><p>引用类型的比较,是数组堆内存的地址的比较,两个数组在堆内存中地址是不同的。</p>\n<h2><span id=\"3-如何将值类型的变量以引用的方式传递\">3、如何将值类型的变量以引用的方式传递</span></h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> str <span class=\"token operator\">=</span> <span class=\"token string\">\"abcd\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//基本类型</span>\n<span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"str\"</span><span class=\"token operator\">:</span>str<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//引用类型</span>\n<span class=\"token keyword\">var</span> boj2 <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">;</span> <span class=\"token comment\">//复制引用地址</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>boj2<span class=\"token punctuation\">.</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//abcd</span>\nobj<span class=\"token punctuation\">.</span>str <span class=\"token operator\">=</span> <span class=\"token string\">\"bcd\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>boj2<span class=\"token punctuation\">.</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//bcd</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<h2><span id=\"4-const定义的array中间元素是否可以被修改如果可以那么const修饰对象有什么意义\">4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义</span></h2><p>const定义的Array中间元素可以被修改,const定义的变量保存的是Array的地址,这个变量本身不可以修改,而存在于堆内存的Array本身是可以修改的。<br>对于const声明,只是它的赋值操作被冻结了,而值不会因为const而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。</p>\n<h2><span id=\"5-null与undefined的区别\">5、null与undefined的区别</span></h2><p>null表示”没有对象”,此处不该有值</p>\n<p>典型用法</p>\n<ul>\n<li>作为函数的参数,表示该函数的参数不是对象</li>\n<li>作为对象原型链的终点</li>\n</ul>\n<p>undefined表示”缺少值”,此处该有值,但是还未定义</p>\n<ul>\n<li>变量被声明了,但是没有赋值,就是undefined</li>\n<li>调用函数时,应该提供的参数没有提供,该参数等于undefined</li>\n<li>对象没有赋值的属性,该属性的值为undefined</li>\n<li>函数没有返回值时,默认返回undefined </li>\n</ul>\n<p>要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,它们就是相等的,在ECMAScript规范中也是这样定义的。</p>\n<h2><span id=\"6-和的操作流程\">6. ==和===的操作流程</span></h2><p>这两个操作符都会先转换操作,再比较它们的相等性<br>转化基本规则</p>\n<ol>\n<li>如果有一个操作数是布尔值,则在比较相等性之前现将其转换为数值-false转换为0,true转换为1</li>\n<li>如果有一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值</li>\n<li>如果一个操作数是对象,另一个操作数不是,则调用对象valueOf( )方法,用得到的基本类型值按照前面的规则进行比较</li>\n<li>如果一个操作数是布尔值,另一个操作数是字符串,会把双方转换为数字,再进行比较</li>\n</ol>\n<p>比较时遵循规则:</p>\n<ol>\n<li>null和undefined相等</li>\n<li>比较相等性之前,不能把null和undefined转换成任何其他值</li>\n<li>如果有一个操作数是NaN,一定返回false,包括NaN==NaN</li>\n<li>如果两个操作数都是对象,则比较它们是不是同一个对象</li>\n</ol>\n<h2><span id=\"7-javascript中不同类型以及不同环境下变量的内存都是何时释放\">7. JavaScript中不同类型以及不同环境下变量的内存都是何时释放</span></h2><p>引用类型是在没有引用之后,通过V8的GC自动回收。<br>值类型如果处于闭包的情况下,要等闭包没有引用才会被GC回收,非闭包的情况下,等待V8的新生代(new space)切换的时候回收。<br>如何爆掉JS的内存<br>数组循环赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>随着死循环会查出数组的最大长度,报错。<br>FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory</p>\n<p>数组循环赋空值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>死循环,不会爆掉V8内存,但是导致进程阻塞。</p>\n<p>push Buffer类型</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Buffer</span><span class=\"token punctuation\">(</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>内存泄露的速度比直接push Number类型的慢很多。<br>因为ES定义的Number类型,实质上是遵循IEEE-2008的64位存储,也就是说,Number类型的1与buffer类型的1,完全不一样,前者在编译器中是00000000000000000000000000(63个0)1,占了64位;但是后者就只是1,只占了1位。当push buffer崩溃时,也会崩溃,只不过比Number类型的慢一些。<br>当push buffer崩溃时…不存在的,push buffer不会崩溃,当内存顶到爆,也就是即将到达100%时,会自动垃圾回收,直观地讲,就是会瞬间降低内存,push工作继续,很是神奇。</p>\n<h2><span id=\"8-js中typeof的类型有哪些\">8. JS中typeof的类型有哪些</span></h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//undefined</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token number\">123</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//number</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token string\">'123'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//string</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//boolean</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">11</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> console<span class=\"token punctuation\">.</span>log<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//function</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<h2><span id=\"9-koa-的中间件机制\">9. koa 的中间件机制</span></h2><ol>\n<li><p>app.use函数,在application中将调用use的参数都添加到this.middleware数组中</p>\n</li>\n<li><p>在push时,对generator语法进行兼容,调用convert函数将其转换为async/await语法</p>\n</li>\n<li><p>源码中,通过 compose() 这个方法,就能将我们传入的中间件数组转换并级联执行,最后 callback() 返回this.handleRequest()的执行结果。<br>compose的函数源码</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">compose</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">middleware</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>middleware<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TypeError</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Middleware stack must be an array!'</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> fn <span class=\"token keyword\">of</span> middleware<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> fn <span class=\"token operator\">!==</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TypeError</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Middleware must be composed of functions!'</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">/**\n * @param {Object} context\n * @return {Promise}\n * @api public\n */</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token comment\">// last called middleware #</span>\n <span class=\"token keyword\">let</span> index <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">dispatch</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">i</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\"><=</span> index<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">reject</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'next() called multiple times'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n index <span class=\"token operator\">=</span> i\n <span class=\"token keyword\">let</span> fn <span class=\"token operator\">=</span> middleware<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">===</span> middleware<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">)</span> fn <span class=\"token operator\">=</span> next\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>fn<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">reject</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n<li><p>compose()返回一个匿名函数的结果,匿名函数自执行了dispatch() 这个函数,并传入了0作为参数。</p>\n</li>\n<li><p>上面的代码执行了中间件 fn(context, next),并传递了 context 和 next 函数两个参数。context 就是 koa 中的上下文对象 context。至于 next 函数则是返回一个 dispatch(i+1) 的执行结果。值得一提的是 i+1 这个参数,传递这个参数就相当于执行了下一个中间件,从而形成递归调用。</p>\n</li>\n<li><p>只有执行了 next 函数,才能正确得执行下一个中间件。<br>所以当我们用 async 的语法写中间件的时候,执行流程大致如下:</p>\n<ol>\n<li>先执行第一个中间件(因为compose 会默认执行 dispatch(0)),该中间件返回 Promise,然后被 Koa 监听,执行对应的逻辑(成功或失败)</li>\n<li>在执行第一个中间件的逻辑时,遇到 await next()时,会继续执行 dispatch(i+1),也就是执行 dispatch(1),会手动触发执行第二个中间件。这时候,第一个中间件 await next() 后面的代码就会被 pending,等待 await next() 返回 Promise,才会继续执行第一个中间件 await next() 后面的代码。</li>\n<li>同样的在执行第二个中间件的时候,遇到 await next() 的时候,会手动执行第三个中间件,await next() 后面的代码依然被 pending,等待 await 下一个中间件的 Promise.resolve。只有在接收到第三个中间件的 resolve 后才会执行后面的代码,然后第二个中间会返回 Promise,被第一个中间件的 await 捕获,这时候才会执行第一个中间件的后续代码,然后再返回 Promise</li>\n<li>以此类推,如果有多个中间件的时候,会依照上面的逻辑不断执行,先执行第一个中间件,在 await next() 出 pending,继续执行第二个中间件,继续在 await next() 出 pending,继续执行第三个中间,直到最后一个中间件执行完,然后返回 Promise,然后倒数第二个中间件才执行后续的代码并返回Promise,然后是倒数第三个中间件,接着一直以这种方式执行直到第一个中间件执行完,并返回 Promise,从而实现文章开头那张图的执行顺序。</li>\n</ol>\n</li>\n</ol>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"1、0-1-0-2为什么不等于0-3\"><a href=\"#1、0-1-0-2为什么不等于0-3\" class=\"headerlink\" title=\"1、0.1+0.2为什么不等于0.3\"></a>1、0.1+0.2为什么不等于0.3</h2><p>JavaScript使用Number类型表示数字(整数和浮点数),遵循 IEEE 754 标准,通过64位来表示一个数字。<br>JS中1位符号位,11位的指数e,剩余52位是尾数。<br>js最大安全数是 Number.MAX_SAFE_INTEGER == Math.pow(2,53) - 1。本来应该是Math.pow(2,52)-1,但是二进制表示的有效数字总是1.xxx。<br>计算机无法计算10进制,因此会先按照IEEE 754转换成二进制进行运算。<br>浮点数运算的五个步骤:对阶、尾数运算、规格化、舍入处理、溢出判断<br>1、0.1和0.2在转化为二进制后,都是无限循环小数,只能保留52位,会有精度损失<br>2、在运算时,需要对阶,一般是小阶对大阶,这一步也可能丢失进度,<br>3、对阶后进行尾数运算,相加后得到可结果,如果结果的整数部分超过1,需要进行规格化<br>4、规格化之后如果小数部分超出52位,需要再次摄入处理<br>5、0.1+0.2不涉及溢出判断,直接将结果转为10进制</p>\n<h2 id=\"2、-1-1-为什么为false\"><a href=\"#2、-1-1-为什么为false\" class=\"headerlink\" title=\"2、[1]==[1]为什么为false\"></a>2、[1]==[1]为什么为false</h2><p>引用类型的比较,是数组堆内存的地址的比较,两个数组在堆内存中地址是不同的。</p>\n<h2 id=\"3、如何将值类型的变量以引用的方式传递\"><a href=\"#3、如何将值类型的变量以引用的方式传递\" class=\"headerlink\" title=\"3、如何将值类型的变量以引用的方式传递\"></a>3、如何将值类型的变量以引用的方式传递</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> str <span class=\"token operator\">=</span> <span class=\"token string\">\"abcd\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//基本类型</span>\n<span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"str\"</span><span class=\"token operator\">:</span>str<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//引用类型</span>\n<span class=\"token keyword\">var</span> boj2 <span class=\"token operator\">=</span> obj<span class=\"token punctuation\">;</span> <span class=\"token comment\">//复制引用地址</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>boj2<span class=\"token punctuation\">.</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//abcd</span>\nobj<span class=\"token punctuation\">.</span>str <span class=\"token operator\">=</span> <span class=\"token string\">\"bcd\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>boj2<span class=\"token punctuation\">.</span>str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//bcd</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<h2 id=\"4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义\"><a href=\"#4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义\" class=\"headerlink\" title=\"4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义\"></a>4、const定义的Array中间元素是否可以被修改?如果可以,那么const修饰对象有什么意义</h2><p>const定义的Array中间元素可以被修改,const定义的变量保存的是Array的地址,这个变量本身不可以修改,而存在于堆内存的Array本身是可以修改的。<br>对于const声明,只是它的赋值操作被冻结了,而值不会因为const而不变。主要是预防在coding过程中的coder因为疏忽对变量的意外修改。</p>\n<h2 id=\"5、null与undefined的区别\"><a href=\"#5、null与undefined的区别\" class=\"headerlink\" title=\"5、null与undefined的区别\"></a>5、null与undefined的区别</h2><p>null表示”没有对象”,此处不该有值</p>\n<p>典型用法</p>\n<ul>\n<li>作为函数的参数,表示该函数的参数不是对象</li>\n<li>作为对象原型链的终点</li>\n</ul>\n<p>undefined表示”缺少值”,此处该有值,但是还未定义</p>\n<ul>\n<li>变量被声明了,但是没有赋值,就是undefined</li>\n<li>调用函数时,应该提供的参数没有提供,该参数等于undefined</li>\n<li>对象没有赋值的属性,该属性的值为undefined</li>\n<li>函数没有返回值时,默认返回undefined </li>\n</ul>\n<p>要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,它们就是相等的,在ECMAScript规范中也是这样定义的。</p>\n<h2 id=\"6-和-的操作流程\"><a href=\"#6-和-的操作流程\" class=\"headerlink\" title=\"6. ==和===的操作流程\"></a>6. ==和===的操作流程</h2><p>这两个操作符都会先转换操作,再比较它们的相等性<br>转化基本规则</p>\n<ol>\n<li>如果有一个操作数是布尔值,则在比较相等性之前现将其转换为数值-false转换为0,true转换为1</li>\n<li>如果有一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值</li>\n<li>如果一个操作数是对象,另一个操作数不是,则调用对象valueOf( )方法,用得到的基本类型值按照前面的规则进行比较</li>\n<li>如果一个操作数是布尔值,另一个操作数是字符串,会把双方转换为数字,再进行比较</li>\n</ol>\n<p>比较时遵循规则:</p>\n<ol>\n<li>null和undefined相等</li>\n<li>比较相等性之前,不能把null和undefined转换成任何其他值</li>\n<li>如果有一个操作数是NaN,一定返回false,包括NaN==NaN</li>\n<li>如果两个操作数都是对象,则比较它们是不是同一个对象</li>\n</ol>\n<h2 id=\"7-JavaScript中不同类型以及不同环境下变量的内存都是何时释放\"><a href=\"#7-JavaScript中不同类型以及不同环境下变量的内存都是何时释放\" class=\"headerlink\" title=\"7. JavaScript中不同类型以及不同环境下变量的内存都是何时释放\"></a>7. JavaScript中不同类型以及不同环境下变量的内存都是何时释放</h2><p>引用类型是在没有引用之后,通过V8的GC自动回收。<br>值类型如果处于闭包的情况下,要等闭包没有引用才会被GC回收,非闭包的情况下,等待V8的新生代(new space)切换的时候回收。<br>如何爆掉JS的内存<br>数组循环赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>随着死循环会查出数组的最大长度,报错。<br>FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory</p>\n<p>数组循环赋空值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>死循环,不会爆掉V8内存,但是导致进程阻塞。</p>\n<p>push Buffer类型</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n arr<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Buffer</span><span class=\"token punctuation\">(</span><span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>内存泄露的速度比直接push Number类型的慢很多。<br>因为ES定义的Number类型,实质上是遵循IEEE-2008的64位存储,也就是说,Number类型的1与buffer类型的1,完全不一样,前者在编译器中是00000000000000000000000000(63个0)1,占了64位;但是后者就只是1,只占了1位。当push buffer崩溃时,也会崩溃,只不过比Number类型的慢一些。<br>当push buffer崩溃时…不存在的,push buffer不会崩溃,当内存顶到爆,也就是即将到达100%时,会自动垃圾回收,直观地讲,就是会瞬间降低内存,push工作继续,很是神奇。</p>\n<h2 id=\"8-JS中typeof的类型有哪些\"><a href=\"#8-JS中typeof的类型有哪些\" class=\"headerlink\" title=\"8. JS中typeof的类型有哪些\"></a>8. JS中typeof的类型有哪些</h2><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\">console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token keyword\">undefined</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//undefined</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token number\">123</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//number</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token string\">'123'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//string</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//boolean</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"id\"</span><span class=\"token operator\">:</span> <span class=\"token number\">11</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//object</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> console<span class=\"token punctuation\">.</span>log<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//function</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<h2 id=\"9-koa-的中间件机制\"><a href=\"#9-koa-的中间件机制\" class=\"headerlink\" title=\"9. koa 的中间件机制\"></a>9. koa 的中间件机制</h2><ol>\n<li><p>app.use函数,在application中将调用use的参数都添加到this.middleware数组中</p>\n</li>\n<li><p>在push时,对generator语法进行兼容,调用convert函数将其转换为async/await语法</p>\n</li>\n<li><p>源码中,通过 compose() 这个方法,就能将我们传入的中间件数组转换并级联执行,最后 callback() 返回this.handleRequest()的执行结果。<br>compose的函数源码</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">compose</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">middleware</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>middleware<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TypeError</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Middleware stack must be an array!'</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> fn <span class=\"token keyword\">of</span> middleware<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> fn <span class=\"token operator\">!==</span> <span class=\"token string\">'function'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">TypeError</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Middleware must be composed of functions!'</span><span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">/**\n * @param {Object} context\n * @return {Promise}\n * @api public\n */</span>\n\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">context<span class=\"token punctuation\">,</span> next</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token comment\">// last called middleware #</span>\n <span class=\"token keyword\">let</span> index <span class=\"token operator\">=</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span>\n <span class=\"token keyword\">return</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">function</span> <span class=\"token function\">dispatch</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">i</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\"><=</span> index<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">reject</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'next() called multiple times'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n index <span class=\"token operator\">=</span> i\n <span class=\"token keyword\">let</span> fn <span class=\"token operator\">=</span> middleware<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span>\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>i <span class=\"token operator\">===</span> middleware<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">)</span> fn <span class=\"token operator\">=</span> next\n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>fn<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token function\">fn</span><span class=\"token punctuation\">(</span>context<span class=\"token punctuation\">,</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> i <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">reject</span><span class=\"token punctuation\">(</span>err<span class=\"token punctuation\">)</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre></li>\n<li><p>compose()返回一个匿名函数的结果,匿名函数自执行了dispatch() 这个函数,并传入了0作为参数。</p>\n</li>\n<li><p>上面的代码执行了中间件 fn(context, next),并传递了 context 和 next 函数两个参数。context 就是 koa 中的上下文对象 context。至于 next 函数则是返回一个 dispatch(i+1) 的执行结果。值得一提的是 i+1 这个参数,传递这个参数就相当于执行了下一个中间件,从而形成递归调用。</p>\n</li>\n<li><p>只有执行了 next 函数,才能正确得执行下一个中间件。<br>所以当我们用 async 的语法写中间件的时候,执行流程大致如下:</p>\n<ol>\n<li>先执行第一个中间件(因为compose 会默认执行 dispatch(0)),该中间件返回 Promise,然后被 Koa 监听,执行对应的逻辑(成功或失败)</li>\n<li>在执行第一个中间件的逻辑时,遇到 await next()时,会继续执行 dispatch(i+1),也就是执行 dispatch(1),会手动触发执行第二个中间件。这时候,第一个中间件 await next() 后面的代码就会被 pending,等待 await next() 返回 Promise,才会继续执行第一个中间件 await next() 后面的代码。</li>\n<li>同样的在执行第二个中间件的时候,遇到 await next() 的时候,会手动执行第三个中间件,await next() 后面的代码依然被 pending,等待 await 下一个中间件的 Promise.resolve。只有在接收到第三个中间件的 resolve 后才会执行后面的代码,然后第二个中间会返回 Promise,被第一个中间件的 await 捕获,这时候才会执行第一个中间件的后续代码,然后再返回 Promise</li>\n<li>以此类推,如果有多个中间件的时候,会依照上面的逻辑不断执行,先执行第一个中间件,在 await next() 出 pending,继续执行第二个中间件,继续在 await next() 出 pending,继续执行第三个中间,直到最后一个中间件执行完,然后返回 Promise,然后倒数第二个中间件才执行后续的代码并返回Promise,然后是倒数第三个中间件,接着一直以这种方式执行直到第一个中间件执行完,并返回 Promise,从而实现文章开头那张图的执行顺序。</li>\n</ol>\n</li>\n</ol>\n"},{"title":"JS数组的深拷贝与浅拷贝","_content":"### js数据类型\njs数据类型包含基本数据类型(String,Number,Boolean,Null,Undefined)和引用数据类型(Array,Object,Function)\n### 堆内存和栈内存\n1、栈内存中存放的是存储对象的地址,而堆内存中存放的是存储对象的具体内容。\n2、基本数据类型的地址和具体值都存在于栈内存中,引用数据类型的地址存在于栈内存中,而具体内容存在在堆内存中。\n3、栈内存运行效率比堆内存高,空间相对堆内存来说较小。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。\n### 浅拷贝与深拷贝\n浅拷贝:复制一份引用,所有引用对象都指向一份数据,且都可以修改这份数据。\n深拷贝:复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。\n### 浅拷贝\n#### 数组的浅拷贝\n```javascript\nlet arr1 = [1,2,3];\nlet arr2 = arr1;\narr1[0] = 2;\nconsole.log(arr1[0]); //2\n```\n#### 对象的浅拷贝\n方式1:\n```javascript\nlet srcObj = {'name': 'lilei', 'age': '20'};\nlet copyObj = srcObj;\ncopyObj.age = '22';\nconsole.log('srcObj', srcObj); // srcObj { name: 'lilei', age: '22' }\nconsole.log('copyObj', copyObj); // copyObj { name: 'lilei', age: '22' }\n```\n方式2:Object.assign\n可以处理对象属性为简单类型的深拷贝\n```javascript\nlet srcObj = {'name': 'lilei', 'age': '20'};\nlet copyObj2 = Object.assign({}, srcObj, {'age': '21'});\ncopyObj2.age = '23';\nconsole.log('srcObj', srcObj); //{ name: 'lilei', age: '20' }\n```\n不能处理对象属性为引用类型,则那对于这个对象而言其实是浅拷贝的\n```javascript\nvar obj = { a: {a: \"hello\", b: 21} };\nvar initalObj = Object.assign({}, obj);\ninitalObj.a.a = \"changed\";\nconsole.log(obj.a.a); // \"changed\"\n```\n### 深拷贝\n#### 数组深拷贝\n方式1:直接遍历赋值\n```javascript\nvar arr1 = [1,3,5];\nvar arr2 = [];\narr1.forEach(function(value,index){\narr2[index] = value;\n})\nconsole.log(arr2);\n//这个时候改变arr1[0] = 3;那么输出arr2[0]还是等于1\n```\n方式2:使用slice方法\n```javascript\nvar arr1 = [1,2,3];\nvar arr2 = arr1.slice(0);\nconsole.log(arr2); //[1,2,3]\n```\n方式3:使用concat方法\n```javascript\nvar arr1 = [1,2,3];\nvar arr2 = arr1.concat();\nconsole.log(arr2); //[1,2,3]\n```\n方式4:使用map方法\n```javascript\nvar arr1 = [2,3,4];\nvar arr2 = arr1.map(function(value){\nreturn value; \n})\nconsole.log(arr2); //[2,3,4]\n```\n方式5:ES6扩展运算符\n```javascript\n var arr = [1,2,3,4,5];\n var [ ... arr2 ] = arr;\n console.log(arr); //[1,2,3,4,5]\n console.log(arr2); //[1,2,3,4,5]\n```\n方式6:for-in连原型链也一并复制的方法\n```javascript\nvar arr = [1,2,3,4,5];\narr.prototype = 5;\nvar arr2 = [];\nfor(var a in arr) {\n arr2[a] = arr[a];\n}\nconsole.log(arr2); // [1,2,3,4,5]\nconsole.log(arr2.prototype); // 5\n//之前的方法中新数组的prototype都是undefined\n```\n多维数组的深拷贝\n```javascript\nvar arr = [[1,2],3,4,[5,6]];\nvar arr3 = JSON.parse(JSON.stringify(arr)); \nconsole.log(arr3) // [[1,2],3,4,[5,6]]\n```\n#### 对象深拷贝\n方式1:手动复制\n```javascript\nvar obj1 = { a: 10, b: 20, c: 30 };\nvar obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };\nobj2.b = 100;\nconsole.log(obj1);\n// { a: 10, b: 20, c: 30 } // 沒被改到\nconsole.log(obj2);\n// { a: 10, b: 100, c: 30 }\n```\n方式2:JSON做字符串转换\n```javascript\nvar obj1 = { body: { a: 10 } };\nvar obj2 = JSON.parse(JSON.stringify(obj1));\nobj2.body.a = 20;\nconsole.log(obj1);\n// { body: { a: 10 } }\nconsole.log(obj2);\n// { body: { a: 20 } }\nconsole.log(obj1 === obj2);\n// false\nconsole.log(obj1.body === obj2.body);\n```\n备注:这种方式简单易用,但是会抛弃对象的constructor,无论之前的构造函数是什么,拷贝后都是Object\n这种方法能正确处理的对象只有Number, String, Boolean, Array, 扁平对象,即那些能够被json直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。\n也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。\n方式3:递归拷贝\n```javascript\nfunction deepClone(initalObj, finalObj) { \n var obj = finalObj || {}; \n for (var i in initalObj) { \n var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况\n if(prop === obj) { \n continue;\n } \n if (typeof prop === 'object') {\n obj[i] = (prop.constructor === Array) ? [] : {}; \n arguments.callee(prop, obj[i]);\n } else {\n obj[i] = prop;\n }\n } \n return obj;\n}\nvar str = {};\nvar obj = { a: {a: \"hello\", b: 21} };\ndeepClone(obj, str);\nconsole.log(str.a);\n```","source":"_posts/js_basic/02-js-copy.md","raw":"---\ntitle: JS数组的深拷贝与浅拷贝\n---\n### js数据类型\njs数据类型包含基本数据类型(String,Number,Boolean,Null,Undefined)和引用数据类型(Array,Object,Function)\n### 堆内存和栈内存\n1、栈内存中存放的是存储对象的地址,而堆内存中存放的是存储对象的具体内容。\n2、基本数据类型的地址和具体值都存在于栈内存中,引用数据类型的地址存在于栈内存中,而具体内容存在在堆内存中。\n3、栈内存运行效率比堆内存高,空间相对堆内存来说较小。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。\n### 浅拷贝与深拷贝\n浅拷贝:复制一份引用,所有引用对象都指向一份数据,且都可以修改这份数据。\n深拷贝:复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。\n### 浅拷贝\n#### 数组的浅拷贝\n```javascript\nlet arr1 = [1,2,3];\nlet arr2 = arr1;\narr1[0] = 2;\nconsole.log(arr1[0]); //2\n```\n#### 对象的浅拷贝\n方式1:\n```javascript\nlet srcObj = {'name': 'lilei', 'age': '20'};\nlet copyObj = srcObj;\ncopyObj.age = '22';\nconsole.log('srcObj', srcObj); // srcObj { name: 'lilei', age: '22' }\nconsole.log('copyObj', copyObj); // copyObj { name: 'lilei', age: '22' }\n```\n方式2:Object.assign\n可以处理对象属性为简单类型的深拷贝\n```javascript\nlet srcObj = {'name': 'lilei', 'age': '20'};\nlet copyObj2 = Object.assign({}, srcObj, {'age': '21'});\ncopyObj2.age = '23';\nconsole.log('srcObj', srcObj); //{ name: 'lilei', age: '20' }\n```\n不能处理对象属性为引用类型,则那对于这个对象而言其实是浅拷贝的\n```javascript\nvar obj = { a: {a: \"hello\", b: 21} };\nvar initalObj = Object.assign({}, obj);\ninitalObj.a.a = \"changed\";\nconsole.log(obj.a.a); // \"changed\"\n```\n### 深拷贝\n#### 数组深拷贝\n方式1:直接遍历赋值\n```javascript\nvar arr1 = [1,3,5];\nvar arr2 = [];\narr1.forEach(function(value,index){\narr2[index] = value;\n})\nconsole.log(arr2);\n//这个时候改变arr1[0] = 3;那么输出arr2[0]还是等于1\n```\n方式2:使用slice方法\n```javascript\nvar arr1 = [1,2,3];\nvar arr2 = arr1.slice(0);\nconsole.log(arr2); //[1,2,3]\n```\n方式3:使用concat方法\n```javascript\nvar arr1 = [1,2,3];\nvar arr2 = arr1.concat();\nconsole.log(arr2); //[1,2,3]\n```\n方式4:使用map方法\n```javascript\nvar arr1 = [2,3,4];\nvar arr2 = arr1.map(function(value){\nreturn value; \n})\nconsole.log(arr2); //[2,3,4]\n```\n方式5:ES6扩展运算符\n```javascript\n var arr = [1,2,3,4,5];\n var [ ... arr2 ] = arr;\n console.log(arr); //[1,2,3,4,5]\n console.log(arr2); //[1,2,3,4,5]\n```\n方式6:for-in连原型链也一并复制的方法\n```javascript\nvar arr = [1,2,3,4,5];\narr.prototype = 5;\nvar arr2 = [];\nfor(var a in arr) {\n arr2[a] = arr[a];\n}\nconsole.log(arr2); // [1,2,3,4,5]\nconsole.log(arr2.prototype); // 5\n//之前的方法中新数组的prototype都是undefined\n```\n多维数组的深拷贝\n```javascript\nvar arr = [[1,2],3,4,[5,6]];\nvar arr3 = JSON.parse(JSON.stringify(arr)); \nconsole.log(arr3) // [[1,2],3,4,[5,6]]\n```\n#### 对象深拷贝\n方式1:手动复制\n```javascript\nvar obj1 = { a: 10, b: 20, c: 30 };\nvar obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };\nobj2.b = 100;\nconsole.log(obj1);\n// { a: 10, b: 20, c: 30 } // 沒被改到\nconsole.log(obj2);\n// { a: 10, b: 100, c: 30 }\n```\n方式2:JSON做字符串转换\n```javascript\nvar obj1 = { body: { a: 10 } };\nvar obj2 = JSON.parse(JSON.stringify(obj1));\nobj2.body.a = 20;\nconsole.log(obj1);\n// { body: { a: 10 } }\nconsole.log(obj2);\n// { body: { a: 20 } }\nconsole.log(obj1 === obj2);\n// false\nconsole.log(obj1.body === obj2.body);\n```\n备注:这种方式简单易用,但是会抛弃对象的constructor,无论之前的构造函数是什么,拷贝后都是Object\n这种方法能正确处理的对象只有Number, String, Boolean, Array, 扁平对象,即那些能够被json直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。\n也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。\n方式3:递归拷贝\n```javascript\nfunction deepClone(initalObj, finalObj) { \n var obj = finalObj || {}; \n for (var i in initalObj) { \n var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况\n if(prop === obj) { \n continue;\n } \n if (typeof prop === 'object') {\n obj[i] = (prop.constructor === Array) ? [] : {}; \n arguments.callee(prop, obj[i]);\n } else {\n obj[i] = prop;\n }\n } \n return obj;\n}\nvar str = {};\nvar obj = { a: {a: \"hello\", b: 21} };\ndeepClone(obj, str);\nconsole.log(str.a);\n```","slug":"js_basic/02-js-copy","published":1,"date":"2021-02-26T11:01:03.194Z","updated":"2021-03-02T06:32:52.630Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk12000af1vp5dyo5gtw","content":"<h3><span id=\"js数据类型\">js数据类型</span></h3><p>js数据类型包含基本数据类型(String,Number,Boolean,Null,Undefined)和引用数据类型(Array,Object,Function)</p>\n<h3><span id=\"堆内存和栈内存\">堆内存和栈内存</span></h3><p>1、栈内存中存放的是存储对象的地址,而堆内存中存放的是存储对象的具体内容。<br>2、基本数据类型的地址和具体值都存在于栈内存中,引用数据类型的地址存在于栈内存中,而具体内容存在在堆内存中。<br>3、栈内存运行效率比堆内存高,空间相对堆内存来说较小。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。</p>\n<h3><span id=\"浅拷贝与深拷贝\">浅拷贝与深拷贝</span></h3><p>浅拷贝:复制一份引用,所有引用对象都指向一份数据,且都可以修改这份数据。<br>深拷贝:复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。</p>\n<h3><span id=\"浅拷贝\">浅拷贝</span></h3><h4><span id=\"数组的浅拷贝\">数组的浅拷贝</span></h4><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">;</span>\narr1<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr1<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//2</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<h4><span id=\"对象的浅拷贝\">对象的浅拷贝</span></h4><p>方式1:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> srcObj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'name'</span><span class=\"token operator\">:</span> <span class=\"token string\">'lilei'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'20'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> copyObj <span class=\"token operator\">=</span> srcObj<span class=\"token punctuation\">;</span>\ncopyObj<span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> <span class=\"token string\">'22'</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'srcObj'</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// srcObj { name: 'lilei', age: '22' }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'copyObj'</span><span class=\"token punctuation\">,</span> copyObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// copyObj { name: 'lilei', age: '22' }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:Object.assign<br>可以处理对象属性为简单类型的深拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> srcObj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'name'</span><span class=\"token operator\">:</span> <span class=\"token string\">'lilei'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'20'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> copyObj2 <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">assign</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'21'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ncopyObj2<span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> <span class=\"token string\">'23'</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'srcObj'</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//{ name: 'lilei', age: '20' }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>不能处理对象属性为引用类型,则那对于这个对象而言其实是浅拷贝的</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>a<span class=\"token operator\">:</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">21</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> initalObj <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">assign</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ninitalObj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token string\">\"changed\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// \"changed\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<h3><span id=\"深拷贝\">深拷贝</span></h3><h4><span id=\"数组深拷贝\">数组深拷贝</span></h4><p>方式1:直接遍历赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr1<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value<span class=\"token punctuation\">,</span>index</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\narr2<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">//这个时候改变arr1[0] = 3;那么输出arr2[0]还是等于1</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:使用slice方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>方式3:使用concat方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>方式4:使用map方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">return</span> value<span class=\"token punctuation\">;</span> \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[2,3,4]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式5:ES6扩展运算符</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> <span class=\"token punctuation\">[</span> <span class=\"token operator\">...</span> arr2 <span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3,4,5]</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3,4,5]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式6:for-in连原型链也一并复制的方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> a <span class=\"token keyword\">in</span> arr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n arr2<span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [1,2,3,4,5]</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span>\n<span class=\"token comment\">//之前的方法中新数组的prototype都是undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>多维数组的深拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr3 <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> \nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr3<span class=\"token punctuation\">)</span> <span class=\"token comment\">// [[1,2],3,4,[5,6]]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<h4><span id=\"对象深拷贝\">对象深拷贝</span></h4><p>方式1:手动复制</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">20</span><span class=\"token punctuation\">,</span> c<span class=\"token operator\">:</span> <span class=\"token number\">30</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>b<span class=\"token punctuation\">,</span> c<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>c <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nobj2<span class=\"token punctuation\">.</span>b <span class=\"token operator\">=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { a: 10, b: 20, c: 30 } // 沒被改到</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { a: 10, b: 100, c: 30 }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:JSON做字符串转换</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> body<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token number\">10</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj2 <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj2<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">20</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { body: { a: 10 } }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { body: { a: 20 } }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1 <span class=\"token operator\">===</span> obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// false</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">.</span>body <span class=\"token operator\">===</span> obj2<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>备注:这种方式简单易用,但是会抛弃对象的constructor,无论之前的构造函数是什么,拷贝后都是Object<br>这种方法能正确处理的对象只有Number, String, Boolean, Array, 扁平对象,即那些能够被json直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。<br>也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。<br>方式3:递归拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deepClone</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">initalObj<span class=\"token punctuation\">,</span> finalObj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> finalObj <span class=\"token operator\">||</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> \n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token keyword\">in</span> initalObj<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">var</span> prop <span class=\"token operator\">=</span> initalObj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况</span>\n <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>prop <span class=\"token operator\">===</span> obj<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> \n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> prop <span class=\"token operator\">===</span> <span class=\"token string\">'object'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">===</span> Array<span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> \n arguments<span class=\"token punctuation\">.</span><span class=\"token function\">callee</span><span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">,</span> obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> prop<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span> \n <span class=\"token keyword\">return</span> obj<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">var</span> str <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>a<span class=\"token operator\">:</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">21</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">deepClone</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>","site":{"data":{}},"excerpt":"","more":"<h3 id=\"js数据类型\"><a href=\"#js数据类型\" class=\"headerlink\" title=\"js数据类型\"></a>js数据类型</h3><p>js数据类型包含基本数据类型(String,Number,Boolean,Null,Undefined)和引用数据类型(Array,Object,Function)</p>\n<h3 id=\"堆内存和栈内存\"><a href=\"#堆内存和栈内存\" class=\"headerlink\" title=\"堆内存和栈内存\"></a>堆内存和栈内存</h3><p>1、栈内存中存放的是存储对象的地址,而堆内存中存放的是存储对象的具体内容。<br>2、基本数据类型的地址和具体值都存在于栈内存中,引用数据类型的地址存在于栈内存中,而具体内容存在在堆内存中。<br>3、栈内存运行效率比堆内存高,空间相对堆内存来说较小。所以将构造简单的原始类型值放在栈内存中,将构造复杂的引用类型值放在堆中而不影响栈的效率。</p>\n<h3 id=\"浅拷贝与深拷贝\"><a href=\"#浅拷贝与深拷贝\" class=\"headerlink\" title=\"浅拷贝与深拷贝\"></a>浅拷贝与深拷贝</h3><p>浅拷贝:复制一份引用,所有引用对象都指向一份数据,且都可以修改这份数据。<br>深拷贝:复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。</p>\n<h3 id=\"浅拷贝\"><a href=\"#浅拷贝\" class=\"headerlink\" title=\"浅拷贝\"></a>浅拷贝</h3><h4 id=\"数组的浅拷贝\"><a href=\"#数组的浅拷贝\" class=\"headerlink\" title=\"数组的浅拷贝\"></a>数组的浅拷贝</h4><pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">;</span>\narr1<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr1<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//2</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<h4 id=\"对象的浅拷贝\"><a href=\"#对象的浅拷贝\" class=\"headerlink\" title=\"对象的浅拷贝\"></a>对象的浅拷贝</h4><p>方式1:</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> srcObj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'name'</span><span class=\"token operator\">:</span> <span class=\"token string\">'lilei'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'20'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> copyObj <span class=\"token operator\">=</span> srcObj<span class=\"token punctuation\">;</span>\ncopyObj<span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> <span class=\"token string\">'22'</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'srcObj'</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// srcObj { name: 'lilei', age: '22' }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'copyObj'</span><span class=\"token punctuation\">,</span> copyObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// copyObj { name: 'lilei', age: '22' }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:Object.assign<br>可以处理对象属性为简单类型的深拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">let</span> srcObj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'name'</span><span class=\"token operator\">:</span> <span class=\"token string\">'lilei'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'20'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> copyObj2 <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">assign</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span><span class=\"token string\">'age'</span><span class=\"token operator\">:</span> <span class=\"token string\">'21'</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ncopyObj2<span class=\"token punctuation\">.</span>age <span class=\"token operator\">=</span> <span class=\"token string\">'23'</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'srcObj'</span><span class=\"token punctuation\">,</span> srcObj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//{ name: 'lilei', age: '20' }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>不能处理对象属性为引用类型,则那对于这个对象而言其实是浅拷贝的</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>a<span class=\"token operator\">:</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">21</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> initalObj <span class=\"token operator\">=</span> Object<span class=\"token punctuation\">.</span><span class=\"token function\">assign</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> obj<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\ninitalObj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token string\">\"changed\"</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// \"changed\"</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<h3 id=\"深拷贝\"><a href=\"#深拷贝\" class=\"headerlink\" title=\"深拷贝\"></a>深拷贝</h3><h4 id=\"数组深拷贝\"><a href=\"#数组深拷贝\" class=\"headerlink\" title=\"数组深拷贝\"></a>数组深拷贝</h4><p>方式1:直接遍历赋值</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr1<span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value<span class=\"token punctuation\">,</span>index</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\narr2<span class=\"token punctuation\">[</span>index<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> value<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">//这个时候改变arr1[0] = 3;那么输出arr2[0]还是等于1</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:使用slice方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>方式3:使用concat方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">concat</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<p>方式4:使用map方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> arr1<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n<span class=\"token keyword\">return</span> value<span class=\"token punctuation\">;</span> \n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[2,3,4]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式5:ES6扩展运算符</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> <span class=\"token punctuation\">[</span> <span class=\"token operator\">...</span> arr2 <span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3,4,5]</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">//[1,2,3,4,5]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式6:for-in连原型链也一并复制的方法</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\narr<span class=\"token punctuation\">.</span>prototype <span class=\"token operator\">=</span> <span class=\"token number\">5</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> a <span class=\"token keyword\">in</span> arr<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n arr2<span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> arr<span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// [1,2,3,4,5]</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr2<span class=\"token punctuation\">.</span>prototype<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 5</span>\n<span class=\"token comment\">//之前的方法中新数组的prototype都是undefined</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>多维数组的深拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> arr <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span><span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">,</span><span class=\"token number\">6</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> arr3 <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>arr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> \nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>arr3<span class=\"token punctuation\">)</span> <span class=\"token comment\">// [[1,2],3,4,[5,6]]</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span></span></code></pre>\n<h4 id=\"对象深拷贝\"><a href=\"#对象深拷贝\" class=\"headerlink\" title=\"对象深拷贝\"></a>对象深拷贝</h4><p>方式1:手动复制</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">20</span><span class=\"token punctuation\">,</span> c<span class=\"token operator\">:</span> <span class=\"token number\">30</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj2 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>b<span class=\"token punctuation\">,</span> c<span class=\"token operator\">:</span> obj1<span class=\"token punctuation\">.</span>c <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\nobj2<span class=\"token punctuation\">.</span>b <span class=\"token operator\">=</span> <span class=\"token number\">100</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { a: 10, b: 20, c: 30 } // 沒被改到</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { a: 10, b: 100, c: 30 }</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>方式2:JSON做字符串转换</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> obj1 <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> body<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token number\">10</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj2 <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">parse</span><span class=\"token punctuation\">(</span><span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nobj2<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">.</span>a <span class=\"token operator\">=</span> <span class=\"token number\">20</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { body: { a: 10 } }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// { body: { a: 20 } }</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1 <span class=\"token operator\">===</span> obj2<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// false</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>obj1<span class=\"token punctuation\">.</span>body <span class=\"token operator\">===</span> obj2<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n<p>备注:这种方式简单易用,但是会抛弃对象的constructor,无论之前的构造函数是什么,拷贝后都是Object<br>这种方法能正确处理的对象只有Number, String, Boolean, Array, 扁平对象,即那些能够被json直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。<br>也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。<br>方式3:递归拷贝</p>\n<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">function</span> <span class=\"token function\">deepClone</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">initalObj<span class=\"token punctuation\">,</span> finalObj</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> finalObj <span class=\"token operator\">||</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> \n <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token keyword\">in</span> initalObj<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">var</span> prop <span class=\"token operator\">=</span> initalObj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况</span>\n <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>prop <span class=\"token operator\">===</span> obj<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> \n <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> \n <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> prop <span class=\"token operator\">===</span> <span class=\"token string\">'object'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">.</span>constructor <span class=\"token operator\">===</span> Array<span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> \n arguments<span class=\"token punctuation\">.</span><span class=\"token function\">callee</span><span class=\"token punctuation\">(</span>prop<span class=\"token punctuation\">,</span> obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n obj<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> prop<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n <span class=\"token punctuation\">}</span> \n <span class=\"token keyword\">return</span> obj<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token keyword\">var</span> str <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">var</span> obj <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> a<span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>a<span class=\"token operator\">:</span> <span class=\"token string\">\"hello\"</span><span class=\"token punctuation\">,</span> b<span class=\"token operator\">:</span> <span class=\"token number\">21</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token function\">deepClone</span><span class=\"token punctuation\">(</span>obj<span class=\"token punctuation\">,</span> str<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>str<span class=\"token punctuation\">.</span>a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>"},{"title":"JS垃圾回收机制","_content":"","source":"_posts/js_basic/03-js-gc.md","raw":"---\ntitle: JS垃圾回收机制\n---","slug":"js_basic/03-js-gc","published":1,"date":"2021-03-05T06:20:37.523Z","updated":"2021-03-05T06:20:55.155Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk13000bf1vp62dzdfui","content":"","site":{"data":{}},"excerpt":"","more":""},{"title":"深入浅出Node","_content":"### Node简介\n1. Node的结构与Chrome十分相似,它们都是基于事件驱动的异步架构,浏览器通过事件驱动来服务界面上的交互,Node通过事件驱动来服务IO。\n2. Node的特点\n- 异步I/O\n- 事件与回调函数(事件的编程方式具有轻量级、松耦合、只关注事务点等有事,但是多个异步任务的场景下事件与事件相互独立,如何协作是一个问题。)\n- 单线程(单线程不用在意状态的同步问题,没有死锁,也没有上下文切换带来的性能开销,但是也有无法利用多核CPU、错误会导致整个应用退出、大量计算占用CPU导致无法继续调用异步I/O。Node通过child_process子进程讲计算来利用多核CPU)\n- 跨平台(基于libuv实现了跨平台)\n3. Node的应用场景\n- I/O密集型(面向网络且擅长并行I/O,优势在于Node利用事件循环的处理能力,而不是为每一个请求启动一个线程)。\n- 是否不擅长CPU密集型任务(如果有长时间运行的计算会导致CPU时间片不能释放,后续I/O无法发起。但是只要适当调整和分解大型运算任务为多个小任务,使运算可以适时释放,不阻塞I/O调用发起)\n4. Node的使用者的倚重点\n- 前后端编程语言环境统一\n- Node带来的高性能I/O用于实时应用\n- 并行I/O使得使用者可以更高效利用分布式环境\n- 并行I/O有效利用稳定借口提升Web渲染能力\n- 云计算平台提供Node支持\n- 工具类应用\n\n### 模块机制\n#### CommonJS规范\nCommonJS规范的提出,主要为了弥补当前JS没有标准的缺陷,达到具备开发大型应用的基础能力。\n模块规范\n- 模块引用\n```javascript\nvar math = require('math');\n```\n- 模块定义\n上下文提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一导出的出口。在模块中,还存在一个module对象,代表模块自身,exports是module的属性。\n- 模块标识\n模块标识就是传递给require()方法的参数,必须符合小拖放命名的字符串,或者相对路径or绝对路径。\n### Node的模块实现\n1. Node中引入模块,需要路径分析、文件定位、编译执行三个步骤。\n2. Node中模块分为两类,一类是Node提供的模块称为核心模块。另一类是用户编写的模块,称为文件模块。\n - 核心模块部分在Node源代码的编译过程中,编译进了二进制执行文件。在Node进程启动时,这部分核心模块被直接加载进内存,就可以省略文件定位和编译执行步骤,路径分析中优先判断\n - 文件模块在运行时动态加载,需要三个步骤,会慢一些\n3. Node对引入过的模块都会进行缓存,缓存的是编译和执行之后的对象。无论核心模块还是文件模块,都是优先采用缓存。核心模块的缓存检查先于文件模块的缓存检查。\n4. 路径分析和文件定位\n###### 模块标识符分析:\n - 模块加载速度:缓存模块<核心模块<路径形式的文件模块<自定义模块\n###### 文件定位分析:\n - 文件扩展名分析,Node会按照.js .json .node的次序补足扩展名,依次尝试。尝试过程中,需要调用fs模块同步阻塞式地判断文件是否存在。\n - 目录分析和包:分析标识符查找到一个目录,Node会当成一个包来处理。会去查找包里面是否有package.json,取出main属性指定的文件来定位。\n如果main属性指定文件名错误,会将index当做默认文件名。如果这一级目录还没有找到,会下一个模块路径进行遍历。如果所有模块路径都找不到,就跑出查找失败的异常。\n###### 模块编译:\n编译和执行是引入文件模块的最后一个阶段。定位到具体的文件后,Node会新建一个模块对象,根据路径载入并编译。\n不同文件名载入方法有所不同\n - .js 通过fs模块同步读取文件后编译执行。\n - .node C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件\n - .json 通过fs模块同步读取文件后,用JSON.parse()解析返回结果\n - 其余扩展名,被当做js文件载入\n每一个编译成功的模块都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能\n##### JS模块的编译\n在编译的过程中,Node对获取的JavaScript文件内容进行了头尾包装。\n```javascript\n(function (exports, require, module, _filename, _dirname) { // 新增行\n var math = require('math');\n exports.area = function (radius) {\n return Math.PI * radius * radius;\n };\n}); // 新增行\n```\n通过新增了头和尾,进行了作用域隔离,包装之后的代码会通过vm原生模块的runInThisContext()方法执行,返回一个具体的function对象。\n最后把当前模块对象的exports属性、require()方法、module及在文件定位中得到的完整的文件路径和文件目录作为参数传入function()执行。\n执行之后,模块的exports属性被返回给了调用方。\nexports对象是通过形参的方式传入的,直接复制会改变形参的引用,但不会改变作用域外的值,因此需要用module.exports迂回一下。\n##### C/C++模块的编译\nNode调用process.dlopen()方法进行加载和执行。dlopen()方法在不同平台不同实现,通过libuv兼容层进行了封装。\n实际上node的模块文件并不需要编译,因为已经是编译生成的,所以只有加载和执行的过程。\n在执行的过程中,模块的exports对象与.node模块产生联系,然后返回给调用者。\nC/C++模块执行效率快,但是入门门槛高。\n##### JSON文件的编译\n利用fs模块同步读取JSON文件的内容之后,调用JSON.parse()方法得到对象,在赋给模块对象的exports,供外部调用。\n\n\n\n\n","source":"_posts/nodejs/01-Node简介.md","raw":"---\ntitle: 深入浅出Node\n---\n### Node简介\n1. Node的结构与Chrome十分相似,它们都是基于事件驱动的异步架构,浏览器通过事件驱动来服务界面上的交互,Node通过事件驱动来服务IO。\n2. Node的特点\n- 异步I/O\n- 事件与回调函数(事件的编程方式具有轻量级、松耦合、只关注事务点等有事,但是多个异步任务的场景下事件与事件相互独立,如何协作是一个问题。)\n- 单线程(单线程不用在意状态的同步问题,没有死锁,也没有上下文切换带来的性能开销,但是也有无法利用多核CPU、错误会导致整个应用退出、大量计算占用CPU导致无法继续调用异步I/O。Node通过child_process子进程讲计算来利用多核CPU)\n- 跨平台(基于libuv实现了跨平台)\n3. Node的应用场景\n- I/O密集型(面向网络且擅长并行I/O,优势在于Node利用事件循环的处理能力,而不是为每一个请求启动一个线程)。\n- 是否不擅长CPU密集型任务(如果有长时间运行的计算会导致CPU时间片不能释放,后续I/O无法发起。但是只要适当调整和分解大型运算任务为多个小任务,使运算可以适时释放,不阻塞I/O调用发起)\n4. Node的使用者的倚重点\n- 前后端编程语言环境统一\n- Node带来的高性能I/O用于实时应用\n- 并行I/O使得使用者可以更高效利用分布式环境\n- 并行I/O有效利用稳定借口提升Web渲染能力\n- 云计算平台提供Node支持\n- 工具类应用\n\n### 模块机制\n#### CommonJS规范\nCommonJS规范的提出,主要为了弥补当前JS没有标准的缺陷,达到具备开发大型应用的基础能力。\n模块规范\n- 模块引用\n```javascript\nvar math = require('math');\n```\n- 模块定义\n上下文提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一导出的出口。在模块中,还存在一个module对象,代表模块自身,exports是module的属性。\n- 模块标识\n模块标识就是传递给require()方法的参数,必须符合小拖放命名的字符串,或者相对路径or绝对路径。\n### Node的模块实现\n1. Node中引入模块,需要路径分析、文件定位、编译执行三个步骤。\n2. Node中模块分为两类,一类是Node提供的模块称为核心模块。另一类是用户编写的模块,称为文件模块。\n - 核心模块部分在Node源代码的编译过程中,编译进了二进制执行文件。在Node进程启动时,这部分核心模块被直接加载进内存,就可以省略文件定位和编译执行步骤,路径分析中优先判断\n - 文件模块在运行时动态加载,需要三个步骤,会慢一些\n3. Node对引入过的模块都会进行缓存,缓存的是编译和执行之后的对象。无论核心模块还是文件模块,都是优先采用缓存。核心模块的缓存检查先于文件模块的缓存检查。\n4. 路径分析和文件定位\n###### 模块标识符分析:\n - 模块加载速度:缓存模块<核心模块<路径形式的文件模块<自定义模块\n###### 文件定位分析:\n - 文件扩展名分析,Node会按照.js .json .node的次序补足扩展名,依次尝试。尝试过程中,需要调用fs模块同步阻塞式地判断文件是否存在。\n - 目录分析和包:分析标识符查找到一个目录,Node会当成一个包来处理。会去查找包里面是否有package.json,取出main属性指定的文件来定位。\n如果main属性指定文件名错误,会将index当做默认文件名。如果这一级目录还没有找到,会下一个模块路径进行遍历。如果所有模块路径都找不到,就跑出查找失败的异常。\n###### 模块编译:\n编译和执行是引入文件模块的最后一个阶段。定位到具体的文件后,Node会新建一个模块对象,根据路径载入并编译。\n不同文件名载入方法有所不同\n - .js 通过fs模块同步读取文件后编译执行。\n - .node C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件\n - .json 通过fs模块同步读取文件后,用JSON.parse()解析返回结果\n - 其余扩展名,被当做js文件载入\n每一个编译成功的模块都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能\n##### JS模块的编译\n在编译的过程中,Node对获取的JavaScript文件内容进行了头尾包装。\n```javascript\n(function (exports, require, module, _filename, _dirname) { // 新增行\n var math = require('math');\n exports.area = function (radius) {\n return Math.PI * radius * radius;\n };\n}); // 新增行\n```\n通过新增了头和尾,进行了作用域隔离,包装之后的代码会通过vm原生模块的runInThisContext()方法执行,返回一个具体的function对象。\n最后把当前模块对象的exports属性、require()方法、module及在文件定位中得到的完整的文件路径和文件目录作为参数传入function()执行。\n执行之后,模块的exports属性被返回给了调用方。\nexports对象是通过形参的方式传入的,直接复制会改变形参的引用,但不会改变作用域外的值,因此需要用module.exports迂回一下。\n##### C/C++模块的编译\nNode调用process.dlopen()方法进行加载和执行。dlopen()方法在不同平台不同实现,通过libuv兼容层进行了封装。\n实际上node的模块文件并不需要编译,因为已经是编译生成的,所以只有加载和执行的过程。\n在执行的过程中,模块的exports对象与.node模块产生联系,然后返回给调用者。\nC/C++模块执行效率快,但是入门门槛高。\n##### JSON文件的编译\n利用fs模块同步读取JSON文件的内容之后,调用JSON.parse()方法得到对象,在赋给模块对象的exports,供外部调用。\n\n\n\n\n","slug":"nodejs/01-Node简介","published":1,"date":"2021-03-01T08:10:55.198Z","updated":"2021-03-02T06:32:52.633Z","comments":1,"layout":"post","photos":[],"link":"","_id":"ckmotuk13000cf1vp4gg7fhhk","content":"<h3><span id=\"node简介\">Node简介</span></h3><ol>\n<li>Node的结构与Chrome十分相似,它们都是基于事件驱动的异步架构,浏览器通过事件驱动来服务界面上的交互,Node通过事件驱动来服务IO。</li>\n<li>Node的特点</li>\n</ol>\n<ul>\n<li>异步I/O</li>\n<li>事件与回调函数(事件的编程方式具有轻量级、松耦合、只关注事务点等有事,但是多个异步任务的场景下事件与事件相互独立,如何协作是一个问题。)</li>\n<li>单线程(单线程不用在意状态的同步问题,没有死锁,也没有上下文切换带来的性能开销,但是也有无法利用多核CPU、错误会导致整个应用退出、大量计算占用CPU导致无法继续调用异步I/O。Node通过child_process子进程讲计算来利用多核CPU)</li>\n<li>跨平台(基于libuv实现了跨平台)</li>\n</ul>\n<ol start=\"3\">\n<li>Node的应用场景</li>\n</ol>\n<ul>\n<li>I/O密集型(面向网络且擅长并行I/O,优势在于Node利用事件循环的处理能力,而不是为每一个请求启动一个线程)。</li>\n<li>是否不擅长CPU密集型任务(如果有长时间运行的计算会导致CPU时间片不能释放,后续I/O无法发起。但是只要适当调整和分解大型运算任务为多个小任务,使运算可以适时释放,不阻塞I/O调用发起)</li>\n</ul>\n<ol start=\"4\">\n<li>Node的使用者的倚重点</li>\n</ol>\n<ul>\n<li>前后端编程语言环境统一</li>\n<li>Node带来的高性能I/O用于实时应用</li>\n<li>并行I/O使得使用者可以更高效利用分布式环境</li>\n<li>并行I/O有效利用稳定借口提升Web渲染能力</li>\n<li>云计算平台提供Node支持</li>\n<li>工具类应用</li>\n</ul>\n<h3><span id=\"模块机制\">模块机制</span></h3><h4><span id=\"commonjs规范\">CommonJS规范</span></h4><p>CommonJS规范的提出,主要为了弥补当前JS没有标准的缺陷,达到具备开发大型应用的基础能力。<br>模块规范</p>\n<ul>\n<li>模块引用<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> math <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'math'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre></li>\n<li>模块定义<br>上下文提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一导出的出口。在模块中,还存在一个module对象,代表模块自身,exports是module的属性。</li>\n<li>模块标识<br>模块标识就是传递给require()方法的参数,必须符合小拖放命名的字符串,或者相对路径or绝对路径。<h3><span id=\"node的模块实现\">Node的模块实现</span></h3></li>\n</ul>\n<ol>\n<li>Node中引入模块,需要路径分析、文件定位、编译执行三个步骤。</li>\n<li>Node中模块分为两类,一类是Node提供的模块称为核心模块。另一类是用户编写的模块,称为文件模块。<ul>\n<li>核心模块部分在Node源代码的编译过程中,编译进了二进制执行文件。在Node进程启动时,这部分核心模块被直接加载进内存,就可以省略文件定位和编译执行步骤,路径分析中优先判断</li>\n<li>文件模块在运行时动态加载,需要三个步骤,会慢一些</li>\n</ul>\n</li>\n<li>Node对引入过的模块都会进行缓存,缓存的是编译和执行之后的对象。无论核心模块还是文件模块,都是优先采用缓存。核心模块的缓存检查先于文件模块的缓存检查。</li>\n<li>路径分析和文件定位<h6><span id=\"模块标识符分析\">模块标识符分析:</span></h6></li>\n</ol>\n<ul>\n<li>模块加载速度:缓存模块<核心模块<路径形式的文件模块<自定义模块<h6><span id=\"文件定位分析\">文件定位分析:</span></h6></li>\n<li>文件扩展名分析,Node会按照.js .json .node的次序补足扩展名,依次尝试。尝试过程中,需要调用fs模块同步阻塞式地判断文件是否存在。</li>\n<li>目录分析和包:分析标识符查找到一个目录,Node会当成一个包来处理。会去查找包里面是否有package.json,取出main属性指定的文件来定位。<br>如果main属性指定文件名错误,会将index当做默认文件名。如果这一级目录还没有找到,会下一个模块路径进行遍历。如果所有模块路径都找不到,就跑出查找失败的异常。<h6><span id=\"模块编译\">模块编译:</span></h6>编译和执行是引入文件模块的最后一个阶段。定位到具体的文件后,Node会新建一个模块对象,根据路径载入并编译。<br>不同文件名载入方法有所不同</li>\n<li>.js 通过fs模块同步读取文件后编译执行。</li>\n<li>.node C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件</li>\n<li>.json 通过fs模块同步读取文件后,用JSON.parse()解析返回结果</li>\n<li>其余扩展名,被当做js文件载入<br>每一个编译成功的模块都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能<h5><span id=\"js模块的编译\">JS模块的编译</span></h5>在编译的过程中,Node对获取的JavaScript文件内容进行了头尾包装。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">exports<span class=\"token punctuation\">,</span> require<span class=\"token punctuation\">,</span> module<span class=\"token punctuation\">,</span> _filename<span class=\"token punctuation\">,</span> _dirname</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token comment\">// 新增行</span>\n <span class=\"token keyword\">var</span> math <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'math'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">area</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> radius <span class=\"token operator\">*</span> radius<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 新增行</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n通过新增了头和尾,进行了作用域隔离,包装之后的代码会通过vm原生模块的runInThisContext()方法执行,返回一个具体的function对象。<br>最后把当前模块对象的exports属性、require()方法、module及在文件定位中得到的完整的文件路径和文件目录作为参数传入function()执行。<br>执行之后,模块的exports属性被返回给了调用方。<br>exports对象是通过形参的方式传入的,直接复制会改变形参的引用,但不会改变作用域外的值,因此需要用module.exports迂回一下。<h5><span id=\"cc模块的编译\">C/C++模块的编译</span></h5>Node调用process.dlopen()方法进行加载和执行。dlopen()方法在不同平台不同实现,通过libuv兼容层进行了封装。<br>实际上node的模块文件并不需要编译,因为已经是编译生成的,所以只有加载和执行的过程。<br>在执行的过程中,模块的exports对象与.node模块产生联系,然后返回给调用者。<br>C/C++模块执行效率快,但是入门门槛高。<h5><span id=\"json文件的编译\">JSON文件的编译</span></h5>利用fs模块同步读取JSON文件的内容之后,调用JSON.parse()方法得到对象,在赋给模块对象的exports,供外部调用。</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h3 id=\"Node简介\"><a href=\"#Node简介\" class=\"headerlink\" title=\"Node简介\"></a>Node简介</h3><ol>\n<li>Node的结构与Chrome十分相似,它们都是基于事件驱动的异步架构,浏览器通过事件驱动来服务界面上的交互,Node通过事件驱动来服务IO。</li>\n<li>Node的特点</li>\n</ol>\n<ul>\n<li>异步I/O</li>\n<li>事件与回调函数(事件的编程方式具有轻量级、松耦合、只关注事务点等有事,但是多个异步任务的场景下事件与事件相互独立,如何协作是一个问题。)</li>\n<li>单线程(单线程不用在意状态的同步问题,没有死锁,也没有上下文切换带来的性能开销,但是也有无法利用多核CPU、错误会导致整个应用退出、大量计算占用CPU导致无法继续调用异步I/O。Node通过child_process子进程讲计算来利用多核CPU)</li>\n<li>跨平台(基于libuv实现了跨平台)</li>\n</ul>\n<ol start=\"3\">\n<li>Node的应用场景</li>\n</ol>\n<ul>\n<li>I/O密集型(面向网络且擅长并行I/O,优势在于Node利用事件循环的处理能力,而不是为每一个请求启动一个线程)。</li>\n<li>是否不擅长CPU密集型任务(如果有长时间运行的计算会导致CPU时间片不能释放,后续I/O无法发起。但是只要适当调整和分解大型运算任务为多个小任务,使运算可以适时释放,不阻塞I/O调用发起)</li>\n</ul>\n<ol start=\"4\">\n<li>Node的使用者的倚重点</li>\n</ol>\n<ul>\n<li>前后端编程语言环境统一</li>\n<li>Node带来的高性能I/O用于实时应用</li>\n<li>并行I/O使得使用者可以更高效利用分布式环境</li>\n<li>并行I/O有效利用稳定借口提升Web渲染能力</li>\n<li>云计算平台提供Node支持</li>\n<li>工具类应用</li>\n</ul>\n<h3 id=\"模块机制\"><a href=\"#模块机制\" class=\"headerlink\" title=\"模块机制\"></a>模块机制</h3><h4 id=\"CommonJS规范\"><a href=\"#CommonJS规范\" class=\"headerlink\" title=\"CommonJS规范\"></a>CommonJS规范</h4><p>CommonJS规范的提出,主要为了弥补当前JS没有标准的缺陷,达到具备开发大型应用的基础能力。<br>模块规范</p>\n<ul>\n<li>模块引用<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">var</span> math <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'math'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span></span></code></pre></li>\n<li>模块定义<br>上下文提供了exports对象用于导出当前模块的方法或者变量,并且它是唯一导出的出口。在模块中,还存在一个module对象,代表模块自身,exports是module的属性。</li>\n<li>模块标识<br>模块标识就是传递给require()方法的参数,必须符合小拖放命名的字符串,或者相对路径or绝对路径。<h3 id=\"Node的模块实现\"><a href=\"#Node的模块实现\" class=\"headerlink\" title=\"Node的模块实现\"></a>Node的模块实现</h3></li>\n</ul>\n<ol>\n<li>Node中引入模块,需要路径分析、文件定位、编译执行三个步骤。</li>\n<li>Node中模块分为两类,一类是Node提供的模块称为核心模块。另一类是用户编写的模块,称为文件模块。<ul>\n<li>核心模块部分在Node源代码的编译过程中,编译进了二进制执行文件。在Node进程启动时,这部分核心模块被直接加载进内存,就可以省略文件定位和编译执行步骤,路径分析中优先判断</li>\n<li>文件模块在运行时动态加载,需要三个步骤,会慢一些</li>\n</ul>\n</li>\n<li>Node对引入过的模块都会进行缓存,缓存的是编译和执行之后的对象。无论核心模块还是文件模块,都是优先采用缓存。核心模块的缓存检查先于文件模块的缓存检查。</li>\n<li>路径分析和文件定位<h6 id=\"模块标识符分析:\"><a href=\"#模块标识符分析:\" class=\"headerlink\" title=\"模块标识符分析:\"></a>模块标识符分析:</h6></li>\n</ol>\n<ul>\n<li>模块加载速度:缓存模块<核心模块<路径形式的文件模块<自定义模块<h6 id=\"文件定位分析:\"><a href=\"#文件定位分析:\" class=\"headerlink\" title=\"文件定位分析:\"></a>文件定位分析:</h6></li>\n<li>文件扩展名分析,Node会按照.js .json .node的次序补足扩展名,依次尝试。尝试过程中,需要调用fs模块同步阻塞式地判断文件是否存在。</li>\n<li>目录分析和包:分析标识符查找到一个目录,Node会当成一个包来处理。会去查找包里面是否有package.json,取出main属性指定的文件来定位。<br>如果main属性指定文件名错误,会将index当做默认文件名。如果这一级目录还没有找到,会下一个模块路径进行遍历。如果所有模块路径都找不到,就跑出查找失败的异常。<h6 id=\"模块编译:\"><a href=\"#模块编译:\" class=\"headerlink\" title=\"模块编译:\"></a>模块编译:</h6>编译和执行是引入文件模块的最后一个阶段。定位到具体的文件后,Node会新建一个模块对象,根据路径载入并编译。<br>不同文件名载入方法有所不同</li>\n<li>.js 通过fs模块同步读取文件后编译执行。</li>\n<li>.node C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件</li>\n<li>.json 通过fs模块同步读取文件后,用JSON.parse()解析返回结果</li>\n<li>其余扩展名,被当做js文件载入<br>每一个编译成功的模块都会将其文件路径作为索引缓存在Module._cache对象上,以提高二次引入的性能<h5 id=\"JS模块的编译\"><a href=\"#JS模块的编译\" class=\"headerlink\" title=\"JS模块的编译\"></a>JS模块的编译</h5>在编译的过程中,Node对获取的JavaScript文件内容进行了头尾包装。<pre class=\"line-numbers language-javascript\" data-language=\"javascript\"><code class=\"language-javascript\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">exports<span class=\"token punctuation\">,</span> require<span class=\"token punctuation\">,</span> module<span class=\"token punctuation\">,</span> _filename<span class=\"token punctuation\">,</span> _dirname</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token comment\">// 新增行</span>\n <span class=\"token keyword\">var</span> math <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'math'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">area</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">radius</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> Math<span class=\"token punctuation\">.</span><span class=\"token constant\">PI</span> <span class=\"token operator\">*</span> radius <span class=\"token operator\">*</span> radius<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 新增行</span><span aria-hidden=\"true\" class=\"line-numbers-rows\"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre>\n通过新增了头和尾,进行了作用域隔离,包装之后的代码会通过vm原生模块的runInThisContext()方法执行,返回一个具体的function对象。<br>最后把当前模块对象的exports属性、require()方法、module及在文件定位中得到的完整的文件路径和文件目录作为参数传入function()执行。<br>执行之后,模块的exports属性被返回给了调用方。<br>exports对象是通过形参的方式传入的,直接复制会改变形参的引用,但不会改变作用域外的值,因此需要用module.exports迂回一下。<h5 id=\"C-C-模块的编译\"><a href=\"#C-C-模块的编译\" class=\"headerlink\" title=\"C/C++模块的编译\"></a>C/C++模块的编译</h5>Node调用process.dlopen()方法进行加载和执行。dlopen()方法在不同平台不同实现,通过libuv兼容层进行了封装。<br>实际上node的模块文件并不需要编译,因为已经是编译生成的,所以只有加载和执行的过程。<br>在执行的过程中,模块的exports对象与.node模块产生联系,然后返回给调用者。<br>C/C++模块执行效率快,但是入门门槛高。<h5 id=\"JSON文件的编译\"><a href=\"#JSON文件的编译\" class=\"headerlink\" title=\"JSON文件的编译\"></a>JSON文件的编译</h5>利用fs模块同步读取JSON文件的内容之后,调用JSON.parse()方法得到对象,在赋给模块对象的exports,供外部调用。</li>\n</ul>\n"}],"PostAsset":[],"PostCategory":[],"PostTag":[],"Tag":[]}}