-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdb.json
1 lines (1 loc) · 831 KB
/
db.json
1
{"meta":{"version":1,"warehouse":"2.2.0"},"models":{"Asset":[{"_id":"themes/Hacker/source/css/style.styl","path":"css/style.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/images/icon-heart.svg","path":"images/icon-heart.svg","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/categories.styl","path":"css/components/categories.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/base/normalize.css","path":"css/base/normalize.css","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/archive.styl","path":"css/components/archive.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/article.styl","path":"css/components/article.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/footer.styl","path":"css/components/footer.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/header.styl","path":"css/components/header.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/icon.styl","path":"css/components/icon.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/pagination.styl","path":"css/components/pagination.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/responsive.styl","path":"css/components/responsive.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/layout.styl","path":"css/components/layout.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/syntax.styl","path":"css/components/syntax.styl","modified":1,"renderable":1},{"_id":"themes/Hacker/source/css/components/tags.styl","path":"css/components/tags.styl","modified":1,"renderable":1}],"Cache":[{"_id":"themes/Hacker/.gitignore","hash":"803c06a7086b5817c03d2e8672da27bc56ba2bce","modified":1498192818000},{"_id":"themes/Hacker/_config.yml","hash":"5d8cc859c48024451a316c50ab16ba58702b062d","modified":1498192818000},{"_id":"themes/Hacker/LICENSE","hash":"3127907a7623734f830e8c69ccee03b693bf993e","modified":1498192818000},{"_id":"themes/Hacker/README.md","hash":"71077f7bdebc6e8d36f763e715ec2d55ddca4141","modified":1498192818000},{"_id":"themes/Hacker/README_zh-CN.md","hash":"d6c9200e96bb3633c3a84de169f91e6c34a5ea14","modified":1498192818000},{"_id":"source/_posts/weekly-1.md","hash":"00aeec819ce7d05265be946fb426c9924b0ff7ef","modified":1503628361000},{"_id":"source/_posts/weekly-10.md","hash":"1e90f34188da4a4a08a62f4131c8942cc7700a2b","modified":1503645819000},{"_id":"source/_posts/5-protocols-for-event-driven-api-architectures.md","hash":"8fc472d56a43aaa7ee1f935501969b469e717c19","modified":1500607722000},{"_id":"source/_posts/weekly-11.md","hash":"8f584409a571a15e411b7f162d3e823935d8eb43","modified":1510299652986},{"_id":"source/_posts/weekly-12.md","hash":"10b8a4d0d789ac720ba08dcd293e8c8416a7432c","modified":1510299652986},{"_id":"source/_posts/weekly-13.md","hash":"7d197044de50ea16e1d86dbbe32b36d748c7bf3b","modified":1510299652986},{"_id":"source/_posts/weekly-14.md","hash":"50a9caa1b4e64054e9545de03d6534709b084913","modified":1510299652987},{"_id":"source/_posts/weekly-15.md","hash":"65bb8a9a19b63be462d613c0d798d5595d423148","modified":1510299652987},{"_id":"source/_posts/weekly-16.md","hash":"cfec7449992be7efa741005433ce73227140b802","modified":1510299652988},{"_id":"source/_posts/weekly-2.md","hash":"d52bc737b4cc6cd9d937e54bab7d72efd4e19d5c","modified":1503628346000},{"_id":"source/_posts/weekly-17.md","hash":"31048a39ac1a1e1a19939b538e8a9e5cec66dced","modified":1510299652988},{"_id":"source/_posts/weekly-18.md","hash":"525df4f3a82bfa9987621217937d2d0bdaf00afa","modified":1510299652988},{"_id":"source/_posts/weekly-19.md","hash":"df15c476141a641d336c435208de8f2435b52f0a","modified":1510299652988},{"_id":"source/_posts/weekly-20.md","hash":"4f753e00afda0e3244974f1cae26a2e1421ae340","modified":1551457576529},{"_id":"source/_posts/weekly-3.md","hash":"5bb26c965db69b1ad74f0bf219976f46e36983a5","modified":1503628343000},{"_id":"source/_posts/weekly-4.md","hash":"d29eac0607de59d4343afb05f491d8d9957f9e45","modified":1503628340000},{"_id":"source/_posts/weekly-21.md","hash":"e245063c1e9213c5f84f12736875fe1f741e0a90","modified":1551457576529},{"_id":"source/_posts/weekly-5.md","hash":"cb2747b0553993c8806d9f68d02113fd0fad0be9","modified":1503628337000},{"_id":"source/_posts/weekly-6.md","hash":"9c39dc01cf57a083ef7ae7ba874cf980e82c0310","modified":1503628333000},{"_id":"source/_posts/weekly-9.md","hash":"86f4fd10c3694def0bff7e55c47be6ccda9cd4bc","modified":1503628320000},{"_id":"source/_posts/weekly-8.md","hash":"8c28d2985df7a0279223840c0eb71b30e1ad6789","modified":1503628325000},{"_id":"source/_posts/weekly-7.md","hash":"059d55b1ca5a2277bfc64fda7e48739074a9686a","modified":1503938718000},{"_id":"themes/Hacker/layout/categories.ejs","hash":"bfad4e7eade650c535f0194974e2646619657b8b","modified":1498192818000},{"_id":"themes/Hacker/layout/archive.ejs","hash":"2238cbe29009aafb16969d2c70dceb3f71772123","modified":1498192818000},{"_id":"themes/Hacker/languages/zh-CN.yml","hash":"18638177b944e0deb4a8c26a1c4a980901151132","modified":1498192818000},{"_id":"themes/Hacker/layout/index.ejs","hash":"1d2c487a95d25e763b5f7e004194eb6ee6b18135","modified":1498192818000},{"_id":"themes/Hacker/layout/post.ejs","hash":"84e00bbcc643dff4bd02880b3bbea658f510835f","modified":1498192818000},{"_id":"themes/Hacker/layout/page.ejs","hash":"84e00bbcc643dff4bd02880b3bbea658f510835f","modified":1498192818000},{"_id":"themes/Hacker/layout/tags.ejs","hash":"ee89e6a9c14bdb5e5e8cf975a558c780fe8dabff","modified":1498192818000},{"_id":"themes/Hacker/layout/layout.ejs","hash":"4e47a1137ec3f0764fb0b9b4ef914cba660e0df7","modified":1551457661188},{"_id":"themes/Hacker/languages/default.yml","hash":"ef90548952b1f9cc88dbe9daad882786212aec38","modified":1498192818000},{"_id":"themes/Hacker/layout/components/article.ejs","hash":"5a08e05eb271589a2ed69fdd08516fa8457af3ed","modified":1498192818000},{"_id":"themes/Hacker/layout/components/categories.ejs","hash":"3665bf5d1c7181db22dc1c48d62ebf42757d8c27","modified":1498192818000},{"_id":"themes/Hacker/layout/components/comment.ejs","hash":"34b72f9819b5298be101f5c568cc7f2a52ab0f7d","modified":1498192818000},{"_id":"themes/Hacker/layout/components/archive.ejs","hash":"1f79ebaf52b8229cf5c58bb8325cf0177859a05c","modified":1498192818000},{"_id":"themes/Hacker/layout/components/googleanalytics.ejs","hash":"fa11251ace0fc61cbcffb74f32fbf5bdbb201ff2","modified":1498192818000},{"_id":"themes/Hacker/layout/components/footer.ejs","hash":"538795f4af3a98e824aefc4b68a1bcd210c091e9","modified":1498192818000},{"_id":"themes/Hacker/layout/components/head.ejs","hash":"10475fdfc513c9380f18d034e15b3b051c8e9269","modified":1498192818000},{"_id":"themes/Hacker/layout/components/header.ejs","hash":"929a8eafa278d49c2f41d3581e2608eca80d7856","modified":1498192818000},{"_id":"themes/Hacker/layout/components/pagination.ejs","hash":"4ab5e3b0239e467923a0f91c771bcc9ee7889cfe","modified":1498192818000},{"_id":"themes/Hacker/source/css/style.styl","hash":"208e5f6d010e4e2c5590dae5e4fca8de592d3ef1","modified":1498192818000},{"_id":"themes/Hacker/source/images/icon-heart.svg","hash":"ec483e96c88eea013fd8ac71a34a875107397f43","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/categories.styl","hash":"c67e20d60351295cb178b568af42d430f4bcc3e6","modified":1498192818000},{"_id":"themes/Hacker/source/css/base/normalize.css","hash":"e58275a588bb631a37a2988145eea231ed23176b","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/archive.styl","hash":"de701a1dee6e870140565044a08c2c45cfcd4bc3","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/article.styl","hash":"e99f13c6744ddaa7f7bfcf0662e4dc6840fae8fa","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/footer.styl","hash":"80ef890252d31d3bbfe71740fdcfc54ae14cad8e","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/header.styl","hash":"fa5e6d715d288a327406df78225284c70530cb98","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/icon.styl","hash":"8da3ff5b6cd1609fdfe0c564d47391367abc8808","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/pagination.styl","hash":"c20a9920bb444c22b20e588f97eba4e03f09a439","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/responsive.styl","hash":"053e7ec4c22845422440660b7e1d6b0dea5b4fbd","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/layout.styl","hash":"73c1688b95b20cd67669bc5567420f5be8448c9f","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/syntax.styl","hash":"68b7deadab1ac13603eb5e812e1060db25227fd0","modified":1498192818000},{"_id":"themes/Hacker/source/css/components/tags.styl","hash":"684cf4eb4b8671476365e955dceebf096cc0e6ed","modified":1498192818000},{"_id":"public/atom.xml","hash":"a44e0aa03a2a1251428df164df8f1482537cdc16","modified":1551458021958},{"_id":"public/2017/11/03/weekly-19/index.html","hash":"52bae5b402d82b0b8e156bc63daed014b1601065","modified":1551458022363},{"_id":"public/2017/11/10/weekly-20/index.html","hash":"69478288f73525f15641a3ec901b8d83235a87d9","modified":1551458022363},{"_id":"public/2017/09/22/weekly-14/index.html","hash":"3d51ec0371006778d004ed580cdb4859e5b2066f","modified":1551458022364},{"_id":"public/2017/09/15/weekly-13/index.html","hash":"8cdf46f63e6b6dfc314bd8c825cff05b5444aa01","modified":1551458022364},{"_id":"public/2017/09/01/weekly-11/index.html","hash":"fb8a8f6a633a09cf7af54051f278f74b54e7d923","modified":1551458022364},{"_id":"public/2017/08/25/weekly-10/index.html","hash":"8562408e45e3754c0343a711f7e9f69abd50dde9","modified":1551458022364},{"_id":"public/2017/08/18/weekly-9/index.html","hash":"56db37cac48c6e094782202508e8c580dc7f6a4f","modified":1551458022364},{"_id":"public/2017/08/11/weekly-8/index.html","hash":"6d6dcd8d401d4f1ba37fce0baea8d5d676b4acd4","modified":1551458022364},{"_id":"public/2017/08/04/weekly-7/index.html","hash":"072be71e40f6d63f51ab20a3172337799a675ac2","modified":1551458022364},{"_id":"public/2017/07/28/weekly-6/index.html","hash":"a79fb94256b3f8c5a69e2963f14bc251109b7bd1","modified":1551458022365},{"_id":"public/2017/07/21/weekly-5/index.html","hash":"2df41e0fe03cc9ef0445af0787fbde2d065c8a1e","modified":1551458022365},{"_id":"public/2017/07/12/weekly-4/index.html","hash":"fda12c17309f8d3269e959d2c3d2ba332eccd631","modified":1551458022365},{"_id":"public/2017/07/07/weekly-3/index.html","hash":"0041f5dd2d7712c1c907f3d7f73aa3c1d751a3b4","modified":1551458022365},{"_id":"public/2017/06/30/weekly-2/index.html","hash":"9825079ee4fbdd5d546e211d603a2750698ee485","modified":1551458022365},{"_id":"public/2017/06/23/weekly-1/index.html","hash":"556c475668cdd373b335df5ae499f44cfb8eec1d","modified":1551458022365},{"_id":"public/archives/index.html","hash":"26429c612d20ee46de0977f85c5ff3c8fc365df9","modified":1551458022365},{"_id":"public/archives/page/2/index.html","hash":"3cd684d78a5a2c9501fd2cc4d7dda35dde69fc36","modified":1551458022365},{"_id":"public/archives/page/3/index.html","hash":"a9799ca8fc5b5285236dc3604710a8c6831462f1","modified":1551458022366},{"_id":"public/archives/2017/index.html","hash":"5460bdaf3ef749b159efbb0a0df17fb09c05a41f","modified":1551458022366},{"_id":"public/archives/2017/page/2/index.html","hash":"48cf5e672f2f0479f376dead0334489c2f8fa610","modified":1551458022366},{"_id":"public/archives/2017/page/3/index.html","hash":"231503bbb47879c609192e697955726bece69c78","modified":1551458022366},{"_id":"public/archives/2017/06/index.html","hash":"c20590c52c727d5776a67e46a11872bc35e3f3e6","modified":1551458022366},{"_id":"public/archives/2017/07/index.html","hash":"9177a7df53aea487dd296a45c6c3923ea2da4951","modified":1551458022367},{"_id":"public/archives/2017/08/index.html","hash":"264789786882677a81ae77e7dcb3f93b9508211f","modified":1551458022367},{"_id":"public/archives/2017/09/index.html","hash":"5d025aa4a9ad7e5e6319f022f1012d3c49a51207","modified":1551458022367},{"_id":"public/archives/2017/10/index.html","hash":"5114c024e62d3714eccbfb8c21e58cd996616c1d","modified":1551458022368},{"_id":"public/archives/2017/11/index.html","hash":"5da242615c6610029e11af99d43cf9f09aad09e8","modified":1551458022368},{"_id":"public/page/3/index.html","hash":"a342ead8d04748ebb62d9614b5c77474db871d70","modified":1551458022368},{"_id":"public/tags/weekly/index.html","hash":"26affd86f335010a0b45252392b5b7c595c12a01","modified":1551458022368},{"_id":"public/tags/weekly/page/2/index.html","hash":"a2d82d6b4f47cc64a3bd887173f941d19f234eab","modified":1551458022369},{"_id":"public/tags/全栈/index.html","hash":"8fd3559f80b91e18404b251c5be3afd0f10f565e","modified":1551458022369},{"_id":"public/tags/Node/index.html","hash":"84afcf7a0262b92837d7bbcec7fa84cb5af62185","modified":1551458022370},{"_id":"public/tags/工程化实践/index.html","hash":"d7fa7f430398ae7563742247c26eb819bfcec44b","modified":1551458022370},{"_id":"public/tags/Vuex/index.html","hash":"d89bd2f4750240c50dda2e5a249e9dbd676b3776","modified":1551458022370},{"_id":"public/tags/Webpack/index.html","hash":"08820e8776b6c3987ebf409150365b524b528d08","modified":1551458022370},{"_id":"public/tags/PWA/index.html","hash":"65c6d949c3775804b469139ca544542c7813f6ad","modified":1551458022370},{"_id":"public/tags/持续部署/index.html","hash":"27336726b5caecefd8d3f62e6f0264482a6224e7","modified":1551458022371},{"_id":"public/tags/开发工具/index.html","hash":"b7f10a75c1a8afa79bb32eafed416526821e37a8","modified":1551458022371},{"_id":"public/tags/测试工具/index.html","hash":"f7a58ee057b4634102bb3a292d975605eef9718a","modified":1551458022372},{"_id":"public/tags/Vue/index.html","hash":"8f2aeb8a25cd3f5bce34822958fafe8c05389775","modified":1551458022372},{"_id":"public/tags/ES6/index.html","hash":"bf8da78237ea74564e49160daa59ec71942b8453","modified":1551458022373},{"_id":"public/tags/设计模式/index.html","hash":"6b9317ec49ed1c1369036d3f8d743624c8f4d046","modified":1551458022373},{"_id":"public/tags/webpack/index.html","hash":"707067be9cfdd04f5cc5481b59db81e09e8225e9","modified":1551458022374},{"_id":"public/tags/koa/index.html","hash":"5d34be48f1f0a3ff8fd22037bc411f9897e82a64","modified":1551458022376},{"_id":"public/tags/web安全/index.html","hash":"ca08c881957d1686d039344fdf03edb93b6f9678","modified":1551458022376},{"_id":"public/tags/http/index.html","hash":"8022e1065fdc4a91eb37d7c4c78a09251c3190dc","modified":1551458022377},{"_id":"public/tags/Trackingjs/index.html","hash":"027b9cca4e389477c1e40642f661bee258c932bb","modified":1551458022377},{"_id":"public/tags/flex/index.html","hash":"6a68df7018790a60546154d6bf224a8dca9c384a","modified":1551458022377},{"_id":"public/tags/postman/index.html","hash":"722ffd759b32f538f7dbdb7598067ce24b714c3b","modified":1551458022377},{"_id":"public/tags/神经网络/index.html","hash":"47113a11ecfc9a5a3d621861754dc722489f591d","modified":1551458022378},{"_id":"public/tags/DOM/index.html","hash":"1aad4e7ccd094bd8a09ee86953e8fa70d71f4d67","modified":1551458022378},{"_id":"public/tags/Nodejs/index.html","hash":"8fa22cbf24f8a35b40b8f74314feb26ee78bacd9","modified":1551458022378},{"_id":"public/tags/Web-Worker/index.html","hash":"95357c880a37304423fbf4750f395b098077f6f8","modified":1551458022380},{"_id":"public/tags/GitHub插件/index.html","hash":"705ea9534a5cd9949cc099e0c5e4c3968b458b48","modified":1551458022380},{"_id":"public/tags/人脸识别/index.html","hash":"3a9628a3ac1cebc0913934fecb8c0789e30df2d2","modified":1551458022380},{"_id":"public/tags/流体排版/index.html","hash":"7f036b3d576a402c9ee9be0af640d43ece919122","modified":1551458022380},{"_id":"public/tags/内存管理/index.html","hash":"42ecf09c8fe1af4f7079ac84163cfb38d1edb0b4","modified":1551458022380},{"_id":"public/tags/散点图/index.html","hash":"b3e1d4d53145ad085df15de228fb9cfd257c3ba4","modified":1551458022380},{"_id":"public/tags/正则/index.html","hash":"aa0dbd3a6786301aa09f4a8f80d04f5fb61f3c70","modified":1551458022380},{"_id":"public/tags/AR/index.html","hash":"f539ed4e5fa54c92e57152e3249a78b741da5bf6","modified":1551458022380},{"_id":"public/tags/IOT/index.html","hash":"81740c0fd3a98aa44bcde442cd5a1041290c44a3","modified":1551458022380},{"_id":"public/tags/虚拟DOM/index.html","hash":"5bae0fea6d028d5bd252db705d97d316308e3b46","modified":1551458022380},{"_id":"public/tags/动画/index.html","hash":"2c24f128f5430cd66b258d278043575d458c205e","modified":1551458022380},{"_id":"public/tags/Babels/index.html","hash":"5f5b745f6e1b34a7717af089673ff0f6005d00c4","modified":1551458022381},{"_id":"public/tags/渲染性能/index.html","hash":"b1b55ac7a11695ec234ae88b391f2cfffc440196","modified":1551458022381},{"_id":"public/tags/this关键字/index.html","hash":"4c0ece75cfa6e1019d1e67760c8c1d97a35a1043","modified":1551458022381},{"_id":"public/tags/http-2升级/index.html","hash":"52034e9b780275994be532bd04f2acbcc954181e","modified":1551458022381},{"_id":"public/tags/CSS黑魔法/index.html","hash":"1594113b79b1781aeab74a3dcafdf54956106445","modified":1551458022381},{"_id":"public/tags/框架/index.html","hash":"1f7e6fedd5eb0eda14657778e2482303231a79b2","modified":1551458022381},{"_id":"public/tags/测试/index.html","hash":"159db65e0cf011bc27734d11d49a8480f38c7c6c","modified":1551458022381},{"_id":"public/tags/three-js/index.html","hash":"6786ada2e80686ce967869b8b2ed7b9e9f2537f5","modified":1551458022381},{"_id":"public/tags/Echarts/index.html","hash":"3af0f69a815273cfe843a0e3d6d39338a571e400","modified":1551458022381},{"_id":"public/tags/SVG/index.html","hash":"e6916521959ff873d80ae94d07f5e7552da06109","modified":1551458022381},{"_id":"public/tags/算法/index.html","hash":"87bb06da0b6e6df3b296b63fbb01ab99db32f145","modified":1551458022381},{"_id":"public/tags/模块化/index.html","hash":"9483b64e15070103e2e745501f1e584b78748871","modified":1551458022381},{"_id":"public/tags/性能优化/index.html","hash":"637fc8044aef2027fca8be27d6572a63900034e0","modified":1551458022382},{"_id":"public/tags/Zepto/index.html","hash":"781f242911d9b110c62d935420f36650763096ee","modified":1551458022382},{"_id":"public/tags/事件驱动/index.html","hash":"874e6fa6468828d372a1130847e3a498319edaf2","modified":1551458022382},{"_id":"public/tags/node/index.html","hash":"3a7c7b7ebd2aecefa2b72b9dc61d95109338c7d5","modified":1551458022382},{"_id":"public/tags/WebSocket/index.html","hash":"8b4adf145be85ead9becca7243ea294fd7e88715","modified":1551458022382},{"_id":"public/tags/iView/index.html","hash":"9d66d0b2a99a745583a1cf6c17c81388470e212a","modified":1551458022382},{"_id":"public/tags/Git/index.html","hash":"7cc8dc17cd326d2fcc16ada56ce82e5aa82ad1ba","modified":1551458022382},{"_id":"public/tags/模块/index.html","hash":"b68531cfa4c384b037ed0a3648a21e5393fd6364","modified":1551458022382},{"_id":"public/tags/API设计,单元测试/index.html","hash":"1514c8539f216e9d988c6d5c0968037a1e09abad","modified":1551458022383},{"_id":"public/tags/函数式/index.html","hash":"c9750cd659c19a501a1709969e2ae358bb6f3073","modified":1551458022383},{"_id":"public/tags/es6/index.html","hash":"e59444881d9a55d4bced6729b364b9629dd2a831","modified":1551458022383},{"_id":"public/tags/vue/index.html","hash":"282e9d96473752089a48afbe4c193907fd49af78","modified":1551458022383},{"_id":"public/tags/工具/index.html","hash":"6012abe938706d3dde9125341939acf61f0eb41d","modified":1551458022383},{"_id":"public/tags/必备技能/index.html","hash":"a3ff569c3b588fc2429515be2a9902b66b3533f2","modified":1551458022383},{"_id":"public/tags/Event-Driven/index.html","hash":"40f1753759442a64fd6adeb2e4efc9c363739ff1","modified":1551458022383},{"_id":"public/2017/11/17/weekly-21/index.html","hash":"3d1db56f929dce935b9303c0d929d60160c8e8d6","modified":1551458022383},{"_id":"public/2017/10/27/weekly-18/index.html","hash":"c23c9d7465fc608e1b635e081f0ccb889ce56162","modified":1551458022383},{"_id":"public/2017/10/20/weekly-17/index.html","hash":"f2ee5bca1e5a0a304aadd3a01e86572df21fc2e0","modified":1551458022384},{"_id":"public/2017/10/13/weekly-16/index.html","hash":"111aa6e70cf530fb458981ac1b47ca613df903d4","modified":1551458022384},{"_id":"public/2017/09/29/weekly-15/index.html","hash":"6134f83bc71b1f084dd3be5a130ebaac96a2d993","modified":1551458022384},{"_id":"public/2017/09/08/weekly-12/index.html","hash":"cb7fae3054ab69f331ce9202c9d3a3264c243fc9","modified":1551458022384},{"_id":"public/2017/07/21/5-protocols-for-event-driven-api-architectures/index.html","hash":"f749f33cc6a6cdb4e45a6bc7d06486c8a9f83b52","modified":1551458022384},{"_id":"public/index.html","hash":"6ba7b6c0c6d37e9667f02a468b4a5a851a428ab3","modified":1551458022385},{"_id":"public/page/2/index.html","hash":"62e7255289ab69e67a6f31deb3b646c13092a074","modified":1551458022385},{"_id":"public/images/icon-heart.svg","hash":"ec483e96c88eea013fd8ac71a34a875107397f43","modified":1551458022396},{"_id":"public/css/components/categories.css","hash":"f181d27640f1408f032c5386836c4c2322724f8d","modified":1551458022657},{"_id":"public/css/base/normalize.css","hash":"e58275a588bb631a37a2988145eea231ed23176b","modified":1551458022657},{"_id":"public/css/components/archive.css","hash":"14902abf01556a3e23e03ac18c87fa7a5a39d89a","modified":1551458022657},{"_id":"public/css/components/article.css","hash":"563b6fd19e1f5ba4787acd2ef2e1ee876e521cab","modified":1551458022657},{"_id":"public/css/components/footer.css","hash":"602def895fd52f288b6e93932284aa2e52b7fee0","modified":1551458022658},{"_id":"public/css/components/header.css","hash":"51f8a4c736f3b180a7c4c8f804d8060031df6a34","modified":1551458022658},{"_id":"public/css/components/icon.css","hash":"cdaf1a152184ff7def760f14095e4a2fa16cd6bd","modified":1551458022658},{"_id":"public/css/components/pagination.css","hash":"2f3f9bb1bc6513d08865e7a2fb2160cc47d4a229","modified":1551458022659},{"_id":"public/css/components/responsive.css","hash":"216eb94fc69007de995fc8d382670ba00a9574e8","modified":1551458022659},{"_id":"public/css/components/syntax.css","hash":"00970bfdb168aa13622c829920907ca3416829f8","modified":1551458022659},{"_id":"public/css/components/layout.css","hash":"b8625c7b90a973f2e37897f346e6f80b779fd9ca","modified":1551458022659},{"_id":"public/css/components/tags.css","hash":"1566e94c23ae19dbfc7d2cf433e68242ed657dea","modified":1551458022659},{"_id":"public/css/style.css","hash":"48373889a036d403ca34bc085cabeb302e2a08ee","modified":1551458022659}],"Category":[],"Data":[],"Page":[],"Post":[{"title":"大前端周刊 第1期 (本期小编:王祥)","date":"2017-06-23T03:18:25.000Z","_content":"\n## 基础\n\n* [Promise](http://es6.ruanyifeng.com/#docs/promise)\n在Javascript的单线程异步架构下,Promise会是很多异步服务的核心知识点,Node 8.X已经可以方便的将回调方式转换为Promise。\n\n* [异步函数async](http://es6.ruanyifeng.com/#docs/async)\n使用异步函数可以实现“用同步的写法,完成异步的事情”,Node 8.X已经在编译器层面对async做了优化。\n* [语义化版本 2.0.0](http://semver.org/lang/zh-CN/)\n玩开源项目的基础,组件发布的约定。\n* [package.json规则](https://docs.npmjs.com/files/package.json)\n项目的依赖列表,区别开发环境、生产环境、面向的平台和组件的规范(CMD、AMD和UMD)等。\n\n## 单元测试工具\nWeb 应用中的单元测试更加重要,在 Web 产品快速迭代的时期,每个测试用例都给应用的稳定性提供了一层保障。 API 升级,测试用例可以很好地检查代码是否向下兼容。 对于各种可能的输入,一旦测试覆盖,都能明确它的输出。 代码改动后,可以通过测试结果判断代码的改动是否影响已确定的结果。\n\n* [mocha单元测试](https://mochajs.org/)\nNPM里每天有25W的下载量,同时支持Node、浏览器多平台的测试用例的执行。\n\n* [power-assert断言库](https://www.npmjs.com/package/power-assert)\npower-assert可以零学习成本,直观的展示出判断条件和结果。\n\n```\n1) Array #indexOf() should return index when the value is present:\n AssertionError: # path/to/test/mocha_node.js:10\n\n assert(ary.indexOf(zero) === two)\n | | | | |\n | | | | 2\n | -1 0 false\n [1,2,3]\n\n [number] two\n => 2\n [number] ary.indexOf(zero)\n => -1\n```\n\n## 文章\n\n* [JavaScript专题之跟着underscore学防抖](https://github.com/mqyqingfeng/Blog/issues/22)\n对防抖的原理介绍的很清晰,从最简单的实现版本一步一步讲解到实现复杂的版本。\n让我对防抖有了重新的认识。\n\n* [从前端开发看面向未来的敏捷学习法](http://www.jianshu.com/p/fd7055705c62)\n授人以鱼不如授人以渔\n前端技术更新速度很快,快速学习已经成了每个工程师必备技能。\n除了掌握技术知识,解决问题的能力在实际项目中也很重要,文中以实际案例给出分解思路和系统敏捷学习新知识思路。\n\n* [前端工程师做事的三重境界:我的进阶之路](https://zhuanlan.zhihu.com/p/26660510)\n从程序员到工程师的进阶之路,精益求精才能称得上是工程师。作者认为这三个单词(Programmer、Developer、Enginner)对应不用的境界。\n\n* [浏览器缓存机制剖析](http://louiszhai.github.io/2017/04/07/http-cache/)\n正如文中所述“缓存一直是前端优化的主战场, 利用好缓存就成功了一半”,利用好缓存在前端优化地位中举足轻重,本文能够带领大家对浏览器缓存机制有一个初步了解。\n\n* [vue-mixins使用注意事项和高级用法](https://www.deboy.cn/Vue-mixins-advance-tips.html)\n在项目开发中经常会碰到两个组件的业务逻辑有所相似,可能共享相同的底层业务逻辑;此时需要考虑如何来合理地划分代码,即避免冗余代码,也不能过度抽象。\n\n* [也谈JavaScript数组去重](https://www.toobug.net/article/array_unique_in_javascript.html)\n去重,首先要思考什么是相等,从最初的循环,到Set集合。\n\n* [大前端公共知识梳理:这些知识你都掌握了吗?](https://mp.weixin.qq.com/s?__biz=MzIwNjQwMzUwMQ==&mid=2247485277&idx=1&sn=82703e13febb1e7947cc18d1f57fc375&key=6b0fbfcb936d93fa91a745202d0f37bffff65fd2cba5ff2cfa25618c8d03951944ae6eb2f4db18aaf1c8893ddaeffb404684dbd7f6159925dbab9411094f960daba3c6f46c1f93d34f9a6d476104fc63&ascene=0&uin=MTQwNzQzODYwMA%3D%3D&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=xJ0pJsFuIsM3Ce35cuVqghSLUWaqU91w%2FEgBgn2%2BhouemlzbFvOIXP3KmJlioe0D)\n文章覆盖非常全面,所介绍基础知识、技术栈、能力、领域有很多都是目前我所欠缺的,介于此推荐给大家。。。看完最直观的感受就是自己是个假前端\n\n* [重温ES6核心概念和基本用法](https://segmentfault.com/a/1190000009885614)\n文章梳理了ES6核心概念及基础用法,推荐给大家。\n","source":"_posts/weekly-1.md","raw":"---\ntitle: 大前端周刊 第1期 (本期小编:王祥)\ndate: 2017-06-23 11:18:25\ntags: [weekly,全栈,Node]\n---\n\n## 基础\n\n* [Promise](http://es6.ruanyifeng.com/#docs/promise)\n在Javascript的单线程异步架构下,Promise会是很多异步服务的核心知识点,Node 8.X已经可以方便的将回调方式转换为Promise。\n\n* [异步函数async](http://es6.ruanyifeng.com/#docs/async)\n使用异步函数可以实现“用同步的写法,完成异步的事情”,Node 8.X已经在编译器层面对async做了优化。\n* [语义化版本 2.0.0](http://semver.org/lang/zh-CN/)\n玩开源项目的基础,组件发布的约定。\n* [package.json规则](https://docs.npmjs.com/files/package.json)\n项目的依赖列表,区别开发环境、生产环境、面向的平台和组件的规范(CMD、AMD和UMD)等。\n\n## 单元测试工具\nWeb 应用中的单元测试更加重要,在 Web 产品快速迭代的时期,每个测试用例都给应用的稳定性提供了一层保障。 API 升级,测试用例可以很好地检查代码是否向下兼容。 对于各种可能的输入,一旦测试覆盖,都能明确它的输出。 代码改动后,可以通过测试结果判断代码的改动是否影响已确定的结果。\n\n* [mocha单元测试](https://mochajs.org/)\nNPM里每天有25W的下载量,同时支持Node、浏览器多平台的测试用例的执行。\n\n* [power-assert断言库](https://www.npmjs.com/package/power-assert)\npower-assert可以零学习成本,直观的展示出判断条件和结果。\n\n```\n1) Array #indexOf() should return index when the value is present:\n AssertionError: # path/to/test/mocha_node.js:10\n\n assert(ary.indexOf(zero) === two)\n | | | | |\n | | | | 2\n | -1 0 false\n [1,2,3]\n\n [number] two\n => 2\n [number] ary.indexOf(zero)\n => -1\n```\n\n## 文章\n\n* [JavaScript专题之跟着underscore学防抖](https://github.com/mqyqingfeng/Blog/issues/22)\n对防抖的原理介绍的很清晰,从最简单的实现版本一步一步讲解到实现复杂的版本。\n让我对防抖有了重新的认识。\n\n* [从前端开发看面向未来的敏捷学习法](http://www.jianshu.com/p/fd7055705c62)\n授人以鱼不如授人以渔\n前端技术更新速度很快,快速学习已经成了每个工程师必备技能。\n除了掌握技术知识,解决问题的能力在实际项目中也很重要,文中以实际案例给出分解思路和系统敏捷学习新知识思路。\n\n* [前端工程师做事的三重境界:我的进阶之路](https://zhuanlan.zhihu.com/p/26660510)\n从程序员到工程师的进阶之路,精益求精才能称得上是工程师。作者认为这三个单词(Programmer、Developer、Enginner)对应不用的境界。\n\n* [浏览器缓存机制剖析](http://louiszhai.github.io/2017/04/07/http-cache/)\n正如文中所述“缓存一直是前端优化的主战场, 利用好缓存就成功了一半”,利用好缓存在前端优化地位中举足轻重,本文能够带领大家对浏览器缓存机制有一个初步了解。\n\n* [vue-mixins使用注意事项和高级用法](https://www.deboy.cn/Vue-mixins-advance-tips.html)\n在项目开发中经常会碰到两个组件的业务逻辑有所相似,可能共享相同的底层业务逻辑;此时需要考虑如何来合理地划分代码,即避免冗余代码,也不能过度抽象。\n\n* [也谈JavaScript数组去重](https://www.toobug.net/article/array_unique_in_javascript.html)\n去重,首先要思考什么是相等,从最初的循环,到Set集合。\n\n* [大前端公共知识梳理:这些知识你都掌握了吗?](https://mp.weixin.qq.com/s?__biz=MzIwNjQwMzUwMQ==&mid=2247485277&idx=1&sn=82703e13febb1e7947cc18d1f57fc375&key=6b0fbfcb936d93fa91a745202d0f37bffff65fd2cba5ff2cfa25618c8d03951944ae6eb2f4db18aaf1c8893ddaeffb404684dbd7f6159925dbab9411094f960daba3c6f46c1f93d34f9a6d476104fc63&ascene=0&uin=MTQwNzQzODYwMA%3D%3D&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=xJ0pJsFuIsM3Ce35cuVqghSLUWaqU91w%2FEgBgn2%2BhouemlzbFvOIXP3KmJlioe0D)\n文章覆盖非常全面,所介绍基础知识、技术栈、能力、领域有很多都是目前我所欠缺的,介于此推荐给大家。。。看完最直观的感受就是自己是个假前端\n\n* [重温ES6核心概念和基本用法](https://segmentfault.com/a/1190000009885614)\n文章梳理了ES6核心概念及基础用法,推荐给大家。\n","slug":"weekly-1","published":1,"updated":"2017-08-25T02:32:41.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qk90000jrs697rh4rca","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/promise\" target=\"_blank\" rel=\"noopener\">Promise</a><br>在Javascript的单线程异步架构下,Promise会是很多异步服务的核心知识点,Node 8.X已经可以方便的将回调方式转换为Promise。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/async\" target=\"_blank\" rel=\"noopener\">异步函数async</a><br>使用异步函数可以实现“用同步的写法,完成异步的事情”,Node 8.X已经在编译器层面对async做了优化。</p>\n</li>\n<li><a href=\"http://semver.org/lang/zh-CN/\" target=\"_blank\" rel=\"noopener\">语义化版本 2.0.0</a><br>玩开源项目的基础,组件发布的约定。</li>\n<li><a href=\"https://docs.npmjs.com/files/package.json\" target=\"_blank\" rel=\"noopener\">package.json规则</a><br>项目的依赖列表,区别开发环境、生产环境、面向的平台和组件的规范(CMD、AMD和UMD)等。</li>\n</ul>\n<h2 id=\"单元测试工具\"><a href=\"#单元测试工具\" class=\"headerlink\" title=\"单元测试工具\"></a>单元测试工具</h2><p>Web 应用中的单元测试更加重要,在 Web 产品快速迭代的时期,每个测试用例都给应用的稳定性提供了一层保障。 API 升级,测试用例可以很好地检查代码是否向下兼容。 对于各种可能的输入,一旦测试覆盖,都能明确它的输出。 代码改动后,可以通过测试结果判断代码的改动是否影响已确定的结果。</p>\n<ul>\n<li><p><a href=\"https://mochajs.org/\" target=\"_blank\" rel=\"noopener\">mocha单元测试</a><br>NPM里每天有25W的下载量,同时支持Node、浏览器多平台的测试用例的执行。</p>\n</li>\n<li><p><a href=\"https://www.npmjs.com/package/power-assert\" target=\"_blank\" rel=\"noopener\">power-assert断言库</a><br>power-assert可以零学习成本,直观的展示出判断条件和结果。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">1) Array #indexOf() should return index when the value is present:</span><br><span class=\"line\"> AssertionError: # path/to/test/mocha_node.js:10</span><br><span class=\"line\"></span><br><span class=\"line\"> assert(ary.indexOf(zero) === two)</span><br><span class=\"line\"> | | | | |</span><br><span class=\"line\"> | | | | 2</span><br><span class=\"line\"> | -1 0 false</span><br><span class=\"line\"> [1,2,3]</span><br><span class=\"line\"></span><br><span class=\"line\"> [number] two</span><br><span class=\"line\"> => 2</span><br><span class=\"line\"> [number] ary.indexOf(zero)</span><br><span class=\"line\"> => -1</span><br></pre></td></tr></table></figure>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://github.com/mqyqingfeng/Blog/issues/22\" target=\"_blank\" rel=\"noopener\">JavaScript专题之跟着underscore学防抖</a><br>对防抖的原理介绍的很清晰,从最简单的实现版本一步一步讲解到实现复杂的版本。<br>让我对防抖有了重新的认识。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/fd7055705c62\" target=\"_blank\" rel=\"noopener\">从前端开发看面向未来的敏捷学习法</a><br>授人以鱼不如授人以渔<br>前端技术更新速度很快,快速学习已经成了每个工程师必备技能。<br>除了掌握技术知识,解决问题的能力在实际项目中也很重要,文中以实际案例给出分解思路和系统敏捷学习新知识思路。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26660510\" target=\"_blank\" rel=\"noopener\">前端工程师做事的三重境界:我的进阶之路</a><br>从程序员到工程师的进阶之路,精益求精才能称得上是工程师。作者认为这三个单词(Programmer、Developer、Enginner)对应不用的境界。</p>\n</li>\n<li><p><a href=\"http://louiszhai.github.io/2017/04/07/http-cache/\" target=\"_blank\" rel=\"noopener\">浏览器缓存机制剖析</a><br>正如文中所述“缓存一直是前端优化的主战场, 利用好缓存就成功了一半”,利用好缓存在前端优化地位中举足轻重,本文能够带领大家对浏览器缓存机制有一个初步了解。</p>\n</li>\n<li><p><a href=\"https://www.deboy.cn/Vue-mixins-advance-tips.html\" target=\"_blank\" rel=\"noopener\">vue-mixins使用注意事项和高级用法</a><br>在项目开发中经常会碰到两个组件的业务逻辑有所相似,可能共享相同的底层业务逻辑;此时需要考虑如何来合理地划分代码,即避免冗余代码,也不能过度抽象。</p>\n</li>\n<li><p><a href=\"https://www.toobug.net/article/array_unique_in_javascript.html\" target=\"_blank\" rel=\"noopener\">也谈JavaScript数组去重</a><br>去重,首先要思考什么是相等,从最初的循环,到Set集合。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIwNjQwMzUwMQ==&mid=2247485277&idx=1&sn=82703e13febb1e7947cc18d1f57fc375&key=6b0fbfcb936d93fa91a745202d0f37bffff65fd2cba5ff2cfa25618c8d03951944ae6eb2f4db18aaf1c8893ddaeffb404684dbd7f6159925dbab9411094f960daba3c6f46c1f93d34f9a6d476104fc63&ascene=0&uin=MTQwNzQzODYwMA%3D%3D&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=xJ0pJsFuIsM3Ce35cuVqghSLUWaqU91w%2FEgBgn2%2BhouemlzbFvOIXP3KmJlioe0D\" target=\"_blank\" rel=\"noopener\">大前端公共知识梳理:这些知识你都掌握了吗?</a><br>文章覆盖非常全面,所介绍基础知识、技术栈、能力、领域有很多都是目前我所欠缺的,介于此推荐给大家。。。看完最直观的感受就是自己是个假前端</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000009885614\" target=\"_blank\" rel=\"noopener\">重温ES6核心概念和基本用法</a><br>文章梳理了ES6核心概念及基础用法,推荐给大家。</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/promise\" target=\"_blank\" rel=\"noopener\">Promise</a><br>在Javascript的单线程异步架构下,Promise会是很多异步服务的核心知识点,Node 8.X已经可以方便的将回调方式转换为Promise。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/async\" target=\"_blank\" rel=\"noopener\">异步函数async</a><br>使用异步函数可以实现“用同步的写法,完成异步的事情”,Node 8.X已经在编译器层面对async做了优化。</p>\n</li>\n<li><a href=\"http://semver.org/lang/zh-CN/\" target=\"_blank\" rel=\"noopener\">语义化版本 2.0.0</a><br>玩开源项目的基础,组件发布的约定。</li>\n<li><a href=\"https://docs.npmjs.com/files/package.json\" target=\"_blank\" rel=\"noopener\">package.json规则</a><br>项目的依赖列表,区别开发环境、生产环境、面向的平台和组件的规范(CMD、AMD和UMD)等。</li>\n</ul>\n<h2 id=\"单元测试工具\"><a href=\"#单元测试工具\" class=\"headerlink\" title=\"单元测试工具\"></a>单元测试工具</h2><p>Web 应用中的单元测试更加重要,在 Web 产品快速迭代的时期,每个测试用例都给应用的稳定性提供了一层保障。 API 升级,测试用例可以很好地检查代码是否向下兼容。 对于各种可能的输入,一旦测试覆盖,都能明确它的输出。 代码改动后,可以通过测试结果判断代码的改动是否影响已确定的结果。</p>\n<ul>\n<li><p><a href=\"https://mochajs.org/\" target=\"_blank\" rel=\"noopener\">mocha单元测试</a><br>NPM里每天有25W的下载量,同时支持Node、浏览器多平台的测试用例的执行。</p>\n</li>\n<li><p><a href=\"https://www.npmjs.com/package/power-assert\" target=\"_blank\" rel=\"noopener\">power-assert断言库</a><br>power-assert可以零学习成本,直观的展示出判断条件和结果。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">1) Array #indexOf() should return index when the value is present:</span><br><span class=\"line\"> AssertionError: # path/to/test/mocha_node.js:10</span><br><span class=\"line\"></span><br><span class=\"line\"> assert(ary.indexOf(zero) === two)</span><br><span class=\"line\"> | | | | |</span><br><span class=\"line\"> | | | | 2</span><br><span class=\"line\"> | -1 0 false</span><br><span class=\"line\"> [1,2,3]</span><br><span class=\"line\"></span><br><span class=\"line\"> [number] two</span><br><span class=\"line\"> => 2</span><br><span class=\"line\"> [number] ary.indexOf(zero)</span><br><span class=\"line\"> => -1</span><br></pre></td></tr></table></figure>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://github.com/mqyqingfeng/Blog/issues/22\" target=\"_blank\" rel=\"noopener\">JavaScript专题之跟着underscore学防抖</a><br>对防抖的原理介绍的很清晰,从最简单的实现版本一步一步讲解到实现复杂的版本。<br>让我对防抖有了重新的认识。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/fd7055705c62\" target=\"_blank\" rel=\"noopener\">从前端开发看面向未来的敏捷学习法</a><br>授人以鱼不如授人以渔<br>前端技术更新速度很快,快速学习已经成了每个工程师必备技能。<br>除了掌握技术知识,解决问题的能力在实际项目中也很重要,文中以实际案例给出分解思路和系统敏捷学习新知识思路。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26660510\" target=\"_blank\" rel=\"noopener\">前端工程师做事的三重境界:我的进阶之路</a><br>从程序员到工程师的进阶之路,精益求精才能称得上是工程师。作者认为这三个单词(Programmer、Developer、Enginner)对应不用的境界。</p>\n</li>\n<li><p><a href=\"http://louiszhai.github.io/2017/04/07/http-cache/\" target=\"_blank\" rel=\"noopener\">浏览器缓存机制剖析</a><br>正如文中所述“缓存一直是前端优化的主战场, 利用好缓存就成功了一半”,利用好缓存在前端优化地位中举足轻重,本文能够带领大家对浏览器缓存机制有一个初步了解。</p>\n</li>\n<li><p><a href=\"https://www.deboy.cn/Vue-mixins-advance-tips.html\" target=\"_blank\" rel=\"noopener\">vue-mixins使用注意事项和高级用法</a><br>在项目开发中经常会碰到两个组件的业务逻辑有所相似,可能共享相同的底层业务逻辑;此时需要考虑如何来合理地划分代码,即避免冗余代码,也不能过度抽象。</p>\n</li>\n<li><p><a href=\"https://www.toobug.net/article/array_unique_in_javascript.html\" target=\"_blank\" rel=\"noopener\">也谈JavaScript数组去重</a><br>去重,首先要思考什么是相等,从最初的循环,到Set集合。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIwNjQwMzUwMQ==&mid=2247485277&idx=1&sn=82703e13febb1e7947cc18d1f57fc375&key=6b0fbfcb936d93fa91a745202d0f37bffff65fd2cba5ff2cfa25618c8d03951944ae6eb2f4db18aaf1c8893ddaeffb404684dbd7f6159925dbab9411094f960daba3c6f46c1f93d34f9a6d476104fc63&ascene=0&uin=MTQwNzQzODYwMA%3D%3D&version=12020810&nettype=WIFI&fontScale=100&pass_ticket=xJ0pJsFuIsM3Ce35cuVqghSLUWaqU91w%2FEgBgn2%2BhouemlzbFvOIXP3KmJlioe0D\" target=\"_blank\" rel=\"noopener\">大前端公共知识梳理:这些知识你都掌握了吗?</a><br>文章覆盖非常全面,所介绍基础知识、技术栈、能力、领域有很多都是目前我所欠缺的,介于此推荐给大家。。。看完最直观的感受就是自己是个假前端</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000009885614\" target=\"_blank\" rel=\"noopener\">重温ES6核心概念和基本用法</a><br>文章梳理了ES6核心概念及基础用法,推荐给大家。</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第10期 (本期小编:王祥)","date":"2017-08-25T02:30:30.000Z","_content":"## Show me the code\nES 6 中引入了很多让代码看起来更简洁的新特性,比如展开运算符 (spread operator)。下面的三段代码,展示了 ES6 更简洁的对象拷贝、数组复制和可变参数的写法。\n\n* 对象拷贝\n\n```javascript\n// very bad\nconst original = { a: 1, b: 2 };\nconst copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ\ndelete copy.a; // so does this\n\n// bad\nconst original = { a: 1, b: 2 };\nconst copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }\n\n// good\nconst original = { a: 1, b: 2 };\nconst copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }\n\nconst { a, ...noA } = copy; // noA => { b: 2, c: 3 }\n```\n\n* 数组复制 (copy arrays)\n\n```javascript\n// bad\nconst len = items.length;\nconst itemsCopy = [];\nlet i;\n\nfor (i = 0; i < len; i += 1) {\n itemsCopy[i] = items[i];\n}\n\n// good\nconst itemsCopy = [...items];\n```\n\n* 可变函数 (variadic function)\n\n```javascript\n// bad\nconst x = [1, 2, 3, 4, 5];\nconsole.log.apply(console, x);\n\n// good\nconst x = [1, 2, 3, 4, 5];\nconsole.log(...x);\n\n// bad\nnew (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));\n\n// good\nnew Date(...[2016, 8, 5]);\n```\n\n## 工具和模块\n推荐一个 Markdown 生成 Word 文档工具 pandoc。\n\n1. 使用 pandoc 将 Markdown 文件转换为 Word 文档。\n``` bash\n$ pandoc -f markdown -t docx front-end-engineering-practice.md -o mydoc.docx\n```\n2. 安装 pandoc ( Mac )\n``` bash\n$ brew install pandoc\n```\n\n## 文章推荐\n* [10 个基于 JavaScript 的机器学习实例](https://zhuanlan.zhihu.com/p/26709518)\n\n虽然,大多数 JavaScript 机器学习库都是“新轮子”,有的甚至还在研发中,但并不会影响你的使用。在这篇文章中,我们将与你分享这些库,以及一些很酷的 AI Web 应用程序实例,帮助你开启机器学习之旅。\n\n* [通俗大白话来理解TCP协议的三次握手和四次分手](https://github.com/jawil/blog/issues/14)\n\n前端工程师也需要了解HTTP方面的一些知识,本篇文章用通俗易懂的方式讲解了平时经常听到的三次握手和四次分手究竟是什么。\n\n* [测试框架 Mocha 实例教程](http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html)\n\nMocha 是目前最流行的测试框架之一,支持浏览器端和 Node 端的单元测试。这篇文章非常全面地介绍如何使用Mocha,让你轻松上手。\n* [前后端分离的思考与实践](https://www.kancloud.cn/kancloud/midway/48192)\n\n本文是阿里某前端团队,在探索一套基于NodeJS的前后端分离方案的过程中,对于前后端分离的一些认识以及思考。\n\n* Mac [Charles 从入门到精通](http://blog.devtang.com/2015/11/14/charles-introduction/)\n PC [Fiddler 抓包工具总结](http://blog.csdn.net/qq_21445563/article/details/51017605)\n\n在PC Web端开发的时候,我们能很方便的从浏览器开发者工具里进行网络接口调试。\n在移动端开发是面对这样的需求,我们可以通过抓包工具来解决这个问题。\n在Mac系统常用的抓包工具是Charles,Windows系统中常用的抓包工具是Fiddler。\n下面的文章分别对Charles和Fiddler进行介绍,并图文显示了使用方法。\n\n* [微信小程序开发教程](https://github.com/zce/weapp-demo/tree/tutorial)\n\n由易到难介绍小程序开发的流程,讲解比较层次化,比较细致,可以让人很快进行上手开发\n\n* [JavaScript Error 指南](https://github.com/Jocs/jocs.github.io/issues/1)\n\n深度的剖析了错误信息和追溯栈,从错误捕获、剖析追溯栈、不同浏览器对于追溯栈格式上的差异等等,讲解相当详细也很透彻。\n\n* [浏览器是怎么看闭包的](http://ifanqi.me/2017/07/25/you-can-understand-closure/)\n\n关于闭包的解释有很多,很多只是从“行”上去解读,理解 JavaScript 闭包绕不开一个问题:闭包是如何实现变量保留在内存中呢?这涉及到浏览器对内存的分配与回收,本文从这个点展开图文详实的解读。拓展阅读:[可视化分析js的内存分配与回收](http://ifanqi.me/2017/07/28/js-variable-memory/)。\n\n* [剖析Promise内部结构](https://github.com/xieranmaya/blog/issues/3)\n\n一步一步实现一个完整的、能通过所有Test case的Promise类。文章由构造简单的promise对象开始,逐步完善逻辑。抛出问题,介绍思路,给出代码示例,比较清晰合理。自己实现已有的轮子,对于编码能力提升还是很有帮助的。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-10.md","raw":"---\ntitle: 大前端周刊 第10期 (本期小编:王祥)\ndate: 2017-08-25 10:30:30\ntags: [weekly,工程化实践,Vuex,Webpack,PWA,持续部署]\n---\n## Show me the code\nES 6 中引入了很多让代码看起来更简洁的新特性,比如展开运算符 (spread operator)。下面的三段代码,展示了 ES6 更简洁的对象拷贝、数组复制和可变参数的写法。\n\n* 对象拷贝\n\n```javascript\n// very bad\nconst original = { a: 1, b: 2 };\nconst copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ\ndelete copy.a; // so does this\n\n// bad\nconst original = { a: 1, b: 2 };\nconst copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }\n\n// good\nconst original = { a: 1, b: 2 };\nconst copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }\n\nconst { a, ...noA } = copy; // noA => { b: 2, c: 3 }\n```\n\n* 数组复制 (copy arrays)\n\n```javascript\n// bad\nconst len = items.length;\nconst itemsCopy = [];\nlet i;\n\nfor (i = 0; i < len; i += 1) {\n itemsCopy[i] = items[i];\n}\n\n// good\nconst itemsCopy = [...items];\n```\n\n* 可变函数 (variadic function)\n\n```javascript\n// bad\nconst x = [1, 2, 3, 4, 5];\nconsole.log.apply(console, x);\n\n// good\nconst x = [1, 2, 3, 4, 5];\nconsole.log(...x);\n\n// bad\nnew (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));\n\n// good\nnew Date(...[2016, 8, 5]);\n```\n\n## 工具和模块\n推荐一个 Markdown 生成 Word 文档工具 pandoc。\n\n1. 使用 pandoc 将 Markdown 文件转换为 Word 文档。\n``` bash\n$ pandoc -f markdown -t docx front-end-engineering-practice.md -o mydoc.docx\n```\n2. 安装 pandoc ( Mac )\n``` bash\n$ brew install pandoc\n```\n\n## 文章推荐\n* [10 个基于 JavaScript 的机器学习实例](https://zhuanlan.zhihu.com/p/26709518)\n\n虽然,大多数 JavaScript 机器学习库都是“新轮子”,有的甚至还在研发中,但并不会影响你的使用。在这篇文章中,我们将与你分享这些库,以及一些很酷的 AI Web 应用程序实例,帮助你开启机器学习之旅。\n\n* [通俗大白话来理解TCP协议的三次握手和四次分手](https://github.com/jawil/blog/issues/14)\n\n前端工程师也需要了解HTTP方面的一些知识,本篇文章用通俗易懂的方式讲解了平时经常听到的三次握手和四次分手究竟是什么。\n\n* [测试框架 Mocha 实例教程](http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html)\n\nMocha 是目前最流行的测试框架之一,支持浏览器端和 Node 端的单元测试。这篇文章非常全面地介绍如何使用Mocha,让你轻松上手。\n* [前后端分离的思考与实践](https://www.kancloud.cn/kancloud/midway/48192)\n\n本文是阿里某前端团队,在探索一套基于NodeJS的前后端分离方案的过程中,对于前后端分离的一些认识以及思考。\n\n* Mac [Charles 从入门到精通](http://blog.devtang.com/2015/11/14/charles-introduction/)\n PC [Fiddler 抓包工具总结](http://blog.csdn.net/qq_21445563/article/details/51017605)\n\n在PC Web端开发的时候,我们能很方便的从浏览器开发者工具里进行网络接口调试。\n在移动端开发是面对这样的需求,我们可以通过抓包工具来解决这个问题。\n在Mac系统常用的抓包工具是Charles,Windows系统中常用的抓包工具是Fiddler。\n下面的文章分别对Charles和Fiddler进行介绍,并图文显示了使用方法。\n\n* [微信小程序开发教程](https://github.com/zce/weapp-demo/tree/tutorial)\n\n由易到难介绍小程序开发的流程,讲解比较层次化,比较细致,可以让人很快进行上手开发\n\n* [JavaScript Error 指南](https://github.com/Jocs/jocs.github.io/issues/1)\n\n深度的剖析了错误信息和追溯栈,从错误捕获、剖析追溯栈、不同浏览器对于追溯栈格式上的差异等等,讲解相当详细也很透彻。\n\n* [浏览器是怎么看闭包的](http://ifanqi.me/2017/07/25/you-can-understand-closure/)\n\n关于闭包的解释有很多,很多只是从“行”上去解读,理解 JavaScript 闭包绕不开一个问题:闭包是如何实现变量保留在内存中呢?这涉及到浏览器对内存的分配与回收,本文从这个点展开图文详实的解读。拓展阅读:[可视化分析js的内存分配与回收](http://ifanqi.me/2017/07/28/js-variable-memory/)。\n\n* [剖析Promise内部结构](https://github.com/xieranmaya/blog/issues/3)\n\n一步一步实现一个完整的、能通过所有Test case的Promise类。文章由构造简单的promise对象开始,逐步完善逻辑。抛出问题,介绍思路,给出代码示例,比较清晰合理。自己实现已有的轮子,对于编码能力提升还是很有帮助的。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-10","published":1,"updated":"2017-08-25T07:23:39.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qke0001jrs62g3pkxfj","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><p>ES 6 中引入了很多让代码看起来更简洁的新特性,比如展开运算符 (spread operator)。下面的三段代码,展示了 ES6 更简洁的对象拷贝、数组复制和可变参数的写法。</p>\n<ul>\n<li>对象拷贝</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// very bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = <span class=\"built_in\">Object</span>.assign(original, { <span class=\"attr\">c</span>: <span class=\"number\">3</span> }); <span class=\"comment\">// this mutates `original` ಠ_ಠ</span></span><br><span class=\"line\"><span class=\"keyword\">delete</span> copy.a; <span class=\"comment\">// so does this</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = <span class=\"built_in\">Object</span>.assign({}, original, { <span class=\"attr\">c</span>: <span class=\"number\">3</span> }); <span class=\"comment\">// copy => { a: 1, b: 2, c: 3 }</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = { ...original, <span class=\"attr\">c</span>: <span class=\"number\">3</span> }; <span class=\"comment\">// copy => { a: 1, b: 2, c: 3 }</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> { a, ...noA } = copy; <span class=\"comment\">// noA => { b: 2, c: 3 }</span></span><br></pre></td></tr></table></figure>\n<ul>\n<li>数组复制 (copy arrays)</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> len = items.length;</span><br><span class=\"line\"><span class=\"keyword\">const</span> itemsCopy = [];</span><br><span class=\"line\"><span class=\"keyword\">let</span> i;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> (i = <span class=\"number\">0</span>; i < len; i += <span class=\"number\">1</span>) {</span><br><span class=\"line\"> itemsCopy[i] = items[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> itemsCopy = [...items];</span><br></pre></td></tr></table></figure>\n<ul>\n<li>可变函数 (variadic function)</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> x = [<span class=\"number\">1</span>, <span class=\"number\">2</span>, <span class=\"number\">3</span>, <span class=\"number\">4</span>, <span class=\"number\">5</span>];</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log.apply(<span class=\"built_in\">console</span>, x);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> x = [<span class=\"number\">1</span>, <span class=\"number\">2</span>, <span class=\"number\">3</span>, <span class=\"number\">4</span>, <span class=\"number\">5</span>];</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(...x);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> (<span class=\"built_in\">Function</span>.prototype.bind.apply(<span class=\"built_in\">Date</span>, [<span class=\"literal\">null</span>, <span class=\"number\">2016</span>, <span class=\"number\">8</span>, <span class=\"number\">5</span>]));</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>(...[<span class=\"number\">2016</span>, <span class=\"number\">8</span>, <span class=\"number\">5</span>]);</span><br></pre></td></tr></table></figure>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐一个 Markdown 生成 Word 文档工具 pandoc。</p>\n<ol>\n<li><p>使用 pandoc 将 Markdown 文件转换为 Word 文档。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ pandoc -f markdown -t docx front-end-engineering-practice.md -o mydoc.docx</span><br></pre></td></tr></table></figure>\n</li>\n<li><p>安装 pandoc ( Mac )</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ brew install pandoc</span><br></pre></td></tr></table></figure>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/26709518\" target=\"_blank\" rel=\"noopener\">10 个基于 JavaScript 的机器学习实例</a></li>\n</ul>\n<p>虽然,大多数 JavaScript 机器学习库都是“新轮子”,有的甚至还在研发中,但并不会影响你的使用。在这篇文章中,我们将与你分享这些库,以及一些很酷的 AI Web 应用程序实例,帮助你开启机器学习之旅。</p>\n<ul>\n<li><a href=\"https://github.com/jawil/blog/issues/14\" target=\"_blank\" rel=\"noopener\">通俗大白话来理解TCP协议的三次握手和四次分手</a></li>\n</ul>\n<p>前端工程师也需要了解HTTP方面的一些知识,本篇文章用通俗易懂的方式讲解了平时经常听到的三次握手和四次分手究竟是什么。</p>\n<ul>\n<li><a href=\"http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html\" target=\"_blank\" rel=\"noopener\">测试框架 Mocha 实例教程</a></li>\n</ul>\n<p>Mocha 是目前最流行的测试框架之一,支持浏览器端和 Node 端的单元测试。这篇文章非常全面地介绍如何使用Mocha,让你轻松上手。</p>\n<ul>\n<li><a href=\"https://www.kancloud.cn/kancloud/midway/48192\" target=\"_blank\" rel=\"noopener\">前后端分离的思考与实践</a></li>\n</ul>\n<p>本文是阿里某前端团队,在探索一套基于NodeJS的前后端分离方案的过程中,对于前后端分离的一些认识以及思考。</p>\n<ul>\n<li>Mac <a href=\"http://blog.devtang.com/2015/11/14/charles-introduction/\" target=\"_blank\" rel=\"noopener\">Charles 从入门到精通</a><br>PC <a href=\"http://blog.csdn.net/qq_21445563/article/details/51017605\" target=\"_blank\" rel=\"noopener\">Fiddler 抓包工具总结</a></li>\n</ul>\n<p>在PC Web端开发的时候,我们能很方便的从浏览器开发者工具里进行网络接口调试。<br>在移动端开发是面对这样的需求,我们可以通过抓包工具来解决这个问题。<br>在Mac系统常用的抓包工具是Charles,Windows系统中常用的抓包工具是Fiddler。<br>下面的文章分别对Charles和Fiddler进行介绍,并图文显示了使用方法。</p>\n<ul>\n<li><a href=\"https://github.com/zce/weapp-demo/tree/tutorial\" target=\"_blank\" rel=\"noopener\">微信小程序开发教程</a></li>\n</ul>\n<p>由易到难介绍小程序开发的流程,讲解比较层次化,比较细致,可以让人很快进行上手开发</p>\n<ul>\n<li><a href=\"https://github.com/Jocs/jocs.github.io/issues/1\" target=\"_blank\" rel=\"noopener\">JavaScript Error 指南</a></li>\n</ul>\n<p>深度的剖析了错误信息和追溯栈,从错误捕获、剖析追溯栈、不同浏览器对于追溯栈格式上的差异等等,讲解相当详细也很透彻。</p>\n<ul>\n<li><a href=\"http://ifanqi.me/2017/07/25/you-can-understand-closure/\" target=\"_blank\" rel=\"noopener\">浏览器是怎么看闭包的</a></li>\n</ul>\n<p>关于闭包的解释有很多,很多只是从“行”上去解读,理解 JavaScript 闭包绕不开一个问题:闭包是如何实现变量保留在内存中呢?这涉及到浏览器对内存的分配与回收,本文从这个点展开图文详实的解读。拓展阅读:<a href=\"http://ifanqi.me/2017/07/28/js-variable-memory/\" target=\"_blank\" rel=\"noopener\">可视化分析js的内存分配与回收</a>。</p>\n<ul>\n<li><a href=\"https://github.com/xieranmaya/blog/issues/3\" target=\"_blank\" rel=\"noopener\">剖析Promise内部结构</a></li>\n</ul>\n<p>一步一步实现一个完整的、能通过所有Test case的Promise类。文章由构造简单的promise对象开始,逐步完善逻辑。抛出问题,介绍思路,给出代码示例,比较清晰合理。自己实现已有的轮子,对于编码能力提升还是很有帮助的。</p>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><p>ES 6 中引入了很多让代码看起来更简洁的新特性,比如展开运算符 (spread operator)。下面的三段代码,展示了 ES6 更简洁的对象拷贝、数组复制和可变参数的写法。</p>\n<ul>\n<li>对象拷贝</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// very bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = <span class=\"built_in\">Object</span>.assign(original, { <span class=\"attr\">c</span>: <span class=\"number\">3</span> }); <span class=\"comment\">// this mutates `original` ಠ_ಠ</span></span><br><span class=\"line\"><span class=\"keyword\">delete</span> copy.a; <span class=\"comment\">// so does this</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = <span class=\"built_in\">Object</span>.assign({}, original, { <span class=\"attr\">c</span>: <span class=\"number\">3</span> }); <span class=\"comment\">// copy => { a: 1, b: 2, c: 3 }</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> original = { <span class=\"attr\">a</span>: <span class=\"number\">1</span>, <span class=\"attr\">b</span>: <span class=\"number\">2</span> };</span><br><span class=\"line\"><span class=\"keyword\">const</span> copy = { ...original, <span class=\"attr\">c</span>: <span class=\"number\">3</span> }; <span class=\"comment\">// copy => { a: 1, b: 2, c: 3 }</span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> { a, ...noA } = copy; <span class=\"comment\">// noA => { b: 2, c: 3 }</span></span><br></pre></td></tr></table></figure>\n<ul>\n<li>数组复制 (copy arrays)</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> len = items.length;</span><br><span class=\"line\"><span class=\"keyword\">const</span> itemsCopy = [];</span><br><span class=\"line\"><span class=\"keyword\">let</span> i;</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> (i = <span class=\"number\">0</span>; i < len; i += <span class=\"number\">1</span>) {</span><br><span class=\"line\"> itemsCopy[i] = items[i];</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> itemsCopy = [...items];</span><br></pre></td></tr></table></figure>\n<ul>\n<li>可变函数 (variadic function)</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> x = [<span class=\"number\">1</span>, <span class=\"number\">2</span>, <span class=\"number\">3</span>, <span class=\"number\">4</span>, <span class=\"number\">5</span>];</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log.apply(<span class=\"built_in\">console</span>, x);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> x = [<span class=\"number\">1</span>, <span class=\"number\">2</span>, <span class=\"number\">3</span>, <span class=\"number\">4</span>, <span class=\"number\">5</span>];</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(...x);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> (<span class=\"built_in\">Function</span>.prototype.bind.apply(<span class=\"built_in\">Date</span>, [<span class=\"literal\">null</span>, <span class=\"number\">2016</span>, <span class=\"number\">8</span>, <span class=\"number\">5</span>]));</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>(...[<span class=\"number\">2016</span>, <span class=\"number\">8</span>, <span class=\"number\">5</span>]);</span><br></pre></td></tr></table></figure>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐一个 Markdown 生成 Word 文档工具 pandoc。</p>\n<ol>\n<li><p>使用 pandoc 将 Markdown 文件转换为 Word 文档。</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ pandoc -f markdown -t docx front-end-engineering-practice.md -o mydoc.docx</span><br></pre></td></tr></table></figure>\n</li>\n<li><p>安装 pandoc ( Mac )</p>\n<figure class=\"highlight bash\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ brew install pandoc</span><br></pre></td></tr></table></figure>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/26709518\" target=\"_blank\" rel=\"noopener\">10 个基于 JavaScript 的机器学习实例</a></li>\n</ul>\n<p>虽然,大多数 JavaScript 机器学习库都是“新轮子”,有的甚至还在研发中,但并不会影响你的使用。在这篇文章中,我们将与你分享这些库,以及一些很酷的 AI Web 应用程序实例,帮助你开启机器学习之旅。</p>\n<ul>\n<li><a href=\"https://github.com/jawil/blog/issues/14\" target=\"_blank\" rel=\"noopener\">通俗大白话来理解TCP协议的三次握手和四次分手</a></li>\n</ul>\n<p>前端工程师也需要了解HTTP方面的一些知识,本篇文章用通俗易懂的方式讲解了平时经常听到的三次握手和四次分手究竟是什么。</p>\n<ul>\n<li><a href=\"http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html\" target=\"_blank\" rel=\"noopener\">测试框架 Mocha 实例教程</a></li>\n</ul>\n<p>Mocha 是目前最流行的测试框架之一,支持浏览器端和 Node 端的单元测试。这篇文章非常全面地介绍如何使用Mocha,让你轻松上手。</p>\n<ul>\n<li><a href=\"https://www.kancloud.cn/kancloud/midway/48192\" target=\"_blank\" rel=\"noopener\">前后端分离的思考与实践</a></li>\n</ul>\n<p>本文是阿里某前端团队,在探索一套基于NodeJS的前后端分离方案的过程中,对于前后端分离的一些认识以及思考。</p>\n<ul>\n<li>Mac <a href=\"http://blog.devtang.com/2015/11/14/charles-introduction/\" target=\"_blank\" rel=\"noopener\">Charles 从入门到精通</a><br>PC <a href=\"http://blog.csdn.net/qq_21445563/article/details/51017605\" target=\"_blank\" rel=\"noopener\">Fiddler 抓包工具总结</a></li>\n</ul>\n<p>在PC Web端开发的时候,我们能很方便的从浏览器开发者工具里进行网络接口调试。<br>在移动端开发是面对这样的需求,我们可以通过抓包工具来解决这个问题。<br>在Mac系统常用的抓包工具是Charles,Windows系统中常用的抓包工具是Fiddler。<br>下面的文章分别对Charles和Fiddler进行介绍,并图文显示了使用方法。</p>\n<ul>\n<li><a href=\"https://github.com/zce/weapp-demo/tree/tutorial\" target=\"_blank\" rel=\"noopener\">微信小程序开发教程</a></li>\n</ul>\n<p>由易到难介绍小程序开发的流程,讲解比较层次化,比较细致,可以让人很快进行上手开发</p>\n<ul>\n<li><a href=\"https://github.com/Jocs/jocs.github.io/issues/1\" target=\"_blank\" rel=\"noopener\">JavaScript Error 指南</a></li>\n</ul>\n<p>深度的剖析了错误信息和追溯栈,从错误捕获、剖析追溯栈、不同浏览器对于追溯栈格式上的差异等等,讲解相当详细也很透彻。</p>\n<ul>\n<li><a href=\"http://ifanqi.me/2017/07/25/you-can-understand-closure/\" target=\"_blank\" rel=\"noopener\">浏览器是怎么看闭包的</a></li>\n</ul>\n<p>关于闭包的解释有很多,很多只是从“行”上去解读,理解 JavaScript 闭包绕不开一个问题:闭包是如何实现变量保留在内存中呢?这涉及到浏览器对内存的分配与回收,本文从这个点展开图文详实的解读。拓展阅读:<a href=\"http://ifanqi.me/2017/07/28/js-variable-memory/\" target=\"_blank\" rel=\"noopener\">可视化分析js的内存分配与回收</a>。</p>\n<ul>\n<li><a href=\"https://github.com/xieranmaya/blog/issues/3\" target=\"_blank\" rel=\"noopener\">剖析Promise内部结构</a></li>\n</ul>\n<p>一步一步实现一个完整的、能通过所有Test case的Promise类。文章由构造简单的promise对象开始,逐步完善逻辑。抛出问题,介绍思路,给出代码示例,比较清晰合理。自己实现已有的轮子,对于编码能力提升还是很有帮助的。</p>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第11期 (本期小编:胡国伟)","date":"2017-09-01T09:00:00.000Z","_content":"## Show me the code\n\n#### 截流(throttle)\n\n概念理解:固定函数执行的速率。\n使用场景:DOM 事件绑定,短时间内触发多次绑定事件造成性能问题,如 `onresize`,`onscroll`等,使用节流函数可确保在指定时间内只触发一次。\n简单实现:\n```javascript\nlet throttle = (func, wait) => {\n\tlet context, args;\n\tlet previous = 0;\n\n\treturn function () {\n\t\tlet now = +new Date();\n\t\tcontext = this;\n\t\targs = arguments;\n\t\tif (now - previous > wait) {\n\t\t\tfunc.apply(context, args);\n\t\t\tprevious = now;\n\t\t}\n\t};\n};\n```\n\n#### 防抖(debounce)\n\n概念理解:强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。\n使用场景:\n1. 表单远程搜索,键盘多次输入取最后一次输入值作为查询关键词。\n2. 下拉菜单的延时消失。\n\n简单实现:\n```javascript\nlet debounce = (func, wait) => {\n\tlet timeout;\n \treturn function () {\n \tlet context = this;\n \tlet args = arguments;\n \tclearTimeout(timeout);\n \ttimeout = setTimeout(function () {\n \t\tfunc.apply(context, args)\n \t}, wait);\n };\n};\n```\n\n## 工具和模块\n\n推荐功能强大的`HTTP`抓包调试工具:Fiddler。假如有这样一个场景,线上突然出现bug,而你正在休假、手头又没有源码,但又急需你参与问题排查,怎么办?Fiddler 便是你的救🔥利器。\n\n1. 官网:http://www.telerik.com/fiddler\n2. 插件(官方&第三方):http://www.telerik.com/fiddler/add-ons\n3. 快速上手:[十分钟学会 Fiddler](https://www.qcloud.com/community/article/115124?fromSource=gwzcw.93596.93596.93596)\n4. 视频教程:http://www.imooc.com/learn/37\n5. 系列文章\n - [【HTTP】Fiddler(一) - Fiddler简介](http://blog.csdn.net/ohmygirl/article/details/17846199)\n - [【HTTP】Fiddler(二) - 使用Fiddler做抓包分析](http://blog.csdn.net/ohmygirl/article/details/17849983)\n - [【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试](http://blog.csdn.net/ohmygirl/article/details/17855031)\n\n\n## 文章推荐\n\n- [代码覆盖率工具 Istanbul 入门教程](http://www.ruanyifeng.com/blog/2015/06/istanbul.html)\n 使用 Mocha 进行单元测试时,还需要了解测试的覆盖程度,这个指标就叫做\"代码覆盖率\"(code coverage)。这篇文章非常全面地介绍了Istanbul,让你轻松上手。深入了解:[nyc](https://github.com/istanbuljs/nyc)\n\n- [深入浅出浏览器渲染原理](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484408&idx=2&sn=456405dd36fd679dea1470b131924980&chksm=e82be2e9df5c6bff70912d297d535bfb747e2598a129641ea3409cedd88f2eac22e2d77dc98b&mpshare=1&scene=1&srcid=0901XT4SSeVjxiKd3Pj6IOvv&pass_ticket=%2BCgbmXT%2FgYy2AZSB%2B2tlPOm2ZM34W2NpPc%2F1G3ifFff91PXQRXcYFvt%2BSdaP7QjU#rd)\n 对于 HTTP 协议和浏览器渲染原理都是理解容易但不好讲明白,那么为什么不采用 Node.js 来阐述呢?以实践的方式、最简单的方式来向你展示不好讲的东西,对于 Node.js 开发者和大前端开发来说都是非常实用的。\n\n- [剖析Vue实现原理 - 如何实现双向绑定mvvm](https://github.com/DMQ/mvvm)\n 1. 了解vue的双向数据绑定原理以及核心代码模块\n 2. 了解如何实现双向绑定\n\n- [不用call和apply方法模拟实现ES5的bind方法](https://github.com/jawil/blog/issues/16)\n 这个问题是对JavaScript基本功很好的一个检测,看JavaScript掌握的怎么样以及平时有没有去深入研究一些方法的实现,简而言之,就是有没有折腾精神。\n\n- [通过ES6 Generator函数实现异步操作](https://github.com/Jocs/jocs.github.io/issues/11)\n 文章对 Generator函数实现异步进行了深入的讲解,最后使用 promise和 generator这样的模式实现异步操作,对于实现的过程进行深入细致的分析。\n\n- [你了解CSS设计模式吗?](http://mp.weixin.qq.com/s?__biz=MzI2MTY0NTEyMA==&mid=2247483871&idx=1&sn=f717d3c787626d997c410117a1cd7fb9&chksm=ea5677f0dd21fee6c7853b60b7e32d744af1abb183903ce8523954e093263a8c375895f0f193&mpshare=1&scene=1&srcid=06289q8vqWAQUGuqdrMsqEzq#)\n 简单来了解下CSS设计模式:\n 1. BEM全称(block、element、modifier)是Yandex 团队提出的CSS Class命名法\n 2. OOCSS全称(Object Oriented CSS)由Nicole Sullivan提出的css理论\n 3. SMACSS是Jonathan Snook的一个CSS框架\n 4. Atomic Design,原子设计\n\n\n - [我接触过的前端数据结构与算法](http://fed.renren.com/2017/07/02/algorithm/)\n 作者总结了前端常常碰到的算法,主要涉及递归、节流、数组去重、栈和堆、图像处理等。代码示例较为清晰,对于初学者还是很有帮助的,比较赞同作者的观点:算法的目的是用最小的时间和最小的空间解决问题。但是有时候不用太拘泥于一定要最优的答案,能够合适地解决问题就是好方法,而且对于不同的应用场景可能要采取不同的策略。\n\n- [JavaScript 中 4 种常见的内存泄露陷阱](http://web.jobbole.com/88463/)\n 虽然Javascript有内存自动回收机制,但这并不以为着js开发使完全不用关心内存管理。文中详细介绍了什么是内存泄漏和js中容易引起内存泄漏的点,并提供了使用Chrome分析内存的方法。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-11.md","raw":"---\ntitle: 大前端周刊 第11期 (本期小编:胡国伟)\ndate: 2017-09-01 17:00:00\ntags: [weekly,开发工具,测试工具,Vue,ES6,设计模式]\n---\n## Show me the code\n\n#### 截流(throttle)\n\n概念理解:固定函数执行的速率。\n使用场景:DOM 事件绑定,短时间内触发多次绑定事件造成性能问题,如 `onresize`,`onscroll`等,使用节流函数可确保在指定时间内只触发一次。\n简单实现:\n```javascript\nlet throttle = (func, wait) => {\n\tlet context, args;\n\tlet previous = 0;\n\n\treturn function () {\n\t\tlet now = +new Date();\n\t\tcontext = this;\n\t\targs = arguments;\n\t\tif (now - previous > wait) {\n\t\t\tfunc.apply(context, args);\n\t\t\tprevious = now;\n\t\t}\n\t};\n};\n```\n\n#### 防抖(debounce)\n\n概念理解:强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。\n使用场景:\n1. 表单远程搜索,键盘多次输入取最后一次输入值作为查询关键词。\n2. 下拉菜单的延时消失。\n\n简单实现:\n```javascript\nlet debounce = (func, wait) => {\n\tlet timeout;\n \treturn function () {\n \tlet context = this;\n \tlet args = arguments;\n \tclearTimeout(timeout);\n \ttimeout = setTimeout(function () {\n \t\tfunc.apply(context, args)\n \t}, wait);\n };\n};\n```\n\n## 工具和模块\n\n推荐功能强大的`HTTP`抓包调试工具:Fiddler。假如有这样一个场景,线上突然出现bug,而你正在休假、手头又没有源码,但又急需你参与问题排查,怎么办?Fiddler 便是你的救🔥利器。\n\n1. 官网:http://www.telerik.com/fiddler\n2. 插件(官方&第三方):http://www.telerik.com/fiddler/add-ons\n3. 快速上手:[十分钟学会 Fiddler](https://www.qcloud.com/community/article/115124?fromSource=gwzcw.93596.93596.93596)\n4. 视频教程:http://www.imooc.com/learn/37\n5. 系列文章\n - [【HTTP】Fiddler(一) - Fiddler简介](http://blog.csdn.net/ohmygirl/article/details/17846199)\n - [【HTTP】Fiddler(二) - 使用Fiddler做抓包分析](http://blog.csdn.net/ohmygirl/article/details/17849983)\n - [【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试](http://blog.csdn.net/ohmygirl/article/details/17855031)\n\n\n## 文章推荐\n\n- [代码覆盖率工具 Istanbul 入门教程](http://www.ruanyifeng.com/blog/2015/06/istanbul.html)\n 使用 Mocha 进行单元测试时,还需要了解测试的覆盖程度,这个指标就叫做\"代码覆盖率\"(code coverage)。这篇文章非常全面地介绍了Istanbul,让你轻松上手。深入了解:[nyc](https://github.com/istanbuljs/nyc)\n\n- [深入浅出浏览器渲染原理](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484408&idx=2&sn=456405dd36fd679dea1470b131924980&chksm=e82be2e9df5c6bff70912d297d535bfb747e2598a129641ea3409cedd88f2eac22e2d77dc98b&mpshare=1&scene=1&srcid=0901XT4SSeVjxiKd3Pj6IOvv&pass_ticket=%2BCgbmXT%2FgYy2AZSB%2B2tlPOm2ZM34W2NpPc%2F1G3ifFff91PXQRXcYFvt%2BSdaP7QjU#rd)\n 对于 HTTP 协议和浏览器渲染原理都是理解容易但不好讲明白,那么为什么不采用 Node.js 来阐述呢?以实践的方式、最简单的方式来向你展示不好讲的东西,对于 Node.js 开发者和大前端开发来说都是非常实用的。\n\n- [剖析Vue实现原理 - 如何实现双向绑定mvvm](https://github.com/DMQ/mvvm)\n 1. 了解vue的双向数据绑定原理以及核心代码模块\n 2. 了解如何实现双向绑定\n\n- [不用call和apply方法模拟实现ES5的bind方法](https://github.com/jawil/blog/issues/16)\n 这个问题是对JavaScript基本功很好的一个检测,看JavaScript掌握的怎么样以及平时有没有去深入研究一些方法的实现,简而言之,就是有没有折腾精神。\n\n- [通过ES6 Generator函数实现异步操作](https://github.com/Jocs/jocs.github.io/issues/11)\n 文章对 Generator函数实现异步进行了深入的讲解,最后使用 promise和 generator这样的模式实现异步操作,对于实现的过程进行深入细致的分析。\n\n- [你了解CSS设计模式吗?](http://mp.weixin.qq.com/s?__biz=MzI2MTY0NTEyMA==&mid=2247483871&idx=1&sn=f717d3c787626d997c410117a1cd7fb9&chksm=ea5677f0dd21fee6c7853b60b7e32d744af1abb183903ce8523954e093263a8c375895f0f193&mpshare=1&scene=1&srcid=06289q8vqWAQUGuqdrMsqEzq#)\n 简单来了解下CSS设计模式:\n 1. BEM全称(block、element、modifier)是Yandex 团队提出的CSS Class命名法\n 2. OOCSS全称(Object Oriented CSS)由Nicole Sullivan提出的css理论\n 3. SMACSS是Jonathan Snook的一个CSS框架\n 4. Atomic Design,原子设计\n\n\n - [我接触过的前端数据结构与算法](http://fed.renren.com/2017/07/02/algorithm/)\n 作者总结了前端常常碰到的算法,主要涉及递归、节流、数组去重、栈和堆、图像处理等。代码示例较为清晰,对于初学者还是很有帮助的,比较赞同作者的观点:算法的目的是用最小的时间和最小的空间解决问题。但是有时候不用太拘泥于一定要最优的答案,能够合适地解决问题就是好方法,而且对于不同的应用场景可能要采取不同的策略。\n\n- [JavaScript 中 4 种常见的内存泄露陷阱](http://web.jobbole.com/88463/)\n 虽然Javascript有内存自动回收机制,但这并不以为着js开发使完全不用关心内存管理。文中详细介绍了什么是内存泄漏和js中容易引起内存泄漏的点,并提供了使用Chrome分析内存的方法。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-11","published":1,"updated":"2017-11-10T07:40:52.986Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkj0003jrs6v6e7m0lp","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h4 id=\"截流-throttle\"><a href=\"#截流-throttle\" class=\"headerlink\" title=\"截流(throttle)\"></a>截流(throttle)</h4><p>概念理解:固定函数执行的速率。<br>使用场景:DOM 事件绑定,短时间内触发多次绑定事件造成性能问题,如 <code>onresize</code>,<code>onscroll</code>等,使用节流函数可确保在指定时间内只触发一次。<br>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> throttle = <span class=\"function\">(<span class=\"params\">func, wait</span>) =></span> {</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> context, args;</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> previous = <span class=\"number\">0</span>;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\">\t\t<span class=\"keyword\">let</span> now = +<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>();</span><br><span class=\"line\">\t\tcontext = <span class=\"keyword\">this</span>;</span><br><span class=\"line\">\t\targs = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\">\t\t<span class=\"keyword\">if</span> (now - previous > wait) {</span><br><span class=\"line\">\t\t\tfunc.apply(context, args);</span><br><span class=\"line\">\t\t\tprevious = now;</span><br><span class=\"line\">\t\t}</span><br><span class=\"line\">\t};</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"防抖-debounce\"><a href=\"#防抖-debounce\" class=\"headerlink\" title=\"防抖(debounce)\"></a>防抖(debounce)</h4><p>概念理解:强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。<br>使用场景:</p>\n<ol>\n<li>表单远程搜索,键盘多次输入取最后一次输入值作为查询关键词。</li>\n<li>下拉菜单的延时消失。</li>\n</ol>\n<p>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> debounce = <span class=\"function\">(<span class=\"params\">func, wait</span>) =></span> {</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> timeout;</span><br><span class=\"line\"> \t<span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> \t<span class=\"keyword\">let</span> context = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> \t<span class=\"keyword\">let</span> args = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\"> \tclearTimeout(timeout);</span><br><span class=\"line\"> \ttimeout = setTimeout(<span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> \t\tfunc.apply(context, args)</span><br><span class=\"line\"> \t}, wait);</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐功能强大的<code>HTTP</code>抓包调试工具:Fiddler。假如有这样一个场景,线上突然出现bug,而你正在休假、手头又没有源码,但又急需你参与问题排查,怎么办?Fiddler 便是你的救🔥利器。</p>\n<ol>\n<li>官网:<a href=\"http://www.telerik.com/fiddler\" target=\"_blank\" rel=\"noopener\">http://www.telerik.com/fiddler</a></li>\n<li>插件(官方&第三方):<a href=\"http://www.telerik.com/fiddler/add-ons\" target=\"_blank\" rel=\"noopener\">http://www.telerik.com/fiddler/add-ons</a></li>\n<li>快速上手:<a href=\"https://www.qcloud.com/community/article/115124?fromSource=gwzcw.93596.93596.93596\" target=\"_blank\" rel=\"noopener\">十分钟学会 Fiddler</a></li>\n<li>视频教程:<a href=\"http://www.imooc.com/learn/37\" target=\"_blank\" rel=\"noopener\">http://www.imooc.com/learn/37</a></li>\n<li>系列文章<ul>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17846199\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(一) - Fiddler简介</a></li>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17849983\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(二) - 使用Fiddler做抓包分析</a></li>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17855031\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试</a></li>\n</ul>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2015/06/istanbul.html\" target=\"_blank\" rel=\"noopener\">代码覆盖率工具 Istanbul 入门教程</a><br>使用 Mocha 进行单元测试时,还需要了解测试的覆盖程度,这个指标就叫做”代码覆盖率”(code coverage)。这篇文章非常全面地介绍了Istanbul,让你轻松上手。深入了解:<a href=\"https://github.com/istanbuljs/nyc\" target=\"_blank\" rel=\"noopener\">nyc</a></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484408&idx=2&sn=456405dd36fd679dea1470b131924980&chksm=e82be2e9df5c6bff70912d297d535bfb747e2598a129641ea3409cedd88f2eac22e2d77dc98b&mpshare=1&scene=1&srcid=0901XT4SSeVjxiKd3Pj6IOvv&pass_ticket=%2BCgbmXT%2FgYy2AZSB%2B2tlPOm2ZM34W2NpPc%2F1G3ifFff91PXQRXcYFvt%2BSdaP7QjU#rd\" target=\"_blank\" rel=\"noopener\">深入浅出浏览器渲染原理</a><br>对于 HTTP 协议和浏览器渲染原理都是理解容易但不好讲明白,那么为什么不采用 Node.js 来阐述呢?以实践的方式、最简单的方式来向你展示不好讲的东西,对于 Node.js 开发者和大前端开发来说都是非常实用的。</p>\n</li>\n<li><p><a href=\"https://github.com/DMQ/mvvm\" target=\"_blank\" rel=\"noopener\">剖析Vue实现原理 - 如何实现双向绑定mvvm</a></p>\n<ol>\n<li>了解vue的双向数据绑定原理以及核心代码模块</li>\n<li>了解如何实现双向绑定</li>\n</ol>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/16\" target=\"_blank\" rel=\"noopener\">不用call和apply方法模拟实现ES5的bind方法</a><br>这个问题是对JavaScript基本功很好的一个检测,看JavaScript掌握的怎么样以及平时有没有去深入研究一些方法的实现,简而言之,就是有没有折腾精神。</p>\n</li>\n<li><p><a href=\"https://github.com/Jocs/jocs.github.io/issues/11\" target=\"_blank\" rel=\"noopener\">通过ES6 Generator函数实现异步操作</a><br>文章对 Generator函数实现异步进行了深入的讲解,最后使用 promise和 generator这样的模式实现异步操作,对于实现的过程进行深入细致的分析。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s?__biz=MzI2MTY0NTEyMA==&mid=2247483871&idx=1&sn=f717d3c787626d997c410117a1cd7fb9&chksm=ea5677f0dd21fee6c7853b60b7e32d744af1abb183903ce8523954e093263a8c375895f0f193&mpshare=1&scene=1&srcid=06289q8vqWAQUGuqdrMsqEzq#\" target=\"_blank\" rel=\"noopener\">你了解CSS设计模式吗?</a><br>简单来了解下CSS设计模式:</p>\n<ol>\n<li>BEM全称(block、element、modifier)是Yandex 团队提出的CSS Class命名法</li>\n<li>OOCSS全称(Object Oriented CSS)由Nicole Sullivan提出的css理论</li>\n<li>SMACSS是Jonathan Snook的一个CSS框架</li>\n<li>Atomic Design,原子设计</li>\n</ol>\n</li>\n</ul>\n<ul>\n<li><a href=\"http://fed.renren.com/2017/07/02/algorithm/\" target=\"_blank\" rel=\"noopener\">我接触过的前端数据结构与算法</a><br> 作者总结了前端常常碰到的算法,主要涉及递归、节流、数组去重、栈和堆、图像处理等。代码示例较为清晰,对于初学者还是很有帮助的,比较赞同作者的观点:算法的目的是用最小的时间和最小的空间解决问题。但是有时候不用太拘泥于一定要最优的答案,能够合适地解决问题就是好方法,而且对于不同的应用场景可能要采取不同的策略。</li>\n</ul>\n<ul>\n<li><a href=\"http://web.jobbole.com/88463/\" target=\"_blank\" rel=\"noopener\">JavaScript 中 4 种常见的内存泄露陷阱</a><br>虽然Javascript有内存自动回收机制,但这并不以为着js开发使完全不用关心内存管理。文中详细介绍了什么是内存泄漏和js中容易引起内存泄漏的点,并提供了使用Chrome分析内存的方法。</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h4 id=\"截流-throttle\"><a href=\"#截流-throttle\" class=\"headerlink\" title=\"截流(throttle)\"></a>截流(throttle)</h4><p>概念理解:固定函数执行的速率。<br>使用场景:DOM 事件绑定,短时间内触发多次绑定事件造成性能问题,如 <code>onresize</code>,<code>onscroll</code>等,使用节流函数可确保在指定时间内只触发一次。<br>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> throttle = <span class=\"function\">(<span class=\"params\">func, wait</span>) =></span> {</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> context, args;</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> previous = <span class=\"number\">0</span>;</span><br><span class=\"line\"></span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\">\t\t<span class=\"keyword\">let</span> now = +<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>();</span><br><span class=\"line\">\t\tcontext = <span class=\"keyword\">this</span>;</span><br><span class=\"line\">\t\targs = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\">\t\t<span class=\"keyword\">if</span> (now - previous > wait) {</span><br><span class=\"line\">\t\t\tfunc.apply(context, args);</span><br><span class=\"line\">\t\t\tprevious = now;</span><br><span class=\"line\">\t\t}</span><br><span class=\"line\">\t};</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"防抖-debounce\"><a href=\"#防抖-debounce\" class=\"headerlink\" title=\"防抖(debounce)\"></a>防抖(debounce)</h4><p>概念理解:强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。<br>使用场景:</p>\n<ol>\n<li>表单远程搜索,键盘多次输入取最后一次输入值作为查询关键词。</li>\n<li>下拉菜单的延时消失。</li>\n</ol>\n<p>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> debounce = <span class=\"function\">(<span class=\"params\">func, wait</span>) =></span> {</span><br><span class=\"line\">\t<span class=\"keyword\">let</span> timeout;</span><br><span class=\"line\"> \t<span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> \t<span class=\"keyword\">let</span> context = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> \t<span class=\"keyword\">let</span> args = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\"> \tclearTimeout(timeout);</span><br><span class=\"line\"> \ttimeout = setTimeout(<span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> \t\tfunc.apply(context, args)</span><br><span class=\"line\"> \t}, wait);</span><br><span class=\"line\"> };</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐功能强大的<code>HTTP</code>抓包调试工具:Fiddler。假如有这样一个场景,线上突然出现bug,而你正在休假、手头又没有源码,但又急需你参与问题排查,怎么办?Fiddler 便是你的救🔥利器。</p>\n<ol>\n<li>官网:<a href=\"http://www.telerik.com/fiddler\" target=\"_blank\" rel=\"noopener\">http://www.telerik.com/fiddler</a></li>\n<li>插件(官方&第三方):<a href=\"http://www.telerik.com/fiddler/add-ons\" target=\"_blank\" rel=\"noopener\">http://www.telerik.com/fiddler/add-ons</a></li>\n<li>快速上手:<a href=\"https://www.qcloud.com/community/article/115124?fromSource=gwzcw.93596.93596.93596\" target=\"_blank\" rel=\"noopener\">十分钟学会 Fiddler</a></li>\n<li>视频教程:<a href=\"http://www.imooc.com/learn/37\" target=\"_blank\" rel=\"noopener\">http://www.imooc.com/learn/37</a></li>\n<li>系列文章<ul>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17846199\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(一) - Fiddler简介</a></li>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17849983\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(二) - 使用Fiddler做抓包分析</a></li>\n<li><a href=\"http://blog.csdn.net/ohmygirl/article/details/17855031\" target=\"_blank\" rel=\"noopener\">【HTTP】Fiddler(三)- Fiddler命令行和HTTP断点调试</a></li>\n</ul>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2015/06/istanbul.html\" target=\"_blank\" rel=\"noopener\">代码覆盖率工具 Istanbul 入门教程</a><br>使用 Mocha 进行单元测试时,还需要了解测试的覆盖程度,这个指标就叫做”代码覆盖率”(code coverage)。这篇文章非常全面地介绍了Istanbul,让你轻松上手。深入了解:<a href=\"https://github.com/istanbuljs/nyc\" target=\"_blank\" rel=\"noopener\">nyc</a></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484408&idx=2&sn=456405dd36fd679dea1470b131924980&chksm=e82be2e9df5c6bff70912d297d535bfb747e2598a129641ea3409cedd88f2eac22e2d77dc98b&mpshare=1&scene=1&srcid=0901XT4SSeVjxiKd3Pj6IOvv&pass_ticket=%2BCgbmXT%2FgYy2AZSB%2B2tlPOm2ZM34W2NpPc%2F1G3ifFff91PXQRXcYFvt%2BSdaP7QjU#rd\" target=\"_blank\" rel=\"noopener\">深入浅出浏览器渲染原理</a><br>对于 HTTP 协议和浏览器渲染原理都是理解容易但不好讲明白,那么为什么不采用 Node.js 来阐述呢?以实践的方式、最简单的方式来向你展示不好讲的东西,对于 Node.js 开发者和大前端开发来说都是非常实用的。</p>\n</li>\n<li><p><a href=\"https://github.com/DMQ/mvvm\" target=\"_blank\" rel=\"noopener\">剖析Vue实现原理 - 如何实现双向绑定mvvm</a></p>\n<ol>\n<li>了解vue的双向数据绑定原理以及核心代码模块</li>\n<li>了解如何实现双向绑定</li>\n</ol>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/16\" target=\"_blank\" rel=\"noopener\">不用call和apply方法模拟实现ES5的bind方法</a><br>这个问题是对JavaScript基本功很好的一个检测,看JavaScript掌握的怎么样以及平时有没有去深入研究一些方法的实现,简而言之,就是有没有折腾精神。</p>\n</li>\n<li><p><a href=\"https://github.com/Jocs/jocs.github.io/issues/11\" target=\"_blank\" rel=\"noopener\">通过ES6 Generator函数实现异步操作</a><br>文章对 Generator函数实现异步进行了深入的讲解,最后使用 promise和 generator这样的模式实现异步操作,对于实现的过程进行深入细致的分析。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s?__biz=MzI2MTY0NTEyMA==&mid=2247483871&idx=1&sn=f717d3c787626d997c410117a1cd7fb9&chksm=ea5677f0dd21fee6c7853b60b7e32d744af1abb183903ce8523954e093263a8c375895f0f193&mpshare=1&scene=1&srcid=06289q8vqWAQUGuqdrMsqEzq#\" target=\"_blank\" rel=\"noopener\">你了解CSS设计模式吗?</a><br>简单来了解下CSS设计模式:</p>\n<ol>\n<li>BEM全称(block、element、modifier)是Yandex 团队提出的CSS Class命名法</li>\n<li>OOCSS全称(Object Oriented CSS)由Nicole Sullivan提出的css理论</li>\n<li>SMACSS是Jonathan Snook的一个CSS框架</li>\n<li>Atomic Design,原子设计</li>\n</ol>\n</li>\n</ul>\n<ul>\n<li><a href=\"http://fed.renren.com/2017/07/02/algorithm/\" target=\"_blank\" rel=\"noopener\">我接触过的前端数据结构与算法</a><br> 作者总结了前端常常碰到的算法,主要涉及递归、节流、数组去重、栈和堆、图像处理等。代码示例较为清晰,对于初学者还是很有帮助的,比较赞同作者的观点:算法的目的是用最小的时间和最小的空间解决问题。但是有时候不用太拘泥于一定要最优的答案,能够合适地解决问题就是好方法,而且对于不同的应用场景可能要采取不同的策略。</li>\n</ul>\n<ul>\n<li><a href=\"http://web.jobbole.com/88463/\" target=\"_blank\" rel=\"noopener\">JavaScript 中 4 种常见的内存泄露陷阱</a><br>虽然Javascript有内存自动回收机制,但这并不以为着js开发使完全不用关心内存管理。文中详细介绍了什么是内存泄漏和js中容易引起内存泄漏的点,并提供了使用Chrome分析内存的方法。</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第12期 (本期小编:李志伟)","date":"2017-09-08T06:55:47.000Z","_content":"## Show me the code\n\n* 回调地狱\n\n需求:异步读取多个文件,等到所有文件读取完毕执行特定操作。\n简单实现:\n```javascript\n// bad\nfs.readFile('./config/test.txt'), (err, data) => {\n if (err) throw err\n fs.readFile('./config/test1.txt'), (err, data1) => {\n if (err) throw err\n fs.readFile('./config/test2.txt'), (err, data2) => {\n if (err) throw err\n fs.readFile('./config/test3.txt'), (err, data3) => {\n if (err) throw err\n console.log('success');\n }\n }\n }\n}\n\n// good\nfunction asyncReadFile (filePath, options) {\n return new Promise((resolve, reject) => {\n fs.readFile(filePath, options, (err, data) => {\n if (err) reject(err);\n resolve(data);\n });\n });\n}\n\nasyncReadFile('./config/test.txt').then(data => {\n return asyncReadFile('./config/test1.txt');\n}).then(data => {\n return asyncReadFile('./config/test2.txt');\n}).then(data => {\n return asyncReadFile('./config/test3.txt');\n});\n```\n\n小结:Promise 是一种对异步操作的封装,在异步操作执行成功或者失败时执行指定方法。将横向的异步调用转换为纵向,因此更符合人类的思维方式。\n\n* async和await\n\n小小面试题:每隔一秒输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5\n\n简单实现:\n```javascript\n// 你首先想到的可能是这样\nfor (var i = 0; i < 5; i++) {\n (function(j) { // j = i\n setTimeout(function() {\n console.log(new Date, j);\n }, 1000);\n })(i);\n}\nconsole.log(new Date, i);\n\n// 利用es7的async和await 你还可以这样\nconst sleep = (timeountMS) => new Promise((resolve) => {\n setTimeout(resolve, timeountMS);\n});\n\n(async () => { // 声明即执行的 async 函数表达式\n for (var i = 0; i < 5; i++) {\n await sleep(1000);\n console.log(new Date, i);\n }\n\n await sleep(1000);\n console.log(new Date, i);\n})();\n```\n\n## 工具和模块\n\n推荐简单易用的git客户端管理工具——Source Tree,支持创建、克隆、提交、push、pull 和合并等操作,其最大优点是拥有可视化界面,大大简化了开发者与代码库之间的Git操作方式,这对于那些不熟悉Git命令的开发者来说非常实用。\n\n1. 官网:https://www.sourcetreeapp.com/\n\n2. git学习教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\n\n\n## 文章推荐\n\n- [从攻击看防御-前端视野下的web安全思考](https://mp.weixin.qq.com/s/mblUhRMgyWUBhtIOaN6bGg)\n 文章基于笔者对自身业务的web安全梳理,引起对web安全的一定思考。因其岗位视野以web前端为主,在对web安全的思考上,难免会有一定的局限性,故题目加上了“前端视野下”这样的修饰词。\n\n- [高性能滚动 scroll 及页面渲染优化](http://www.cnblogs.com/coco1s/p/5499469.html)\n 本文算是对上一期关于函数节流与防抖的实际场景中的实践,阅读本文以助于更好好的理解函数节流与防抖,并且本文也提供了一些其他的优化思路。\n\n- [基于koajs的前后端分离实践](http://cnodejs.org/topic/57b062ed144011da12ff4183)\n 要实现前后端分离框架,无非要满足这样几点:\n 更便捷地创建路由、更高效地代理数据请求、更灵活地环境部署\n\n- [深入理解CSS时序函数](https://segmentfault.com/a/1190000011019534)\n 本文非常详细的介绍制作动画时所使用的时序函数,对于动画的实现有详细的demo和说明。总之对于CSS动画来说,还是要看大家怎么玩这些属性了。\n\n- [Webpack 的静态资源持久缓存](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651225513&idx=1&sn=d247881a71f06e75478611e40b3d4e01&chksm=bd49a42d8a3e2d3bc783fc1b75672b3e2069b48c1add29f64dd626b0b8d4c5c6c1bdb09e2565&mpshare=1&scene=1&srcid=09081NPEMSgj7Z8J7G4807ps#rd)\n 代码每次更新->服务器重新部署->客户端重新下载资源,显然低效。所以这就是浏览器会缓存静态资源的原因,但存在缺陷:文件不修改文件名,浏览器会认为没有更新,就会使用缓存中的版本。文章介绍webpack如何配置以开启静态资源的持久缓存,内置详细代码示例,易懂易用。\n\n- [js 深拷贝 vs 浅拷贝](https://juejin.im/post/59ac1c4ef265da248e75892b)\n 主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。\n\n- [关于HTTP协议](http://www.jianshu.com/p/80e25cb1d81a)\n http协议作为连接浏览器和服务器之间的协议,有着重要的作用,为前端开发必了解内容之一。\n 下文介绍了http的概要,偏理论,可作为了解。\n\n- [前端校招面试该考察什么?](https://zhuanlan.zhihu.com/p/29010060)\n 文章总结了腾讯的校招流程和校招(实习生)对候选人技能的侧重方面。除了招聘,文章还对前端工程师的技术栈做了非常全面的总结。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-12.md","raw":"---\ntitle: 大前端周刊 第12期 (本期小编:李志伟)\ndate: 2017-09-08 14:55:47\ntags: [weekly,webpack,koa,web安全,ES6,http]\n---\n## Show me the code\n\n* 回调地狱\n\n需求:异步读取多个文件,等到所有文件读取完毕执行特定操作。\n简单实现:\n```javascript\n// bad\nfs.readFile('./config/test.txt'), (err, data) => {\n if (err) throw err\n fs.readFile('./config/test1.txt'), (err, data1) => {\n if (err) throw err\n fs.readFile('./config/test2.txt'), (err, data2) => {\n if (err) throw err\n fs.readFile('./config/test3.txt'), (err, data3) => {\n if (err) throw err\n console.log('success');\n }\n }\n }\n}\n\n// good\nfunction asyncReadFile (filePath, options) {\n return new Promise((resolve, reject) => {\n fs.readFile(filePath, options, (err, data) => {\n if (err) reject(err);\n resolve(data);\n });\n });\n}\n\nasyncReadFile('./config/test.txt').then(data => {\n return asyncReadFile('./config/test1.txt');\n}).then(data => {\n return asyncReadFile('./config/test2.txt');\n}).then(data => {\n return asyncReadFile('./config/test3.txt');\n});\n```\n\n小结:Promise 是一种对异步操作的封装,在异步操作执行成功或者失败时执行指定方法。将横向的异步调用转换为纵向,因此更符合人类的思维方式。\n\n* async和await\n\n小小面试题:每隔一秒输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5\n\n简单实现:\n```javascript\n// 你首先想到的可能是这样\nfor (var i = 0; i < 5; i++) {\n (function(j) { // j = i\n setTimeout(function() {\n console.log(new Date, j);\n }, 1000);\n })(i);\n}\nconsole.log(new Date, i);\n\n// 利用es7的async和await 你还可以这样\nconst sleep = (timeountMS) => new Promise((resolve) => {\n setTimeout(resolve, timeountMS);\n});\n\n(async () => { // 声明即执行的 async 函数表达式\n for (var i = 0; i < 5; i++) {\n await sleep(1000);\n console.log(new Date, i);\n }\n\n await sleep(1000);\n console.log(new Date, i);\n})();\n```\n\n## 工具和模块\n\n推荐简单易用的git客户端管理工具——Source Tree,支持创建、克隆、提交、push、pull 和合并等操作,其最大优点是拥有可视化界面,大大简化了开发者与代码库之间的Git操作方式,这对于那些不熟悉Git命令的开发者来说非常实用。\n\n1. 官网:https://www.sourcetreeapp.com/\n\n2. git学习教程:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\n\n\n## 文章推荐\n\n- [从攻击看防御-前端视野下的web安全思考](https://mp.weixin.qq.com/s/mblUhRMgyWUBhtIOaN6bGg)\n 文章基于笔者对自身业务的web安全梳理,引起对web安全的一定思考。因其岗位视野以web前端为主,在对web安全的思考上,难免会有一定的局限性,故题目加上了“前端视野下”这样的修饰词。\n\n- [高性能滚动 scroll 及页面渲染优化](http://www.cnblogs.com/coco1s/p/5499469.html)\n 本文算是对上一期关于函数节流与防抖的实际场景中的实践,阅读本文以助于更好好的理解函数节流与防抖,并且本文也提供了一些其他的优化思路。\n\n- [基于koajs的前后端分离实践](http://cnodejs.org/topic/57b062ed144011da12ff4183)\n 要实现前后端分离框架,无非要满足这样几点:\n 更便捷地创建路由、更高效地代理数据请求、更灵活地环境部署\n\n- [深入理解CSS时序函数](https://segmentfault.com/a/1190000011019534)\n 本文非常详细的介绍制作动画时所使用的时序函数,对于动画的实现有详细的demo和说明。总之对于CSS动画来说,还是要看大家怎么玩这些属性了。\n\n- [Webpack 的静态资源持久缓存](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651225513&idx=1&sn=d247881a71f06e75478611e40b3d4e01&chksm=bd49a42d8a3e2d3bc783fc1b75672b3e2069b48c1add29f64dd626b0b8d4c5c6c1bdb09e2565&mpshare=1&scene=1&srcid=09081NPEMSgj7Z8J7G4807ps#rd)\n 代码每次更新->服务器重新部署->客户端重新下载资源,显然低效。所以这就是浏览器会缓存静态资源的原因,但存在缺陷:文件不修改文件名,浏览器会认为没有更新,就会使用缓存中的版本。文章介绍webpack如何配置以开启静态资源的持久缓存,内置详细代码示例,易懂易用。\n\n- [js 深拷贝 vs 浅拷贝](https://juejin.im/post/59ac1c4ef265da248e75892b)\n 主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。\n\n- [关于HTTP协议](http://www.jianshu.com/p/80e25cb1d81a)\n http协议作为连接浏览器和服务器之间的协议,有着重要的作用,为前端开发必了解内容之一。\n 下文介绍了http的概要,偏理论,可作为了解。\n\n- [前端校招面试该考察什么?](https://zhuanlan.zhihu.com/p/29010060)\n 文章总结了腾讯的校招流程和校招(实习生)对候选人技能的侧重方面。除了招聘,文章还对前端工程师的技术栈做了非常全面的总结。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-12","published":1,"updated":"2017-11-10T07:40:52.986Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkk0004jrs6aqqwpeu9","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>回调地狱</li>\n</ul>\n<p>需求:异步读取多个文件,等到所有文件读取完毕执行特定操作。<br>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\">fs.readFile(<span class=\"string\">'./config/test.txt'</span>), (err, data) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test1.txt'</span>), (err, data1) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test2.txt'</span>), (err, data2) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test3.txt'</span>), (err, data3) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'success'</span>);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">asyncReadFile</span> (<span class=\"params\">filePath, options</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> fs.readFile(filePath, options, (err, data) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) reject(err);</span><br><span class=\"line\"> resolve(data);</span><br><span class=\"line\"> });</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">asyncReadFile(<span class=\"string\">'./config/test.txt'</span>).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test1.txt'</span>);</span><br><span class=\"line\">}).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test2.txt'</span>);</span><br><span class=\"line\">}).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test3.txt'</span>);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>小结:Promise 是一种对异步操作的封装,在异步操作执行成功或者失败时执行指定方法。将横向的异步调用转换为纵向,因此更符合人类的思维方式。</p>\n<ul>\n<li>async和await</li>\n</ul>\n<p>小小面试题:每隔一秒输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5</p>\n<p>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 你首先想到的可能是这样</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">5</span>; i++) {</span><br><span class=\"line\"> (<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">j</span>) </span>{ <span class=\"comment\">// j = i</span></span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, j);</span><br><span class=\"line\"> }, <span class=\"number\">1000</span>);</span><br><span class=\"line\"> })(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 利用es7的async和await 你还可以这样</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> sleep = <span class=\"function\">(<span class=\"params\">timeountMS</span>) =></span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> setTimeout(resolve, timeountMS);</span><br><span class=\"line\">});</span><br><span class=\"line\"></span><br><span class=\"line\">(<span class=\"keyword\">async</span> () => { <span class=\"comment\">// 声明即执行的 async 函数表达式</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">5</span>; i++) {</span><br><span class=\"line\"> <span class=\"keyword\">await</span> sleep(<span class=\"number\">1000</span>);</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">await</span> sleep(<span class=\"number\">1000</span>);</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\">})();</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐简单易用的git客户端管理工具——Source Tree,支持创建、克隆、提交、push、pull 和合并等操作,其最大优点是拥有可视化界面,大大简化了开发者与代码库之间的Git操作方式,这对于那些不熟悉Git命令的开发者来说非常实用。</p>\n<ol>\n<li><p>官网:<a href=\"https://www.sourcetreeapp.com/\" target=\"_blank\" rel=\"noopener\">https://www.sourcetreeapp.com/</a></p>\n</li>\n<li><p>git学习教程:<a href=\"https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\" target=\"_blank\" rel=\"noopener\">https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000</a></p>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s/mblUhRMgyWUBhtIOaN6bGg\" target=\"_blank\" rel=\"noopener\">从攻击看防御-前端视野下的web安全思考</a><br>文章基于笔者对自身业务的web安全梳理,引起对web安全的一定思考。因其岗位视野以web前端为主,在对web安全的思考上,难免会有一定的局限性,故题目加上了“前端视野下”这样的修饰词。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/coco1s/p/5499469.html\" target=\"_blank\" rel=\"noopener\">高性能滚动 scroll 及页面渲染优化</a><br>本文算是对上一期关于函数节流与防抖的实际场景中的实践,阅读本文以助于更好好的理解函数节流与防抖,并且本文也提供了一些其他的优化思路。</p>\n</li>\n<li><p><a href=\"http://cnodejs.org/topic/57b062ed144011da12ff4183\" target=\"_blank\" rel=\"noopener\">基于koajs的前后端分离实践</a><br>要实现前后端分离框架,无非要满足这样几点:<br>更便捷地创建路由、更高效地代理数据请求、更灵活地环境部署</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011019534\" target=\"_blank\" rel=\"noopener\">深入理解CSS时序函数</a><br>本文非常详细的介绍制作动画时所使用的时序函数,对于动画的实现有详细的demo和说明。总之对于CSS动画来说,还是要看大家怎么玩这些属性了。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651225513&idx=1&sn=d247881a71f06e75478611e40b3d4e01&chksm=bd49a42d8a3e2d3bc783fc1b75672b3e2069b48c1add29f64dd626b0b8d4c5c6c1bdb09e2565&mpshare=1&scene=1&srcid=09081NPEMSgj7Z8J7G4807ps#rd\" target=\"_blank\" rel=\"noopener\">Webpack 的静态资源持久缓存</a><br>代码每次更新->服务器重新部署->客户端重新下载资源,显然低效。所以这就是浏览器会缓存静态资源的原因,但存在缺陷:文件不修改文件名,浏览器会认为没有更新,就会使用缓存中的版本。文章介绍webpack如何配置以开启静态资源的持久缓存,内置详细代码示例,易懂易用。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ac1c4ef265da248e75892b\" target=\"_blank\" rel=\"noopener\">js 深拷贝 vs 浅拷贝</a><br>主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/80e25cb1d81a\" target=\"_blank\" rel=\"noopener\">关于HTTP协议</a><br>http协议作为连接浏览器和服务器之间的协议,有着重要的作用,为前端开发必了解内容之一。<br>下文介绍了http的概要,偏理论,可作为了解。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29010060\" target=\"_blank\" rel=\"noopener\">前端校招面试该考察什么?</a><br>文章总结了腾讯的校招流程和校招(实习生)对候选人技能的侧重方面。除了招聘,文章还对前端工程师的技术栈做了非常全面的总结。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>回调地狱</li>\n</ul>\n<p>需求:异步读取多个文件,等到所有文件读取完毕执行特定操作。<br>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// bad</span></span><br><span class=\"line\">fs.readFile(<span class=\"string\">'./config/test.txt'</span>), (err, data) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test1.txt'</span>), (err, data1) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test2.txt'</span>), (err, data2) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> fs.readFile(<span class=\"string\">'./config/test3.txt'</span>), (err, data3) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) <span class=\"keyword\">throw</span> err</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'success'</span>);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// good</span></span><br><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">asyncReadFile</span> (<span class=\"params\">filePath, options</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> fs.readFile(filePath, options, (err, data) => {</span><br><span class=\"line\"> <span class=\"keyword\">if</span> (err) reject(err);</span><br><span class=\"line\"> resolve(data);</span><br><span class=\"line\"> });</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">asyncReadFile(<span class=\"string\">'./config/test.txt'</span>).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test1.txt'</span>);</span><br><span class=\"line\">}).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test2.txt'</span>);</span><br><span class=\"line\">}).then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> asyncReadFile(<span class=\"string\">'./config/test3.txt'</span>);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>小结:Promise 是一种对异步操作的封装,在异步操作执行成功或者失败时执行指定方法。将横向的异步调用转换为纵向,因此更符合人类的思维方式。</p>\n<ul>\n<li>async和await</li>\n</ul>\n<p>小小面试题:每隔一秒输出一个数字,顺序是:0 -> 1 -> 2 -> 3 -> 4 -> 5</p>\n<p>简单实现:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">// 你首先想到的可能是这样</span></span><br><span class=\"line\"><span class=\"keyword\">for</span> (<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">5</span>; i++) {</span><br><span class=\"line\"> (<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">j</span>) </span>{ <span class=\"comment\">// j = i</span></span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, j);</span><br><span class=\"line\"> }, <span class=\"number\">1000</span>);</span><br><span class=\"line\"> })(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">// 利用es7的async和await 你还可以这样</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> sleep = <span class=\"function\">(<span class=\"params\">timeountMS</span>) =></span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> setTimeout(resolve, timeountMS);</span><br><span class=\"line\">});</span><br><span class=\"line\"></span><br><span class=\"line\">(<span class=\"keyword\">async</span> () => { <span class=\"comment\">// 声明即执行的 async 函数表达式</span></span><br><span class=\"line\"> <span class=\"keyword\">for</span> (<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">5</span>; i++) {</span><br><span class=\"line\"> <span class=\"keyword\">await</span> sleep(<span class=\"number\">1000</span>);</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\"> }</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">await</span> sleep(<span class=\"number\">1000</span>);</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"keyword\">new</span> <span class=\"built_in\">Date</span>, i);</span><br><span class=\"line\">})();</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>推荐简单易用的git客户端管理工具——Source Tree,支持创建、克隆、提交、push、pull 和合并等操作,其最大优点是拥有可视化界面,大大简化了开发者与代码库之间的Git操作方式,这对于那些不熟悉Git命令的开发者来说非常实用。</p>\n<ol>\n<li><p>官网:<a href=\"https://www.sourcetreeapp.com/\" target=\"_blank\" rel=\"noopener\">https://www.sourcetreeapp.com/</a></p>\n</li>\n<li><p>git学习教程:<a href=\"https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000\" target=\"_blank\" rel=\"noopener\">https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000</a></p>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s/mblUhRMgyWUBhtIOaN6bGg\" target=\"_blank\" rel=\"noopener\">从攻击看防御-前端视野下的web安全思考</a><br>文章基于笔者对自身业务的web安全梳理,引起对web安全的一定思考。因其岗位视野以web前端为主,在对web安全的思考上,难免会有一定的局限性,故题目加上了“前端视野下”这样的修饰词。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/coco1s/p/5499469.html\" target=\"_blank\" rel=\"noopener\">高性能滚动 scroll 及页面渲染优化</a><br>本文算是对上一期关于函数节流与防抖的实际场景中的实践,阅读本文以助于更好好的理解函数节流与防抖,并且本文也提供了一些其他的优化思路。</p>\n</li>\n<li><p><a href=\"http://cnodejs.org/topic/57b062ed144011da12ff4183\" target=\"_blank\" rel=\"noopener\">基于koajs的前后端分离实践</a><br>要实现前后端分离框架,无非要满足这样几点:<br>更便捷地创建路由、更高效地代理数据请求、更灵活地环境部署</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011019534\" target=\"_blank\" rel=\"noopener\">深入理解CSS时序函数</a><br>本文非常详细的介绍制作动画时所使用的时序函数,对于动画的实现有详细的demo和说明。总之对于CSS动画来说,还是要看大家怎么玩这些属性了。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651225513&idx=1&sn=d247881a71f06e75478611e40b3d4e01&chksm=bd49a42d8a3e2d3bc783fc1b75672b3e2069b48c1add29f64dd626b0b8d4c5c6c1bdb09e2565&mpshare=1&scene=1&srcid=09081NPEMSgj7Z8J7G4807ps#rd\" target=\"_blank\" rel=\"noopener\">Webpack 的静态资源持久缓存</a><br>代码每次更新->服务器重新部署->客户端重新下载资源,显然低效。所以这就是浏览器会缓存静态资源的原因,但存在缺陷:文件不修改文件名,浏览器会认为没有更新,就会使用缓存中的版本。文章介绍webpack如何配置以开启静态资源的持久缓存,内置详细代码示例,易懂易用。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ac1c4ef265da248e75892b\" target=\"_blank\" rel=\"noopener\">js 深拷贝 vs 浅拷贝</a><br>主要讲一下 js 的基本数据类型以及一些堆和栈的知识和什么是深拷贝、什么是浅拷贝、深拷贝与浅拷贝的区别,以及怎么进行深拷贝和怎么进行浅拷贝。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/80e25cb1d81a\" target=\"_blank\" rel=\"noopener\">关于HTTP协议</a><br>http协议作为连接浏览器和服务器之间的协议,有着重要的作用,为前端开发必了解内容之一。<br>下文介绍了http的概要,偏理论,可作为了解。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29010060\" target=\"_blank\" rel=\"noopener\">前端校招面试该考察什么?</a><br>文章总结了腾讯的校招流程和校招(实习生)对候选人技能的侧重方面。除了招聘,文章还对前端工程师的技术栈做了非常全面的总结。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第13期 (本期小编:李丽娇)","date":"2017-09-15T06:55:47.000Z","_content":"## Show me the code\n\n* 剩余参数\n\n概念:剩余参数(rest parameter)语法允许我们将一个不定数量的参数表示为一个数组。\n使用场景:在不确定参数个数的函数中,设置部分行参。\n语法:\n```\nfunction(a, b, ...restArgs) {\n // ...\n}\n```\n示例:\n```\nfunction multiply(multiplier, ...theArgs) {\n return theArgs.map(function (element) {\n return multiplier * element;\n });\n}\n\nvar arr = multiply(2, 1, 2, 3); \nconsole.log(arr); // [2, 4, 6]\n```\n说明:\n剩余参数和 arguments 对象的区别:\n1. 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。\n2. arguments 对象不是一个真实的数组,而剩余参数是真实的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach,pop。\n3. arguments 对象对象还有一些附加的属性 (比如callee属性)。\n\n\n* 逗号操作符\n\n概念:逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值。\n语法:expr1, expr2, expr3...\n示例:\n```\nfunction a(num) {\n console.log(num);\n}\n\nfunction b(num) {\n console.log(num * 2);\n}\n\na(1), b(1); // 1 2\nb(1), a(1); // 2 1\n```\n小结:\n逗号表达式最常用的地方是是用一句代码定义多个变量的场景。在许多大厂的源码中也被用在如上示例的函数调用。\n\n\n## 解决方案\n\n* Trackingjs\n\njs实现人脸识别,看这里:[https://trackingjs.com](https://trackingjs.com/),文章推荐板块中有成功的实践案例。\n\n* 图片渐进式加载\n\n需求:在网速不好的情况下,网站上的某张图片用上向下一点点加载,用户体现不友好。希望先显示整张图片然后渐渐变清晰。\n方案:使用渐进式加载的图片,详情见文章:[渐进式jpeg(progressive jpeg)图片](http://www.zhangxinxu.com/wordpress/2013/01/progressive-jpeg-image-and-so-on/)。\n\n\n* Flex布局\n\n自从有了flex布局,处女座的设计师再也不用担心内容没有中间对其或上下对齐了。图文详解flex语法,戳下文:[Flex 布局教程-语法篇](http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html)\n\n## 工具和模块\n\n作为前端童鞋,平时开发免不了和接口打交道,拿到接口后需要测试一下接口返回是否正常,这时最后有一款支持各种请求方式的模拟Http请求工具。现在来介绍一些一款解决这个问题的工具-Postman,Postman支持各种请求方式,支持添加各个请求头参数。对写接口或用接口的同学来说都是利器。\n\n1. 官网:[https://www.getpostman.com/](https://www.getpostman.com/)\n\n2. 推荐文章:[Postman用法简介](http://blog.csdn.net/flowerspring/article/details/52774399)\n\n\n## 文章推荐\n\n- [面向 Web 开发者的 VR 指南](https://www.smashingmagazine.com/2017/09/guide-virtual-reality-web-developers/?utm_source=frontendfocus&utm_medium=email)\n 近日来,越来越多的浏览器添加了对于 VR 特性的支持,本文即是盘点下目前浏览器中 VR 技术发展的现状,并且对可用的 WebVR 相关 API 进行简要介绍。\n\n- [深入浅出基于“依赖收集”的响应式原理](https://segmentfault.com/a/1190000011153487)\n 文章很透彻的解析了对于使用Object.defineProperty()实现的响应式原理;从一个简单的实例逐步分析响应式原理的具体思路。讲解响应式原理的文章很多,这篇还是很形象的。\n\n- [30 行 JavaScript 代码搭建神经网络](https://zhuanlan.zhihu.com/p/28653993)\n 数据科学部的同学推荐的一篇神经网络入门实践文章,这篇文章图文并茂的介绍了神经网络的基础知识:神经元、神经网络等。深入阅读:[神经网络入门](http://www.ruanyifeng.com/blog/2017/07/neural-network.html)\n\n- [深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记](https://github.com/jawil/blog/issues/9)\n 文章稍长,本文只论述DOM基础概念,不涉及DOM的一些事件原理机制,页面元素的操作和常用API的讲解以及兼容性事项,所以概念性东西比较多,稍微有点抽象。\n\n- [编写可维护代码之“中间件模式”](https://zhuanlan.zhihu.com/p/26063036)\n 中间件可以介入请求和相应的处理,是一个轻量级的模块,每个中间负责完成某个特定的功能。\n\n- [当我们学习 Node.js 时,我们在学习什么?](http://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0727KaC7tg9V5Sa1mhiVeInx#rd)\n 大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?\n\n- [石墨表格之 Web Worker 应用实战](https://zhuanlan.zhihu.com/p/29165800)\n JavaScript 执行是单线程的,如运行 CPU 密集型任务会阻塞线程,此时浏览器会被卡住。解决该问题的办法之一就是引入Web Worker。Web Worker 为前端带来了后台计算的能力,可以实现主 UI 线程与复杂计运算线程的分离,从而极大减轻了因计算量大而造成 UI 阻塞而出现的界面渲染卡、掉帧的情况,从而更大程度地的提高我们的页面性能。\n\n- [那些你不能错过的 GitHub 插件和工具](https://juejin.im/post/59ade28051882538fd72fa2c)\n 既然 GitHub 这么重要,又被我们使用得这么频繁,那关于 GitHub 的一些优秀浏览器插件或者其他工具,我们就一定不可错过啦。本文就来整理一些,都是我平常使用最得心应手的东西,全都倾力推荐出来,绝对干货!\n\n- [纯前端实现人脸识别-提取-合成](http://refined-x.com/2017/09/06/%E7%BA%AF%E5%89%8D%E7%AB%AF%E5%AE%9E%E7%8E%B0%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E6%8F%90%E5%8F%96-%E5%90%88%E6%88%90/)\n 前段时间火遍朋友圈的军装照竟然是用纯前段实现的!\n 实现原理已在文中揭秘,速度get起来~\n\n- [实现精准的流体排版原理](http://www.w3cplus.com/css/css-polyfluidsizing-using-calc-vw-breakpoints-and-linear-equations.html)\n 文章介绍了如何实现精准的流式排版。其中原理非常的简单,通过CSS的Viewport单位和calc()配合一些数学公式,较为精准的实现随着视窗改变,能较为精准的改变font-size的大小,甚至只要是带有长度单位的属性都可以通过这样方式,达到精准的值。\n\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-13.md","raw":"---\ntitle: 大前端周刊 第13期 (本期小编:李丽娇)\ndate: 2017-09-15 14:55:47\ntags: [weekly,Trackingjs,flex,postman,神经网络,DOM,Nodejs,Web Worker,GitHub插件,人脸识别,流体排版]\n---\n## Show me the code\n\n* 剩余参数\n\n概念:剩余参数(rest parameter)语法允许我们将一个不定数量的参数表示为一个数组。\n使用场景:在不确定参数个数的函数中,设置部分行参。\n语法:\n```\nfunction(a, b, ...restArgs) {\n // ...\n}\n```\n示例:\n```\nfunction multiply(multiplier, ...theArgs) {\n return theArgs.map(function (element) {\n return multiplier * element;\n });\n}\n\nvar arr = multiply(2, 1, 2, 3); \nconsole.log(arr); // [2, 4, 6]\n```\n说明:\n剩余参数和 arguments 对象的区别:\n1. 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。\n2. arguments 对象不是一个真实的数组,而剩余参数是真实的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach,pop。\n3. arguments 对象对象还有一些附加的属性 (比如callee属性)。\n\n\n* 逗号操作符\n\n概念:逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值。\n语法:expr1, expr2, expr3...\n示例:\n```\nfunction a(num) {\n console.log(num);\n}\n\nfunction b(num) {\n console.log(num * 2);\n}\n\na(1), b(1); // 1 2\nb(1), a(1); // 2 1\n```\n小结:\n逗号表达式最常用的地方是是用一句代码定义多个变量的场景。在许多大厂的源码中也被用在如上示例的函数调用。\n\n\n## 解决方案\n\n* Trackingjs\n\njs实现人脸识别,看这里:[https://trackingjs.com](https://trackingjs.com/),文章推荐板块中有成功的实践案例。\n\n* 图片渐进式加载\n\n需求:在网速不好的情况下,网站上的某张图片用上向下一点点加载,用户体现不友好。希望先显示整张图片然后渐渐变清晰。\n方案:使用渐进式加载的图片,详情见文章:[渐进式jpeg(progressive jpeg)图片](http://www.zhangxinxu.com/wordpress/2013/01/progressive-jpeg-image-and-so-on/)。\n\n\n* Flex布局\n\n自从有了flex布局,处女座的设计师再也不用担心内容没有中间对其或上下对齐了。图文详解flex语法,戳下文:[Flex 布局教程-语法篇](http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html)\n\n## 工具和模块\n\n作为前端童鞋,平时开发免不了和接口打交道,拿到接口后需要测试一下接口返回是否正常,这时最后有一款支持各种请求方式的模拟Http请求工具。现在来介绍一些一款解决这个问题的工具-Postman,Postman支持各种请求方式,支持添加各个请求头参数。对写接口或用接口的同学来说都是利器。\n\n1. 官网:[https://www.getpostman.com/](https://www.getpostman.com/)\n\n2. 推荐文章:[Postman用法简介](http://blog.csdn.net/flowerspring/article/details/52774399)\n\n\n## 文章推荐\n\n- [面向 Web 开发者的 VR 指南](https://www.smashingmagazine.com/2017/09/guide-virtual-reality-web-developers/?utm_source=frontendfocus&utm_medium=email)\n 近日来,越来越多的浏览器添加了对于 VR 特性的支持,本文即是盘点下目前浏览器中 VR 技术发展的现状,并且对可用的 WebVR 相关 API 进行简要介绍。\n\n- [深入浅出基于“依赖收集”的响应式原理](https://segmentfault.com/a/1190000011153487)\n 文章很透彻的解析了对于使用Object.defineProperty()实现的响应式原理;从一个简单的实例逐步分析响应式原理的具体思路。讲解响应式原理的文章很多,这篇还是很形象的。\n\n- [30 行 JavaScript 代码搭建神经网络](https://zhuanlan.zhihu.com/p/28653993)\n 数据科学部的同学推荐的一篇神经网络入门实践文章,这篇文章图文并茂的介绍了神经网络的基础知识:神经元、神经网络等。深入阅读:[神经网络入门](http://www.ruanyifeng.com/blog/2017/07/neural-network.html)\n\n- [深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记](https://github.com/jawil/blog/issues/9)\n 文章稍长,本文只论述DOM基础概念,不涉及DOM的一些事件原理机制,页面元素的操作和常用API的讲解以及兼容性事项,所以概念性东西比较多,稍微有点抽象。\n\n- [编写可维护代码之“中间件模式”](https://zhuanlan.zhihu.com/p/26063036)\n 中间件可以介入请求和相应的处理,是一个轻量级的模块,每个中间负责完成某个特定的功能。\n\n- [当我们学习 Node.js 时,我们在学习什么?](http://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0727KaC7tg9V5Sa1mhiVeInx#rd)\n 大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?\n\n- [石墨表格之 Web Worker 应用实战](https://zhuanlan.zhihu.com/p/29165800)\n JavaScript 执行是单线程的,如运行 CPU 密集型任务会阻塞线程,此时浏览器会被卡住。解决该问题的办法之一就是引入Web Worker。Web Worker 为前端带来了后台计算的能力,可以实现主 UI 线程与复杂计运算线程的分离,从而极大减轻了因计算量大而造成 UI 阻塞而出现的界面渲染卡、掉帧的情况,从而更大程度地的提高我们的页面性能。\n\n- [那些你不能错过的 GitHub 插件和工具](https://juejin.im/post/59ade28051882538fd72fa2c)\n 既然 GitHub 这么重要,又被我们使用得这么频繁,那关于 GitHub 的一些优秀浏览器插件或者其他工具,我们就一定不可错过啦。本文就来整理一些,都是我平常使用最得心应手的东西,全都倾力推荐出来,绝对干货!\n\n- [纯前端实现人脸识别-提取-合成](http://refined-x.com/2017/09/06/%E7%BA%AF%E5%89%8D%E7%AB%AF%E5%AE%9E%E7%8E%B0%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E6%8F%90%E5%8F%96-%E5%90%88%E6%88%90/)\n 前段时间火遍朋友圈的军装照竟然是用纯前段实现的!\n 实现原理已在文中揭秘,速度get起来~\n\n- [实现精准的流体排版原理](http://www.w3cplus.com/css/css-polyfluidsizing-using-calc-vw-breakpoints-and-linear-equations.html)\n 文章介绍了如何实现精准的流式排版。其中原理非常的简单,通过CSS的Viewport单位和calc()配合一些数学公式,较为精准的实现随着视窗改变,能较为精准的改变font-size的大小,甚至只要是带有长度单位的属性都可以通过这样方式,达到精准的值。\n\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-13","published":1,"updated":"2017-11-10T07:40:52.986Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkk0005jrs63sdwu1kx","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>剩余参数</li>\n</ul>\n<p>概念:剩余参数(rest parameter)语法允许我们将一个不定数量的参数表示为一个数组。<br>使用场景:在不确定参数个数的函数中,设置部分行参。<br>语法:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function(a, b, ...restArgs) {</span><br><span class=\"line\"> // ...</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>示例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function multiply(multiplier, ...theArgs) {</span><br><span class=\"line\"> return theArgs.map(function (element) {</span><br><span class=\"line\"> return multiplier * element;</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">var arr = multiply(2, 1, 2, 3); </span><br><span class=\"line\">console.log(arr); // [2, 4, 6]</span><br></pre></td></tr></table></figure></p>\n<p>说明:<br>剩余参数和 arguments 对象的区别:</p>\n<ol>\n<li>剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。</li>\n<li>arguments 对象不是一个真实的数组,而剩余参数是真实的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach,pop。</li>\n<li>arguments 对象对象还有一些附加的属性 (比如callee属性)。</li>\n</ol>\n<ul>\n<li>逗号操作符</li>\n</ul>\n<p>概念:逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值。<br>语法:expr1, expr2, expr3…<br>示例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function a(num) {</span><br><span class=\"line\"> console.log(num);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">function b(num) {</span><br><span class=\"line\"> console.log(num * 2);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">a(1), b(1); // 1 2</span><br><span class=\"line\">b(1), a(1); // 2 1</span><br></pre></td></tr></table></figure></p>\n<p>小结:<br>逗号表达式最常用的地方是是用一句代码定义多个变量的场景。在许多大厂的源码中也被用在如上示例的函数调用。</p>\n<h2 id=\"解决方案\"><a href=\"#解决方案\" class=\"headerlink\" title=\"解决方案\"></a>解决方案</h2><ul>\n<li>Trackingjs</li>\n</ul>\n<p>js实现人脸识别,看这里:<a href=\"https://trackingjs.com/\" target=\"_blank\" rel=\"noopener\">https://trackingjs.com</a>,文章推荐板块中有成功的实践案例。</p>\n<ul>\n<li>图片渐进式加载</li>\n</ul>\n<p>需求:在网速不好的情况下,网站上的某张图片用上向下一点点加载,用户体现不友好。希望先显示整张图片然后渐渐变清晰。<br>方案:使用渐进式加载的图片,详情见文章:<a href=\"http://www.zhangxinxu.com/wordpress/2013/01/progressive-jpeg-image-and-so-on/\" target=\"_blank\" rel=\"noopener\">渐进式jpeg(progressive jpeg)图片</a>。</p>\n<ul>\n<li>Flex布局</li>\n</ul>\n<p>自从有了flex布局,处女座的设计师再也不用担心内容没有中间对其或上下对齐了。图文详解flex语法,戳下文:<a href=\"http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html\" target=\"_blank\" rel=\"noopener\">Flex 布局教程-语法篇</a></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>作为前端童鞋,平时开发免不了和接口打交道,拿到接口后需要测试一下接口返回是否正常,这时最后有一款支持各种请求方式的模拟Http请求工具。现在来介绍一些一款解决这个问题的工具-Postman,Postman支持各种请求方式,支持添加各个请求头参数。对写接口或用接口的同学来说都是利器。</p>\n<ol>\n<li><p>官网:<a href=\"https://www.getpostman.com/\" target=\"_blank\" rel=\"noopener\">https://www.getpostman.com/</a></p>\n</li>\n<li><p>推荐文章:<a href=\"http://blog.csdn.net/flowerspring/article/details/52774399\" target=\"_blank\" rel=\"noopener\">Postman用法简介</a></p>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://www.smashingmagazine.com/2017/09/guide-virtual-reality-web-developers/?utm_source=frontendfocus&utm_medium=email\" target=\"_blank\" rel=\"noopener\">面向 Web 开发者的 VR 指南</a><br>近日来,越来越多的浏览器添加了对于 VR 特性的支持,本文即是盘点下目前浏览器中 VR 技术发展的现状,并且对可用的 WebVR 相关 API 进行简要介绍。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011153487\" target=\"_blank\" rel=\"noopener\">深入浅出基于“依赖收集”的响应式原理</a><br>文章很透彻的解析了对于使用Object.defineProperty()实现的响应式原理;从一个简单的实例逐步分析响应式原理的具体思路。讲解响应式原理的文章很多,这篇还是很形象的。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28653993\" target=\"_blank\" rel=\"noopener\">30 行 JavaScript 代码搭建神经网络</a><br>数据科学部的同学推荐的一篇神经网络入门实践文章,这篇文章图文并茂的介绍了神经网络的基础知识:神经元、神经网络等。深入阅读:<a href=\"http://www.ruanyifeng.com/blog/2017/07/neural-network.html\" target=\"_blank\" rel=\"noopener\">神经网络入门</a></p>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/9\" target=\"_blank\" rel=\"noopener\">深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记</a><br>文章稍长,本文只论述DOM基础概念,不涉及DOM的一些事件原理机制,页面元素的操作和常用API的讲解以及兼容性事项,所以概念性东西比较多,稍微有点抽象。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26063036\" target=\"_blank\" rel=\"noopener\">编写可维护代码之“中间件模式”</a><br>中间件可以介入请求和相应的处理,是一个轻量级的模块,每个中间负责完成某个特定的功能。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0727KaC7tg9V5Sa1mhiVeInx#rd\" target=\"_blank\" rel=\"noopener\">当我们学习 Node.js 时,我们在学习什么?</a><br>大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29165800\" target=\"_blank\" rel=\"noopener\">石墨表格之 Web Worker 应用实战</a><br>JavaScript 执行是单线程的,如运行 CPU 密集型任务会阻塞线程,此时浏览器会被卡住。解决该问题的办法之一就是引入Web Worker。Web Worker 为前端带来了后台计算的能力,可以实现主 UI 线程与复杂计运算线程的分离,从而极大减轻了因计算量大而造成 UI 阻塞而出现的界面渲染卡、掉帧的情况,从而更大程度地的提高我们的页面性能。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ade28051882538fd72fa2c\" target=\"_blank\" rel=\"noopener\">那些你不能错过的 GitHub 插件和工具</a><br>既然 GitHub 这么重要,又被我们使用得这么频繁,那关于 GitHub 的一些优秀浏览器插件或者其他工具,我们就一定不可错过啦。本文就来整理一些,都是我平常使用最得心应手的东西,全都倾力推荐出来,绝对干货!</p>\n</li>\n<li><p><a href=\"http://refined-x.com/2017/09/06/%E7%BA%AF%E5%89%8D%E7%AB%AF%E5%AE%9E%E7%8E%B0%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E6%8F%90%E5%8F%96-%E5%90%88%E6%88%90/\" target=\"_blank\" rel=\"noopener\">纯前端实现人脸识别-提取-合成</a><br>前段时间火遍朋友圈的军装照竟然是用纯前段实现的!<br>实现原理已在文中揭秘,速度get起来~</p>\n</li>\n<li><p><a href=\"http://www.w3cplus.com/css/css-polyfluidsizing-using-calc-vw-breakpoints-and-linear-equations.html\" target=\"_blank\" rel=\"noopener\">实现精准的流体排版原理</a><br>文章介绍了如何实现精准的流式排版。其中原理非常的简单,通过CSS的Viewport单位和calc()配合一些数学公式,较为精准的实现随着视窗改变,能较为精准的改变font-size的大小,甚至只要是带有长度单位的属性都可以通过这样方式,达到精准的值。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>剩余参数</li>\n</ul>\n<p>概念:剩余参数(rest parameter)语法允许我们将一个不定数量的参数表示为一个数组。<br>使用场景:在不确定参数个数的函数中,设置部分行参。<br>语法:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function(a, b, ...restArgs) {</span><br><span class=\"line\"> // ...</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>示例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function multiply(multiplier, ...theArgs) {</span><br><span class=\"line\"> return theArgs.map(function (element) {</span><br><span class=\"line\"> return multiplier * element;</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">var arr = multiply(2, 1, 2, 3); </span><br><span class=\"line\">console.log(arr); // [2, 4, 6]</span><br></pre></td></tr></table></figure></p>\n<p>说明:<br>剩余参数和 arguments 对象的区别:</p>\n<ol>\n<li>剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。</li>\n<li>arguments 对象不是一个真实的数组,而剩余参数是真实的 Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如 sort,map,forEach,pop。</li>\n<li>arguments 对象对象还有一些附加的属性 (比如callee属性)。</li>\n</ol>\n<ul>\n<li>逗号操作符</li>\n</ul>\n<p>概念:逗号操作符 对它的每个操作数求值(从左到右),并返回最后一个操作数的值。<br>语法:expr1, expr2, expr3…<br>示例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">function a(num) {</span><br><span class=\"line\"> console.log(num);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">function b(num) {</span><br><span class=\"line\"> console.log(num * 2);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">a(1), b(1); // 1 2</span><br><span class=\"line\">b(1), a(1); // 2 1</span><br></pre></td></tr></table></figure></p>\n<p>小结:<br>逗号表达式最常用的地方是是用一句代码定义多个变量的场景。在许多大厂的源码中也被用在如上示例的函数调用。</p>\n<h2 id=\"解决方案\"><a href=\"#解决方案\" class=\"headerlink\" title=\"解决方案\"></a>解决方案</h2><ul>\n<li>Trackingjs</li>\n</ul>\n<p>js实现人脸识别,看这里:<a href=\"https://trackingjs.com/\" target=\"_blank\" rel=\"noopener\">https://trackingjs.com</a>,文章推荐板块中有成功的实践案例。</p>\n<ul>\n<li>图片渐进式加载</li>\n</ul>\n<p>需求:在网速不好的情况下,网站上的某张图片用上向下一点点加载,用户体现不友好。希望先显示整张图片然后渐渐变清晰。<br>方案:使用渐进式加载的图片,详情见文章:<a href=\"http://www.zhangxinxu.com/wordpress/2013/01/progressive-jpeg-image-and-so-on/\" target=\"_blank\" rel=\"noopener\">渐进式jpeg(progressive jpeg)图片</a>。</p>\n<ul>\n<li>Flex布局</li>\n</ul>\n<p>自从有了flex布局,处女座的设计师再也不用担心内容没有中间对其或上下对齐了。图文详解flex语法,戳下文:<a href=\"http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html\" target=\"_blank\" rel=\"noopener\">Flex 布局教程-语法篇</a></p>\n<h2 id=\"工具和模块\"><a href=\"#工具和模块\" class=\"headerlink\" title=\"工具和模块\"></a>工具和模块</h2><p>作为前端童鞋,平时开发免不了和接口打交道,拿到接口后需要测试一下接口返回是否正常,这时最后有一款支持各种请求方式的模拟Http请求工具。现在来介绍一些一款解决这个问题的工具-Postman,Postman支持各种请求方式,支持添加各个请求头参数。对写接口或用接口的同学来说都是利器。</p>\n<ol>\n<li><p>官网:<a href=\"https://www.getpostman.com/\" target=\"_blank\" rel=\"noopener\">https://www.getpostman.com/</a></p>\n</li>\n<li><p>推荐文章:<a href=\"http://blog.csdn.net/flowerspring/article/details/52774399\" target=\"_blank\" rel=\"noopener\">Postman用法简介</a></p>\n</li>\n</ol>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://www.smashingmagazine.com/2017/09/guide-virtual-reality-web-developers/?utm_source=frontendfocus&utm_medium=email\" target=\"_blank\" rel=\"noopener\">面向 Web 开发者的 VR 指南</a><br>近日来,越来越多的浏览器添加了对于 VR 特性的支持,本文即是盘点下目前浏览器中 VR 技术发展的现状,并且对可用的 WebVR 相关 API 进行简要介绍。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011153487\" target=\"_blank\" rel=\"noopener\">深入浅出基于“依赖收集”的响应式原理</a><br>文章很透彻的解析了对于使用Object.defineProperty()实现的响应式原理;从一个简单的实例逐步分析响应式原理的具体思路。讲解响应式原理的文章很多,这篇还是很形象的。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28653993\" target=\"_blank\" rel=\"noopener\">30 行 JavaScript 代码搭建神经网络</a><br>数据科学部的同学推荐的一篇神经网络入门实践文章,这篇文章图文并茂的介绍了神经网络的基础知识:神经元、神经网络等。深入阅读:<a href=\"http://www.ruanyifeng.com/blog/2017/07/neural-network.html\" target=\"_blank\" rel=\"noopener\">神经网络入门</a></p>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/9\" target=\"_blank\" rel=\"noopener\">深入浅出DOM基础——《DOM探索之基础详解篇》学习笔记</a><br>文章稍长,本文只论述DOM基础概念,不涉及DOM的一些事件原理机制,页面元素的操作和常用API的讲解以及兼容性事项,所以概念性东西比较多,稍微有点抽象。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26063036\" target=\"_blank\" rel=\"noopener\">编写可维护代码之“中间件模式”</a><br>中间件可以介入请求和相应的处理,是一个轻量级的模块,每个中间负责完成某个特定的功能。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0727KaC7tg9V5Sa1mhiVeInx#rd\" target=\"_blank\" rel=\"noopener\">当我们学习 Node.js 时,我们在学习什么?</a><br>大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29165800\" target=\"_blank\" rel=\"noopener\">石墨表格之 Web Worker 应用实战</a><br>JavaScript 执行是单线程的,如运行 CPU 密集型任务会阻塞线程,此时浏览器会被卡住。解决该问题的办法之一就是引入Web Worker。Web Worker 为前端带来了后台计算的能力,可以实现主 UI 线程与复杂计运算线程的分离,从而极大减轻了因计算量大而造成 UI 阻塞而出现的界面渲染卡、掉帧的情况,从而更大程度地的提高我们的页面性能。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ade28051882538fd72fa2c\" target=\"_blank\" rel=\"noopener\">那些你不能错过的 GitHub 插件和工具</a><br>既然 GitHub 这么重要,又被我们使用得这么频繁,那关于 GitHub 的一些优秀浏览器插件或者其他工具,我们就一定不可错过啦。本文就来整理一些,都是我平常使用最得心应手的东西,全都倾力推荐出来,绝对干货!</p>\n</li>\n<li><p><a href=\"http://refined-x.com/2017/09/06/%E7%BA%AF%E5%89%8D%E7%AB%AF%E5%AE%9E%E7%8E%B0%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E6%8F%90%E5%8F%96-%E5%90%88%E6%88%90/\" target=\"_blank\" rel=\"noopener\">纯前端实现人脸识别-提取-合成</a><br>前段时间火遍朋友圈的军装照竟然是用纯前段实现的!<br>实现原理已在文中揭秘,速度get起来~</p>\n</li>\n<li><p><a href=\"http://www.w3cplus.com/css/css-polyfluidsizing-using-calc-vw-breakpoints-and-linear-equations.html\" target=\"_blank\" rel=\"noopener\">实现精准的流体排版原理</a><br>文章介绍了如何实现精准的流式排版。其中原理非常的简单,通过CSS的Viewport单位和calc()配合一些数学公式,较为精准的实现随着视窗改变,能较为精准的改变font-size的大小,甚至只要是带有长度单位的属性都可以通过这样方式,达到精准的值。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第14期 (本期小编:陶明)","date":"2017-09-22T07:56:42.000Z","_content":"## Show me the code\n\n* Set\n\n语法:new Set([iterable])\n\n- 参数介绍:\n - iterable\n 如果传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。\n\n- 返回值\n 一个新的Set对象。\n\n 简单说一下为什么要用 Set,因为 Set中的值具有唯一性(划重点!!!)。\n 唯一性!\n 所以,我就用它来去重。\n 嗯,对。\n 只用来数组去重!!!\n\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const ArraySet = new Set(arr);\n\n Array.from(ArraySet); // [1, 2, 3, 4, 5, 0]\n [...ArraySet]; // [1, 2, 3, 4, 5, 0]\n\n const emoji = ['↖', '💎', '↗', '♠', '↖', '😏', '💎', '😍', '😏',];\n const emojiSet = new Set(arr);\n \n Array.from(emojiSet) // [\"↖\", \"💎\", \"↗\", \"♠\", \"😏\", \"😍\"]\n [...emojiSet] // [\"↖\", \"💎\", \"↗\", \"♠\", \"😏\", \"😍\"]\n```\n 只能 Array?\n```\n const text = 'prototype';\n new Set(text); // Set {\"p\", \"r\", \"o\", \"t\", \"y\", \"e\"} 我是 String Set的\n```\n 上面说到它的返回值是一个对象\n So, 它有自己属性及方法。\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n \n mySet.size; // 6 剩 6 个了\n mySet.length; // undefined\n```\n 都叫 'size'了,当然是它的个数啊,\n 没 length(手动痴呆脸)我就试试看而已...\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n\n /* 我要加个 10 */\n mySet.add(10) // [1, 2, 3, 4, 5, 0, 10] 加上了!\n\n /* 我要加个 1 */\n mySet.add(1) // [1, 2, 3, 4, 5, 0] 233 加不上!说了 Set有唯一性了!\n\n /* 我不要 0 了 */\n mySet.clear(0) // undefined !!!\n mySet.clear() // undefined !!!\n```\n 刷出来算我输...\n Set.prototype.clear(),没参数,调用就清空啦.\n\n 当然是可以删除了,开了一个好冷的笑话(故作镇定接着写...)\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n \n /* 我不要 0 了 */\n mySet.delete(0) // [1, 2, 3, 4, 5] 删掉了!\n\n /* 有 1 吗? */\n mySet.has(1); // true 有的!\n\n /* 有 2 吗? */\n mySet.has(2); // true 有的!\n\n /* 有 0 吗? */\n mySet.has(0); // false 没有!刚才删了!\n```\n 其实还有几个方法,\n 这里只是简单的说一下这个 Set 而已\n 你以为我结束了?\n 我再说最后一个!\n 嗯!\n 最后一个!\n 我保证!\n```\n /* 用 forEach 能干点什么? */\n mySet.forEach(function(value) {\n // use value do something ...\n });\n```\n OK,能力有限...\n\n## 插件推荐\n\n- [消息气泡拖拽插件, 基于vue实现的仿QQ消息气泡拖拽插件](https://github.com/lucefer/vue-bubble)\n #### 安装 \n```\n npm install vue-bubble\n```\n\n #### 引入 \n```\n const vueBubble from 'vue-bubble'\n Vue.use(vueBubble)\n```\n\n## 文章推荐\n\n- [JavaScript 工作原理:内存管理与常见内存泄露分析](https://segmentfault.com/a/1190000011229300)\n 本系列文章皆着眼于深度解析 JavaScript 内部运行原理,而本文则重点讨论编程语言中常见的内存管理问题;并且还提出了对于处理常见的内存泄露的建议。\n\n- [可视化基础之散点图介绍](https://antv.alipay.com/vis/doc/chart/details/scatter-plot.html)\n 这篇文章介绍了散点图的科学意义,推荐大家阅读学习。可视化是前端发展的一个大方向,可视化工程师除了技术实现之外,还应该学习各种图表所能表达的科学含义。感谢蚂蚁金服体验技术部同学们,整理了一整套科学规范的可视化图表“字典”,让大家详细了解每种图表背后的含义。扩展阅读:[可视化基础](https://antv.alipay.com/vis/doc/chart/classify/compare.html)\n\n- [JS正则表达式完整教程](https://juejin.im/post/5965943ff265da6c30653879)\n 非常详细的介绍了JS中和正则相关的知识,文章很长,适合慢慢研读\n\n- [webpack:从入门到真实项目配置](https://juejin.im/post/59bb37fa6fb9a00a554f89d2)\n 文章主要介绍webpack配置,由简入繁、逐步优化,从简单的打包为一个bundle到分离代码、抽离共同代码、按需加载代码、自动刷新,每一步都非常详细,适合初学者快速入门。\n\n- [AR.js 初探](https://zhuanlan.zhihu.com/p/26364493)\n AR技术(增强现实技术Augmented Reality,简称 AR),AR技术在Native中已经兴起了,并且市场上有许多成功的APP,但是对于JavaScript怎么来玩转AR呢?下面我来简单的给大家演示两个不同版本,不同场景的AR小例子。\n\n- [史上最全面、最透彻的BFC原理剖析](https://github.com/zuopf769/notebook/blob/master/fe/BFC%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90/README.md)\n 介绍FC的概念是什么; BFC的约束规则;咋样才能触发生成新的BFC;BFC在布局中的应用:防止margin重叠(塌陷,以最大的为准); 清除内部浮动;自适应两(多)栏布局。 \n\n- [JS遇上IOT](https://zhuanlan.zhihu.com/p/29137921)\n IOT是 Internet of Things 的缩写,字面翻译是“物体组成的因特网”,准确的翻译应该为“物联网”。凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript ——Atwood 定律。逃不出这个定律,JavaScript 也能用于物联网开发了。本文介绍了使用 JavaScript 在 ruff 开发平台上的小实例,有树莓派的小伙伴可以尝试把玩一下。\n\n- [上手 Webpack ? 这篇就够了!](https://segmentfault.com/a/1190000010921801)\n 文章系统的概述了 Webpack 从安装到配置以及插件等等;讲述的还是比较全面。对于使用 Webpack 来说,完全可以说是够用。\n\n- [实现一个简单的虚拟DOM](http://www.cnblogs.com/giggle/p/7538533.html)\n 现在的流行框架,无论React还是Vue,都采用虚拟DOM。文中介绍了虚拟DOM的实现原理,能帮助更好理解双向绑定实现。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-14.md","raw":"---\ntitle: 大前端周刊 第14期 (本期小编:陶明)\ndate: 2017-09-22 15:56:42\ntags: [内存管理, 散点图, 正则, AR, Webpack, IOT, 虚拟DOM]\n---\n## Show me the code\n\n* Set\n\n语法:new Set([iterable])\n\n- 参数介绍:\n - iterable\n 如果传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。\n\n- 返回值\n 一个新的Set对象。\n\n 简单说一下为什么要用 Set,因为 Set中的值具有唯一性(划重点!!!)。\n 唯一性!\n 所以,我就用它来去重。\n 嗯,对。\n 只用来数组去重!!!\n\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const ArraySet = new Set(arr);\n\n Array.from(ArraySet); // [1, 2, 3, 4, 5, 0]\n [...ArraySet]; // [1, 2, 3, 4, 5, 0]\n\n const emoji = ['↖', '💎', '↗', '♠', '↖', '😏', '💎', '😍', '😏',];\n const emojiSet = new Set(arr);\n \n Array.from(emojiSet) // [\"↖\", \"💎\", \"↗\", \"♠\", \"😏\", \"😍\"]\n [...emojiSet] // [\"↖\", \"💎\", \"↗\", \"♠\", \"😏\", \"😍\"]\n```\n 只能 Array?\n```\n const text = 'prototype';\n new Set(text); // Set {\"p\", \"r\", \"o\", \"t\", \"y\", \"e\"} 我是 String Set的\n```\n 上面说到它的返回值是一个对象\n So, 它有自己属性及方法。\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n \n mySet.size; // 6 剩 6 个了\n mySet.length; // undefined\n```\n 都叫 'size'了,当然是它的个数啊,\n 没 length(手动痴呆脸)我就试试看而已...\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n\n /* 我要加个 10 */\n mySet.add(10) // [1, 2, 3, 4, 5, 0, 10] 加上了!\n\n /* 我要加个 1 */\n mySet.add(1) // [1, 2, 3, 4, 5, 0] 233 加不上!说了 Set有唯一性了!\n\n /* 我不要 0 了 */\n mySet.clear(0) // undefined !!!\n mySet.clear() // undefined !!!\n```\n 刷出来算我输...\n Set.prototype.clear(),没参数,调用就清空啦.\n\n 当然是可以删除了,开了一个好冷的笑话(故作镇定接着写...)\n```\n const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];\n const mySet = new Set(arr);\n \n /* 我不要 0 了 */\n mySet.delete(0) // [1, 2, 3, 4, 5] 删掉了!\n\n /* 有 1 吗? */\n mySet.has(1); // true 有的!\n\n /* 有 2 吗? */\n mySet.has(2); // true 有的!\n\n /* 有 0 吗? */\n mySet.has(0); // false 没有!刚才删了!\n```\n 其实还有几个方法,\n 这里只是简单的说一下这个 Set 而已\n 你以为我结束了?\n 我再说最后一个!\n 嗯!\n 最后一个!\n 我保证!\n```\n /* 用 forEach 能干点什么? */\n mySet.forEach(function(value) {\n // use value do something ...\n });\n```\n OK,能力有限...\n\n## 插件推荐\n\n- [消息气泡拖拽插件, 基于vue实现的仿QQ消息气泡拖拽插件](https://github.com/lucefer/vue-bubble)\n #### 安装 \n```\n npm install vue-bubble\n```\n\n #### 引入 \n```\n const vueBubble from 'vue-bubble'\n Vue.use(vueBubble)\n```\n\n## 文章推荐\n\n- [JavaScript 工作原理:内存管理与常见内存泄露分析](https://segmentfault.com/a/1190000011229300)\n 本系列文章皆着眼于深度解析 JavaScript 内部运行原理,而本文则重点讨论编程语言中常见的内存管理问题;并且还提出了对于处理常见的内存泄露的建议。\n\n- [可视化基础之散点图介绍](https://antv.alipay.com/vis/doc/chart/details/scatter-plot.html)\n 这篇文章介绍了散点图的科学意义,推荐大家阅读学习。可视化是前端发展的一个大方向,可视化工程师除了技术实现之外,还应该学习各种图表所能表达的科学含义。感谢蚂蚁金服体验技术部同学们,整理了一整套科学规范的可视化图表“字典”,让大家详细了解每种图表背后的含义。扩展阅读:[可视化基础](https://antv.alipay.com/vis/doc/chart/classify/compare.html)\n\n- [JS正则表达式完整教程](https://juejin.im/post/5965943ff265da6c30653879)\n 非常详细的介绍了JS中和正则相关的知识,文章很长,适合慢慢研读\n\n- [webpack:从入门到真实项目配置](https://juejin.im/post/59bb37fa6fb9a00a554f89d2)\n 文章主要介绍webpack配置,由简入繁、逐步优化,从简单的打包为一个bundle到分离代码、抽离共同代码、按需加载代码、自动刷新,每一步都非常详细,适合初学者快速入门。\n\n- [AR.js 初探](https://zhuanlan.zhihu.com/p/26364493)\n AR技术(增强现实技术Augmented Reality,简称 AR),AR技术在Native中已经兴起了,并且市场上有许多成功的APP,但是对于JavaScript怎么来玩转AR呢?下面我来简单的给大家演示两个不同版本,不同场景的AR小例子。\n\n- [史上最全面、最透彻的BFC原理剖析](https://github.com/zuopf769/notebook/blob/master/fe/BFC%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90/README.md)\n 介绍FC的概念是什么; BFC的约束规则;咋样才能触发生成新的BFC;BFC在布局中的应用:防止margin重叠(塌陷,以最大的为准); 清除内部浮动;自适应两(多)栏布局。 \n\n- [JS遇上IOT](https://zhuanlan.zhihu.com/p/29137921)\n IOT是 Internet of Things 的缩写,字面翻译是“物体组成的因特网”,准确的翻译应该为“物联网”。凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript ——Atwood 定律。逃不出这个定律,JavaScript 也能用于物联网开发了。本文介绍了使用 JavaScript 在 ruff 开发平台上的小实例,有树莓派的小伙伴可以尝试把玩一下。\n\n- [上手 Webpack ? 这篇就够了!](https://segmentfault.com/a/1190000010921801)\n 文章系统的概述了 Webpack 从安装到配置以及插件等等;讲述的还是比较全面。对于使用 Webpack 来说,完全可以说是够用。\n\n- [实现一个简单的虚拟DOM](http://www.cnblogs.com/giggle/p/7538533.html)\n 现在的流行框架,无论React还是Vue,都采用虚拟DOM。文中介绍了虚拟DOM的实现原理,能帮助更好理解双向绑定实现。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-14","published":1,"updated":"2017-11-10T07:40:52.987Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkm0007jrs64f4k2hpz","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>Set</li>\n</ul>\n<p>语法:new Set([iterable])</p>\n<ul>\n<li><p>参数介绍:</p>\n<ul>\n<li>iterable<br>如果传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。</li>\n</ul>\n</li>\n<li><p>返回值<br>一个新的Set对象。</p>\n<p>简单说一下为什么要用 Set,因为 Set中的值具有唯一性(划重点!!!)。<br>唯一性!<br>所以,我就用它来去重。<br>嗯,对。<br>只用来数组去重!!!</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const ArraySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">Array.from(ArraySet); // [1, 2, 3, 4, 5, 0]</span><br><span class=\"line\">[...ArraySet]; // [1, 2, 3, 4, 5, 0]</span><br><span class=\"line\"></span><br><span class=\"line\">const emoji = ['↖', '💎', '↗', '♠', '↖', '😏', '💎', '😍', '😏',];</span><br><span class=\"line\">const emojiSet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">Array.from(emojiSet) // ["↖", "💎", "↗", "♠", "😏", "😍"]</span><br><span class=\"line\">[...emojiSet] // ["↖", "💎", "↗", "♠", "😏", "😍"]</span><br></pre></td></tr></table></figure>\n<p> 只能 Array?<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const text = 'prototype';</span><br><span class=\"line\">new Set(text); // Set {"p", "r", "o", "t", "y", "e"} 我是 String Set的</span><br></pre></td></tr></table></figure></p>\n<p> 上面说到它的返回值是一个对象<br> So, 它有自己属性及方法。<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">mySet.size; // 6 剩 6 个了</span><br><span class=\"line\">mySet.length; // undefined</span><br></pre></td></tr></table></figure></p>\n<p> 都叫 ‘size’了,当然是它的个数啊,<br> 没 length(手动痴呆脸)我就试试看而已…<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我要加个 10 */</span><br><span class=\"line\">mySet.add(10) // [1, 2, 3, 4, 5, 0, 10] 加上了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我要加个 1 */</span><br><span class=\"line\">mySet.add(1) // [1, 2, 3, 4, 5, 0] 233 加不上!说了 Set有唯一性了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我不要 0 了 */</span><br><span class=\"line\">mySet.clear(0) // undefined !!!</span><br><span class=\"line\">mySet.clear() // undefined !!!</span><br></pre></td></tr></table></figure></p>\n<p> 刷出来算我输…<br> Set.prototype.clear(),没参数,调用就清空啦.</p>\n<p> 当然是可以删除了,开了一个好冷的笑话(故作镇定接着写…)<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我不要 0 了 */</span><br><span class=\"line\">mySet.delete(0) // [1, 2, 3, 4, 5] 删掉了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 1 吗? */</span><br><span class=\"line\">mySet.has(1); // true 有的!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 2 吗? */</span><br><span class=\"line\">mySet.has(2); // true 有的!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 0 吗? */</span><br><span class=\"line\">mySet.has(0); // false 没有!刚才删了!</span><br></pre></td></tr></table></figure></p>\n<p> 其实还有几个方法,<br> 这里只是简单的说一下这个 Set 而已<br> 你以为我结束了?<br> 我再说最后一个!<br> 嗯!<br> 最后一个!<br> 我保证!<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/* 用 forEach 能干点什么? */</span><br><span class=\"line\">mySet.forEach(function(value) {</span><br><span class=\"line\"> // use value do something ...</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p> OK,能力有限…</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><p><a href=\"https://github.com/lucefer/vue-bubble\" target=\"_blank\" rel=\"noopener\">消息气泡拖拽插件, 基于vue实现的仿QQ消息气泡拖拽插件</a></p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install vue-bubble</span><br></pre></td></tr></table></figure>\n<h4 id=\"引入\"><a href=\"#引入\" class=\"headerlink\" title=\"引入\"></a>引入</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const vueBubble from 'vue-bubble'</span><br><span class=\"line\">Vue.use(vueBubble)</span><br></pre></td></tr></table></figure>\n</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://segmentfault.com/a/1190000011229300\" target=\"_blank\" rel=\"noopener\">JavaScript 工作原理:内存管理与常见内存泄露分析</a><br>本系列文章皆着眼于深度解析 JavaScript 内部运行原理,而本文则重点讨论编程语言中常见的内存管理问题;并且还提出了对于处理常见的内存泄露的建议。</p>\n</li>\n<li><p><a href=\"https://antv.alipay.com/vis/doc/chart/details/scatter-plot.html\" target=\"_blank\" rel=\"noopener\">可视化基础之散点图介绍</a><br>这篇文章介绍了散点图的科学意义,推荐大家阅读学习。可视化是前端发展的一个大方向,可视化工程师除了技术实现之外,还应该学习各种图表所能表达的科学含义。感谢蚂蚁金服体验技术部同学们,整理了一整套科学规范的可视化图表“字典”,让大家详细了解每种图表背后的含义。扩展阅读:<a href=\"https://antv.alipay.com/vis/doc/chart/classify/compare.html\" target=\"_blank\" rel=\"noopener\">可视化基础</a></p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5965943ff265da6c30653879\" target=\"_blank\" rel=\"noopener\">JS正则表达式完整教程</a><br>非常详细的介绍了JS中和正则相关的知识,文章很长,适合慢慢研读</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59bb37fa6fb9a00a554f89d2\" target=\"_blank\" rel=\"noopener\">webpack:从入门到真实项目配置</a><br>文章主要介绍webpack配置,由简入繁、逐步优化,从简单的打包为一个bundle到分离代码、抽离共同代码、按需加载代码、自动刷新,每一步都非常详细,适合初学者快速入门。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26364493\" target=\"_blank\" rel=\"noopener\">AR.js 初探</a><br>AR技术(增强现实技术Augmented Reality,简称 AR),AR技术在Native中已经兴起了,并且市场上有许多成功的APP,但是对于JavaScript怎么来玩转AR呢?下面我来简单的给大家演示两个不同版本,不同场景的AR小例子。</p>\n</li>\n<li><p><a href=\"https://github.com/zuopf769/notebook/blob/master/fe/BFC%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90/README.md\" target=\"_blank\" rel=\"noopener\">史上最全面、最透彻的BFC原理剖析</a><br>介绍FC的概念是什么; BFC的约束规则;咋样才能触发生成新的BFC;BFC在布局中的应用:防止margin重叠(塌陷,以最大的为准); 清除内部浮动;自适应两(多)栏布局。 </p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29137921\" target=\"_blank\" rel=\"noopener\">JS遇上IOT</a><br>IOT是 Internet of Things 的缩写,字面翻译是“物体组成的因特网”,准确的翻译应该为“物联网”。凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript ——Atwood 定律。逃不出这个定律,JavaScript 也能用于物联网开发了。本文介绍了使用 JavaScript 在 ruff 开发平台上的小实例,有树莓派的小伙伴可以尝试把玩一下。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010921801\" target=\"_blank\" rel=\"noopener\">上手 Webpack ? 这篇就够了!</a><br>文章系统的概述了 Webpack 从安装到配置以及插件等等;讲述的还是比较全面。对于使用 Webpack 来说,完全可以说是够用。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/giggle/p/7538533.html\" target=\"_blank\" rel=\"noopener\">实现一个简单的虚拟DOM</a><br>现在的流行框架,无论React还是Vue,都采用虚拟DOM。文中介绍了虚拟DOM的实现原理,能帮助更好理解双向绑定实现。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>Set</li>\n</ul>\n<p>语法:new Set([iterable])</p>\n<ul>\n<li><p>参数介绍:</p>\n<ul>\n<li>iterable<br>如果传递一个可迭代对象,它的所有元素将被添加到新的 Set中。如果不指定此参数或其值为null,则新的 Set为空。</li>\n</ul>\n</li>\n<li><p>返回值<br>一个新的Set对象。</p>\n<p>简单说一下为什么要用 Set,因为 Set中的值具有唯一性(划重点!!!)。<br>唯一性!<br>所以,我就用它来去重。<br>嗯,对。<br>只用来数组去重!!!</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const ArraySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">Array.from(ArraySet); // [1, 2, 3, 4, 5, 0]</span><br><span class=\"line\">[...ArraySet]; // [1, 2, 3, 4, 5, 0]</span><br><span class=\"line\"></span><br><span class=\"line\">const emoji = ['↖', '💎', '↗', '♠', '↖', '😏', '💎', '😍', '😏',];</span><br><span class=\"line\">const emojiSet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">Array.from(emojiSet) // ["↖", "💎", "↗", "♠", "😏", "😍"]</span><br><span class=\"line\">[...emojiSet] // ["↖", "💎", "↗", "♠", "😏", "😍"]</span><br></pre></td></tr></table></figure>\n<p> 只能 Array?<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const text = 'prototype';</span><br><span class=\"line\">new Set(text); // Set {"p", "r", "o", "t", "y", "e"} 我是 String Set的</span><br></pre></td></tr></table></figure></p>\n<p> 上面说到它的返回值是一个对象<br> So, 它有自己属性及方法。<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">mySet.size; // 6 剩 6 个了</span><br><span class=\"line\">mySet.length; // undefined</span><br></pre></td></tr></table></figure></p>\n<p> 都叫 ‘size’了,当然是它的个数啊,<br> 没 length(手动痴呆脸)我就试试看而已…<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我要加个 10 */</span><br><span class=\"line\">mySet.add(10) // [1, 2, 3, 4, 5, 0, 10] 加上了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我要加个 1 */</span><br><span class=\"line\">mySet.add(1) // [1, 2, 3, 4, 5, 0] 233 加不上!说了 Set有唯一性了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我不要 0 了 */</span><br><span class=\"line\">mySet.clear(0) // undefined !!!</span><br><span class=\"line\">mySet.clear() // undefined !!!</span><br></pre></td></tr></table></figure></p>\n<p> 刷出来算我输…<br> Set.prototype.clear(),没参数,调用就清空啦.</p>\n<p> 当然是可以删除了,开了一个好冷的笑话(故作镇定接着写…)<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const arr = [1, 2, 3, 4, 5, 5, 4, 3, 2, 0];</span><br><span class=\"line\">const mySet = new Set(arr);</span><br><span class=\"line\"></span><br><span class=\"line\">/* 我不要 0 了 */</span><br><span class=\"line\">mySet.delete(0) // [1, 2, 3, 4, 5] 删掉了!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 1 吗? */</span><br><span class=\"line\">mySet.has(1); // true 有的!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 2 吗? */</span><br><span class=\"line\">mySet.has(2); // true 有的!</span><br><span class=\"line\"></span><br><span class=\"line\">/* 有 0 吗? */</span><br><span class=\"line\">mySet.has(0); // false 没有!刚才删了!</span><br></pre></td></tr></table></figure></p>\n<p> 其实还有几个方法,<br> 这里只是简单的说一下这个 Set 而已<br> 你以为我结束了?<br> 我再说最后一个!<br> 嗯!<br> 最后一个!<br> 我保证!<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">/* 用 forEach 能干点什么? */</span><br><span class=\"line\">mySet.forEach(function(value) {</span><br><span class=\"line\"> // use value do something ...</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p> OK,能力有限…</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><p><a href=\"https://github.com/lucefer/vue-bubble\" target=\"_blank\" rel=\"noopener\">消息气泡拖拽插件, 基于vue实现的仿QQ消息气泡拖拽插件</a></p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install vue-bubble</span><br></pre></td></tr></table></figure>\n<h4 id=\"引入\"><a href=\"#引入\" class=\"headerlink\" title=\"引入\"></a>引入</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const vueBubble from 'vue-bubble'</span><br><span class=\"line\">Vue.use(vueBubble)</span><br></pre></td></tr></table></figure>\n</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://segmentfault.com/a/1190000011229300\" target=\"_blank\" rel=\"noopener\">JavaScript 工作原理:内存管理与常见内存泄露分析</a><br>本系列文章皆着眼于深度解析 JavaScript 内部运行原理,而本文则重点讨论编程语言中常见的内存管理问题;并且还提出了对于处理常见的内存泄露的建议。</p>\n</li>\n<li><p><a href=\"https://antv.alipay.com/vis/doc/chart/details/scatter-plot.html\" target=\"_blank\" rel=\"noopener\">可视化基础之散点图介绍</a><br>这篇文章介绍了散点图的科学意义,推荐大家阅读学习。可视化是前端发展的一个大方向,可视化工程师除了技术实现之外,还应该学习各种图表所能表达的科学含义。感谢蚂蚁金服体验技术部同学们,整理了一整套科学规范的可视化图表“字典”,让大家详细了解每种图表背后的含义。扩展阅读:<a href=\"https://antv.alipay.com/vis/doc/chart/classify/compare.html\" target=\"_blank\" rel=\"noopener\">可视化基础</a></p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5965943ff265da6c30653879\" target=\"_blank\" rel=\"noopener\">JS正则表达式完整教程</a><br>非常详细的介绍了JS中和正则相关的知识,文章很长,适合慢慢研读</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59bb37fa6fb9a00a554f89d2\" target=\"_blank\" rel=\"noopener\">webpack:从入门到真实项目配置</a><br>文章主要介绍webpack配置,由简入繁、逐步优化,从简单的打包为一个bundle到分离代码、抽离共同代码、按需加载代码、自动刷新,每一步都非常详细,适合初学者快速入门。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26364493\" target=\"_blank\" rel=\"noopener\">AR.js 初探</a><br>AR技术(增强现实技术Augmented Reality,简称 AR),AR技术在Native中已经兴起了,并且市场上有许多成功的APP,但是对于JavaScript怎么来玩转AR呢?下面我来简单的给大家演示两个不同版本,不同场景的AR小例子。</p>\n</li>\n<li><p><a href=\"https://github.com/zuopf769/notebook/blob/master/fe/BFC%E5%8E%9F%E7%90%86%E5%89%96%E6%9E%90/README.md\" target=\"_blank\" rel=\"noopener\">史上最全面、最透彻的BFC原理剖析</a><br>介绍FC的概念是什么; BFC的约束规则;咋样才能触发生成新的BFC;BFC在布局中的应用:防止margin重叠(塌陷,以最大的为准); 清除内部浮动;自适应两(多)栏布局。 </p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29137921\" target=\"_blank\" rel=\"noopener\">JS遇上IOT</a><br>IOT是 Internet of Things 的缩写,字面翻译是“物体组成的因特网”,准确的翻译应该为“物联网”。凡是可以用 JavaScript 来写的应用,最终都会用 JavaScript ——Atwood 定律。逃不出这个定律,JavaScript 也能用于物联网开发了。本文介绍了使用 JavaScript 在 ruff 开发平台上的小实例,有树莓派的小伙伴可以尝试把玩一下。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010921801\" target=\"_blank\" rel=\"noopener\">上手 Webpack ? 这篇就够了!</a><br>文章系统的概述了 Webpack 从安装到配置以及插件等等;讲述的还是比较全面。对于使用 Webpack 来说,完全可以说是够用。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/giggle/p/7538533.html\" target=\"_blank\" rel=\"noopener\">实现一个简单的虚拟DOM</a><br>现在的流行框架,无论React还是Vue,都采用虚拟DOM。文中介绍了虚拟DOM的实现原理,能帮助更好理解双向绑定实现。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第15期 (本期小编:郭俊兵)","date":"2017-09-29T08:23:27.000Z","_content":"## Show me the code\n\n* 对象数组排序\n\n概念:javascript实现多维数组、对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序。\n\n语法:arr.sort(by('xx'))\n\n- 参数介绍:\n - function, key\n 使用回调函数,处理需要排序的对象key。\n\n- 返回值\n 排序以后的数组。\n\n 针对于偶尔需要前端排序的情况,可以使用该方式。\n\n```\n // 回调函数\n function by(name) {\n return function(o, p) {\n let a;\n let b;\n if (typeof o === 'object' && typeof p === 'object' && o && p) {\n a = o[name];\n b = p[name];\n if (a === b) {\n return 0;\n }\n if (typeof a === typeof b) {\n return a < b ? -1 : 1;\n }\n return typeof a < typeof b ? -1 : 1;\n }\n };\n }\n```\n 需要排序的 Array:\n```\n const employees = [{\n name: 'George',\n age: 32,\n retiredate: 'March 12, 2014'\n }, {\n name: 'Edward',\n age: 17,\n retiredate: 'June 2, 2023'\n }, {\n name: 'Christine',\n age: 58,\n retiredate: 'December 20, 2036'\n }, {\n name: 'Sarah',\n age: 62,\n retiredate: 'April 30, 2020'\n }];\n```\n 通过 age 排序:\n```\n employees.sort(by('age'));\n```\n 结果:\n```\n [{\"name\":\"Edward\",\"age\":17,\"retiredate\":\"June 2, 2023\"},\n {\"name\":\"George\",\"age\":32,\"retiredate\":\"March 12, 2014\"},\n {\"name\":\"Christine\",\"age\":58,\"retiredate\":\"December 20, 2036\"},\n {\"name\":\"Sarah\",\"age\":62,\"retiredate\":\"April 30, 2020\"}]\n```\n 到这里,对象数组排序就算基本实现了。那如何实现多个键值排序呢?意思就是先是对age排序,如果age相同,再比较name。\n\t这时,我们可以进一步修改by函数,让其可以接受第二个参数,当主要的键值产生一个匹配的时候,另一个compare方法将被调用以决出高下:\n```\n // by函数接受一个成员名字符串和一个可选的次要比较函数做为参数\n // 并返回一个可以用来包含该成员的对象数组进行排序的比较函数\n // 当o[age]和 p[age] 相等时, 次要比较函数被用来决出高下\n function by(name, minor) {\n return function(o, p) {\n let a;\n let b;\n if (o && p && typeof o === 'object' && typeof p === 'object') {\n a = o[name];\n b = p[name];\n if (a === b) {\n return typeof minor === 'function' ? minor(o, p) : 0;\n }\n if (typeof a === typeof b) {\n return a < b ? -1 : 1;\n }\n return typeof a < typeof b ? -1 : 1;\n } else {\n thro(\"error\");\n }\n }\n }\n```\n 待排序数组:\n```\n const employees = [{\n name: 'George',\n age: 32,\n retiredate: 'March 12, 2014'\n }, {\n name: 'Edward',\n age: 17,\n retiredate: 'June 2, 2023'\n }, {\n name: 'Christine',\n age: 32,\n retiredate: 'December 20, 2036'\n }, {\n name: 'Sarah',\n age: 62,\n retiredate: 'April 30, 2020'\n }];\n // 排序操作\n employees.sort(by('age', by('name')))\n```\n 结果:\n```\n\t[{\"name\":\"Edward\",\"age\":17,\"retiredate\":\"June 2, 2023\"},\n\t{\"name\":\"George\",\"age\":32,\"retiredate\":\"March 12, 2014\"},\n\t{\"name\":\"Sarah\",\"age\":32,\"retiredate\":\"April 30, 2020\"},\n\t{\"name\":\"Christine\",\"age\":58,\"retiredate\":\"December 20, 2036\"}]\n```\n\n## 插件推荐\n- [jsoneditor JOSN格式编辑器](https://github.com/josdejong/jsoneditor/)\n #### 安装 \n```\n npm install jsoneditor\n```\n\n #### 引入 \n```\n import JSONEditor from 'jsoneditor/dist/jsoneditor';\n const container = document.getElementById('jsonEdit');\n container.innerHTML = '';\n const options = {\n mode: 'code',\n };\n const editor = new JSONEditor(container, options);\n // 添加数据\n editor.set(JSON);\n // 获取数据\n editor.get();\n```\n\n## 文章推荐\n\n- [实现达到 60FPS 的高性能交互动画](https://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425040&idx=1&sn=523695a371f87ce6f4f1c003ef937f0b&chksm=80dff773b7a87e65fa93ce9f059d3b1f6af1c2115c3bf5356357f25fab730cab4f8ae67cb70d&mpshare=1&scene=1&srcid=0929ZyVAlRQeJ9EX6qEuuq5C#rd)\n\t对于页面优化而言,开发者往往会花大量精力在优化首屏加载,为了几毫秒锱铢必较,但忽略了页面交互动画所带来的性能问题。本文从浏览器渲染原理的角度,给出了实现60FPS交互动画的方法。\n\n- [Node.js cluster 踩坑小结](https://zhuanlan.zhihu.com/p/27069865)\n\t推荐大家深入阅读这篇来自饿了么 Node 大神黄鼎恒的文章,内容深入介绍了进程与 process 对象、子进程 和 IPC ,负载实现等知识点和踩过的坑。\n\n- [你真的会用 Babel 吗](https://juejin.im/post/59b9ffa8f265da06710d8e89)\n\t对于 babel 的使用,大部分同学一直停留在与 webpack 结合使用,以及在浏览器开发环境下。导致很多 babel 的包,都不清楚他们是干嘛的。本篇文章可以当个入门来读\n\n- [JavaScript 数组的演进及其性能](http://www.zcfy.cc/article/diving-deep-into-javascript-array-8211-evolution-038-performance-void-canvas-4202.html?t=new)\n[MDN JavaScript typed arrays](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays)\n\t文章通过数组与类型化数组(Typed Arrays)进行对比,从创建,插入,读取等方面进行性能比较;从而直观的介绍类型化数组的,并没有深入Typed Arrays。\n\n- [RAIL 性能模型](http://web.jobbole.com/86941/)\n\t资源加载之后的性能,因为大多数用户关注的不是应用如何加载而是具体的使用。所以要快速响应用户,尤其是无线端,我们有必要了解浏览器渲染性能。\n\n- [CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅](https://segmentfault.com/a/1190000011354975)\n\t[这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已](https://github.com/jawil/blog/issues/24)\n\t很有意思的两篇代码小技巧,几行代码实现让人惊诧的功能、效果。思路清奇,仔细阅读代码相信会沉淀不少有用的东西。\n\n- [javascript 函数中的 this 的四种绑定形式](http://web.jobbole.com/92207/)\n \tjavascript中的this和函数息息相关,谈到this很多让人晕晕乎乎的抽象概念就跑出来了,这里只说最核心的一点——函数中的this总指向调用它的对象\n\n- [怎样把网站升级到http/2](https://fed.renren.com/2017/09/23/http2/)\n\t为何升级http/2理由[在这里](https://fed.renren.com/2017/09/03/upgrade-to-https/),本文是实践部分。http/2给前端优化带来了[新的机遇与挑战](https://imququ.com/post/http2-new-opportunities-and-challenges.html),有兴趣的小伙伴可以了解下。\n\n- [JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS](https://segmentfault.com/a/1190000007484357)\n\tV8做为Javascript引擎,使用范围已经越来越广泛。文中简单介绍了V8引擎在NodeJS的中运用。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","source":"_posts/weekly-15.md","raw":"---\ntitle: 大前端周刊 第15期 (本期小编:郭俊兵)\ndate: 2017-09-29 16:23:27\ntags: [动画, Node, Babels, 渲染性能, this关键字, http/2升级, CSS黑魔法]\n---\n## Show me the code\n\n* 对象数组排序\n\n概念:javascript实现多维数组、对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序。\n\n语法:arr.sort(by('xx'))\n\n- 参数介绍:\n - function, key\n 使用回调函数,处理需要排序的对象key。\n\n- 返回值\n 排序以后的数组。\n\n 针对于偶尔需要前端排序的情况,可以使用该方式。\n\n```\n // 回调函数\n function by(name) {\n return function(o, p) {\n let a;\n let b;\n if (typeof o === 'object' && typeof p === 'object' && o && p) {\n a = o[name];\n b = p[name];\n if (a === b) {\n return 0;\n }\n if (typeof a === typeof b) {\n return a < b ? -1 : 1;\n }\n return typeof a < typeof b ? -1 : 1;\n }\n };\n }\n```\n 需要排序的 Array:\n```\n const employees = [{\n name: 'George',\n age: 32,\n retiredate: 'March 12, 2014'\n }, {\n name: 'Edward',\n age: 17,\n retiredate: 'June 2, 2023'\n }, {\n name: 'Christine',\n age: 58,\n retiredate: 'December 20, 2036'\n }, {\n name: 'Sarah',\n age: 62,\n retiredate: 'April 30, 2020'\n }];\n```\n 通过 age 排序:\n```\n employees.sort(by('age'));\n```\n 结果:\n```\n [{\"name\":\"Edward\",\"age\":17,\"retiredate\":\"June 2, 2023\"},\n {\"name\":\"George\",\"age\":32,\"retiredate\":\"March 12, 2014\"},\n {\"name\":\"Christine\",\"age\":58,\"retiredate\":\"December 20, 2036\"},\n {\"name\":\"Sarah\",\"age\":62,\"retiredate\":\"April 30, 2020\"}]\n```\n 到这里,对象数组排序就算基本实现了。那如何实现多个键值排序呢?意思就是先是对age排序,如果age相同,再比较name。\n\t这时,我们可以进一步修改by函数,让其可以接受第二个参数,当主要的键值产生一个匹配的时候,另一个compare方法将被调用以决出高下:\n```\n // by函数接受一个成员名字符串和一个可选的次要比较函数做为参数\n // 并返回一个可以用来包含该成员的对象数组进行排序的比较函数\n // 当o[age]和 p[age] 相等时, 次要比较函数被用来决出高下\n function by(name, minor) {\n return function(o, p) {\n let a;\n let b;\n if (o && p && typeof o === 'object' && typeof p === 'object') {\n a = o[name];\n b = p[name];\n if (a === b) {\n return typeof minor === 'function' ? minor(o, p) : 0;\n }\n if (typeof a === typeof b) {\n return a < b ? -1 : 1;\n }\n return typeof a < typeof b ? -1 : 1;\n } else {\n thro(\"error\");\n }\n }\n }\n```\n 待排序数组:\n```\n const employees = [{\n name: 'George',\n age: 32,\n retiredate: 'March 12, 2014'\n }, {\n name: 'Edward',\n age: 17,\n retiredate: 'June 2, 2023'\n }, {\n name: 'Christine',\n age: 32,\n retiredate: 'December 20, 2036'\n }, {\n name: 'Sarah',\n age: 62,\n retiredate: 'April 30, 2020'\n }];\n // 排序操作\n employees.sort(by('age', by('name')))\n```\n 结果:\n```\n\t[{\"name\":\"Edward\",\"age\":17,\"retiredate\":\"June 2, 2023\"},\n\t{\"name\":\"George\",\"age\":32,\"retiredate\":\"March 12, 2014\"},\n\t{\"name\":\"Sarah\",\"age\":32,\"retiredate\":\"April 30, 2020\"},\n\t{\"name\":\"Christine\",\"age\":58,\"retiredate\":\"December 20, 2036\"}]\n```\n\n## 插件推荐\n- [jsoneditor JOSN格式编辑器](https://github.com/josdejong/jsoneditor/)\n #### 安装 \n```\n npm install jsoneditor\n```\n\n #### 引入 \n```\n import JSONEditor from 'jsoneditor/dist/jsoneditor';\n const container = document.getElementById('jsonEdit');\n container.innerHTML = '';\n const options = {\n mode: 'code',\n };\n const editor = new JSONEditor(container, options);\n // 添加数据\n editor.set(JSON);\n // 获取数据\n editor.get();\n```\n\n## 文章推荐\n\n- [实现达到 60FPS 的高性能交互动画](https://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425040&idx=1&sn=523695a371f87ce6f4f1c003ef937f0b&chksm=80dff773b7a87e65fa93ce9f059d3b1f6af1c2115c3bf5356357f25fab730cab4f8ae67cb70d&mpshare=1&scene=1&srcid=0929ZyVAlRQeJ9EX6qEuuq5C#rd)\n\t对于页面优化而言,开发者往往会花大量精力在优化首屏加载,为了几毫秒锱铢必较,但忽略了页面交互动画所带来的性能问题。本文从浏览器渲染原理的角度,给出了实现60FPS交互动画的方法。\n\n- [Node.js cluster 踩坑小结](https://zhuanlan.zhihu.com/p/27069865)\n\t推荐大家深入阅读这篇来自饿了么 Node 大神黄鼎恒的文章,内容深入介绍了进程与 process 对象、子进程 和 IPC ,负载实现等知识点和踩过的坑。\n\n- [你真的会用 Babel 吗](https://juejin.im/post/59b9ffa8f265da06710d8e89)\n\t对于 babel 的使用,大部分同学一直停留在与 webpack 结合使用,以及在浏览器开发环境下。导致很多 babel 的包,都不清楚他们是干嘛的。本篇文章可以当个入门来读\n\n- [JavaScript 数组的演进及其性能](http://www.zcfy.cc/article/diving-deep-into-javascript-array-8211-evolution-038-performance-void-canvas-4202.html?t=new)\n[MDN JavaScript typed arrays](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays)\n\t文章通过数组与类型化数组(Typed Arrays)进行对比,从创建,插入,读取等方面进行性能比较;从而直观的介绍类型化数组的,并没有深入Typed Arrays。\n\n- [RAIL 性能模型](http://web.jobbole.com/86941/)\n\t资源加载之后的性能,因为大多数用户关注的不是应用如何加载而是具体的使用。所以要快速响应用户,尤其是无线端,我们有必要了解浏览器渲染性能。\n\n- [CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅](https://segmentfault.com/a/1190000011354975)\n\t[这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已](https://github.com/jawil/blog/issues/24)\n\t很有意思的两篇代码小技巧,几行代码实现让人惊诧的功能、效果。思路清奇,仔细阅读代码相信会沉淀不少有用的东西。\n\n- [javascript 函数中的 this 的四种绑定形式](http://web.jobbole.com/92207/)\n \tjavascript中的this和函数息息相关,谈到this很多让人晕晕乎乎的抽象概念就跑出来了,这里只说最核心的一点——函数中的this总指向调用它的对象\n\n- [怎样把网站升级到http/2](https://fed.renren.com/2017/09/23/http2/)\n\t为何升级http/2理由[在这里](https://fed.renren.com/2017/09/03/upgrade-to-https/),本文是实践部分。http/2给前端优化带来了[新的机遇与挑战](https://imququ.com/post/http2-new-opportunities-and-challenges.html),有兴趣的小伙伴可以了解下。\n\n- [JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS](https://segmentfault.com/a/1190000007484357)\n\tV8做为Javascript引擎,使用范围已经越来越广泛。文中简单介绍了V8引擎在NodeJS的中运用。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n* 前端实习生\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","slug":"weekly-15","published":1,"updated":"2017-11-10T07:40:52.987Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkn0008jrs67pwmuobx","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>对象数组排序</li>\n</ul>\n<p>概念:javascript实现多维数组、对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序。</p>\n<p>语法:arr.sort(by(‘xx’))</p>\n<ul>\n<li><p>参数介绍:</p>\n<ul>\n<li>function, key<br>使用回调函数,处理需要排序的对象key。</li>\n</ul>\n</li>\n<li><p>返回值<br>排序以后的数组。</p>\n<p>针对于偶尔需要前端排序的情况,可以使用该方式。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">// 回调函数</span><br><span class=\"line\">function by(name) {</span><br><span class=\"line\"> return function(o, p) {</span><br><span class=\"line\"> let a;</span><br><span class=\"line\"> let b;</span><br><span class=\"line\"> if (typeof o === 'object' && typeof p === 'object' && o && p) {</span><br><span class=\"line\"> a = o[name];</span><br><span class=\"line\"> b = p[name];</span><br><span class=\"line\"> if (a === b) {</span><br><span class=\"line\"> return 0;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> if (typeof a === typeof b) {</span><br><span class=\"line\"> return a < b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> return typeof a < typeof b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p> 需要排序的 Array:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const employees = [{</span><br><span class=\"line\"> name: 'George',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'March 12, 2014'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Edward',</span><br><span class=\"line\"> age: 17,</span><br><span class=\"line\"> retiredate: 'June 2, 2023'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Christine',</span><br><span class=\"line\"> age: 58,</span><br><span class=\"line\"> retiredate: 'December 20, 2036'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Sarah',</span><br><span class=\"line\"> age: 62,</span><br><span class=\"line\"> retiredate: 'April 30, 2020'</span><br><span class=\"line\">}];</span><br></pre></td></tr></table></figure></p>\n<p> 通过 age 排序:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">employees.sort(by('age'));</span><br></pre></td></tr></table></figure></p>\n<p> 结果:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},</span><br><span class=\"line\">{"name":"George","age":32,"retiredate":"March 12, 2014"},</span><br><span class=\"line\">{"name":"Christine","age":58,"retiredate":"December 20, 2036"},</span><br><span class=\"line\">{"name":"Sarah","age":62,"retiredate":"April 30, 2020"}]</span><br></pre></td></tr></table></figure></p>\n<p> 到这里,对象数组排序就算基本实现了。那如何实现多个键值排序呢?意思就是先是对age排序,如果age相同,再比较name。<br> 这时,我们可以进一步修改by函数,让其可以接受第二个参数,当主要的键值产生一个匹配的时候,另一个compare方法将被调用以决出高下:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">// by函数接受一个成员名字符串和一个可选的次要比较函数做为参数</span><br><span class=\"line\">// 并返回一个可以用来包含该成员的对象数组进行排序的比较函数</span><br><span class=\"line\">// 当o[age]和 p[age] 相等时, 次要比较函数被用来决出高下</span><br><span class=\"line\">function by(name, minor) {</span><br><span class=\"line\"> return function(o, p) {</span><br><span class=\"line\"> let a;</span><br><span class=\"line\"> let b;</span><br><span class=\"line\"> if (o && p && typeof o === 'object' && typeof p === 'object') {</span><br><span class=\"line\"> a = o[name];</span><br><span class=\"line\"> b = p[name];</span><br><span class=\"line\"> if (a === b) {</span><br><span class=\"line\"> return typeof minor === 'function' ? minor(o, p) : 0;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> if (typeof a === typeof b) {</span><br><span class=\"line\"> return a < b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> return typeof a < typeof b ? -1 : 1;</span><br><span class=\"line\"> } else {</span><br><span class=\"line\"> thro("error");</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p> 待排序数组:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const employees = [{</span><br><span class=\"line\"> name: 'George',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'March 12, 2014'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Edward',</span><br><span class=\"line\"> age: 17,</span><br><span class=\"line\"> retiredate: 'June 2, 2023'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Christine',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'December 20, 2036'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Sarah',</span><br><span class=\"line\"> age: 62,</span><br><span class=\"line\"> retiredate: 'April 30, 2020'</span><br><span class=\"line\">}];</span><br><span class=\"line\">// 排序操作</span><br><span class=\"line\">employees.sort(by('age', by('name')))</span><br></pre></td></tr></table></figure></p>\n<p> 结果:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},</span><br><span class=\"line\">{"name":"George","age":32,"retiredate":"March 12, 2014"},</span><br><span class=\"line\">{"name":"Sarah","age":32,"retiredate":"April 30, 2020"},</span><br><span class=\"line\">{"name":"Christine","age":58,"retiredate":"December 20, 2036"}]</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><p><a href=\"https://github.com/josdejong/jsoneditor/\" target=\"_blank\" rel=\"noopener\">jsoneditor JOSN格式编辑器</a></p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install jsoneditor</span><br></pre></td></tr></table></figure>\n<h4 id=\"引入\"><a href=\"#引入\" class=\"headerlink\" title=\"引入\"></a>引入</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">import JSONEditor from 'jsoneditor/dist/jsoneditor';</span><br><span class=\"line\">const container = document.getElementById('jsonEdit');</span><br><span class=\"line\">container.innerHTML = '';</span><br><span class=\"line\">const options = {</span><br><span class=\"line\"> mode: 'code',</span><br><span class=\"line\">};</span><br><span class=\"line\">const editor = new JSONEditor(container, options);</span><br><span class=\"line\">// 添加数据</span><br><span class=\"line\">editor.set(JSON);</span><br><span class=\"line\">// 获取数据</span><br><span class=\"line\">editor.get();</span><br></pre></td></tr></table></figure>\n</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425040&idx=1&sn=523695a371f87ce6f4f1c003ef937f0b&chksm=80dff773b7a87e65fa93ce9f059d3b1f6af1c2115c3bf5356357f25fab730cab4f8ae67cb70d&mpshare=1&scene=1&srcid=0929ZyVAlRQeJ9EX6qEuuq5C#rd\" target=\"_blank\" rel=\"noopener\">实现达到 60FPS 的高性能交互动画</a><br> 对于页面优化而言,开发者往往会花大量精力在优化首屏加载,为了几毫秒锱铢必较,但忽略了页面交互动画所带来的性能问题。本文从浏览器渲染原理的角度,给出了实现60FPS交互动画的方法。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27069865\" target=\"_blank\" rel=\"noopener\">Node.js cluster 踩坑小结</a><br> 推荐大家深入阅读这篇来自饿了么 Node 大神黄鼎恒的文章,内容深入介绍了进程与 process 对象、子进程 和 IPC ,负载实现等知识点和踩过的坑。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59b9ffa8f265da06710d8e89\" target=\"_blank\" rel=\"noopener\">你真的会用 Babel 吗</a><br> 对于 babel 的使用,大部分同学一直停留在与 webpack 结合使用,以及在浏览器开发环境下。导致很多 babel 的包,都不清楚他们是干嘛的。本篇文章可以当个入门来读</p>\n</li>\n<li><p><a href=\"http://www.zcfy.cc/article/diving-deep-into-javascript-array-8211-evolution-038-performance-void-canvas-4202.html?t=new\" target=\"_blank\" rel=\"noopener\">JavaScript 数组的演进及其性能</a><br><a href=\"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays\" target=\"_blank\" rel=\"noopener\">MDN JavaScript typed arrays</a><br> 文章通过数组与类型化数组(Typed Arrays)进行对比,从创建,插入,读取等方面进行性能比较;从而直观的介绍类型化数组的,并没有深入Typed Arrays。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/86941/\" target=\"_blank\" rel=\"noopener\">RAIL 性能模型</a><br> 资源加载之后的性能,因为大多数用户关注的不是应用如何加载而是具体的使用。所以要快速响应用户,尤其是无线端,我们有必要了解浏览器渲染性能。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011354975\" target=\"_blank\" rel=\"noopener\">CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅</a><br> <a href=\"https://github.com/jawil/blog/issues/24\" target=\"_blank\" rel=\"noopener\">这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已</a><br> 很有意思的两篇代码小技巧,几行代码实现让人惊诧的功能、效果。思路清奇,仔细阅读代码相信会沉淀不少有用的东西。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92207/\" target=\"_blank\" rel=\"noopener\">javascript 函数中的 this 的四种绑定形式</a><br> javascript中的this和函数息息相关,谈到this很多让人晕晕乎乎的抽象概念就跑出来了,这里只说最核心的一点——函数中的this总指向调用它的对象</p>\n</li>\n<li><p><a href=\"https://fed.renren.com/2017/09/23/http2/\" target=\"_blank\" rel=\"noopener\">怎样把网站升级到http/2</a><br> 为何升级http/2理由<a href=\"https://fed.renren.com/2017/09/03/upgrade-to-https/\" target=\"_blank\" rel=\"noopener\">在这里</a>,本文是实践部分。http/2给前端优化带来了<a href=\"https://imququ.com/post/http2-new-opportunities-and-challenges.html\" target=\"_blank\" rel=\"noopener\">新的机遇与挑战</a>,有兴趣的小伙伴可以了解下。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000007484357\" target=\"_blank\" rel=\"noopener\">JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS</a><br> V8做为Javascript引擎,使用范围已经越来越广泛。文中简单介绍了V8引擎在NodeJS的中运用。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><ul>\n<li>对象数组排序</li>\n</ul>\n<p>概念:javascript实现多维数组、对象数组排序,其实用的就是原生的sort()方法,用于对数组的元素进行排序。</p>\n<p>语法:arr.sort(by(‘xx’))</p>\n<ul>\n<li><p>参数介绍:</p>\n<ul>\n<li>function, key<br>使用回调函数,处理需要排序的对象key。</li>\n</ul>\n</li>\n<li><p>返回值<br>排序以后的数组。</p>\n<p>针对于偶尔需要前端排序的情况,可以使用该方式。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">// 回调函数</span><br><span class=\"line\">function by(name) {</span><br><span class=\"line\"> return function(o, p) {</span><br><span class=\"line\"> let a;</span><br><span class=\"line\"> let b;</span><br><span class=\"line\"> if (typeof o === 'object' && typeof p === 'object' && o && p) {</span><br><span class=\"line\"> a = o[name];</span><br><span class=\"line\"> b = p[name];</span><br><span class=\"line\"> if (a === b) {</span><br><span class=\"line\"> return 0;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> if (typeof a === typeof b) {</span><br><span class=\"line\"> return a < b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> return typeof a < typeof b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p> 需要排序的 Array:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const employees = [{</span><br><span class=\"line\"> name: 'George',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'March 12, 2014'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Edward',</span><br><span class=\"line\"> age: 17,</span><br><span class=\"line\"> retiredate: 'June 2, 2023'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Christine',</span><br><span class=\"line\"> age: 58,</span><br><span class=\"line\"> retiredate: 'December 20, 2036'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Sarah',</span><br><span class=\"line\"> age: 62,</span><br><span class=\"line\"> retiredate: 'April 30, 2020'</span><br><span class=\"line\">}];</span><br></pre></td></tr></table></figure></p>\n<p> 通过 age 排序:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">employees.sort(by('age'));</span><br></pre></td></tr></table></figure></p>\n<p> 结果:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},</span><br><span class=\"line\">{"name":"George","age":32,"retiredate":"March 12, 2014"},</span><br><span class=\"line\">{"name":"Christine","age":58,"retiredate":"December 20, 2036"},</span><br><span class=\"line\">{"name":"Sarah","age":62,"retiredate":"April 30, 2020"}]</span><br></pre></td></tr></table></figure></p>\n<p> 到这里,对象数组排序就算基本实现了。那如何实现多个键值排序呢?意思就是先是对age排序,如果age相同,再比较name。<br> 这时,我们可以进一步修改by函数,让其可以接受第二个参数,当主要的键值产生一个匹配的时候,另一个compare方法将被调用以决出高下:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">// by函数接受一个成员名字符串和一个可选的次要比较函数做为参数</span><br><span class=\"line\">// 并返回一个可以用来包含该成员的对象数组进行排序的比较函数</span><br><span class=\"line\">// 当o[age]和 p[age] 相等时, 次要比较函数被用来决出高下</span><br><span class=\"line\">function by(name, minor) {</span><br><span class=\"line\"> return function(o, p) {</span><br><span class=\"line\"> let a;</span><br><span class=\"line\"> let b;</span><br><span class=\"line\"> if (o && p && typeof o === 'object' && typeof p === 'object') {</span><br><span class=\"line\"> a = o[name];</span><br><span class=\"line\"> b = p[name];</span><br><span class=\"line\"> if (a === b) {</span><br><span class=\"line\"> return typeof minor === 'function' ? minor(o, p) : 0;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> if (typeof a === typeof b) {</span><br><span class=\"line\"> return a < b ? -1 : 1;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> return typeof a < typeof b ? -1 : 1;</span><br><span class=\"line\"> } else {</span><br><span class=\"line\"> thro("error");</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p> 待排序数组:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">const employees = [{</span><br><span class=\"line\"> name: 'George',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'March 12, 2014'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Edward',</span><br><span class=\"line\"> age: 17,</span><br><span class=\"line\"> retiredate: 'June 2, 2023'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Christine',</span><br><span class=\"line\"> age: 32,</span><br><span class=\"line\"> retiredate: 'December 20, 2036'</span><br><span class=\"line\">}, {</span><br><span class=\"line\"> name: 'Sarah',</span><br><span class=\"line\"> age: 62,</span><br><span class=\"line\"> retiredate: 'April 30, 2020'</span><br><span class=\"line\">}];</span><br><span class=\"line\">// 排序操作</span><br><span class=\"line\">employees.sort(by('age', by('name')))</span><br></pre></td></tr></table></figure></p>\n<p> 结果:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">[{"name":"Edward","age":17,"retiredate":"June 2, 2023"},</span><br><span class=\"line\">{"name":"George","age":32,"retiredate":"March 12, 2014"},</span><br><span class=\"line\">{"name":"Sarah","age":32,"retiredate":"April 30, 2020"},</span><br><span class=\"line\">{"name":"Christine","age":58,"retiredate":"December 20, 2036"}]</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><p><a href=\"https://github.com/josdejong/jsoneditor/\" target=\"_blank\" rel=\"noopener\">jsoneditor JOSN格式编辑器</a></p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">npm install jsoneditor</span><br></pre></td></tr></table></figure>\n<h4 id=\"引入\"><a href=\"#引入\" class=\"headerlink\" title=\"引入\"></a>引入</h4><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">import JSONEditor from 'jsoneditor/dist/jsoneditor';</span><br><span class=\"line\">const container = document.getElementById('jsonEdit');</span><br><span class=\"line\">container.innerHTML = '';</span><br><span class=\"line\">const options = {</span><br><span class=\"line\"> mode: 'code',</span><br><span class=\"line\">};</span><br><span class=\"line\">const editor = new JSONEditor(container, options);</span><br><span class=\"line\">// 添加数据</span><br><span class=\"line\">editor.set(JSON);</span><br><span class=\"line\">// 获取数据</span><br><span class=\"line\">editor.get();</span><br></pre></td></tr></table></figure>\n</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAwNTAzMjcxNg==&mid=2651425040&idx=1&sn=523695a371f87ce6f4f1c003ef937f0b&chksm=80dff773b7a87e65fa93ce9f059d3b1f6af1c2115c3bf5356357f25fab730cab4f8ae67cb70d&mpshare=1&scene=1&srcid=0929ZyVAlRQeJ9EX6qEuuq5C#rd\" target=\"_blank\" rel=\"noopener\">实现达到 60FPS 的高性能交互动画</a><br> 对于页面优化而言,开发者往往会花大量精力在优化首屏加载,为了几毫秒锱铢必较,但忽略了页面交互动画所带来的性能问题。本文从浏览器渲染原理的角度,给出了实现60FPS交互动画的方法。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27069865\" target=\"_blank\" rel=\"noopener\">Node.js cluster 踩坑小结</a><br> 推荐大家深入阅读这篇来自饿了么 Node 大神黄鼎恒的文章,内容深入介绍了进程与 process 对象、子进程 和 IPC ,负载实现等知识点和踩过的坑。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59b9ffa8f265da06710d8e89\" target=\"_blank\" rel=\"noopener\">你真的会用 Babel 吗</a><br> 对于 babel 的使用,大部分同学一直停留在与 webpack 结合使用,以及在浏览器开发环境下。导致很多 babel 的包,都不清楚他们是干嘛的。本篇文章可以当个入门来读</p>\n</li>\n<li><p><a href=\"http://www.zcfy.cc/article/diving-deep-into-javascript-array-8211-evolution-038-performance-void-canvas-4202.html?t=new\" target=\"_blank\" rel=\"noopener\">JavaScript 数组的演进及其性能</a><br><a href=\"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays\" target=\"_blank\" rel=\"noopener\">MDN JavaScript typed arrays</a><br> 文章通过数组与类型化数组(Typed Arrays)进行对比,从创建,插入,读取等方面进行性能比较;从而直观的介绍类型化数组的,并没有深入Typed Arrays。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/86941/\" target=\"_blank\" rel=\"noopener\">RAIL 性能模型</a><br> 资源加载之后的性能,因为大多数用户关注的不是应用如何加载而是具体的使用。所以要快速响应用户,尤其是无线端,我们有必要了解浏览器渲染性能。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011354975\" target=\"_blank\" rel=\"noopener\">CSS 黑魔法小技巧,让你少写不必要的JS,代码更优雅</a><br> <a href=\"https://github.com/jawil/blog/issues/24\" target=\"_blank\" rel=\"noopener\">这些JavaScript编程黑科技,装逼指南,高逼格代码,让你惊叹不已</a><br> 很有意思的两篇代码小技巧,几行代码实现让人惊诧的功能、效果。思路清奇,仔细阅读代码相信会沉淀不少有用的东西。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92207/\" target=\"_blank\" rel=\"noopener\">javascript 函数中的 this 的四种绑定形式</a><br> javascript中的this和函数息息相关,谈到this很多让人晕晕乎乎的抽象概念就跑出来了,这里只说最核心的一点——函数中的this总指向调用它的对象</p>\n</li>\n<li><p><a href=\"https://fed.renren.com/2017/09/23/http2/\" target=\"_blank\" rel=\"noopener\">怎样把网站升级到http/2</a><br> 为何升级http/2理由<a href=\"https://fed.renren.com/2017/09/03/upgrade-to-https/\" target=\"_blank\" rel=\"noopener\">在这里</a>,本文是实践部分。http/2给前端优化带来了<a href=\"https://imququ.com/post/http2-new-opportunities-and-challenges.html\" target=\"_blank\" rel=\"noopener\">新的机遇与挑战</a>,有兴趣的小伙伴可以了解下。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000007484357\" target=\"_blank\" rel=\"noopener\">JavaScript 开发者所需要知道的 V8(一):V8 In NodeJS</a><br> V8做为Javascript引擎,使用范围已经越来越广泛。文中简单介绍了V8引擎在NodeJS的中运用。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n<li>前端实习生</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第16期 (本期小编:张成斌)","date":"2017-10-13T02:24:12.000Z","_content":"\n## Show me the code \n \n### ES6中的`class`语法\n\nJavaScript 语言中,生成实例对象的传统方法是通过构造函数。这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大。ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。\n\n#### Class Definition\n\nES6语法\n\n``` javascript\nclass Shape {\n constructor (id, x, y) {\n this.id = id;\n this.move(x, y);\n }\n move (x, y) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\nES5语法\n``` javascript\nvar Shape = function (id, x, y) {\n this.id = id;\n this.move(x, y);\n};\nShape.prototype.move = function (x, y) {\n this.x = x;\n this.y = y;\n};\n```\n\n上面ES6代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Shape,对应 ES6 的Shape类的构造方法。Shape类除了构造方法,还定义了一个move方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。\n\n#### Class Inheritance\n\nES6语法\n\n``` javascript\nclass Shape {\n constructor (id, x, y) {\n this.id = id;\n this.move(x, y);\n }\n move (x, y) {\n this.x = x;\n this.y = y;\n }\n}\nclass Rectangle extends Shape {\n constructor (id, x, y, width, height) {\n super(id, x, y);\n this.width = width;\n this.height = height;\n }\n}\nclass Circle extends Shape {\n constructor (id, x, y, radius) {\n super(id, x, y);\n this.radius = radius;\n }\n}\n```\n\nES5语法\n``` javascript\nvar Shape = function (id, x, y) {\n this.id = id;\n this.move(x, y);\n};\nShape.prototype.move = function (x, y) {\n this.x = x;\n this.y = y;\n};\nvar Rectangle = function (id, x, y, width, height) {\n Shape.call(this, id, x, y);\n this.width = width;\n this.height = height;\n};\nRectangle.prototype = Object.create(Shape.prototype);\nRectangle.prototype.constructor = Rectangle;\nvar Circle = function (id, x, y, radius) {\n Shape.call(this, id, x, y);\n this.radius = radius;\n};\nCircle.prototype = Object.create(Shape.prototype);\nCircle.prototype.constructor = Circle;\n```\n\n上面的ES6代码定义了一个Rectangle类和一个Circle类,它们通过extends关键字,继承了Shape类的所有属性和方法。子类里都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。对照ES5语法我们可以发现使用class语法更简洁明了。\n\n## 插件推荐\n\n- [whatruns](https://www.whatruns.com/)\n\n这个chrome插件可以查看网站,包括但不限于web框架、web服务器、js框架、js图表插件、字体、CDN。可以很方便的查看你感兴趣的网站所使用的技术。直接在chrome\b扩展商店里面搜whatruns就能安装。\n\n## 文章推荐\n- [美团外卖前端可视化界面组装平台](https://zhuanlan.zhihu.com/p/27288444) \n前端如何才能提高生产效率,普遍的共识是要做到组件化开发,很多团队已经这样做了。虽然很多的产品已经实现了组件化开发,但不同产品间依然存在很多重复的劳动,比如登录框、导航等等。这里推荐一篇美团外卖在效率方面尝试的一个解决方案。\n\n- [如何处理 JavaScript 内存泄露](https://mp.weixin.qq.com/s?__biz=MzA4NjE3MDg4OQ==&mid=2650965216&idx=1&sn=758f45497eb1755c84de7c4afbd494eb&chksm=843ae886b34d6190e9c720c495952b8c7e045e6af40b35c5192d1f0450856f4d44c2536a970d&mpshare=1&scene=1&srcid=1001pdkcvIK6jOSK62fc15aq#)\n讨论开发者容易忽视的重要主题 :内存管理。文章也提供一些关于如何处理JavaScript内存泄露的技巧。在SessionStack,我们需要确保不会造成内存泄露或者不会增加我们集成的Web应用的内存消耗。\n\n- [反击爬虫,前端工程师的脑洞可以有多大?](https://juejin.im/entry/59deb55951882578c2084a63)\n关于反击爬虫,本文给了很多前端反爬虫例子;\n真的感叹为了反爬虫,前段工程师真的费尽心思,脑洞大开!\n\n- [Promise 异步流程控制](http://web.jobbole.com/92605/)\n网页中预加载20张图片资源,分步加载,一次加载10张,两次完成,怎么控制图片请求的并发,怎样感知当前异步请求是否已完成?\n\n- [设计模式之观察者模式](http://www.cnblogs.com/TomXu/archive/2012/03/02/2355128.html)\n观察者模式是一种常用的设置模式。文中提供了多种实现观察者模式的方式,并带有调用方式。可作为实现观察者模式的源码和研究观察者模式使用。\n\n- [用 threejs 制作一款简单的赛车游戏](http://www.alloyteam.com/2017/09/13139/)\n通过学习本教程,可以熟悉 `webgl` 和 `threejs` 相关的知识。\n\n- [使用 SRI 增强 localStorage 代码安全](https://imququ.com/post/enhance-security-for-ls-code.html)\n大部分 Web 应用从 localStorage 中获取缓存代码后,没有任何检测机制,直接执行。而 localStorage 是跨页面的,同域下任何页面有 XSS 漏洞,就可以被攻击者用来往 localStorage 写入恶意代码,可以使用 SRI 增强 localStorage 代码安全。\n\n- [浏览器缓存机制小结](http://mp.weixin.qq.com/s/a7UtcAUnifrNCzegfDYaig)\n本文总结了浏览器缓存的基本机制,将各种情况分为:强缓存和协商缓存两种方式。对三组核心的HTTP请求以及响应头参数:cache-control和expire, last-modified和if-modified-since,etag和if-none-matched,做了清晰的解释,很好理解它们之间的区别、优先级等关系。\n\n- [HTTP 缓存机制一二三](https://zhuanlan.zhihu.com/p/29750583)\n作为前端,常与请求打交道,HTTP缓存应该作为基本知识储备。文章介绍了强缓存和协商缓存,响应头各个字段的含义简单了解下,具体业务需要后端配合设置。\n\n- [如何优雅的在 koa 中处理错误](https://yq.aliyun.com/articles/8539?spm=5176.100240.searchblog.8.u2w8qY)\n软件开发时,有 80% 的代码在处理各种错误。 ——某著名开发者 想让自己的代码健壮,错误处理是必不可少的。这篇文章将主要介绍 koa 框架中错误处理的实现(其实主要是 co 的实现),使用 koa 框架开发 web 应用时进行错误处理的一些方法。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","source":"_posts/weekly-16.md","raw":"---\ntitle: 大前端周刊 第16期 (本期小编:张成斌)\ndate: 2017-10-13 10:24:12\ntags:\n---\n\n## Show me the code \n \n### ES6中的`class`语法\n\nJavaScript 语言中,生成实例对象的传统方法是通过构造函数。这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大。ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。\n\n#### Class Definition\n\nES6语法\n\n``` javascript\nclass Shape {\n constructor (id, x, y) {\n this.id = id;\n this.move(x, y);\n }\n move (x, y) {\n this.x = x;\n this.y = y;\n }\n}\n```\n\nES5语法\n``` javascript\nvar Shape = function (id, x, y) {\n this.id = id;\n this.move(x, y);\n};\nShape.prototype.move = function (x, y) {\n this.x = x;\n this.y = y;\n};\n```\n\n上面ES6代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Shape,对应 ES6 的Shape类的构造方法。Shape类除了构造方法,还定义了一个move方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。\n\n#### Class Inheritance\n\nES6语法\n\n``` javascript\nclass Shape {\n constructor (id, x, y) {\n this.id = id;\n this.move(x, y);\n }\n move (x, y) {\n this.x = x;\n this.y = y;\n }\n}\nclass Rectangle extends Shape {\n constructor (id, x, y, width, height) {\n super(id, x, y);\n this.width = width;\n this.height = height;\n }\n}\nclass Circle extends Shape {\n constructor (id, x, y, radius) {\n super(id, x, y);\n this.radius = radius;\n }\n}\n```\n\nES5语法\n``` javascript\nvar Shape = function (id, x, y) {\n this.id = id;\n this.move(x, y);\n};\nShape.prototype.move = function (x, y) {\n this.x = x;\n this.y = y;\n};\nvar Rectangle = function (id, x, y, width, height) {\n Shape.call(this, id, x, y);\n this.width = width;\n this.height = height;\n};\nRectangle.prototype = Object.create(Shape.prototype);\nRectangle.prototype.constructor = Rectangle;\nvar Circle = function (id, x, y, radius) {\n Shape.call(this, id, x, y);\n this.radius = radius;\n};\nCircle.prototype = Object.create(Shape.prototype);\nCircle.prototype.constructor = Circle;\n```\n\n上面的ES6代码定义了一个Rectangle类和一个Circle类,它们通过extends关键字,继承了Shape类的所有属性和方法。子类里都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。对照ES5语法我们可以发现使用class语法更简洁明了。\n\n## 插件推荐\n\n- [whatruns](https://www.whatruns.com/)\n\n这个chrome插件可以查看网站,包括但不限于web框架、web服务器、js框架、js图表插件、字体、CDN。可以很方便的查看你感兴趣的网站所使用的技术。直接在chrome\b扩展商店里面搜whatruns就能安装。\n\n## 文章推荐\n- [美团外卖前端可视化界面组装平台](https://zhuanlan.zhihu.com/p/27288444) \n前端如何才能提高生产效率,普遍的共识是要做到组件化开发,很多团队已经这样做了。虽然很多的产品已经实现了组件化开发,但不同产品间依然存在很多重复的劳动,比如登录框、导航等等。这里推荐一篇美团外卖在效率方面尝试的一个解决方案。\n\n- [如何处理 JavaScript 内存泄露](https://mp.weixin.qq.com/s?__biz=MzA4NjE3MDg4OQ==&mid=2650965216&idx=1&sn=758f45497eb1755c84de7c4afbd494eb&chksm=843ae886b34d6190e9c720c495952b8c7e045e6af40b35c5192d1f0450856f4d44c2536a970d&mpshare=1&scene=1&srcid=1001pdkcvIK6jOSK62fc15aq#)\n讨论开发者容易忽视的重要主题 :内存管理。文章也提供一些关于如何处理JavaScript内存泄露的技巧。在SessionStack,我们需要确保不会造成内存泄露或者不会增加我们集成的Web应用的内存消耗。\n\n- [反击爬虫,前端工程师的脑洞可以有多大?](https://juejin.im/entry/59deb55951882578c2084a63)\n关于反击爬虫,本文给了很多前端反爬虫例子;\n真的感叹为了反爬虫,前段工程师真的费尽心思,脑洞大开!\n\n- [Promise 异步流程控制](http://web.jobbole.com/92605/)\n网页中预加载20张图片资源,分步加载,一次加载10张,两次完成,怎么控制图片请求的并发,怎样感知当前异步请求是否已完成?\n\n- [设计模式之观察者模式](http://www.cnblogs.com/TomXu/archive/2012/03/02/2355128.html)\n观察者模式是一种常用的设置模式。文中提供了多种实现观察者模式的方式,并带有调用方式。可作为实现观察者模式的源码和研究观察者模式使用。\n\n- [用 threejs 制作一款简单的赛车游戏](http://www.alloyteam.com/2017/09/13139/)\n通过学习本教程,可以熟悉 `webgl` 和 `threejs` 相关的知识。\n\n- [使用 SRI 增强 localStorage 代码安全](https://imququ.com/post/enhance-security-for-ls-code.html)\n大部分 Web 应用从 localStorage 中获取缓存代码后,没有任何检测机制,直接执行。而 localStorage 是跨页面的,同域下任何页面有 XSS 漏洞,就可以被攻击者用来往 localStorage 写入恶意代码,可以使用 SRI 增强 localStorage 代码安全。\n\n- [浏览器缓存机制小结](http://mp.weixin.qq.com/s/a7UtcAUnifrNCzegfDYaig)\n本文总结了浏览器缓存的基本机制,将各种情况分为:强缓存和协商缓存两种方式。对三组核心的HTTP请求以及响应头参数:cache-control和expire, last-modified和if-modified-since,etag和if-none-matched,做了清晰的解释,很好理解它们之间的区别、优先级等关系。\n\n- [HTTP 缓存机制一二三](https://zhuanlan.zhihu.com/p/29750583)\n作为前端,常与请求打交道,HTTP缓存应该作为基本知识储备。文章介绍了强缓存和协商缓存,响应头各个字段的含义简单了解下,具体业务需要后端配合设置。\n\n- [如何优雅的在 koa 中处理错误](https://yq.aliyun.com/articles/8539?spm=5176.100240.searchblog.8.u2w8qY)\n软件开发时,有 80% 的代码在处理各种错误。 ——某著名开发者 想让自己的代码健壮,错误处理是必不可少的。这篇文章将主要介绍 koa 框架中错误处理的实现(其实主要是 co 的实现),使用 koa 框架开发 web 应用时进行错误处理的一些方法。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","slug":"weekly-16","published":1,"updated":"2017-11-10T07:40:52.988Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qko000ajrs6g2wujbmh","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"ES6中的class语法\"><a href=\"#ES6中的class语法\" class=\"headerlink\" title=\"ES6中的class语法\"></a>ES6中的<code>class</code>语法</h3><p>JavaScript 语言中,生成实例对象的传统方法是通过构造函数。这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大。ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。</p>\n<h4 id=\"Class-Definition\"><a href=\"#Class-Definition\" class=\"headerlink\" title=\"Class Definition\"></a>Class Definition</h4><p>ES6语法</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> move (x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>ES5语法<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> Shape = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\">};</span><br><span class=\"line\">Shape.prototype.move = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<p>上面ES6代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Shape,对应 ES6 的Shape类的构造方法。Shape类除了构造方法,还定义了一个move方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。</p>\n<h4 id=\"Class-Inheritance\"><a href=\"#Class-Inheritance\" class=\"headerlink\" title=\"Class Inheritance\"></a>Class Inheritance</h4><p>ES6语法</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> move (x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Rectangle</span> <span class=\"keyword\">extends</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y, width, height) {</span><br><span class=\"line\"> <span class=\"keyword\">super</span>(id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.width = width;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.height = height;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Circle</span> <span class=\"keyword\">extends</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y, radius) {</span><br><span class=\"line\"> <span class=\"keyword\">super</span>(id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.radius = radius;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>ES5语法<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> Shape = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\">};</span><br><span class=\"line\">Shape.prototype.move = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"keyword\">var</span> Rectangle = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y, width, height</span>) </span>{</span><br><span class=\"line\"> Shape.call(<span class=\"keyword\">this</span>, id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.width = width;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.height = height;</span><br><span class=\"line\">};</span><br><span class=\"line\">Rectangle.prototype = <span class=\"built_in\">Object</span>.create(Shape.prototype);</span><br><span class=\"line\">Rectangle.prototype.constructor = Rectangle;</span><br><span class=\"line\"><span class=\"keyword\">var</span> Circle = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y, radius</span>) </span>{</span><br><span class=\"line\"> Shape.call(<span class=\"keyword\">this</span>, id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.radius = radius;</span><br><span class=\"line\">};</span><br><span class=\"line\">Circle.prototype = <span class=\"built_in\">Object</span>.create(Shape.prototype);</span><br><span class=\"line\">Circle.prototype.constructor = Circle;</span><br></pre></td></tr></table></figure></p>\n<p>上面的ES6代码定义了一个Rectangle类和一个Circle类,它们通过extends关键字,继承了Shape类的所有属性和方法。子类里都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。对照ES5语法我们可以发现使用class语法更简洁明了。</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://www.whatruns.com/\" target=\"_blank\" rel=\"noopener\">whatruns</a></li>\n</ul>\n<p>这个chrome插件可以查看网站,包括但不限于web框架、web服务器、js框架、js图表插件、字体、CDN。可以很方便的查看你感兴趣的网站所使用的技术。直接在chrome\b扩展商店里面搜whatruns就能安装。</p>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27288444\" target=\"_blank\" rel=\"noopener\">美团外卖前端可视化界面组装平台</a><br>前端如何才能提高生产效率,普遍的共识是要做到组件化开发,很多团队已经这样做了。虽然很多的产品已经实现了组件化开发,但不同产品间依然存在很多重复的劳动,比如登录框、导航等等。这里推荐一篇美团外卖在效率方面尝试的一个解决方案。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzA4NjE3MDg4OQ==&mid=2650965216&idx=1&sn=758f45497eb1755c84de7c4afbd494eb&chksm=843ae886b34d6190e9c720c495952b8c7e045e6af40b35c5192d1f0450856f4d44c2536a970d&mpshare=1&scene=1&srcid=1001pdkcvIK6jOSK62fc15aq#\" target=\"_blank\" rel=\"noopener\">如何处理 JavaScript 内存泄露</a><br>讨论开发者容易忽视的重要主题 :内存管理。文章也提供一些关于如何处理JavaScript内存泄露的技巧。在SessionStack,我们需要确保不会造成内存泄露或者不会增加我们集成的Web应用的内存消耗。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/59deb55951882578c2084a63\" target=\"_blank\" rel=\"noopener\">反击爬虫,前端工程师的脑洞可以有多大?</a><br>关于反击爬虫,本文给了很多前端反爬虫例子;<br>真的感叹为了反爬虫,前段工程师真的费尽心思,脑洞大开!</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92605/\" target=\"_blank\" rel=\"noopener\">Promise 异步流程控制</a><br>网页中预加载20张图片资源,分步加载,一次加载10张,两次完成,怎么控制图片请求的并发,怎样感知当前异步请求是否已完成?</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/TomXu/archive/2012/03/02/2355128.html\" target=\"_blank\" rel=\"noopener\">设计模式之观察者模式</a><br>观察者模式是一种常用的设置模式。文中提供了多种实现观察者模式的方式,并带有调用方式。可作为实现观察者模式的源码和研究观察者模式使用。</p>\n</li>\n<li><p><a href=\"http://www.alloyteam.com/2017/09/13139/\" target=\"_blank\" rel=\"noopener\">用 threejs 制作一款简单的赛车游戏</a><br>通过学习本教程,可以熟悉 <code>webgl</code> 和 <code>threejs</code> 相关的知识。</p>\n</li>\n<li><p><a href=\"https://imququ.com/post/enhance-security-for-ls-code.html\" target=\"_blank\" rel=\"noopener\">使用 SRI 增强 localStorage 代码安全</a><br>大部分 Web 应用从 localStorage 中获取缓存代码后,没有任何检测机制,直接执行。而 localStorage 是跨页面的,同域下任何页面有 XSS 漏洞,就可以被攻击者用来往 localStorage 写入恶意代码,可以使用 SRI 增强 localStorage 代码安全。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/a7UtcAUnifrNCzegfDYaig\" target=\"_blank\" rel=\"noopener\">浏览器缓存机制小结</a><br>本文总结了浏览器缓存的基本机制,将各种情况分为:强缓存和协商缓存两种方式。对三组核心的HTTP请求以及响应头参数:cache-control和expire, last-modified和if-modified-since,etag和if-none-matched,做了清晰的解释,很好理解它们之间的区别、优先级等关系。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29750583\" target=\"_blank\" rel=\"noopener\">HTTP 缓存机制一二三</a><br>作为前端,常与请求打交道,HTTP缓存应该作为基本知识储备。文章介绍了强缓存和协商缓存,响应头各个字段的含义简单了解下,具体业务需要后端配合设置。</p>\n</li>\n<li><p><a href=\"https://yq.aliyun.com/articles/8539?spm=5176.100240.searchblog.8.u2w8qY\" target=\"_blank\" rel=\"noopener\">如何优雅的在 koa 中处理错误</a><br>软件开发时,有 80% 的代码在处理各种错误。 ——某著名开发者 想让自己的代码健壮,错误处理是必不可少的。这篇文章将主要介绍 koa 框架中错误处理的实现(其实主要是 co 的实现),使用 koa 框架开发 web 应用时进行错误处理的一些方法。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"ES6中的class语法\"><a href=\"#ES6中的class语法\" class=\"headerlink\" title=\"ES6中的class语法\"></a>ES6中的<code>class</code>语法</h3><p>JavaScript 语言中,生成实例对象的传统方法是通过构造函数。这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大。ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。</p>\n<h4 id=\"Class-Definition\"><a href=\"#Class-Definition\" class=\"headerlink\" title=\"Class Definition\"></a>Class Definition</h4><p>ES6语法</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> move (x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>ES5语法<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> Shape = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\">};</span><br><span class=\"line\">Shape.prototype.move = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure></p>\n<p>上面ES6代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Shape,对应 ES6 的Shape类的构造方法。Shape类除了构造方法,还定义了一个move方法。注意,定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。</p>\n<h4 id=\"Class-Inheritance\"><a href=\"#Class-Inheritance\" class=\"headerlink\" title=\"Class Inheritance\"></a>Class Inheritance</h4><p>ES6语法</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> move (x, y) {</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Rectangle</span> <span class=\"keyword\">extends</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y, width, height) {</span><br><span class=\"line\"> <span class=\"keyword\">super</span>(id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.width = width;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.height = height;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"><span class=\"class\"><span class=\"keyword\">class</span> <span class=\"title\">Circle</span> <span class=\"keyword\">extends</span> <span class=\"title\">Shape</span> </span>{</span><br><span class=\"line\"> <span class=\"keyword\">constructor</span> (id, x, y, radius) {</span><br><span class=\"line\"> <span class=\"keyword\">super</span>(id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.radius = radius;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>ES5语法<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">var</span> Shape = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.id = id;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.move(x, y);</span><br><span class=\"line\">};</span><br><span class=\"line\">Shape.prototype.move = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">x, y</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.x = x;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.y = y;</span><br><span class=\"line\">};</span><br><span class=\"line\"><span class=\"keyword\">var</span> Rectangle = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y, width, height</span>) </span>{</span><br><span class=\"line\"> Shape.call(<span class=\"keyword\">this</span>, id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.width = width;</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.height = height;</span><br><span class=\"line\">};</span><br><span class=\"line\">Rectangle.prototype = <span class=\"built_in\">Object</span>.create(Shape.prototype);</span><br><span class=\"line\">Rectangle.prototype.constructor = Rectangle;</span><br><span class=\"line\"><span class=\"keyword\">var</span> Circle = <span class=\"function\"><span class=\"keyword\">function</span> (<span class=\"params\">id, x, y, radius</span>) </span>{</span><br><span class=\"line\"> Shape.call(<span class=\"keyword\">this</span>, id, x, y);</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.radius = radius;</span><br><span class=\"line\">};</span><br><span class=\"line\">Circle.prototype = <span class=\"built_in\">Object</span>.create(Shape.prototype);</span><br><span class=\"line\">Circle.prototype.constructor = Circle;</span><br></pre></td></tr></table></figure></p>\n<p>上面的ES6代码定义了一个Rectangle类和一个Circle类,它们通过extends关键字,继承了Shape类的所有属性和方法。子类里都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。对照ES5语法我们可以发现使用class语法更简洁明了。</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://www.whatruns.com/\" target=\"_blank\" rel=\"noopener\">whatruns</a></li>\n</ul>\n<p>这个chrome插件可以查看网站,包括但不限于web框架、web服务器、js框架、js图表插件、字体、CDN。可以很方便的查看你感兴趣的网站所使用的技术。直接在chrome\b扩展商店里面搜whatruns就能安装。</p>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27288444\" target=\"_blank\" rel=\"noopener\">美团外卖前端可视化界面组装平台</a><br>前端如何才能提高生产效率,普遍的共识是要做到组件化开发,很多团队已经这样做了。虽然很多的产品已经实现了组件化开发,但不同产品间依然存在很多重复的劳动,比如登录框、导航等等。这里推荐一篇美团外卖在效率方面尝试的一个解决方案。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzA4NjE3MDg4OQ==&mid=2650965216&idx=1&sn=758f45497eb1755c84de7c4afbd494eb&chksm=843ae886b34d6190e9c720c495952b8c7e045e6af40b35c5192d1f0450856f4d44c2536a970d&mpshare=1&scene=1&srcid=1001pdkcvIK6jOSK62fc15aq#\" target=\"_blank\" rel=\"noopener\">如何处理 JavaScript 内存泄露</a><br>讨论开发者容易忽视的重要主题 :内存管理。文章也提供一些关于如何处理JavaScript内存泄露的技巧。在SessionStack,我们需要确保不会造成内存泄露或者不会增加我们集成的Web应用的内存消耗。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/59deb55951882578c2084a63\" target=\"_blank\" rel=\"noopener\">反击爬虫,前端工程师的脑洞可以有多大?</a><br>关于反击爬虫,本文给了很多前端反爬虫例子;<br>真的感叹为了反爬虫,前段工程师真的费尽心思,脑洞大开!</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92605/\" target=\"_blank\" rel=\"noopener\">Promise 异步流程控制</a><br>网页中预加载20张图片资源,分步加载,一次加载10张,两次完成,怎么控制图片请求的并发,怎样感知当前异步请求是否已完成?</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/TomXu/archive/2012/03/02/2355128.html\" target=\"_blank\" rel=\"noopener\">设计模式之观察者模式</a><br>观察者模式是一种常用的设置模式。文中提供了多种实现观察者模式的方式,并带有调用方式。可作为实现观察者模式的源码和研究观察者模式使用。</p>\n</li>\n<li><p><a href=\"http://www.alloyteam.com/2017/09/13139/\" target=\"_blank\" rel=\"noopener\">用 threejs 制作一款简单的赛车游戏</a><br>通过学习本教程,可以熟悉 <code>webgl</code> 和 <code>threejs</code> 相关的知识。</p>\n</li>\n<li><p><a href=\"https://imququ.com/post/enhance-security-for-ls-code.html\" target=\"_blank\" rel=\"noopener\">使用 SRI 增强 localStorage 代码安全</a><br>大部分 Web 应用从 localStorage 中获取缓存代码后,没有任何检测机制,直接执行。而 localStorage 是跨页面的,同域下任何页面有 XSS 漏洞,就可以被攻击者用来往 localStorage 写入恶意代码,可以使用 SRI 增强 localStorage 代码安全。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/a7UtcAUnifrNCzegfDYaig\" target=\"_blank\" rel=\"noopener\">浏览器缓存机制小结</a><br>本文总结了浏览器缓存的基本机制,将各种情况分为:强缓存和协商缓存两种方式。对三组核心的HTTP请求以及响应头参数:cache-control和expire, last-modified和if-modified-since,etag和if-none-matched,做了清晰的解释,很好理解它们之间的区别、优先级等关系。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29750583\" target=\"_blank\" rel=\"noopener\">HTTP 缓存机制一二三</a><br>作为前端,常与请求打交道,HTTP缓存应该作为基本知识储备。文章介绍了强缓存和协商缓存,响应头各个字段的含义简单了解下,具体业务需要后端配合设置。</p>\n</li>\n<li><p><a href=\"https://yq.aliyun.com/articles/8539?spm=5176.100240.searchblog.8.u2w8qY\" target=\"_blank\" rel=\"noopener\">如何优雅的在 koa 中处理错误</a><br>软件开发时,有 80% 的代码在处理各种错误。 ——某著名开发者 想让自己的代码健壮,错误处理是必不可少的。这篇文章将主要介绍 koa 框架中错误处理的实现(其实主要是 co 的实现),使用 koa 框架开发 web 应用时进行错误处理的一些方法。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第2期 (本期小编:胡国伟)","date":"2017-06-30T03:18:25.000Z","_content":"\n## 基础\n* [Class 的基本语法](http://es6.ruanyifeng.com/#docs/class)\n尽管基本上,`ES6`的`class`可以看作只是一个语法糖,但使得`JavaScript`对象原型的写法更加清晰、更像面向对象编程的语法,更接近传统语言的写法。\n\n* [Module 的语法](http://es6.ruanyifeng.com/#docs/module)\n相交于社区提供了各种模块化解决方案,`ES6`语言标准的层面上实现了模块功能,成为浏览器和服务器通用的模块解决方案。\n\n* [数组的扩展](http://es6.ruanyifeng.com/#docs/array)\n`ES6`内置新数组方法,无需再自己再实现相应的`polyfill`了,赶紧学习充能,搭配[该文(*【深度长文】JavaScript数组所有API全解密*)](http://louiszhai.github.io/2017/04/28/array/)食用,更易消化。\n\n* [webpack 中文](https://webpack-china.org/)\n旧版的`webpack`官方文档有些糟糕,幸好后来有了新版,并且还有志愿者维护了相对应的中文版本,这下查阅学习就更轻松了。近日`webpack 3.0` 已经释出,大家赶快跟进。\n\n* [EditorConfig使用介绍](https://segmentfault.com/a/1190000007599845)\n团队合作,统一编辑器行为非常必要,本文对`EditorConfig`中的配置进行了讲解。\nps:[EditorConfig](http://editorconfig.org/)规范在这里。\n\n## 文章\n\n* 1. [Server-Sent Events 教程](http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html)\n 2. [WebSocket 教程](http://www.ruanyifeng.com/blog/2017/05/websocket.html) <br/>\n这两篇文章一起读,就可以很全面的了解现代浏览器和服务器通信技术。\n\n* [深入理解 JavaScript 异步](https://github.com/wangfupeng1988/js-async-tutorial)\n这个系列文章把异步方面的知识以及原理讲解的比较清楚,从传统的方式到`promise`到`generator`到`async`,值得一读。\n\n* [koa2从起步到填坑](http://www.jianshu.com/p/6b816c609669)\n比较系统简介`koa2`使用,包含一些例子,可以让人更快上手。\n\n* [现代前端科技解析 —— 数据响应式系统](https://www.404forest.com/2017/06/28/modern-web-development-tech-analysis-data-reactivity-system/)\n文章讲解数据响应式系统及其构建,分步骤实现了`vue2.0`的响应式,还有详细的代码示例及注释。\n\n* [关于前端开发谈谈单元测试](https://segmentfault.com/a/1190000000317146)\n阐述了做单元测试的必要性,\n着重介绍了`Jasmine`的常用语法,\n并对其他流行测试框架和工具做了介绍。\n\n* [Three.js入门指南](http://www.ituring.com.cn/book/1272)\n关于`Three.js`中文文章资料还是不够丰富,以至于这本免费小书时至今日还是`Three.js`入门的最佳选择之一。\n\n* 1. [测试你的前端代码 – part1(介绍篇)](https://mp.weixin.qq.com/s/jUJXmis0_u6BzQDT2mCltA)\n 2. [测试你的前端代码 – part2(单元测试)](https://mp.weixin.qq.com/s/pYUePHOsZegMf4MmJCoJeA)\n 3. [测试你的前端代码 – part3(端到端测试)](https://mp.weixin.qq.com/s/8UfR8bsPd2bkmPg_xkAKKg)\n 4. [测试你的前端代码 – part4(集成测试)](https://mp.weixin.qq.com/s/CpNUn5AWbP4aH0yirwuizQ)\n<br>\n文章由浅入深的介绍前端工程的测试,覆盖单元测试、端到端测试、集成测试,较为简单的事例介绍有利于你快速掌握这些知识。\n\n* [学用 JavaScript 设计模式](http://www.oschina.net/translate/learning-javascript-design-patterns?cmp)\n文章讲解数据响应式系统及其构建,分步骤实现了 vue2.0的响应式,还有详细的代码示例及注释。\n","source":"_posts/weekly-2.md","raw":"---\ntitle: 大前端周刊 第2期 (本期小编:胡国伟)\ndate: 2017-06-30 11:18:25\ntags: [weekly,框架,测试,设计模式,three.js]\n---\n\n## 基础\n* [Class 的基本语法](http://es6.ruanyifeng.com/#docs/class)\n尽管基本上,`ES6`的`class`可以看作只是一个语法糖,但使得`JavaScript`对象原型的写法更加清晰、更像面向对象编程的语法,更接近传统语言的写法。\n\n* [Module 的语法](http://es6.ruanyifeng.com/#docs/module)\n相交于社区提供了各种模块化解决方案,`ES6`语言标准的层面上实现了模块功能,成为浏览器和服务器通用的模块解决方案。\n\n* [数组的扩展](http://es6.ruanyifeng.com/#docs/array)\n`ES6`内置新数组方法,无需再自己再实现相应的`polyfill`了,赶紧学习充能,搭配[该文(*【深度长文】JavaScript数组所有API全解密*)](http://louiszhai.github.io/2017/04/28/array/)食用,更易消化。\n\n* [webpack 中文](https://webpack-china.org/)\n旧版的`webpack`官方文档有些糟糕,幸好后来有了新版,并且还有志愿者维护了相对应的中文版本,这下查阅学习就更轻松了。近日`webpack 3.0` 已经释出,大家赶快跟进。\n\n* [EditorConfig使用介绍](https://segmentfault.com/a/1190000007599845)\n团队合作,统一编辑器行为非常必要,本文对`EditorConfig`中的配置进行了讲解。\nps:[EditorConfig](http://editorconfig.org/)规范在这里。\n\n## 文章\n\n* 1. [Server-Sent Events 教程](http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html)\n 2. [WebSocket 教程](http://www.ruanyifeng.com/blog/2017/05/websocket.html) <br/>\n这两篇文章一起读,就可以很全面的了解现代浏览器和服务器通信技术。\n\n* [深入理解 JavaScript 异步](https://github.com/wangfupeng1988/js-async-tutorial)\n这个系列文章把异步方面的知识以及原理讲解的比较清楚,从传统的方式到`promise`到`generator`到`async`,值得一读。\n\n* [koa2从起步到填坑](http://www.jianshu.com/p/6b816c609669)\n比较系统简介`koa2`使用,包含一些例子,可以让人更快上手。\n\n* [现代前端科技解析 —— 数据响应式系统](https://www.404forest.com/2017/06/28/modern-web-development-tech-analysis-data-reactivity-system/)\n文章讲解数据响应式系统及其构建,分步骤实现了`vue2.0`的响应式,还有详细的代码示例及注释。\n\n* [关于前端开发谈谈单元测试](https://segmentfault.com/a/1190000000317146)\n阐述了做单元测试的必要性,\n着重介绍了`Jasmine`的常用语法,\n并对其他流行测试框架和工具做了介绍。\n\n* [Three.js入门指南](http://www.ituring.com.cn/book/1272)\n关于`Three.js`中文文章资料还是不够丰富,以至于这本免费小书时至今日还是`Three.js`入门的最佳选择之一。\n\n* 1. [测试你的前端代码 – part1(介绍篇)](https://mp.weixin.qq.com/s/jUJXmis0_u6BzQDT2mCltA)\n 2. [测试你的前端代码 – part2(单元测试)](https://mp.weixin.qq.com/s/pYUePHOsZegMf4MmJCoJeA)\n 3. [测试你的前端代码 – part3(端到端测试)](https://mp.weixin.qq.com/s/8UfR8bsPd2bkmPg_xkAKKg)\n 4. [测试你的前端代码 – part4(集成测试)](https://mp.weixin.qq.com/s/CpNUn5AWbP4aH0yirwuizQ)\n<br>\n文章由浅入深的介绍前端工程的测试,覆盖单元测试、端到端测试、集成测试,较为简单的事例介绍有利于你快速掌握这些知识。\n\n* [学用 JavaScript 设计模式](http://www.oschina.net/translate/learning-javascript-design-patterns?cmp)\n文章讲解数据响应式系统及其构建,分步骤实现了 vue2.0的响应式,还有详细的代码示例及注释。\n","slug":"weekly-2","published":1,"updated":"2017-08-25T02:32:26.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkp000bjrs6ta6bve1y","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/class\" target=\"_blank\" rel=\"noopener\">Class 的基本语法</a><br>尽管基本上,<code>ES6</code>的<code>class</code>可以看作只是一个语法糖,但使得<code>JavaScript</code>对象原型的写法更加清晰、更像面向对象编程的语法,更接近传统语言的写法。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/module\" target=\"_blank\" rel=\"noopener\">Module 的语法</a><br>相交于社区提供了各种模块化解决方案,<code>ES6</code>语言标准的层面上实现了模块功能,成为浏览器和服务器通用的模块解决方案。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/array\" target=\"_blank\" rel=\"noopener\">数组的扩展</a><br><code>ES6</code>内置新数组方法,无需再自己再实现相应的<code>polyfill</code>了,赶紧学习充能,搭配<a href=\"http://louiszhai.github.io/2017/04/28/array/\" target=\"_blank\" rel=\"noopener\">该文(<em>【深度长文】JavaScript数组所有API全解密</em>)</a>食用,更易消化。</p>\n</li>\n<li><p><a href=\"https://webpack-china.org/\" target=\"_blank\" rel=\"noopener\">webpack 中文</a><br>旧版的<code>webpack</code>官方文档有些糟糕,幸好后来有了新版,并且还有志愿者维护了相对应的中文版本,这下查阅学习就更轻松了。近日<code>webpack 3.0</code> 已经释出,大家赶快跟进。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000007599845\" target=\"_blank\" rel=\"noopener\">EditorConfig使用介绍</a><br>团队合作,统一编辑器行为非常必要,本文对<code>EditorConfig</code>中的配置进行了讲解。<br>ps:<a href=\"http://editorconfig.org/\" target=\"_blank\" rel=\"noopener\">EditorConfig</a>规范在这里。</p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><ol>\n<li><a href=\"http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html\" target=\"_blank\" rel=\"noopener\">Server-Sent Events 教程</a></li>\n<li><a href=\"http://www.ruanyifeng.com/blog/2017/05/websocket.html\" target=\"_blank\" rel=\"noopener\">WebSocket 教程</a> <br><br>这两篇文章一起读,就可以很全面的了解现代浏览器和服务器通信技术。</li>\n</ol>\n</li>\n<li><p><a href=\"https://github.com/wangfupeng1988/js-async-tutorial\" target=\"_blank\" rel=\"noopener\">深入理解 JavaScript 异步</a><br>这个系列文章把异步方面的知识以及原理讲解的比较清楚,从传统的方式到<code>promise</code>到<code>generator</code>到<code>async</code>,值得一读。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/6b816c609669\" target=\"_blank\" rel=\"noopener\">koa2从起步到填坑</a><br>比较系统简介<code>koa2</code>使用,包含一些例子,可以让人更快上手。</p>\n</li>\n<li><p><a href=\"https://www.404forest.com/2017/06/28/modern-web-development-tech-analysis-data-reactivity-system/\" target=\"_blank\" rel=\"noopener\">现代前端科技解析 —— 数据响应式系统</a><br>文章讲解数据响应式系统及其构建,分步骤实现了<code>vue2.0</code>的响应式,还有详细的代码示例及注释。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000000317146\" target=\"_blank\" rel=\"noopener\">关于前端开发谈谈单元测试</a><br>阐述了做单元测试的必要性,<br>着重介绍了<code>Jasmine</code>的常用语法,<br>并对其他流行测试框架和工具做了介绍。</p>\n</li>\n<li><p><a href=\"http://www.ituring.com.cn/book/1272\" target=\"_blank\" rel=\"noopener\">Three.js入门指南</a><br>关于<code>Three.js</code>中文文章资料还是不够丰富,以至于这本免费小书时至今日还是<code>Three.js</code>入门的最佳选择之一。</p>\n</li>\n<li><ol>\n<li><a href=\"https://mp.weixin.qq.com/s/jUJXmis0_u6BzQDT2mCltA\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part1(介绍篇)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/pYUePHOsZegMf4MmJCoJeA\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part2(单元测试)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/8UfR8bsPd2bkmPg_xkAKKg\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part3(端到端测试)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/CpNUn5AWbP4aH0yirwuizQ\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part4(集成测试)</a><br><br><br>文章由浅入深的介绍前端工程的测试,覆盖单元测试、端到端测试、集成测试,较为简单的事例介绍有利于你快速掌握这些知识。</li>\n</ol>\n</li>\n<li><p><a href=\"http://www.oschina.net/translate/learning-javascript-design-patterns?cmp\" target=\"_blank\" rel=\"noopener\">学用 JavaScript 设计模式</a><br>文章讲解数据响应式系统及其构建,分步骤实现了 vue2.0的响应式,还有详细的代码示例及注释。</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/class\" target=\"_blank\" rel=\"noopener\">Class 的基本语法</a><br>尽管基本上,<code>ES6</code>的<code>class</code>可以看作只是一个语法糖,但使得<code>JavaScript</code>对象原型的写法更加清晰、更像面向对象编程的语法,更接近传统语言的写法。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/module\" target=\"_blank\" rel=\"noopener\">Module 的语法</a><br>相交于社区提供了各种模块化解决方案,<code>ES6</code>语言标准的层面上实现了模块功能,成为浏览器和服务器通用的模块解决方案。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/array\" target=\"_blank\" rel=\"noopener\">数组的扩展</a><br><code>ES6</code>内置新数组方法,无需再自己再实现相应的<code>polyfill</code>了,赶紧学习充能,搭配<a href=\"http://louiszhai.github.io/2017/04/28/array/\" target=\"_blank\" rel=\"noopener\">该文(<em>【深度长文】JavaScript数组所有API全解密</em>)</a>食用,更易消化。</p>\n</li>\n<li><p><a href=\"https://webpack-china.org/\" target=\"_blank\" rel=\"noopener\">webpack 中文</a><br>旧版的<code>webpack</code>官方文档有些糟糕,幸好后来有了新版,并且还有志愿者维护了相对应的中文版本,这下查阅学习就更轻松了。近日<code>webpack 3.0</code> 已经释出,大家赶快跟进。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000007599845\" target=\"_blank\" rel=\"noopener\">EditorConfig使用介绍</a><br>团队合作,统一编辑器行为非常必要,本文对<code>EditorConfig</code>中的配置进行了讲解。<br>ps:<a href=\"http://editorconfig.org/\" target=\"_blank\" rel=\"noopener\">EditorConfig</a>规范在这里。</p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><ol>\n<li><a href=\"http://www.ruanyifeng.com/blog/2017/05/server-sent_events.html\" target=\"_blank\" rel=\"noopener\">Server-Sent Events 教程</a></li>\n<li><a href=\"http://www.ruanyifeng.com/blog/2017/05/websocket.html\" target=\"_blank\" rel=\"noopener\">WebSocket 教程</a> <br><br>这两篇文章一起读,就可以很全面的了解现代浏览器和服务器通信技术。</li>\n</ol>\n</li>\n<li><p><a href=\"https://github.com/wangfupeng1988/js-async-tutorial\" target=\"_blank\" rel=\"noopener\">深入理解 JavaScript 异步</a><br>这个系列文章把异步方面的知识以及原理讲解的比较清楚,从传统的方式到<code>promise</code>到<code>generator</code>到<code>async</code>,值得一读。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/6b816c609669\" target=\"_blank\" rel=\"noopener\">koa2从起步到填坑</a><br>比较系统简介<code>koa2</code>使用,包含一些例子,可以让人更快上手。</p>\n</li>\n<li><p><a href=\"https://www.404forest.com/2017/06/28/modern-web-development-tech-analysis-data-reactivity-system/\" target=\"_blank\" rel=\"noopener\">现代前端科技解析 —— 数据响应式系统</a><br>文章讲解数据响应式系统及其构建,分步骤实现了<code>vue2.0</code>的响应式,还有详细的代码示例及注释。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000000317146\" target=\"_blank\" rel=\"noopener\">关于前端开发谈谈单元测试</a><br>阐述了做单元测试的必要性,<br>着重介绍了<code>Jasmine</code>的常用语法,<br>并对其他流行测试框架和工具做了介绍。</p>\n</li>\n<li><p><a href=\"http://www.ituring.com.cn/book/1272\" target=\"_blank\" rel=\"noopener\">Three.js入门指南</a><br>关于<code>Three.js</code>中文文章资料还是不够丰富,以至于这本免费小书时至今日还是<code>Three.js</code>入门的最佳选择之一。</p>\n</li>\n<li><ol>\n<li><a href=\"https://mp.weixin.qq.com/s/jUJXmis0_u6BzQDT2mCltA\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part1(介绍篇)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/pYUePHOsZegMf4MmJCoJeA\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part2(单元测试)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/8UfR8bsPd2bkmPg_xkAKKg\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part3(端到端测试)</a></li>\n<li><a href=\"https://mp.weixin.qq.com/s/CpNUn5AWbP4aH0yirwuizQ\" target=\"_blank\" rel=\"noopener\">测试你的前端代码 – part4(集成测试)</a><br><br><br>文章由浅入深的介绍前端工程的测试,覆盖单元测试、端到端测试、集成测试,较为简单的事例介绍有利于你快速掌握这些知识。</li>\n</ol>\n</li>\n<li><p><a href=\"http://www.oschina.net/translate/learning-javascript-design-patterns?cmp\" target=\"_blank\" rel=\"noopener\">学用 JavaScript 设计模式</a><br>文章讲解数据响应式系统及其构建,分步骤实现了 vue2.0的响应式,还有详细的代码示例及注释。</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第18期 (本期小编:包京京)","date":"2017-10-27T02:24:12.000Z","_content":"\n## Show me the code\n\n### 用Javascript学习数据结构之栈(Stack)\n\n栈(Stack)是一种遵循后进先出(LIFO)的有序集合,较新的元素会靠近顶部,较旧的元素会在栈的底部。\n接下来我们正式开始实现栈(Stack)。首先,建立一个Stack类:\n\n\n``` javascript\nfunction Stack() {\n // 类内部定义Stack的属性和方法\n}\n```\n#### 属性:\n1. let items = []; //使用array来存储栈内的元素\n\n#### 方法:\n1. push(elements): 新增一个或者多个元素到栈的顶部\n2. pop(): 移除栈顶部元素,同时返回被移除的元素\n3. peek()或top(): 仅返回stack元素,不做任何修改\n4. isEmpty(): 检查栈是否为空?若无任何元素则返回true,反之返回false\n5. clear(): 清空栈内的所有元素\n6. size(): 返回栈的元素个数\n\n#### 1.push(elements)和pop()\n由于我们使用array当做stack的存储方式,所以我们可以使用array内建的push(element)和pop()方式来实现LIFO的特性,让元素的新增和删除只能发生在尾端。\n``` javascript\nfunction Stack() {\n let items = [];\n this.push = function(element) {\n items.push(element);\n }\n this.pop = function() {\n return items.pop();\n }\n}\n```\n\n#### 2.peek():\n若是我们想知道栈中的最后一个元素(最顶端的元素),我们可以实现peek()方法,返回顶部元素\n``` javascript\nfunction Stack() {\n let items = [];\n this.peek = function() {\n return items[items.length - 1];\n }\n}\n```\n#### 3.isEmpty():\n若我们想知道栈内是否还有元素,我们可以使用isEmpty()来判断\n``` javascript\nfunction Stack() {\n let items = [];\n this.isEmpty = function() {\n return items.length === 0;\n }\n}\n```\n#### 4.clear():\n若我们想清空栈的话,可以使用clear()方法,将所有元素删除\n``` javascript\nfunction Stack() {\n let items = [];\n this.clear = function() {\n items = [];\n }\n}\n```\n#### 5.size():\n通过size()方法我们可以取得栈的大小(共有几个元素)\n``` javascript\nfunction Stack() {\n let items = [];\n this.size = function() {\n return items.length;\n }\n}\n```\n#### 完整代码:\n把上面各种方法放到一起\n``` javascript\nfunction Stack() {\n var items = [];\n this.push = function(element) {\n items.push(element);\n }\n this.pop = function() {\n return items.pop();\n }\n this.peek = function() {\n return items[items.length - 1];\n }\n this.isEmpty = function() {\n return items.length === 0;\n }\n this.clear = function() {\n items = [];\n }\n this.size = function() {\n return items.length;\n }\n // 加入打印方法\n this.print = function() {\n console.log(items.toString());\n }\n}\n```\n## 插件推荐\n\n- [PhantomJS](http://phantomjs.org/)\nPhantomJS可以应用于下面这几个典型场景:无需浏览器的web测试,页面自动化操作,屏幕截图和网络监控等\n\n## 文章推荐\n- [Node.js的事件轮询Event Loop原理解释](http://www.jdon.com/idea/nodejs/event-loop.html)\nEvent Loop是理解Node实现事件驱动、异步高并发服务的关键。这篇文章中解释了下面几个容易被忽略的点: 1. Node.js的底层其实也是有一个线程池的,用来执行各种堵塞操作。2. 一个Event loop的三个基本组件:事件队列、读取事件的轮询线程、以及线程池。3. 各个事件的回调函数是如何激活并执行的。\n\n- [jsonp原理详解](http://www.qdfuns.com/notes/16738/1b6ad6125747d28592a53a960b44c6f4.html)\njsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!\n\n- [this , apply , call , bind详解](https://juejin.im/post/59bfe84351882531b730bac2)\n几个ES5 的坑,this是其中经常搞晕的一个,上一篇通俗且易理解的文章\n\n- [深入理解 Node.js Stream 内部机制](http://taobaofed.org/blog/2017/08/31/nodejs-stream/)\n知其然知其所以然,来了解一下nodejs stream内部机制。\n\n- [基于 Electron 开发客户端产品的体验](https://segmentfault.com/a/1190000011699304)\n基于 Electron 开发的产品非常多,文章主要是针对于如何入门 Electron,可以说是作者开发的总结;非常适合计划使用 Electron的开发者阅读。\n\n- [babel到底该如何配置?](https://juejin.im/post/59ec657ef265da431b6c5b03)\n大家都知道js作为宿主语言,很依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,虽然每年更新的幅度不大,但是每年的提案可不少。babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译(转码+编译)到ES5。\n\n- [CSS 新的长度单位 fr 你知道么?](https://zhuanlan.zhihu.com/p/27502596)\n本文介绍了 CSS Grid 规范中引入的一个新的长度单位 fr,我们一起来看看到底是怎么回事吧!\n\n- [使用 webpack 优化资源](https://qiutc.me/post/resource-optimization-webpack.html)\n本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。\n\n- [SASS用法指南](http://www.ruanyifeng.com/blog/2012/06/sass.html)\n今年TalkingData团队将 CSS 预处理器切换到了 SASS,代码层面只是简单直接的做了风格转换,还没有挖掘出 SASS 更深入的能力。本周推荐一篇 SASS “基础”内容,推荐大家阅读和实践,以提升大家在 CSS 方面的编程能力。\n\n- [VirtualDOM与diff(Vue实现)](https://zhuanlan.zhihu.com/p/29450092)\n我们是不是可以把真实DOM树抽象成一棵以JavaScript对象构成的抽象树,在修改抽象树数据后将抽象树转化成真实DOM重绘到页面上呢?于是虚拟DOM出现了,它是真实DOM的一层抽象,用属性描述真实DOM的各个特性。当它发生变化的时候,就会去修改视图。\n\n- [多“维”优化——前端高并发策略的更深层思考](http://wetest.qq.com/lab/view/316.html)\n一项指标的变好,总少不了相应优化策略的实施。优化并不是简单的一蹴而就,而是个不断迭代与推翻的过程。更深层的优化方案,往往是在某种思维策略之下,对问题场景和基本策略优缺的深刻理解后做出的当下最优的权衡结果——作者导读。\n\n- [Egg 源码解析之 egg-cluster](https://juejin.im/entry/59bcce1b5188257e82676b53)\nNode.js 进程只能运行在一个 CPU 上,而 egg 采用多进程模型,使多核 CPU 的性能发挥到极致,最大程度地榨干服务器资源,进而解决了该问题。egg-cluster 是用于 egg 多进程管理的基础模块,负责底层的 IPC 通道的建立以及处理各进程的通信,本文解析了实现原理,值得一看。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","source":"_posts/weekly-18.md","raw":"---\ntitle: 大前端周刊 第18期 (本期小编:包京京)\ndate: 2017-10-27 10:24:12\ntags:\n---\n\n## Show me the code\n\n### 用Javascript学习数据结构之栈(Stack)\n\n栈(Stack)是一种遵循后进先出(LIFO)的有序集合,较新的元素会靠近顶部,较旧的元素会在栈的底部。\n接下来我们正式开始实现栈(Stack)。首先,建立一个Stack类:\n\n\n``` javascript\nfunction Stack() {\n // 类内部定义Stack的属性和方法\n}\n```\n#### 属性:\n1. let items = []; //使用array来存储栈内的元素\n\n#### 方法:\n1. push(elements): 新增一个或者多个元素到栈的顶部\n2. pop(): 移除栈顶部元素,同时返回被移除的元素\n3. peek()或top(): 仅返回stack元素,不做任何修改\n4. isEmpty(): 检查栈是否为空?若无任何元素则返回true,反之返回false\n5. clear(): 清空栈内的所有元素\n6. size(): 返回栈的元素个数\n\n#### 1.push(elements)和pop()\n由于我们使用array当做stack的存储方式,所以我们可以使用array内建的push(element)和pop()方式来实现LIFO的特性,让元素的新增和删除只能发生在尾端。\n``` javascript\nfunction Stack() {\n let items = [];\n this.push = function(element) {\n items.push(element);\n }\n this.pop = function() {\n return items.pop();\n }\n}\n```\n\n#### 2.peek():\n若是我们想知道栈中的最后一个元素(最顶端的元素),我们可以实现peek()方法,返回顶部元素\n``` javascript\nfunction Stack() {\n let items = [];\n this.peek = function() {\n return items[items.length - 1];\n }\n}\n```\n#### 3.isEmpty():\n若我们想知道栈内是否还有元素,我们可以使用isEmpty()来判断\n``` javascript\nfunction Stack() {\n let items = [];\n this.isEmpty = function() {\n return items.length === 0;\n }\n}\n```\n#### 4.clear():\n若我们想清空栈的话,可以使用clear()方法,将所有元素删除\n``` javascript\nfunction Stack() {\n let items = [];\n this.clear = function() {\n items = [];\n }\n}\n```\n#### 5.size():\n通过size()方法我们可以取得栈的大小(共有几个元素)\n``` javascript\nfunction Stack() {\n let items = [];\n this.size = function() {\n return items.length;\n }\n}\n```\n#### 完整代码:\n把上面各种方法放到一起\n``` javascript\nfunction Stack() {\n var items = [];\n this.push = function(element) {\n items.push(element);\n }\n this.pop = function() {\n return items.pop();\n }\n this.peek = function() {\n return items[items.length - 1];\n }\n this.isEmpty = function() {\n return items.length === 0;\n }\n this.clear = function() {\n items = [];\n }\n this.size = function() {\n return items.length;\n }\n // 加入打印方法\n this.print = function() {\n console.log(items.toString());\n }\n}\n```\n## 插件推荐\n\n- [PhantomJS](http://phantomjs.org/)\nPhantomJS可以应用于下面这几个典型场景:无需浏览器的web测试,页面自动化操作,屏幕截图和网络监控等\n\n## 文章推荐\n- [Node.js的事件轮询Event Loop原理解释](http://www.jdon.com/idea/nodejs/event-loop.html)\nEvent Loop是理解Node实现事件驱动、异步高并发服务的关键。这篇文章中解释了下面几个容易被忽略的点: 1. Node.js的底层其实也是有一个线程池的,用来执行各种堵塞操作。2. 一个Event loop的三个基本组件:事件队列、读取事件的轮询线程、以及线程池。3. 各个事件的回调函数是如何激活并执行的。\n\n- [jsonp原理详解](http://www.qdfuns.com/notes/16738/1b6ad6125747d28592a53a960b44c6f4.html)\njsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!\n\n- [this , apply , call , bind详解](https://juejin.im/post/59bfe84351882531b730bac2)\n几个ES5 的坑,this是其中经常搞晕的一个,上一篇通俗且易理解的文章\n\n- [深入理解 Node.js Stream 内部机制](http://taobaofed.org/blog/2017/08/31/nodejs-stream/)\n知其然知其所以然,来了解一下nodejs stream内部机制。\n\n- [基于 Electron 开发客户端产品的体验](https://segmentfault.com/a/1190000011699304)\n基于 Electron 开发的产品非常多,文章主要是针对于如何入门 Electron,可以说是作者开发的总结;非常适合计划使用 Electron的开发者阅读。\n\n- [babel到底该如何配置?](https://juejin.im/post/59ec657ef265da431b6c5b03)\n大家都知道js作为宿主语言,很依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,虽然每年更新的幅度不大,但是每年的提案可不少。babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译(转码+编译)到ES5。\n\n- [CSS 新的长度单位 fr 你知道么?](https://zhuanlan.zhihu.com/p/27502596)\n本文介绍了 CSS Grid 规范中引入的一个新的长度单位 fr,我们一起来看看到底是怎么回事吧!\n\n- [使用 webpack 优化资源](https://qiutc.me/post/resource-optimization-webpack.html)\n本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。\n\n- [SASS用法指南](http://www.ruanyifeng.com/blog/2012/06/sass.html)\n今年TalkingData团队将 CSS 预处理器切换到了 SASS,代码层面只是简单直接的做了风格转换,还没有挖掘出 SASS 更深入的能力。本周推荐一篇 SASS “基础”内容,推荐大家阅读和实践,以提升大家在 CSS 方面的编程能力。\n\n- [VirtualDOM与diff(Vue实现)](https://zhuanlan.zhihu.com/p/29450092)\n我们是不是可以把真实DOM树抽象成一棵以JavaScript对象构成的抽象树,在修改抽象树数据后将抽象树转化成真实DOM重绘到页面上呢?于是虚拟DOM出现了,它是真实DOM的一层抽象,用属性描述真实DOM的各个特性。当它发生变化的时候,就会去修改视图。\n\n- [多“维”优化——前端高并发策略的更深层思考](http://wetest.qq.com/lab/view/316.html)\n一项指标的变好,总少不了相应优化策略的实施。优化并不是简单的一蹴而就,而是个不断迭代与推翻的过程。更深层的优化方案,往往是在某种思维策略之下,对问题场景和基本策略优缺的深刻理解后做出的当下最优的权衡结果——作者导读。\n\n- [Egg 源码解析之 egg-cluster](https://juejin.im/entry/59bcce1b5188257e82676b53)\nNode.js 进程只能运行在一个 CPU 上,而 egg 采用多进程模型,使多核 CPU 的性能发挥到极致,最大程度地榨干服务器资源,进而解决了该问题。egg-cluster 是用于 egg 多进程管理的基础模块,负责底层的 IPC 通道的建立以及处理各进程的通信,本文解析了实现原理,值得一看。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","slug":"weekly-18","published":1,"updated":"2017-11-10T07:40:52.988Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkr000djrs6wrqpgymk","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"用Javascript学习数据结构之栈-Stack\"><a href=\"#用Javascript学习数据结构之栈-Stack\" class=\"headerlink\" title=\"用Javascript学习数据结构之栈(Stack)\"></a>用Javascript学习数据结构之栈(Stack)</h3><p>栈(Stack)是一种遵循后进先出(LIFO)的有序集合,较新的元素会靠近顶部,较旧的元素会在栈的底部。<br>接下来我们正式开始实现栈(Stack)。首先,建立一个Stack类:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"comment\">// 类内部定义Stack的属性和方法</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<h4 id=\"属性:\"><a href=\"#属性:\" class=\"headerlink\" title=\"属性:\"></a>属性:</h4><ol>\n<li>let items = []; //使用array来存储栈内的元素</li>\n</ol>\n<h4 id=\"方法:\"><a href=\"#方法:\" class=\"headerlink\" title=\"方法:\"></a>方法:</h4><ol>\n<li>push(elements): 新增一个或者多个元素到栈的顶部</li>\n<li>pop(): 移除栈顶部元素,同时返回被移除的元素</li>\n<li>peek()或top(): 仅返回stack元素,不做任何修改</li>\n<li>isEmpty(): 检查栈是否为空?若无任何元素则返回true,反之返回false</li>\n<li>clear(): 清空栈内的所有元素</li>\n<li>size(): 返回栈的元素个数</li>\n</ol>\n<h4 id=\"1-push-elements-和pop\"><a href=\"#1-push-elements-和pop\" class=\"headerlink\" title=\"1.push(elements)和pop()\"></a>1.push(elements)和pop()</h4><p>由于我们使用array当做stack的存储方式,所以我们可以使用array内建的push(element)和pop()方式来实现LIFO的特性,让元素的新增和删除只能发生在尾端。<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.push = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">element</span>) </span>{</span><br><span class=\"line\"> items.push(element);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.pop = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.pop();</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"2-peek-:\"><a href=\"#2-peek-:\" class=\"headerlink\" title=\"2.peek():\"></a>2.peek():</h4><p>若是我们想知道栈中的最后一个元素(最顶端的元素),我们可以实现peek()方法,返回顶部元素<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.peek = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items[items.length - <span class=\"number\">1</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"3-isEmpty-:\"><a href=\"#3-isEmpty-:\" class=\"headerlink\" title=\"3.isEmpty():\"></a>3.isEmpty():</h4><p>若我们想知道栈内是否还有元素,我们可以使用isEmpty()来判断<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.isEmpty = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length === <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"4-clear-:\"><a href=\"#4-clear-:\" class=\"headerlink\" title=\"4.clear():\"></a>4.clear():</h4><p>若我们想清空栈的话,可以使用clear()方法,将所有元素删除<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.clear = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> items = [];</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"5-size-:\"><a href=\"#5-size-:\" class=\"headerlink\" title=\"5.size():\"></a>5.size():</h4><p>通过size()方法我们可以取得栈的大小(共有几个元素)<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.size = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"完整代码:\"><a href=\"#完整代码:\" class=\"headerlink\" title=\"完整代码:\"></a>完整代码:</h4><p>把上面各种方法放到一起<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">var</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.push = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">element</span>) </span>{</span><br><span class=\"line\"> items.push(element);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.pop = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.pop();</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.peek = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items[items.length - <span class=\"number\">1</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.isEmpty = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length === <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.clear = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> items = [];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.size = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">// 加入打印方法</span></span><br><span class=\"line\"> <span class=\"keyword\">this</span>.print = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(items.toString());</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"http://phantomjs.org/\" target=\"_blank\" rel=\"noopener\">PhantomJS</a><br>PhantomJS可以应用于下面这几个典型场景:无需浏览器的web测试,页面自动化操作,屏幕截图和网络监控等</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.jdon.com/idea/nodejs/event-loop.html\" target=\"_blank\" rel=\"noopener\">Node.js的事件轮询Event Loop原理解释</a><br>Event Loop是理解Node实现事件驱动、异步高并发服务的关键。这篇文章中解释了下面几个容易被忽略的点: 1. Node.js的底层其实也是有一个线程池的,用来执行各种堵塞操作。2. 一个Event loop的三个基本组件:事件队列、读取事件的轮询线程、以及线程池。3. 各个事件的回调函数是如何激活并执行的。</p>\n</li>\n<li><p><a href=\"http://www.qdfuns.com/notes/16738/1b6ad6125747d28592a53a960b44c6f4.html\" target=\"_blank\" rel=\"noopener\">jsonp原理详解</a><br>jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59bfe84351882531b730bac2\" target=\"_blank\" rel=\"noopener\">this , apply , call , bind详解</a><br>几个ES5 的坑,this是其中经常搞晕的一个,上一篇通俗且易理解的文章</p>\n</li>\n<li><p><a href=\"http://taobaofed.org/blog/2017/08/31/nodejs-stream/\" target=\"_blank\" rel=\"noopener\">深入理解 Node.js Stream 内部机制</a><br>知其然知其所以然,来了解一下nodejs stream内部机制。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011699304\" target=\"_blank\" rel=\"noopener\">基于 Electron 开发客户端产品的体验</a><br>基于 Electron 开发的产品非常多,文章主要是针对于如何入门 Electron,可以说是作者开发的总结;非常适合计划使用 Electron的开发者阅读。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ec657ef265da431b6c5b03\" target=\"_blank\" rel=\"noopener\">babel到底该如何配置?</a><br>大家都知道js作为宿主语言,很依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,虽然每年更新的幅度不大,但是每年的提案可不少。babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译(转码+编译)到ES5。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27502596\" target=\"_blank\" rel=\"noopener\">CSS 新的长度单位 fr 你知道么?</a><br>本文介绍了 CSS Grid 规范中引入的一个新的长度单位 fr,我们一起来看看到底是怎么回事吧!</p>\n</li>\n<li><p><a href=\"https://qiutc.me/post/resource-optimization-webpack.html\" target=\"_blank\" rel=\"noopener\">使用 webpack 优化资源</a><br>本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/06/sass.html\" target=\"_blank\" rel=\"noopener\">SASS用法指南</a><br>今年TalkingData团队将 CSS 预处理器切换到了 SASS,代码层面只是简单直接的做了风格转换,还没有挖掘出 SASS 更深入的能力。本周推荐一篇 SASS “基础”内容,推荐大家阅读和实践,以提升大家在 CSS 方面的编程能力。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29450092\" target=\"_blank\" rel=\"noopener\">VirtualDOM与diff(Vue实现)</a><br>我们是不是可以把真实DOM树抽象成一棵以JavaScript对象构成的抽象树,在修改抽象树数据后将抽象树转化成真实DOM重绘到页面上呢?于是虚拟DOM出现了,它是真实DOM的一层抽象,用属性描述真实DOM的各个特性。当它发生变化的时候,就会去修改视图。</p>\n</li>\n<li><p><a href=\"http://wetest.qq.com/lab/view/316.html\" target=\"_blank\" rel=\"noopener\">多“维”优化——前端高并发策略的更深层思考</a><br>一项指标的变好,总少不了相应优化策略的实施。优化并不是简单的一蹴而就,而是个不断迭代与推翻的过程。更深层的优化方案,往往是在某种思维策略之下,对问题场景和基本策略优缺的深刻理解后做出的当下最优的权衡结果——作者导读。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/59bcce1b5188257e82676b53\" target=\"_blank\" rel=\"noopener\">Egg 源码解析之 egg-cluster</a><br>Node.js 进程只能运行在一个 CPU 上,而 egg 采用多进程模型,使多核 CPU 的性能发挥到极致,最大程度地榨干服务器资源,进而解决了该问题。egg-cluster 是用于 egg 多进程管理的基础模块,负责底层的 IPC 通道的建立以及处理各进程的通信,本文解析了实现原理,值得一看。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"用Javascript学习数据结构之栈-Stack\"><a href=\"#用Javascript学习数据结构之栈-Stack\" class=\"headerlink\" title=\"用Javascript学习数据结构之栈(Stack)\"></a>用Javascript学习数据结构之栈(Stack)</h3><p>栈(Stack)是一种遵循后进先出(LIFO)的有序集合,较新的元素会靠近顶部,较旧的元素会在栈的底部。<br>接下来我们正式开始实现栈(Stack)。首先,建立一个Stack类:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"comment\">// 类内部定义Stack的属性和方法</span></span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<h4 id=\"属性:\"><a href=\"#属性:\" class=\"headerlink\" title=\"属性:\"></a>属性:</h4><ol>\n<li>let items = []; //使用array来存储栈内的元素</li>\n</ol>\n<h4 id=\"方法:\"><a href=\"#方法:\" class=\"headerlink\" title=\"方法:\"></a>方法:</h4><ol>\n<li>push(elements): 新增一个或者多个元素到栈的顶部</li>\n<li>pop(): 移除栈顶部元素,同时返回被移除的元素</li>\n<li>peek()或top(): 仅返回stack元素,不做任何修改</li>\n<li>isEmpty(): 检查栈是否为空?若无任何元素则返回true,反之返回false</li>\n<li>clear(): 清空栈内的所有元素</li>\n<li>size(): 返回栈的元素个数</li>\n</ol>\n<h4 id=\"1-push-elements-和pop\"><a href=\"#1-push-elements-和pop\" class=\"headerlink\" title=\"1.push(elements)和pop()\"></a>1.push(elements)和pop()</h4><p>由于我们使用array当做stack的存储方式,所以我们可以使用array内建的push(element)和pop()方式来实现LIFO的特性,让元素的新增和删除只能发生在尾端。<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.push = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">element</span>) </span>{</span><br><span class=\"line\"> items.push(element);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.pop = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.pop();</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"2-peek-:\"><a href=\"#2-peek-:\" class=\"headerlink\" title=\"2.peek():\"></a>2.peek():</h4><p>若是我们想知道栈中的最后一个元素(最顶端的元素),我们可以实现peek()方法,返回顶部元素<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.peek = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items[items.length - <span class=\"number\">1</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"3-isEmpty-:\"><a href=\"#3-isEmpty-:\" class=\"headerlink\" title=\"3.isEmpty():\"></a>3.isEmpty():</h4><p>若我们想知道栈内是否还有元素,我们可以使用isEmpty()来判断<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.isEmpty = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length === <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"4-clear-:\"><a href=\"#4-clear-:\" class=\"headerlink\" title=\"4.clear():\"></a>4.clear():</h4><p>若我们想清空栈的话,可以使用clear()方法,将所有元素删除<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.clear = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> items = [];</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"5-size-:\"><a href=\"#5-size-:\" class=\"headerlink\" title=\"5.size():\"></a>5.size():</h4><p>通过size()方法我们可以取得栈的大小(共有几个元素)<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.size = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h4 id=\"完整代码:\"><a href=\"#完整代码:\" class=\"headerlink\" title=\"完整代码:\"></a>完整代码:</h4><p>把上面各种方法放到一起<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">Stack</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">var</span> items = [];</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.push = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">element</span>) </span>{</span><br><span class=\"line\"> items.push(element);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.pop = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.pop();</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.peek = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items[items.length - <span class=\"number\">1</span>];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.isEmpty = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length === <span class=\"number\">0</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.clear = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> items = [];</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">this</span>.size = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> items.length;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"comment\">// 加入打印方法</span></span><br><span class=\"line\"> <span class=\"keyword\">this</span>.print = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(items.toString());</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"http://phantomjs.org/\" target=\"_blank\" rel=\"noopener\">PhantomJS</a><br>PhantomJS可以应用于下面这几个典型场景:无需浏览器的web测试,页面自动化操作,屏幕截图和网络监控等</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.jdon.com/idea/nodejs/event-loop.html\" target=\"_blank\" rel=\"noopener\">Node.js的事件轮询Event Loop原理解释</a><br>Event Loop是理解Node实现事件驱动、异步高并发服务的关键。这篇文章中解释了下面几个容易被忽略的点: 1. Node.js的底层其实也是有一个线程池的,用来执行各种堵塞操作。2. 一个Event loop的三个基本组件:事件队列、读取事件的轮询线程、以及线程池。3. 各个事件的回调函数是如何激活并执行的。</p>\n</li>\n<li><p><a href=\"http://www.qdfuns.com/notes/16738/1b6ad6125747d28592a53a960b44c6f4.html\" target=\"_blank\" rel=\"noopener\">jsonp原理详解</a><br>jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59bfe84351882531b730bac2\" target=\"_blank\" rel=\"noopener\">this , apply , call , bind详解</a><br>几个ES5 的坑,this是其中经常搞晕的一个,上一篇通俗且易理解的文章</p>\n</li>\n<li><p><a href=\"http://taobaofed.org/blog/2017/08/31/nodejs-stream/\" target=\"_blank\" rel=\"noopener\">深入理解 Node.js Stream 内部机制</a><br>知其然知其所以然,来了解一下nodejs stream内部机制。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011699304\" target=\"_blank\" rel=\"noopener\">基于 Electron 开发客户端产品的体验</a><br>基于 Electron 开发的产品非常多,文章主要是针对于如何入门 Electron,可以说是作者开发的总结;非常适合计划使用 Electron的开发者阅读。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59ec657ef265da431b6c5b03\" target=\"_blank\" rel=\"noopener\">babel到底该如何配置?</a><br>大家都知道js作为宿主语言,很依赖执行的环境(浏览器、node等),不同环境对js语法的支持不尽相同,特别是ES6之后,ECMAScrip对版本的更新已经到了一年一次的节奏,虽然每年更新的幅度不大,但是每年的提案可不少。babel的出现就是为了解决这个问题,把那些使用新标准编写的代码转译为当前环境可运行的代码,简单点说就是把ES6代码转译(转码+编译)到ES5。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27502596\" target=\"_blank\" rel=\"noopener\">CSS 新的长度单位 fr 你知道么?</a><br>本文介绍了 CSS Grid 规范中引入的一个新的长度单位 fr,我们一起来看看到底是怎么回事吧!</p>\n</li>\n<li><p><a href=\"https://qiutc.me/post/resource-optimization-webpack.html\" target=\"_blank\" rel=\"noopener\">使用 webpack 优化资源</a><br>本片文章中主要是基于 webpack 打包,以 React、vue 等生态开发的单页面应用来举例说明如何从 webpack 打包的层面去处理资源以及缓存,其中主要我们需要做的是对 webpack 进行配置的优化,同时涉及少量的业务代码的更改。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/06/sass.html\" target=\"_blank\" rel=\"noopener\">SASS用法指南</a><br>今年TalkingData团队将 CSS 预处理器切换到了 SASS,代码层面只是简单直接的做了风格转换,还没有挖掘出 SASS 更深入的能力。本周推荐一篇 SASS “基础”内容,推荐大家阅读和实践,以提升大家在 CSS 方面的编程能力。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29450092\" target=\"_blank\" rel=\"noopener\">VirtualDOM与diff(Vue实现)</a><br>我们是不是可以把真实DOM树抽象成一棵以JavaScript对象构成的抽象树,在修改抽象树数据后将抽象树转化成真实DOM重绘到页面上呢?于是虚拟DOM出现了,它是真实DOM的一层抽象,用属性描述真实DOM的各个特性。当它发生变化的时候,就会去修改视图。</p>\n</li>\n<li><p><a href=\"http://wetest.qq.com/lab/view/316.html\" target=\"_blank\" rel=\"noopener\">多“维”优化——前端高并发策略的更深层思考</a><br>一项指标的变好,总少不了相应优化策略的实施。优化并不是简单的一蹴而就,而是个不断迭代与推翻的过程。更深层的优化方案,往往是在某种思维策略之下,对问题场景和基本策略优缺的深刻理解后做出的当下最优的权衡结果——作者导读。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/59bcce1b5188257e82676b53\" target=\"_blank\" rel=\"noopener\">Egg 源码解析之 egg-cluster</a><br>Node.js 进程只能运行在一个 CPU 上,而 egg 采用多进程模型,使多核 CPU 的性能发挥到极致,最大程度地榨干服务器资源,进而解决了该问题。egg-cluster 是用于 egg 多进程管理的基础模块,负责底层的 IPC 通道的建立以及处理各进程的通信,本文解析了实现原理,值得一看。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第20期 (本期小编:杨齐)","date":"2017-11-10T07:08:59.000Z","_content":"\n## Show me the code\n\n### 前端工程化工具 Dawn (来自阿里云开源)\n\n阿里云内部的前端构建和工程化工具,现已完全开源。它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。\n\n#### 特点\n\n采用中间件技术,封装常用功能,易于扩展,方便重用\n支持 pipeline 让多个 task 协同完成构建任务\n简单、一致的命令行接口,易于开发人员使用\n支持基于「中心服务」管理中件间和工程模板\n支持搭建私有中心服务,并统一下发构建规则,易于团队统一管理\n\n#### 安装\n\n``` javascript\n$ npm install dawn -g\n```\n\n#### 使用\n\n``` javascript\n# 1. 创建 & 初始化\n$ dn init -t front\n\n# 2. 开发 & 实时编译\n$ dn dev\n\n# 3. 语法检查 & 测试\n$ dn test\n\n# 4. 构建 & 打包\n$ dn build\n```\n\n#### 示例\n\n``` javascript\n# 启动开发服务\ndev:\n - name: webpack\n entry: ./src/.js\n template: ./assets/.html\n watch: true\n - name: server\n port: 8001\n\n# 直接构建\nbuid:\n - name: webpack\n entry: ./src/.js\n template: ./assets/.html\n\n```\n#### 文档\n\n使用入门: [getting-started](https://user-gold-cdn.xitu.io/2017/11/2/68184fa8fc078832871f8ef138b9a8bf)\n\n配置Pipeline: [pipeline.md](https://github.com/alibaba/dawn/blob/master/docs/markdowns/pipeline.md)\n\n\n## 插件推荐\n\n- [Frontend Tracker](https://github.com/Pgyer/frontend-tracker)\nFrontend Tracker 可以发现前端页面的错误,并且用户察觉错误前将错误发送至指定服务器。\n\n## 文章推荐\n- [Node.js加密算法库Crypto](http://blog.fens.me/nodejs-crypto/)\n用Node做web服务进行用户认证的场合下,经常需要对用户密码进行加密和解码的操作。Crypto是NodeJS的内置库,提供了必要的功能,值得学习收藏。\n\n- [Web 应用内存分析与内存泄漏定位](https://github.com/wxyyxc1992/Web-Development-And-Engineering-Practices/blob/master/Modern-Web-Engineering-Practices/%E8%B0%83%E8%AF%95/%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90%E4%B8%8E%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E5%AE%9A%E4%BD%8D.md)\n无论是分布式计算系统、服务端应用程序还是 iOS、Android 原生应用都会存在内存泄漏问题,Web 应用自然也不可避免地存在着类似的问题。虽然因为网页往往都是即用即走,较少地存在某个网页长期运行的问题,即使存在内存泄漏可能表现地也不明显;但是在某些数据展示型的,需要长期运行的页面上,如果不及时解决内存泄漏可能会导致网页占据过大地内存,不仅影响页面性能,还可能导致整个系统的崩溃。\n\n- [前端状态管理请三思](https://juejin.im/post/59fd94475188254115703461)\n有关前端状态管理的一篇文章,结合实际中的问题,实现一个好用的状态机。\n\n- [前端API备忘录](https://juejin.im/entry/5a0149a9f265da431f4a7999)\n好脑筋不如烂笔头,平时还是要多写,多记,推荐一个比较常用的前端API合集,忘得时候查一下,很方便\n\n- [性能优化之组件懒加载](https://zhuanlan.zhihu.com/p/29433875)\n文章首先抛出实际场景遇到的性能问题,给出现象,然后分析问题,提出两个解决思路,最后梳理优化并产出通用的Vue 2.x 组件级懒加载解决方案(Vue Lazy Component )。\n\n- [JavaScript 在 V8 中的元素种类及性能优化](https://segmentfault.com/a/1190000011303679)\nJavaScript 对象可以具有与它们相关联的任意属性。对象属性的名称可以包含任何字符。JavaScript 引擎可以进行优化的一个有趣的例子是当属性名是纯数字时,一个特例就是数组索引的属性。\n\n- [Webpack 热更新实现原理分析](https://zhuanlan.zhihu.com/p/30623057?utm_medium=social&utm_source=wechat_session)\n在使用 Webpack 构建开发期时,Webpack 提供热更新功能为开发带来良好的体验和开发效率,该文分析关于webpack热更新技术的实现原理。\n\n- [JavaScript Event Loop 机制详解与 Vue.js 中实践应用](https://segmentfault.com/a/1190000011044242)\n依次介绍了函数调用栈、MacroTask 与 MicroTask 执行顺序、浅析 Vue.js 中 nextTick 实现等内容\n\n- [从Chrome源码看浏览器如何加载资源](https://fed.renren.com/2017/10/29/chrome-fetch-resource/)\n本文通过源码层面解释了浏览器如何加载资源,解决了前端对浏览器加载资源有很多不确定性的困惑,非常实用。\n\n- [sass语法总结](http://www.jianshu.com/p/e139d449f5bb)\nCSS 本身是非常强大的,但随着样式表变大,变复杂,维护 CSS 变得越来越难。这时候预处理就有用了。Sass 是一种预处理,它能让你使用一些 CSS 中没有的特性,比如:变量,嵌套(nesting),混入(mixins),继承等。这些特性能让 CSS 变的容易维护。\n\n- [HTTP中GET与POST的区别](http://bbs.thankbabe.com/topic/72/99-%E7%9A%84%E4%BA%BA%E9%83%BD%E7%90%86%E8%A7%A3%E9%94%99%E4%BA%86http%E4%B8%ADget%E4%B8%8Epost%E7%9A%84%E5%8C%BA%E5%88%AB)\n看这霸气的文章标题!快来看看和自己理解的是否一致吧\n\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-20.md","raw":"---\ntitle: 大前端周刊 第20期 (本期小编:杨齐)\ndate: 2017-11-10 15:08:59\ntags:\n---\n\n## Show me the code\n\n### 前端工程化工具 Dawn (来自阿里云开源)\n\n阿里云内部的前端构建和工程化工具,现已完全开源。它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。\n\n#### 特点\n\n采用中间件技术,封装常用功能,易于扩展,方便重用\n支持 pipeline 让多个 task 协同完成构建任务\n简单、一致的命令行接口,易于开发人员使用\n支持基于「中心服务」管理中件间和工程模板\n支持搭建私有中心服务,并统一下发构建规则,易于团队统一管理\n\n#### 安装\n\n``` javascript\n$ npm install dawn -g\n```\n\n#### 使用\n\n``` javascript\n# 1. 创建 & 初始化\n$ dn init -t front\n\n# 2. 开发 & 实时编译\n$ dn dev\n\n# 3. 语法检查 & 测试\n$ dn test\n\n# 4. 构建 & 打包\n$ dn build\n```\n\n#### 示例\n\n``` javascript\n# 启动开发服务\ndev:\n - name: webpack\n entry: ./src/.js\n template: ./assets/.html\n watch: true\n - name: server\n port: 8001\n\n# 直接构建\nbuid:\n - name: webpack\n entry: ./src/.js\n template: ./assets/.html\n\n```\n#### 文档\n\n使用入门: [getting-started](https://user-gold-cdn.xitu.io/2017/11/2/68184fa8fc078832871f8ef138b9a8bf)\n\n配置Pipeline: [pipeline.md](https://github.com/alibaba/dawn/blob/master/docs/markdowns/pipeline.md)\n\n\n## 插件推荐\n\n- [Frontend Tracker](https://github.com/Pgyer/frontend-tracker)\nFrontend Tracker 可以发现前端页面的错误,并且用户察觉错误前将错误发送至指定服务器。\n\n## 文章推荐\n- [Node.js加密算法库Crypto](http://blog.fens.me/nodejs-crypto/)\n用Node做web服务进行用户认证的场合下,经常需要对用户密码进行加密和解码的操作。Crypto是NodeJS的内置库,提供了必要的功能,值得学习收藏。\n\n- [Web 应用内存分析与内存泄漏定位](https://github.com/wxyyxc1992/Web-Development-And-Engineering-Practices/blob/master/Modern-Web-Engineering-Practices/%E8%B0%83%E8%AF%95/%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90%E4%B8%8E%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E5%AE%9A%E4%BD%8D.md)\n无论是分布式计算系统、服务端应用程序还是 iOS、Android 原生应用都会存在内存泄漏问题,Web 应用自然也不可避免地存在着类似的问题。虽然因为网页往往都是即用即走,较少地存在某个网页长期运行的问题,即使存在内存泄漏可能表现地也不明显;但是在某些数据展示型的,需要长期运行的页面上,如果不及时解决内存泄漏可能会导致网页占据过大地内存,不仅影响页面性能,还可能导致整个系统的崩溃。\n\n- [前端状态管理请三思](https://juejin.im/post/59fd94475188254115703461)\n有关前端状态管理的一篇文章,结合实际中的问题,实现一个好用的状态机。\n\n- [前端API备忘录](https://juejin.im/entry/5a0149a9f265da431f4a7999)\n好脑筋不如烂笔头,平时还是要多写,多记,推荐一个比较常用的前端API合集,忘得时候查一下,很方便\n\n- [性能优化之组件懒加载](https://zhuanlan.zhihu.com/p/29433875)\n文章首先抛出实际场景遇到的性能问题,给出现象,然后分析问题,提出两个解决思路,最后梳理优化并产出通用的Vue 2.x 组件级懒加载解决方案(Vue Lazy Component )。\n\n- [JavaScript 在 V8 中的元素种类及性能优化](https://segmentfault.com/a/1190000011303679)\nJavaScript 对象可以具有与它们相关联的任意属性。对象属性的名称可以包含任何字符。JavaScript 引擎可以进行优化的一个有趣的例子是当属性名是纯数字时,一个特例就是数组索引的属性。\n\n- [Webpack 热更新实现原理分析](https://zhuanlan.zhihu.com/p/30623057?utm_medium=social&utm_source=wechat_session)\n在使用 Webpack 构建开发期时,Webpack 提供热更新功能为开发带来良好的体验和开发效率,该文分析关于webpack热更新技术的实现原理。\n\n- [JavaScript Event Loop 机制详解与 Vue.js 中实践应用](https://segmentfault.com/a/1190000011044242)\n依次介绍了函数调用栈、MacroTask 与 MicroTask 执行顺序、浅析 Vue.js 中 nextTick 实现等内容\n\n- [从Chrome源码看浏览器如何加载资源](https://fed.renren.com/2017/10/29/chrome-fetch-resource/)\n本文通过源码层面解释了浏览器如何加载资源,解决了前端对浏览器加载资源有很多不确定性的困惑,非常实用。\n\n- [sass语法总结](http://www.jianshu.com/p/e139d449f5bb)\nCSS 本身是非常强大的,但随着样式表变大,变复杂,维护 CSS 变得越来越难。这时候预处理就有用了。Sass 是一种预处理,它能让你使用一些 CSS 中没有的特性,比如:变量,嵌套(nesting),混入(mixins),继承等。这些特性能让 CSS 变的容易维护。\n\n- [HTTP中GET与POST的区别](http://bbs.thankbabe.com/topic/72/99-%E7%9A%84%E4%BA%BA%E9%83%BD%E7%90%86%E8%A7%A3%E9%94%99%E4%BA%86http%E4%B8%ADget%E4%B8%8Epost%E7%9A%84%E5%8C%BA%E5%88%AB)\n看这霸气的文章标题!快来看看和自己理解的是否一致吧\n\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-20","published":1,"updated":"2019-03-01T16:26:16.529Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkv000fjrs6fpid39wi","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"前端工程化工具-Dawn-来自阿里云开源\"><a href=\"#前端工程化工具-Dawn-来自阿里云开源\" class=\"headerlink\" title=\"前端工程化工具 Dawn (来自阿里云开源)\"></a>前端工程化工具 Dawn (来自阿里云开源)</h3><p>阿里云内部的前端构建和工程化工具,现已完全开源。它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。</p>\n<h4 id=\"特点\"><a href=\"#特点\" class=\"headerlink\" title=\"特点\"></a>特点</h4><p>采用中间件技术,封装常用功能,易于扩展,方便重用<br>支持 pipeline 让多个 task 协同完成构建任务<br>简单、一致的命令行接口,易于开发人员使用<br>支持基于「中心服务」管理中件间和工程模板<br>支持搭建私有中心服务,并统一下发构建规则,易于团队统一管理</p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ npm install dawn -g</span><br></pre></td></tr></table></figure>\n<h4 id=\"使用\"><a href=\"#使用\" class=\"headerlink\" title=\"使用\"></a>使用</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># 1. 创建 & 初始化</span><br><span class=\"line\">$ dn init -t front</span><br><span class=\"line\"></span><br><span class=\"line\"># 2. 开发 & 实时编译</span><br><span class=\"line\">$ dn dev</span><br><span class=\"line\"></span><br><span class=\"line\"># 3. 语法检查 & 测试</span><br><span class=\"line\">$ dn test</span><br><span class=\"line\"></span><br><span class=\"line\"># 4. 构建 & 打包</span><br><span class=\"line\">$ dn build</span><br></pre></td></tr></table></figure>\n<h4 id=\"示例\"><a href=\"#示例\" class=\"headerlink\" title=\"示例\"></a>示例</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># 启动开发服务</span><br><span class=\"line\">dev:</span><br><span class=\"line\"> - name: webpack</span><br><span class=\"line\"> entry: ./src/.js</span><br><span class=\"line\"> template: ./assets/.html</span><br><span class=\"line\"> watch: <span class=\"literal\">true</span></span><br><span class=\"line\"> - name: server</span><br><span class=\"line\"> port: <span class=\"number\">8001</span></span><br><span class=\"line\"></span><br><span class=\"line\"># 直接构建</span><br><span class=\"line\">buid:</span><br><span class=\"line\"> - name: webpack</span><br><span class=\"line\"> entry: ./src/.js</span><br><span class=\"line\"> template: ./assets/.html</span><br></pre></td></tr></table></figure>\n<h4 id=\"文档\"><a href=\"#文档\" class=\"headerlink\" title=\"文档\"></a>文档</h4><p>使用入门: <a href=\"https://user-gold-cdn.xitu.io/2017/11/2/68184fa8fc078832871f8ef138b9a8bf\" target=\"_blank\" rel=\"noopener\">getting-started</a></p>\n<p>配置Pipeline: <a href=\"https://github.com/alibaba/dawn/blob/master/docs/markdowns/pipeline.md\" target=\"_blank\" rel=\"noopener\">pipeline.md</a></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://github.com/Pgyer/frontend-tracker\" target=\"_blank\" rel=\"noopener\">Frontend Tracker</a><br>Frontend Tracker 可以发现前端页面的错误,并且用户察觉错误前将错误发送至指定服务器。</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://blog.fens.me/nodejs-crypto/\" target=\"_blank\" rel=\"noopener\">Node.js加密算法库Crypto</a><br>用Node做web服务进行用户认证的场合下,经常需要对用户密码进行加密和解码的操作。Crypto是NodeJS的内置库,提供了必要的功能,值得学习收藏。</p>\n</li>\n<li><p><a href=\"https://github.com/wxyyxc1992/Web-Development-And-Engineering-Practices/blob/master/Modern-Web-Engineering-Practices/%E8%B0%83%E8%AF%95/%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90%E4%B8%8E%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E5%AE%9A%E4%BD%8D.md\" target=\"_blank\" rel=\"noopener\">Web 应用内存分析与内存泄漏定位</a><br>无论是分布式计算系统、服务端应用程序还是 iOS、Android 原生应用都会存在内存泄漏问题,Web 应用自然也不可避免地存在着类似的问题。虽然因为网页往往都是即用即走,较少地存在某个网页长期运行的问题,即使存在内存泄漏可能表现地也不明显;但是在某些数据展示型的,需要长期运行的页面上,如果不及时解决内存泄漏可能会导致网页占据过大地内存,不仅影响页面性能,还可能导致整个系统的崩溃。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59fd94475188254115703461\" target=\"_blank\" rel=\"noopener\">前端状态管理请三思</a><br>有关前端状态管理的一篇文章,结合实际中的问题,实现一个好用的状态机。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/5a0149a9f265da431f4a7999\" target=\"_blank\" rel=\"noopener\">前端API备忘录</a><br>好脑筋不如烂笔头,平时还是要多写,多记,推荐一个比较常用的前端API合集,忘得时候查一下,很方便</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29433875\" target=\"_blank\" rel=\"noopener\">性能优化之组件懒加载</a><br>文章首先抛出实际场景遇到的性能问题,给出现象,然后分析问题,提出两个解决思路,最后梳理优化并产出通用的Vue 2.x 组件级懒加载解决方案(Vue Lazy Component )。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011303679\" target=\"_blank\" rel=\"noopener\">JavaScript 在 V8 中的元素种类及性能优化</a><br>JavaScript 对象可以具有与它们相关联的任意属性。对象属性的名称可以包含任何字符。JavaScript 引擎可以进行优化的一个有趣的例子是当属性名是纯数字时,一个特例就是数组索引的属性。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/30623057?utm_medium=social&utm_source=wechat_session\" target=\"_blank\" rel=\"noopener\">Webpack 热更新实现原理分析</a><br>在使用 Webpack 构建开发期时,Webpack 提供热更新功能为开发带来良好的体验和开发效率,该文分析关于webpack热更新技术的实现原理。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011044242\" target=\"_blank\" rel=\"noopener\">JavaScript Event Loop 机制详解与 Vue.js 中实践应用</a><br>依次介绍了函数调用栈、MacroTask 与 MicroTask 执行顺序、浅析 Vue.js 中 nextTick 实现等内容</p>\n</li>\n<li><p><a href=\"https://fed.renren.com/2017/10/29/chrome-fetch-resource/\" target=\"_blank\" rel=\"noopener\">从Chrome源码看浏览器如何加载资源</a><br>本文通过源码层面解释了浏览器如何加载资源,解决了前端对浏览器加载资源有很多不确定性的困惑,非常实用。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/e139d449f5bb\" target=\"_blank\" rel=\"noopener\">sass语法总结</a><br>CSS 本身是非常强大的,但随着样式表变大,变复杂,维护 CSS 变得越来越难。这时候预处理就有用了。Sass 是一种预处理,它能让你使用一些 CSS 中没有的特性,比如:变量,嵌套(nesting),混入(mixins),继承等。这些特性能让 CSS 变的容易维护。</p>\n</li>\n<li><p><a href=\"http://bbs.thankbabe.com/topic/72/99-%E7%9A%84%E4%BA%BA%E9%83%BD%E7%90%86%E8%A7%A3%E9%94%99%E4%BA%86http%E4%B8%ADget%E4%B8%8Epost%E7%9A%84%E5%8C%BA%E5%88%AB\" target=\"_blank\" rel=\"noopener\">HTTP中GET与POST的区别</a><br>看这霸气的文章标题!快来看看和自己理解的是否一致吧</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"前端工程化工具-Dawn-来自阿里云开源\"><a href=\"#前端工程化工具-Dawn-来自阿里云开源\" class=\"headerlink\" title=\"前端工程化工具 Dawn (来自阿里云开源)\"></a>前端工程化工具 Dawn (来自阿里云开源)</h3><p>阿里云内部的前端构建和工程化工具,现已完全开源。它通过 pipeline 和 middleware 将开发过程抽象为相对固定的阶段和有限的操作,简化并统一了开发人员的日常构建与开发相关的工作。</p>\n<h4 id=\"特点\"><a href=\"#特点\" class=\"headerlink\" title=\"特点\"></a>特点</h4><p>采用中间件技术,封装常用功能,易于扩展,方便重用<br>支持 pipeline 让多个 task 协同完成构建任务<br>简单、一致的命令行接口,易于开发人员使用<br>支持基于「中心服务」管理中件间和工程模板<br>支持搭建私有中心服务,并统一下发构建规则,易于团队统一管理</p>\n<h4 id=\"安装\"><a href=\"#安装\" class=\"headerlink\" title=\"安装\"></a>安装</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ npm install dawn -g</span><br></pre></td></tr></table></figure>\n<h4 id=\"使用\"><a href=\"#使用\" class=\"headerlink\" title=\"使用\"></a>使用</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># 1. 创建 & 初始化</span><br><span class=\"line\">$ dn init -t front</span><br><span class=\"line\"></span><br><span class=\"line\"># 2. 开发 & 实时编译</span><br><span class=\"line\">$ dn dev</span><br><span class=\"line\"></span><br><span class=\"line\"># 3. 语法检查 & 测试</span><br><span class=\"line\">$ dn test</span><br><span class=\"line\"></span><br><span class=\"line\"># 4. 构建 & 打包</span><br><span class=\"line\">$ dn build</span><br></pre></td></tr></table></figure>\n<h4 id=\"示例\"><a href=\"#示例\" class=\"headerlink\" title=\"示例\"></a>示例</h4><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"># 启动开发服务</span><br><span class=\"line\">dev:</span><br><span class=\"line\"> - name: webpack</span><br><span class=\"line\"> entry: ./src/.js</span><br><span class=\"line\"> template: ./assets/.html</span><br><span class=\"line\"> watch: <span class=\"literal\">true</span></span><br><span class=\"line\"> - name: server</span><br><span class=\"line\"> port: <span class=\"number\">8001</span></span><br><span class=\"line\"></span><br><span class=\"line\"># 直接构建</span><br><span class=\"line\">buid:</span><br><span class=\"line\"> - name: webpack</span><br><span class=\"line\"> entry: ./src/.js</span><br><span class=\"line\"> template: ./assets/.html</span><br></pre></td></tr></table></figure>\n<h4 id=\"文档\"><a href=\"#文档\" class=\"headerlink\" title=\"文档\"></a>文档</h4><p>使用入门: <a href=\"https://user-gold-cdn.xitu.io/2017/11/2/68184fa8fc078832871f8ef138b9a8bf\" target=\"_blank\" rel=\"noopener\">getting-started</a></p>\n<p>配置Pipeline: <a href=\"https://github.com/alibaba/dawn/blob/master/docs/markdowns/pipeline.md\" target=\"_blank\" rel=\"noopener\">pipeline.md</a></p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://github.com/Pgyer/frontend-tracker\" target=\"_blank\" rel=\"noopener\">Frontend Tracker</a><br>Frontend Tracker 可以发现前端页面的错误,并且用户察觉错误前将错误发送至指定服务器。</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://blog.fens.me/nodejs-crypto/\" target=\"_blank\" rel=\"noopener\">Node.js加密算法库Crypto</a><br>用Node做web服务进行用户认证的场合下,经常需要对用户密码进行加密和解码的操作。Crypto是NodeJS的内置库,提供了必要的功能,值得学习收藏。</p>\n</li>\n<li><p><a href=\"https://github.com/wxyyxc1992/Web-Development-And-Engineering-Practices/blob/master/Modern-Web-Engineering-Practices/%E8%B0%83%E8%AF%95/%E5%86%85%E5%AD%98%E5%88%86%E6%9E%90%E4%B8%8E%E5%86%85%E5%AD%98%E6%B3%84%E9%9C%B2%E5%AE%9A%E4%BD%8D.md\" target=\"_blank\" rel=\"noopener\">Web 应用内存分析与内存泄漏定位</a><br>无论是分布式计算系统、服务端应用程序还是 iOS、Android 原生应用都会存在内存泄漏问题,Web 应用自然也不可避免地存在着类似的问题。虽然因为网页往往都是即用即走,较少地存在某个网页长期运行的问题,即使存在内存泄漏可能表现地也不明显;但是在某些数据展示型的,需要长期运行的页面上,如果不及时解决内存泄漏可能会导致网页占据过大地内存,不仅影响页面性能,还可能导致整个系统的崩溃。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59fd94475188254115703461\" target=\"_blank\" rel=\"noopener\">前端状态管理请三思</a><br>有关前端状态管理的一篇文章,结合实际中的问题,实现一个好用的状态机。</p>\n</li>\n<li><p><a href=\"https://juejin.im/entry/5a0149a9f265da431f4a7999\" target=\"_blank\" rel=\"noopener\">前端API备忘录</a><br>好脑筋不如烂笔头,平时还是要多写,多记,推荐一个比较常用的前端API合集,忘得时候查一下,很方便</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/29433875\" target=\"_blank\" rel=\"noopener\">性能优化之组件懒加载</a><br>文章首先抛出实际场景遇到的性能问题,给出现象,然后分析问题,提出两个解决思路,最后梳理优化并产出通用的Vue 2.x 组件级懒加载解决方案(Vue Lazy Component )。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011303679\" target=\"_blank\" rel=\"noopener\">JavaScript 在 V8 中的元素种类及性能优化</a><br>JavaScript 对象可以具有与它们相关联的任意属性。对象属性的名称可以包含任何字符。JavaScript 引擎可以进行优化的一个有趣的例子是当属性名是纯数字时,一个特例就是数组索引的属性。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/30623057?utm_medium=social&utm_source=wechat_session\" target=\"_blank\" rel=\"noopener\">Webpack 热更新实现原理分析</a><br>在使用 Webpack 构建开发期时,Webpack 提供热更新功能为开发带来良好的体验和开发效率,该文分析关于webpack热更新技术的实现原理。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011044242\" target=\"_blank\" rel=\"noopener\">JavaScript Event Loop 机制详解与 Vue.js 中实践应用</a><br>依次介绍了函数调用栈、MacroTask 与 MicroTask 执行顺序、浅析 Vue.js 中 nextTick 实现等内容</p>\n</li>\n<li><p><a href=\"https://fed.renren.com/2017/10/29/chrome-fetch-resource/\" target=\"_blank\" rel=\"noopener\">从Chrome源码看浏览器如何加载资源</a><br>本文通过源码层面解释了浏览器如何加载资源,解决了前端对浏览器加载资源有很多不确定性的困惑,非常实用。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/e139d449f5bb\" target=\"_blank\" rel=\"noopener\">sass语法总结</a><br>CSS 本身是非常强大的,但随着样式表变大,变复杂,维护 CSS 变得越来越难。这时候预处理就有用了。Sass 是一种预处理,它能让你使用一些 CSS 中没有的特性,比如:变量,嵌套(nesting),混入(mixins),继承等。这些特性能让 CSS 变的容易维护。</p>\n</li>\n<li><p><a href=\"http://bbs.thankbabe.com/topic/72/99-%E7%9A%84%E4%BA%BA%E9%83%BD%E7%90%86%E8%A7%A3%E9%94%99%E4%BA%86http%E4%B8%ADget%E4%B8%8Epost%E7%9A%84%E5%8C%BA%E5%88%AB\" target=\"_blank\" rel=\"noopener\">HTTP中GET与POST的区别</a><br>看这霸气的文章标题!快来看看和自己理解的是否一致吧</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第19期 (本期小编:段扬帅)","date":"2017-11-03T03:08:59.000Z","_content":"\n## Show me the code\n\n### HTML5 桌面通知(Notification API)\n\nHTML5新增的桌面通知API:Notification API是用于向用户推送通知消息的API。\n值得注意的是,该通知不管用户在不在当前标签页都会进行推送\n\n#### 权限\n\n该API需要用户明确授权同意推送后,才能进行推送!\n那么怎么才能知道用户有没有同意呢?\n\n``` javascript\nNotification.permission\n```\n返回值:granted(用户同意) 、 denied(用户拒绝) 、 default(用户还没有选择)\n\n#### 获取权限\n\nNotification 对象提供了requestPermission():\n\n``` javascript\nNotification.requestPermission().then(function(permission) {\n console.log(permission) // 返回用户的选择\n});\n```\n#### 推送\n\n得到用户的许可后,就可以愉快的进行推送了\n\n``` javascript\nnew Notification(title, options)\n```\n\n参数说明:\ntitle: 通知的标题。 必传\noptions:通知的设置选项。 可选:\n- dir:默认值是auto, 可以是ltr或rtl,表示提示主体内容的水平书写顺序。\n- body:通知的内容。\n- tag:代表通知的唯一标识,相同tag时只会打开同一个通知窗口。\n- icon:要在通知中显示的图标的URL。\n- data:想要和通知关联的数据。\n- requireInteraction:通知保持有效不自动关闭,默认为false。\n- vibrate: 通知显示时候,设备震动硬件需要的振动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去,例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。\n- renotify: 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。\n- silent: 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。\n- sound: 字符串。音频地址。表示通知出现要播放的声音资源。\n- noscreen: 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。\n- sticky: 布尔值。是否通知具有粘性,这样用户不太容易清除通知。默认false, 表示没有粘性。\n\n\n#### 关闭\n\nNotification.close() 关闭通知\n\n#### 支持事件\n\nonclick 点击触发\nonerror 显示异常触发\nonclose 消息关闭时触发\nonshow 消息显示的时候触发\n\n#### 兼容性\n移动端几乎都不支持,PC端大部分都支持,IE需要14.0版本以上\n\n## 插件推荐\n\n- [gpu.js](https://github.com/gpujs/gpu.js/tree/develop)\ngpu.js这个库会把你写的js编译成GLSL然后在GPU上执行,以达到加速的效果。并且,如果电脑不支持GPU,它还会当成普通的js执行。\n\n## 文章推荐\n- [探索nodeJS事件机制源码 打造属于自己的事件发布订阅系统](https://zhuanlan.zhihu.com/p/26300877)\n本文探索并解析了nodejs的event实现和设计原理,解释了“事件发布订阅模式”,详细介绍了eventEmitter的一些核心属性和方法。另外,还基于ES6语法,DIY了一个简单的事件订阅发布系统。\n\n- [http请求的理解](https://blog.souche.com/jie-kou-ce-shi-zhi-httpqing-qiu-de-li-jie/)\n从tcp到http,从计算机网络来看一个http请求,理解前后端网络通讯\n\n- [深入认识vue-cli:能做的不仅仅是初始化vue工程](https://segmentfault.com/a/1190000011643581?_ea=2709729)\n有许多同学没有搞清楚vue-cli和vue工程之间的关系,导致没有充分发挥vue-cli的功能。在这篇文章中,我将从底层原理开始并结合几个例子,告诉大家vue-cli还能这样用\n\n- [CSS Modules 用法教程](http://www.ruanyifeng.com/blog/2016/06/css_modules.html)\n在前端模块化大行其道的今天,开发者发布的开源模块,如何避免 CSS 样式被宿主页面的样式所覆盖是非常重要的问题。CSS Modules 加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。\n\n- [JavaScript 中的对象拷贝](https://scotch.io/bar-talk/copying-objects-in-javascript#toc-the-naive-way-of-copying-objects)\n在 JavaScript 中拷贝一个对象可能会碰到各种各样的问题,本文详细描述了各种拷贝的方法及注意点\n\n- [Vue 2.0 的数据依赖实现原理简析](https://github.com/DDFE/DDFE-blog/issues/17)\n源码解析,一步一步讲解 vue 的响应式是如何实现的,信息量比较大。\n\n- [在js里写SQL](http://zzfe.org/#/detail/59e42c3b91d3e35ba880fd0e)\n在日新月异的前端领域中,前端工程师能做的事情越来越多,前端页面可能出现一些数据逻辑复杂的页面,传统的js逻辑处理起来比较复杂,因此需要引入新的东西来简化逻辑。\n\n- [ES6 模块系统](http://www.zcfy.cc/article/es6-modules-in-depth-4436.html?t=new)\n对于ES6的模块系统,文章首先是对严格模式的一些总结,然后是对export 和 import 展开总结性的说明了各种绑定方式。\n\n- [Vue 项目架构设计与工程化实践 ](https://github.com/berwin/Blog/issues/14)\n作者详述了自己Vue搭建项目的过程:技术选型(Vue全家桶)->架构设计(不同层面的职责)->发布上线。整个过程较为详细,举例项目遇到的问题及解决方案,对于搭建项目有一定的参考价值。\n\n- [深入探讨前端组件化开发](http://web.jobbole.com/92879/)\n这几年,从陷入 “React、Vue 和 Angular 哪个性能好?”的争论,到现在的各个框架(库)的生态越来越完善,讨论性能差距已经没有价值了。而国内的前端娱乐圈,最火的就是 React 和 Vue 了,而 Angular 由于历史原因,在国内的占有率确实不高。\n\n- [打造丝般顺滑的 H5 翻页库](http://fex.baidu.com/blog/2017/10/build-a-silky-smooth-slide-library/)\n翻页组件实现起来并不难,本文在此基础上进一步尝试打造丝般顺滑的效果,各种优化手段值得学习。\n\n- [使用Node+Koa2+Mysql搭建简易博客](http://blog.csdn.net/wclimb/article/details/77890793)\nKoa2使用实例,从Koa安装到项目建立模版使用,代码很详细的项目实例。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","source":"_posts/weekly-19.md","raw":"---\ntitle: 大前端周刊 第19期 (本期小编:段扬帅)\ndate: 2017-11-03 11:08:59\ntags:\n---\n\n## Show me the code\n\n### HTML5 桌面通知(Notification API)\n\nHTML5新增的桌面通知API:Notification API是用于向用户推送通知消息的API。\n值得注意的是,该通知不管用户在不在当前标签页都会进行推送\n\n#### 权限\n\n该API需要用户明确授权同意推送后,才能进行推送!\n那么怎么才能知道用户有没有同意呢?\n\n``` javascript\nNotification.permission\n```\n返回值:granted(用户同意) 、 denied(用户拒绝) 、 default(用户还没有选择)\n\n#### 获取权限\n\nNotification 对象提供了requestPermission():\n\n``` javascript\nNotification.requestPermission().then(function(permission) {\n console.log(permission) // 返回用户的选择\n});\n```\n#### 推送\n\n得到用户的许可后,就可以愉快的进行推送了\n\n``` javascript\nnew Notification(title, options)\n```\n\n参数说明:\ntitle: 通知的标题。 必传\noptions:通知的设置选项。 可选:\n- dir:默认值是auto, 可以是ltr或rtl,表示提示主体内容的水平书写顺序。\n- body:通知的内容。\n- tag:代表通知的唯一标识,相同tag时只会打开同一个通知窗口。\n- icon:要在通知中显示的图标的URL。\n- data:想要和通知关联的数据。\n- requireInteraction:通知保持有效不自动关闭,默认为false。\n- vibrate: 通知显示时候,设备震动硬件需要的振动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去,例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。\n- renotify: 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。\n- silent: 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。\n- sound: 字符串。音频地址。表示通知出现要播放的声音资源。\n- noscreen: 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。\n- sticky: 布尔值。是否通知具有粘性,这样用户不太容易清除通知。默认false, 表示没有粘性。\n\n\n#### 关闭\n\nNotification.close() 关闭通知\n\n#### 支持事件\n\nonclick 点击触发\nonerror 显示异常触发\nonclose 消息关闭时触发\nonshow 消息显示的时候触发\n\n#### 兼容性\n移动端几乎都不支持,PC端大部分都支持,IE需要14.0版本以上\n\n## 插件推荐\n\n- [gpu.js](https://github.com/gpujs/gpu.js/tree/develop)\ngpu.js这个库会把你写的js编译成GLSL然后在GPU上执行,以达到加速的效果。并且,如果电脑不支持GPU,它还会当成普通的js执行。\n\n## 文章推荐\n- [探索nodeJS事件机制源码 打造属于自己的事件发布订阅系统](https://zhuanlan.zhihu.com/p/26300877)\n本文探索并解析了nodejs的event实现和设计原理,解释了“事件发布订阅模式”,详细介绍了eventEmitter的一些核心属性和方法。另外,还基于ES6语法,DIY了一个简单的事件订阅发布系统。\n\n- [http请求的理解](https://blog.souche.com/jie-kou-ce-shi-zhi-httpqing-qiu-de-li-jie/)\n从tcp到http,从计算机网络来看一个http请求,理解前后端网络通讯\n\n- [深入认识vue-cli:能做的不仅仅是初始化vue工程](https://segmentfault.com/a/1190000011643581?_ea=2709729)\n有许多同学没有搞清楚vue-cli和vue工程之间的关系,导致没有充分发挥vue-cli的功能。在这篇文章中,我将从底层原理开始并结合几个例子,告诉大家vue-cli还能这样用\n\n- [CSS Modules 用法教程](http://www.ruanyifeng.com/blog/2016/06/css_modules.html)\n在前端模块化大行其道的今天,开发者发布的开源模块,如何避免 CSS 样式被宿主页面的样式所覆盖是非常重要的问题。CSS Modules 加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。\n\n- [JavaScript 中的对象拷贝](https://scotch.io/bar-talk/copying-objects-in-javascript#toc-the-naive-way-of-copying-objects)\n在 JavaScript 中拷贝一个对象可能会碰到各种各样的问题,本文详细描述了各种拷贝的方法及注意点\n\n- [Vue 2.0 的数据依赖实现原理简析](https://github.com/DDFE/DDFE-blog/issues/17)\n源码解析,一步一步讲解 vue 的响应式是如何实现的,信息量比较大。\n\n- [在js里写SQL](http://zzfe.org/#/detail/59e42c3b91d3e35ba880fd0e)\n在日新月异的前端领域中,前端工程师能做的事情越来越多,前端页面可能出现一些数据逻辑复杂的页面,传统的js逻辑处理起来比较复杂,因此需要引入新的东西来简化逻辑。\n\n- [ES6 模块系统](http://www.zcfy.cc/article/es6-modules-in-depth-4436.html?t=new)\n对于ES6的模块系统,文章首先是对严格模式的一些总结,然后是对export 和 import 展开总结性的说明了各种绑定方式。\n\n- [Vue 项目架构设计与工程化实践 ](https://github.com/berwin/Blog/issues/14)\n作者详述了自己Vue搭建项目的过程:技术选型(Vue全家桶)->架构设计(不同层面的职责)->发布上线。整个过程较为详细,举例项目遇到的问题及解决方案,对于搭建项目有一定的参考价值。\n\n- [深入探讨前端组件化开发](http://web.jobbole.com/92879/)\n这几年,从陷入 “React、Vue 和 Angular 哪个性能好?”的争论,到现在的各个框架(库)的生态越来越完善,讨论性能差距已经没有价值了。而国内的前端娱乐圈,最火的就是 React 和 Vue 了,而 Angular 由于历史原因,在国内的占有率确实不高。\n\n- [打造丝般顺滑的 H5 翻页库](http://fex.baidu.com/blog/2017/10/build-a-silky-smooth-slide-library/)\n翻页组件实现起来并不难,本文在此基础上进一步尝试打造丝般顺滑的效果,各种优化手段值得学习。\n\n- [使用Node+Koa2+Mysql搭建简易博客](http://blog.csdn.net/wclimb/article/details/77890793)\nKoa2使用实例,从Koa安装到项目建立模版使用,代码很详细的项目实例。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","slug":"weekly-19","published":1,"updated":"2017-11-10T07:40:52.988Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkw000ijrs69uip4qap","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"HTML5-桌面通知-Notification-API\"><a href=\"#HTML5-桌面通知-Notification-API\" class=\"headerlink\" title=\"HTML5 桌面通知(Notification API)\"></a>HTML5 桌面通知(Notification API)</h3><p>HTML5新增的桌面通知API:Notification API是用于向用户推送通知消息的API。<br>值得注意的是,该通知不管用户在不在当前标签页都会进行推送</p>\n<h4 id=\"权限\"><a href=\"#权限\" class=\"headerlink\" title=\"权限\"></a>权限</h4><p>该API需要用户明确授权同意推送后,才能进行推送!<br>那么怎么才能知道用户有没有同意呢?</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Notification.permission</span><br></pre></td></tr></table></figure>\n<p>返回值:granted(用户同意) 、 denied(用户拒绝) 、 default(用户还没有选择)</p>\n<h4 id=\"获取权限\"><a href=\"#获取权限\" class=\"headerlink\" title=\"获取权限\"></a>获取权限</h4><p>Notification 对象提供了requestPermission():</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Notification.requestPermission().then(<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">permission</span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(permission) <span class=\"comment\">// 返回用户的选择</span></span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure>\n<h4 id=\"推送\"><a href=\"#推送\" class=\"headerlink\" title=\"推送\"></a>推送</h4><p>得到用户的许可后,就可以愉快的进行推送了</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">new</span> Notification(title, options)</span><br></pre></td></tr></table></figure>\n<p>参数说明:<br>title: 通知的标题。 必传<br>options:通知的设置选项。 可选:</p>\n<ul>\n<li>dir:默认值是auto, 可以是ltr或rtl,表示提示主体内容的水平书写顺序。</li>\n<li>body:通知的内容。</li>\n<li>tag:代表通知的唯一标识,相同tag时只会打开同一个通知窗口。</li>\n<li>icon:要在通知中显示的图标的URL。</li>\n<li>data:想要和通知关联的数据。</li>\n<li>requireInteraction:通知保持有效不自动关闭,默认为false。</li>\n<li>vibrate: 通知显示时候,设备震动硬件需要的振动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去,例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。</li>\n<li>renotify: 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。</li>\n<li>silent: 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。</li>\n<li>sound: 字符串。音频地址。表示通知出现要播放的声音资源。</li>\n<li>noscreen: 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。</li>\n<li>sticky: 布尔值。是否通知具有粘性,这样用户不太容易清除通知。默认false, 表示没有粘性。</li>\n</ul>\n<h4 id=\"关闭\"><a href=\"#关闭\" class=\"headerlink\" title=\"关闭\"></a>关闭</h4><p>Notification.close() 关闭通知</p>\n<h4 id=\"支持事件\"><a href=\"#支持事件\" class=\"headerlink\" title=\"支持事件\"></a>支持事件</h4><p>onclick 点击触发<br>onerror 显示异常触发<br>onclose 消息关闭时触发<br>onshow 消息显示的时候触发</p>\n<h4 id=\"兼容性\"><a href=\"#兼容性\" class=\"headerlink\" title=\"兼容性\"></a>兼容性</h4><p>移动端几乎都不支持,PC端大部分都支持,IE需要14.0版本以上</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://github.com/gpujs/gpu.js/tree/develop\" target=\"_blank\" rel=\"noopener\">gpu.js</a><br>gpu.js这个库会把你写的js编译成GLSL然后在GPU上执行,以达到加速的效果。并且,如果电脑不支持GPU,它还会当成普通的js执行。</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26300877\" target=\"_blank\" rel=\"noopener\">探索nodeJS事件机制源码 打造属于自己的事件发布订阅系统</a><br>本文探索并解析了nodejs的event实现和设计原理,解释了“事件发布订阅模式”,详细介绍了eventEmitter的一些核心属性和方法。另外,还基于ES6语法,DIY了一个简单的事件订阅发布系统。</p>\n</li>\n<li><p><a href=\"https://blog.souche.com/jie-kou-ce-shi-zhi-httpqing-qiu-de-li-jie/\" target=\"_blank\" rel=\"noopener\">http请求的理解</a><br>从tcp到http,从计算机网络来看一个http请求,理解前后端网络通讯</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011643581?_ea=2709729\" target=\"_blank\" rel=\"noopener\">深入认识vue-cli:能做的不仅仅是初始化vue工程</a><br>有许多同学没有搞清楚vue-cli和vue工程之间的关系,导致没有充分发挥vue-cli的功能。在这篇文章中,我将从底层原理开始并结合几个例子,告诉大家vue-cli还能这样用</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2016/06/css_modules.html\" target=\"_blank\" rel=\"noopener\">CSS Modules 用法教程</a><br>在前端模块化大行其道的今天,开发者发布的开源模块,如何避免 CSS 样式被宿主页面的样式所覆盖是非常重要的问题。CSS Modules 加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。</p>\n</li>\n<li><p><a href=\"https://scotch.io/bar-talk/copying-objects-in-javascript#toc-the-naive-way-of-copying-objects\" target=\"_blank\" rel=\"noopener\">JavaScript 中的对象拷贝</a><br>在 JavaScript 中拷贝一个对象可能会碰到各种各样的问题,本文详细描述了各种拷贝的方法及注意点</p>\n</li>\n<li><p><a href=\"https://github.com/DDFE/DDFE-blog/issues/17\" target=\"_blank\" rel=\"noopener\">Vue 2.0 的数据依赖实现原理简析</a><br>源码解析,一步一步讲解 vue 的响应式是如何实现的,信息量比较大。</p>\n</li>\n<li><p><a href=\"http://zzfe.org/#/detail/59e42c3b91d3e35ba880fd0e\" target=\"_blank\" rel=\"noopener\">在js里写SQL</a><br>在日新月异的前端领域中,前端工程师能做的事情越来越多,前端页面可能出现一些数据逻辑复杂的页面,传统的js逻辑处理起来比较复杂,因此需要引入新的东西来简化逻辑。</p>\n</li>\n<li><p><a href=\"http://www.zcfy.cc/article/es6-modules-in-depth-4436.html?t=new\" target=\"_blank\" rel=\"noopener\">ES6 模块系统</a><br>对于ES6的模块系统,文章首先是对严格模式的一些总结,然后是对export 和 import 展开总结性的说明了各种绑定方式。</p>\n</li>\n<li><p><a href=\"https://github.com/berwin/Blog/issues/14\" target=\"_blank\" rel=\"noopener\">Vue 项目架构设计与工程化实践 </a><br>作者详述了自己Vue搭建项目的过程:技术选型(Vue全家桶)->架构设计(不同层面的职责)->发布上线。整个过程较为详细,举例项目遇到的问题及解决方案,对于搭建项目有一定的参考价值。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92879/\" target=\"_blank\" rel=\"noopener\">深入探讨前端组件化开发</a><br>这几年,从陷入 “React、Vue 和 Angular 哪个性能好?”的争论,到现在的各个框架(库)的生态越来越完善,讨论性能差距已经没有价值了。而国内的前端娱乐圈,最火的就是 React 和 Vue 了,而 Angular 由于历史原因,在国内的占有率确实不高。</p>\n</li>\n<li><p><a href=\"http://fex.baidu.com/blog/2017/10/build-a-silky-smooth-slide-library/\" target=\"_blank\" rel=\"noopener\">打造丝般顺滑的 H5 翻页库</a><br>翻页组件实现起来并不难,本文在此基础上进一步尝试打造丝般顺滑的效果,各种优化手段值得学习。</p>\n</li>\n<li><p><a href=\"http://blog.csdn.net/wclimb/article/details/77890793\" target=\"_blank\" rel=\"noopener\">使用Node+Koa2+Mysql搭建简易博客</a><br>Koa2使用实例,从Koa安装到项目建立模版使用,代码很详细的项目实例。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"HTML5-桌面通知-Notification-API\"><a href=\"#HTML5-桌面通知-Notification-API\" class=\"headerlink\" title=\"HTML5 桌面通知(Notification API)\"></a>HTML5 桌面通知(Notification API)</h3><p>HTML5新增的桌面通知API:Notification API是用于向用户推送通知消息的API。<br>值得注意的是,该通知不管用户在不在当前标签页都会进行推送</p>\n<h4 id=\"权限\"><a href=\"#权限\" class=\"headerlink\" title=\"权限\"></a>权限</h4><p>该API需要用户明确授权同意推送后,才能进行推送!<br>那么怎么才能知道用户有没有同意呢?</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Notification.permission</span><br></pre></td></tr></table></figure>\n<p>返回值:granted(用户同意) 、 denied(用户拒绝) 、 default(用户还没有选择)</p>\n<h4 id=\"获取权限\"><a href=\"#获取权限\" class=\"headerlink\" title=\"获取权限\"></a>获取权限</h4><p>Notification 对象提供了requestPermission():</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">Notification.requestPermission().then(<span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\">permission</span>) </span>{</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(permission) <span class=\"comment\">// 返回用户的选择</span></span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure>\n<h4 id=\"推送\"><a href=\"#推送\" class=\"headerlink\" title=\"推送\"></a>推送</h4><p>得到用户的许可后,就可以愉快的进行推送了</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">new</span> Notification(title, options)</span><br></pre></td></tr></table></figure>\n<p>参数说明:<br>title: 通知的标题。 必传<br>options:通知的设置选项。 可选:</p>\n<ul>\n<li>dir:默认值是auto, 可以是ltr或rtl,表示提示主体内容的水平书写顺序。</li>\n<li>body:通知的内容。</li>\n<li>tag:代表通知的唯一标识,相同tag时只会打开同一个通知窗口。</li>\n<li>icon:要在通知中显示的图标的URL。</li>\n<li>data:想要和通知关联的数据。</li>\n<li>requireInteraction:通知保持有效不自动关闭,默认为false。</li>\n<li>vibrate: 通知显示时候,设备震动硬件需要的振动模式。所谓振动模式,指的是一个描述交替时间的数组,分别表示振动和不振动的毫秒数,一直交替下去,例如[200, 100, 200]表示设备振动200毫秒,然后停止100毫秒,再振动200毫秒。</li>\n<li>renotify: 布尔值。新通知出现的时候是否替换之前的。如果设为true,则表示替换,表示当前标记的通知只会出现一个。</li>\n<li>silent: 布尔值。通知出现的时候,是否要有声音。默认false, 表示无声。</li>\n<li>sound: 字符串。音频地址。表示通知出现要播放的声音资源。</li>\n<li>noscreen: 布尔值。是否不再屏幕上显示通知信息。默认false, 表示要在屏幕上显示通知内容。</li>\n<li>sticky: 布尔值。是否通知具有粘性,这样用户不太容易清除通知。默认false, 表示没有粘性。</li>\n</ul>\n<h4 id=\"关闭\"><a href=\"#关闭\" class=\"headerlink\" title=\"关闭\"></a>关闭</h4><p>Notification.close() 关闭通知</p>\n<h4 id=\"支持事件\"><a href=\"#支持事件\" class=\"headerlink\" title=\"支持事件\"></a>支持事件</h4><p>onclick 点击触发<br>onerror 显示异常触发<br>onclose 消息关闭时触发<br>onshow 消息显示的时候触发</p>\n<h4 id=\"兼容性\"><a href=\"#兼容性\" class=\"headerlink\" title=\"兼容性\"></a>兼容性</h4><p>移动端几乎都不支持,PC端大部分都支持,IE需要14.0版本以上</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://github.com/gpujs/gpu.js/tree/develop\" target=\"_blank\" rel=\"noopener\">gpu.js</a><br>gpu.js这个库会把你写的js编译成GLSL然后在GPU上执行,以达到加速的效果。并且,如果电脑不支持GPU,它还会当成普通的js执行。</li>\n</ul>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26300877\" target=\"_blank\" rel=\"noopener\">探索nodeJS事件机制源码 打造属于自己的事件发布订阅系统</a><br>本文探索并解析了nodejs的event实现和设计原理,解释了“事件发布订阅模式”,详细介绍了eventEmitter的一些核心属性和方法。另外,还基于ES6语法,DIY了一个简单的事件订阅发布系统。</p>\n</li>\n<li><p><a href=\"https://blog.souche.com/jie-kou-ce-shi-zhi-httpqing-qiu-de-li-jie/\" target=\"_blank\" rel=\"noopener\">http请求的理解</a><br>从tcp到http,从计算机网络来看一个http请求,理解前后端网络通讯</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011643581?_ea=2709729\" target=\"_blank\" rel=\"noopener\">深入认识vue-cli:能做的不仅仅是初始化vue工程</a><br>有许多同学没有搞清楚vue-cli和vue工程之间的关系,导致没有充分发挥vue-cli的功能。在这篇文章中,我将从底层原理开始并结合几个例子,告诉大家vue-cli还能这样用</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2016/06/css_modules.html\" target=\"_blank\" rel=\"noopener\">CSS Modules 用法教程</a><br>在前端模块化大行其道的今天,开发者发布的开源模块,如何避免 CSS 样式被宿主页面的样式所覆盖是非常重要的问题。CSS Modules 加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。</p>\n</li>\n<li><p><a href=\"https://scotch.io/bar-talk/copying-objects-in-javascript#toc-the-naive-way-of-copying-objects\" target=\"_blank\" rel=\"noopener\">JavaScript 中的对象拷贝</a><br>在 JavaScript 中拷贝一个对象可能会碰到各种各样的问题,本文详细描述了各种拷贝的方法及注意点</p>\n</li>\n<li><p><a href=\"https://github.com/DDFE/DDFE-blog/issues/17\" target=\"_blank\" rel=\"noopener\">Vue 2.0 的数据依赖实现原理简析</a><br>源码解析,一步一步讲解 vue 的响应式是如何实现的,信息量比较大。</p>\n</li>\n<li><p><a href=\"http://zzfe.org/#/detail/59e42c3b91d3e35ba880fd0e\" target=\"_blank\" rel=\"noopener\">在js里写SQL</a><br>在日新月异的前端领域中,前端工程师能做的事情越来越多,前端页面可能出现一些数据逻辑复杂的页面,传统的js逻辑处理起来比较复杂,因此需要引入新的东西来简化逻辑。</p>\n</li>\n<li><p><a href=\"http://www.zcfy.cc/article/es6-modules-in-depth-4436.html?t=new\" target=\"_blank\" rel=\"noopener\">ES6 模块系统</a><br>对于ES6的模块系统,文章首先是对严格模式的一些总结,然后是对export 和 import 展开总结性的说明了各种绑定方式。</p>\n</li>\n<li><p><a href=\"https://github.com/berwin/Blog/issues/14\" target=\"_blank\" rel=\"noopener\">Vue 项目架构设计与工程化实践 </a><br>作者详述了自己Vue搭建项目的过程:技术选型(Vue全家桶)->架构设计(不同层面的职责)->发布上线。整个过程较为详细,举例项目遇到的问题及解决方案,对于搭建项目有一定的参考价值。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92879/\" target=\"_blank\" rel=\"noopener\">深入探讨前端组件化开发</a><br>这几年,从陷入 “React、Vue 和 Angular 哪个性能好?”的争论,到现在的各个框架(库)的生态越来越完善,讨论性能差距已经没有价值了。而国内的前端娱乐圈,最火的就是 React 和 Vue 了,而 Angular 由于历史原因,在国内的占有率确实不高。</p>\n</li>\n<li><p><a href=\"http://fex.baidu.com/blog/2017/10/build-a-silky-smooth-slide-library/\" target=\"_blank\" rel=\"noopener\">打造丝般顺滑的 H5 翻页库</a><br>翻页组件实现起来并不难,本文在此基础上进一步尝试打造丝般顺滑的效果,各种优化手段值得学习。</p>\n</li>\n<li><p><a href=\"http://blog.csdn.net/wclimb/article/details/77890793\" target=\"_blank\" rel=\"noopener\">使用Node+Koa2+Mysql搭建简易博客</a><br>Koa2使用实例,从Koa安装到项目建立模版使用,代码很详细的项目实例。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第4期 (本期小编:李丽娇)","date":"2017-07-12T07:16:43.000Z","_content":"\n## 基础\n* [SVG的用法](http://www.webhek.com/post/svg.html)\n**SVG基础和使用介绍**\n\n* [浏览器的渲染原理简介](http://coolshell.cn/articles/9666.html)\n**由浅到深、简单易懂的浏览器渲染原理介绍**\n\n* [Mongoose学习参考文档——基础篇](http://ourjs.com/detail/53ad24edb984bb4659000013)\n**Nodejs使用MongoDB的详细介绍**\n\n\n## 文章\n* [ECMAScript 6 入门-Symbol](http://es6.ruanyifeng.com/#docs/symbol)\n [symbols类型](http://www.infoq.com/cn/articles/es6-in-depth-symbols)\n<small>*推荐人:王祥*</small>\n继六种数据类型(Undefined、Null、Boolean、Number、String、Object)后,ES6又新增了Symbols类型。Symbols类型比较抽象,要了解相关的适应场景,可以看这两篇文章。\n\n* [Vue 与 iOS 的组件化](https://juejin.im/post/59626ca0f265da6c2442fbdf)\n<small>*推荐人:张成斌*</small>\n对Vue的组件化有一个非常清晰的讲解。组件化原理,组件化分,组件间传递都有涉及。另外笔者是一名普通的全职 iOS 开发者,还介绍iOS的组件化的东西,对前端和移动端进行了一些对比。\n\n* [SVG Sprite技术介绍](http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/)\n<small>*推荐人:李丽娇*</small>\n使用svg文件显示小图标已经成为趋势,随之而来地,svg文件合并也成为必然需求。文中介绍了svg sprite的使用原理,并介绍了多种生成svg sprite的方式来满足偏前端、偏命令、偏设计各类coder的需求。\n\n* [ECharts 统计扩展教程](http://efe.baidu.com/blog/echarts-statistical-extension-tutorial/)\n<small>*推荐人:胡国伟*</small>\nECharts 统计扩展,包含的功能有直方图、聚类、回归、以及常用的汇总统计。通过统计扩展和 ECharts 的结合,可以使大家方便地实现可视分析,也就是将数据分析的结果,通过可视化直观地呈现出来。\n\n* [前端性能优化相关](https://github.com/wy-ei/notebook/issues/34#issuecomment-266946255)\n<small>*推荐人:陶明*</small>\n从多角度进行性能问题剖析,对JavaScript,DOM,CSS都介绍了性能优化方面的问题因素及解决方案;内容介绍不是很详细,例如对于debounce 进行消抖只是简单说明,这方面在第一期成斌有推荐详细的[文章](https://github.com/mqyqingfeng/Blog/issues/22)。\n\n* [JavaScript问题集锦](https://github.com/creeperyang/blog/issues/2)\n<small>*推荐人:李志伟*</small>\n文章整理了一些比较有价值且常见的JS问题,看似简单,但深究其原理还是很有必要的,相信对你的JS基础功底是个考验。\n\n* [浅谈 JS 对象之扩展、密封及冻结三大特性](https://segmentfault.com/a/1190000003894119)\n<small>*推荐人:耿少真*</small>\n由浅入深讨论JS中对象的扩展、密封及冻结特性,从三种不同的冻结程度介绍了 js 冻结对象的方法。\n##### 扩展特性:\n - Object.isExtensible 方法\n - Object.preventExtensions 方法\n##### 密封特性:\n - Object.isSealed 方法\n - Object.seal 方法\n##### 冻结特性\n - Object.isFrozen 方法\n - Object.freeze 方法\n\n* [十大经典排序算法](https://github.com/hustcc/JS-Sorting-Algorithm)\n<small>*推荐人:郭俊兵*</small>\n排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。\n\n* [Javascript模块化编程(一):模块的写法](http://www.ruanyifeng.com/blog/2012/10/javascript_module.html)\n [Javascript模块化编程(二):AMD规范](http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html)\n [Javascript模块化编程(三):require.js的用法](http://www.ruanyifeng.com/blog/2012/11/require_js.html)\n<small>*推荐人:包京京*</small>\n阮一峰的文章最大的好处就是解释的清楚,很多大牛工程师不善表达,自己会但不一定能教得会。\n三篇系列文章介绍了:js模块花的基本概念,AMD规范以及require.js的实践。\n","source":"_posts/weekly-4.md","raw":"---\ntitle: 大前端周刊 第4期 (本期小编:李丽娇)\ndate: 2017-07-12 15:16:43\ntags: [weekly,Echarts,ES6,Vue,SVG,算法,模块化,性能优化]\n\n---\n\n## 基础\n* [SVG的用法](http://www.webhek.com/post/svg.html)\n**SVG基础和使用介绍**\n\n* [浏览器的渲染原理简介](http://coolshell.cn/articles/9666.html)\n**由浅到深、简单易懂的浏览器渲染原理介绍**\n\n* [Mongoose学习参考文档——基础篇](http://ourjs.com/detail/53ad24edb984bb4659000013)\n**Nodejs使用MongoDB的详细介绍**\n\n\n## 文章\n* [ECMAScript 6 入门-Symbol](http://es6.ruanyifeng.com/#docs/symbol)\n [symbols类型](http://www.infoq.com/cn/articles/es6-in-depth-symbols)\n<small>*推荐人:王祥*</small>\n继六种数据类型(Undefined、Null、Boolean、Number、String、Object)后,ES6又新增了Symbols类型。Symbols类型比较抽象,要了解相关的适应场景,可以看这两篇文章。\n\n* [Vue 与 iOS 的组件化](https://juejin.im/post/59626ca0f265da6c2442fbdf)\n<small>*推荐人:张成斌*</small>\n对Vue的组件化有一个非常清晰的讲解。组件化原理,组件化分,组件间传递都有涉及。另外笔者是一名普通的全职 iOS 开发者,还介绍iOS的组件化的东西,对前端和移动端进行了一些对比。\n\n* [SVG Sprite技术介绍](http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/)\n<small>*推荐人:李丽娇*</small>\n使用svg文件显示小图标已经成为趋势,随之而来地,svg文件合并也成为必然需求。文中介绍了svg sprite的使用原理,并介绍了多种生成svg sprite的方式来满足偏前端、偏命令、偏设计各类coder的需求。\n\n* [ECharts 统计扩展教程](http://efe.baidu.com/blog/echarts-statistical-extension-tutorial/)\n<small>*推荐人:胡国伟*</small>\nECharts 统计扩展,包含的功能有直方图、聚类、回归、以及常用的汇总统计。通过统计扩展和 ECharts 的结合,可以使大家方便地实现可视分析,也就是将数据分析的结果,通过可视化直观地呈现出来。\n\n* [前端性能优化相关](https://github.com/wy-ei/notebook/issues/34#issuecomment-266946255)\n<small>*推荐人:陶明*</small>\n从多角度进行性能问题剖析,对JavaScript,DOM,CSS都介绍了性能优化方面的问题因素及解决方案;内容介绍不是很详细,例如对于debounce 进行消抖只是简单说明,这方面在第一期成斌有推荐详细的[文章](https://github.com/mqyqingfeng/Blog/issues/22)。\n\n* [JavaScript问题集锦](https://github.com/creeperyang/blog/issues/2)\n<small>*推荐人:李志伟*</small>\n文章整理了一些比较有价值且常见的JS问题,看似简单,但深究其原理还是很有必要的,相信对你的JS基础功底是个考验。\n\n* [浅谈 JS 对象之扩展、密封及冻结三大特性](https://segmentfault.com/a/1190000003894119)\n<small>*推荐人:耿少真*</small>\n由浅入深讨论JS中对象的扩展、密封及冻结特性,从三种不同的冻结程度介绍了 js 冻结对象的方法。\n##### 扩展特性:\n - Object.isExtensible 方法\n - Object.preventExtensions 方法\n##### 密封特性:\n - Object.isSealed 方法\n - Object.seal 方法\n##### 冻结特性\n - Object.isFrozen 方法\n - Object.freeze 方法\n\n* [十大经典排序算法](https://github.com/hustcc/JS-Sorting-Algorithm)\n<small>*推荐人:郭俊兵*</small>\n排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。\n\n* [Javascript模块化编程(一):模块的写法](http://www.ruanyifeng.com/blog/2012/10/javascript_module.html)\n [Javascript模块化编程(二):AMD规范](http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html)\n [Javascript模块化编程(三):require.js的用法](http://www.ruanyifeng.com/blog/2012/11/require_js.html)\n<small>*推荐人:包京京*</small>\n阮一峰的文章最大的好处就是解释的清楚,很多大牛工程师不善表达,自己会但不一定能教得会。\n三篇系列文章介绍了:js模块花的基本概念,AMD规范以及require.js的实践。\n","slug":"weekly-4","published":1,"updated":"2017-08-25T02:32:20.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qkx000kjrs6twvxrcgr","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://www.webhek.com/post/svg.html\" target=\"_blank\" rel=\"noopener\">SVG的用法</a><br><strong>SVG基础和使用介绍</strong></p>\n</li>\n<li><p><a href=\"http://coolshell.cn/articles/9666.html\" target=\"_blank\" rel=\"noopener\">浏览器的渲染原理简介</a><br><strong>由浅到深、简单易懂的浏览器渲染原理介绍</strong></p>\n</li>\n<li><p><a href=\"http://ourjs.com/detail/53ad24edb984bb4659000013\" target=\"_blank\" rel=\"noopener\">Mongoose学习参考文档——基础篇</a><br><strong>Nodejs使用MongoDB的详细介绍</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/symbol\" target=\"_blank\" rel=\"noopener\">ECMAScript 6 入门-Symbol</a><br><a href=\"http://www.infoq.com/cn/articles/es6-in-depth-symbols\" target=\"_blank\" rel=\"noopener\">symbols类型</a><br><small><em>推荐人:王祥</em></small><br>继六种数据类型(Undefined、Null、Boolean、Number、String、Object)后,ES6又新增了Symbols类型。Symbols类型比较抽象,要了解相关的适应场景,可以看这两篇文章。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59626ca0f265da6c2442fbdf\" target=\"_blank\" rel=\"noopener\">Vue 与 iOS 的组件化</a><br><small><em>推荐人:张成斌</em></small><br>对Vue的组件化有一个非常清晰的讲解。组件化原理,组件化分,组件间传递都有涉及。另外笔者是一名普通的全职 iOS 开发者,还介绍iOS的组件化的东西,对前端和移动端进行了一些对比。</p>\n</li>\n<li><p><a href=\"http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/\" target=\"_blank\" rel=\"noopener\">SVG Sprite技术介绍</a><br><small><em>推荐人:李丽娇</em></small><br>使用svg文件显示小图标已经成为趋势,随之而来地,svg文件合并也成为必然需求。文中介绍了svg sprite的使用原理,并介绍了多种生成svg sprite的方式来满足偏前端、偏命令、偏设计各类coder的需求。</p>\n</li>\n<li><p><a href=\"http://efe.baidu.com/blog/echarts-statistical-extension-tutorial/\" target=\"_blank\" rel=\"noopener\">ECharts 统计扩展教程</a><br><small><em>推荐人:胡国伟</em></small><br>ECharts 统计扩展,包含的功能有直方图、聚类、回归、以及常用的汇总统计。通过统计扩展和 ECharts 的结合,可以使大家方便地实现可视分析,也就是将数据分析的结果,通过可视化直观地呈现出来。</p>\n</li>\n<li><p><a href=\"https://github.com/wy-ei/notebook/issues/34#issuecomment-266946255\" target=\"_blank\" rel=\"noopener\">前端性能优化相关</a><br><small><em>推荐人:陶明</em></small><br>从多角度进行性能问题剖析,对JavaScript,DOM,CSS都介绍了性能优化方面的问题因素及解决方案;内容介绍不是很详细,例如对于debounce 进行消抖只是简单说明,这方面在第一期成斌有推荐详细的<a href=\"https://github.com/mqyqingfeng/Blog/issues/22\" target=\"_blank\" rel=\"noopener\">文章</a>。</p>\n</li>\n<li><p><a href=\"https://github.com/creeperyang/blog/issues/2\" target=\"_blank\" rel=\"noopener\">JavaScript问题集锦</a><br><small><em>推荐人:李志伟</em></small><br>文章整理了一些比较有价值且常见的JS问题,看似简单,但深究其原理还是很有必要的,相信对你的JS基础功底是个考验。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000003894119\" target=\"_blank\" rel=\"noopener\">浅谈 JS 对象之扩展、密封及冻结三大特性</a><br><small><em>推荐人:耿少真</em></small><br>由浅入深讨论JS中对象的扩展、密封及冻结特性,从三种不同的冻结程度介绍了 js 冻结对象的方法。</p>\n<h5 id=\"扩展特性\"><a href=\"#扩展特性\" class=\"headerlink\" title=\"扩展特性:\"></a>扩展特性:</h5><ul>\n<li>Object.isExtensible 方法</li>\n<li>Object.preventExtensions 方法<h5 id=\"密封特性\"><a href=\"#密封特性\" class=\"headerlink\" title=\"密封特性:\"></a>密封特性:</h5></li>\n<li>Object.isSealed 方法</li>\n<li>Object.seal 方法<h5 id=\"冻结特性\"><a href=\"#冻结特性\" class=\"headerlink\" title=\"冻结特性\"></a>冻结特性</h5></li>\n<li>Object.isFrozen 方法</li>\n<li>Object.freeze 方法</li>\n</ul>\n</li>\n<li><p><a href=\"https://github.com/hustcc/JS-Sorting-Algorithm\" target=\"_blank\" rel=\"noopener\">十大经典排序算法</a><br><small><em>推荐人:郭俊兵</em></small><br>排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/10/javascript_module.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(一):模块的写法</a><br><a href=\"http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(二):AMD规范</a><br><a href=\"http://www.ruanyifeng.com/blog/2012/11/require_js.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(三):require.js的用法</a><br><small><em>推荐人:包京京</em></small><br>阮一峰的文章最大的好处就是解释的清楚,很多大牛工程师不善表达,自己会但不一定能教得会。<br>三篇系列文章介绍了:js模块花的基本概念,AMD规范以及require.js的实践。</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://www.webhek.com/post/svg.html\" target=\"_blank\" rel=\"noopener\">SVG的用法</a><br><strong>SVG基础和使用介绍</strong></p>\n</li>\n<li><p><a href=\"http://coolshell.cn/articles/9666.html\" target=\"_blank\" rel=\"noopener\">浏览器的渲染原理简介</a><br><strong>由浅到深、简单易懂的浏览器渲染原理介绍</strong></p>\n</li>\n<li><p><a href=\"http://ourjs.com/detail/53ad24edb984bb4659000013\" target=\"_blank\" rel=\"noopener\">Mongoose学习参考文档——基础篇</a><br><strong>Nodejs使用MongoDB的详细介绍</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/symbol\" target=\"_blank\" rel=\"noopener\">ECMAScript 6 入门-Symbol</a><br><a href=\"http://www.infoq.com/cn/articles/es6-in-depth-symbols\" target=\"_blank\" rel=\"noopener\">symbols类型</a><br><small><em>推荐人:王祥</em></small><br>继六种数据类型(Undefined、Null、Boolean、Number、String、Object)后,ES6又新增了Symbols类型。Symbols类型比较抽象,要了解相关的适应场景,可以看这两篇文章。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59626ca0f265da6c2442fbdf\" target=\"_blank\" rel=\"noopener\">Vue 与 iOS 的组件化</a><br><small><em>推荐人:张成斌</em></small><br>对Vue的组件化有一个非常清晰的讲解。组件化原理,组件化分,组件间传递都有涉及。另外笔者是一名普通的全职 iOS 开发者,还介绍iOS的组件化的东西,对前端和移动端进行了一些对比。</p>\n</li>\n<li><p><a href=\"http://www.zhangxinxu.com/wordpress/2014/07/introduce-svg-sprite-technology/\" target=\"_blank\" rel=\"noopener\">SVG Sprite技术介绍</a><br><small><em>推荐人:李丽娇</em></small><br>使用svg文件显示小图标已经成为趋势,随之而来地,svg文件合并也成为必然需求。文中介绍了svg sprite的使用原理,并介绍了多种生成svg sprite的方式来满足偏前端、偏命令、偏设计各类coder的需求。</p>\n</li>\n<li><p><a href=\"http://efe.baidu.com/blog/echarts-statistical-extension-tutorial/\" target=\"_blank\" rel=\"noopener\">ECharts 统计扩展教程</a><br><small><em>推荐人:胡国伟</em></small><br>ECharts 统计扩展,包含的功能有直方图、聚类、回归、以及常用的汇总统计。通过统计扩展和 ECharts 的结合,可以使大家方便地实现可视分析,也就是将数据分析的结果,通过可视化直观地呈现出来。</p>\n</li>\n<li><p><a href=\"https://github.com/wy-ei/notebook/issues/34#issuecomment-266946255\" target=\"_blank\" rel=\"noopener\">前端性能优化相关</a><br><small><em>推荐人:陶明</em></small><br>从多角度进行性能问题剖析,对JavaScript,DOM,CSS都介绍了性能优化方面的问题因素及解决方案;内容介绍不是很详细,例如对于debounce 进行消抖只是简单说明,这方面在第一期成斌有推荐详细的<a href=\"https://github.com/mqyqingfeng/Blog/issues/22\" target=\"_blank\" rel=\"noopener\">文章</a>。</p>\n</li>\n<li><p><a href=\"https://github.com/creeperyang/blog/issues/2\" target=\"_blank\" rel=\"noopener\">JavaScript问题集锦</a><br><small><em>推荐人:李志伟</em></small><br>文章整理了一些比较有价值且常见的JS问题,看似简单,但深究其原理还是很有必要的,相信对你的JS基础功底是个考验。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000003894119\" target=\"_blank\" rel=\"noopener\">浅谈 JS 对象之扩展、密封及冻结三大特性</a><br><small><em>推荐人:耿少真</em></small><br>由浅入深讨论JS中对象的扩展、密封及冻结特性,从三种不同的冻结程度介绍了 js 冻结对象的方法。</p>\n<h5 id=\"扩展特性\"><a href=\"#扩展特性\" class=\"headerlink\" title=\"扩展特性:\"></a>扩展特性:</h5><ul>\n<li>Object.isExtensible 方法</li>\n<li>Object.preventExtensions 方法<h5 id=\"密封特性\"><a href=\"#密封特性\" class=\"headerlink\" title=\"密封特性:\"></a>密封特性:</h5></li>\n<li>Object.isSealed 方法</li>\n<li>Object.seal 方法<h5 id=\"冻结特性\"><a href=\"#冻结特性\" class=\"headerlink\" title=\"冻结特性\"></a>冻结特性</h5></li>\n<li>Object.isFrozen 方法</li>\n<li>Object.freeze 方法</li>\n</ul>\n</li>\n<li><p><a href=\"https://github.com/hustcc/JS-Sorting-Algorithm\" target=\"_blank\" rel=\"noopener\">十大经典排序算法</a><br><small><em>推荐人:郭俊兵</em></small><br>排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/10/javascript_module.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(一):模块的写法</a><br><a href=\"http://www.ruanyifeng.com/blog/2012/10/asynchronous_module_definition.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(二):AMD规范</a><br><a href=\"http://www.ruanyifeng.com/blog/2012/11/require_js.html\" target=\"_blank\" rel=\"noopener\">Javascript模块化编程(三):require.js的用法</a><br><small><em>推荐人:包京京</em></small><br>阮一峰的文章最大的好处就是解释的清楚,很多大牛工程师不善表达,自己会但不一定能教得会。<br>三篇系列文章介绍了:js模块花的基本概念,AMD规范以及require.js的实践。</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第21期 (本期小编:李凡)","date":"2017-11-17T04:52:13.000Z","_content":"## Show me the code\n\n### 关于Promise对象容易忽视的几个问题\n\n1.resolve后的执行情况\n\n无论是 resolve, reject,都会将函数剩余的代码执行完\n``` javascript\nconst promise = new Promise((resolve, reject) => {\n console.log('mark 1');\n resolve('hello world'); // reject('hello world');\n console.log('mark 2');\n});\n\npromise.then(result => {\n console.log(result);\n}).catch(err => {\n console.log(err);\n});\n```\n2.调用 then 方法返回新的 Promise 对象\n``` javascript\nlet promise1 = new Promise((resolve) => {\n resolve('Hello world')\n})\n\nlet promise2 = promise1.then()\n\nconsole.log(promise1 === promise2) // false\nconsole.log(promise1 instanceof Promise) // true\nconsole.log(promise2 instanceof Promise) // true\n```\n3.串行执行和并行执行\n- 串行执行:有一堆 Promise 对象,它们的执行顺序是固定的,前一个 promise 执行完后,后一个 promise 才开始执行,比如数据库查询,它们往往有前后的因果关系。\n- 并行执行:有一堆 Promise 对象,它们的执行顺序是不固定的,没有前后因果关系,可以并发地去执行。\n\n\n```javascript\n//串行方式一\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\nlet serial = Promise.resolve();\n\nfor(let i of datum) {\n serial = serial.then(data => {\n console.log(data);\n\treturn new Promise((resolve, reject) => {\n\t setTimeout(() => {\n\t\tconsole.log(i * 200 + \" ms 后执行结束\");\n\t\tresolve(\"第 \" + (i + 1) + \" 个 Promise 执行结束\");\n\t }, i * 200);\n\t})\t\n });\n}\n\n//串行方式二 使用reduce\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\ndatum.reduce((prev, cur) => {\n return prev.then(data => {\n\tconsole.log(data);\n\treturn new Promise((resolve, reject) => {\n\t setTimeout(() => {\n\t\tconsole.log(cur * 200 + \" ms 后执行结束\");\n\t\tresolve(\"第 \" + (cur + 1) + \" 个 Promise 执行结束\");\n\t }, cur * 200);\n\t})\t\n })\n}, Promise.resolve(true));\n```\n并行执行很好解决,在 Promise中有 all 这个函数支持, Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当多个 Promise 实例执行完后才去执行最后新的 Promise 实例。\n```javascript\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\nPromise.all(datum.map(i => {\n return new Promise((resolve, reject) => {\n\tsetTimeout(() => {\n\t console.log(i * 200 + \" ms 后执行结束\");\n\t resolve(\"第 \" + (i + 1) + \" 个 Promise 执行结束\");\n\t}, i * 200);\n })\n})).then((data) => {\n console.log(data);\n});\n\n```\n如果不使用 Promise.all 这个方法的话,你也可以使用像 ES7 的 async/await\n\n```javascript\nconst asyncFun = async () => {\n const datum = []\n for(let i = 0; i < 10; i++) {\n datum.push(new Promise((resolve, reject) => {\n setTimeout(() => {\n console.log(i * 200 + 'ms 后执行结束')\n resolve('第 ' + (i + 1) + ' 个 Promise 执行结束')\n }, i * 200)\n }))\n }\n const result = []\n for(let promise of datum) {\n result.push(await promise)\n }\n console.log(result)\n}\nasyncFun()\n```\n\n4 . 结合 async/await 编写同步代码\n- async/await 函数可以帮助我们彻底摆脱回调地狱的烦恼,用一种同步的方式来编写异步函数。\n- await 后面可以接数值,如果是异步请求的话可以接 Thunk 函数和 Promise 对象。\n\n```javascript\nconst timeout = (ms) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(ms + ' passed')\n }, ms)\n })\n}\n\nconst asyncFunc = async () => {\n const value1 = await timeout(2000)\n console.log(value1)\n const value2 = await timeout(2000)\n console.log(value2)\n}\n\nasyncFunc()\nconsole.log('now')\n```\n5 .resolved 状态的 Promise 不会立即执行\n\n```javascript\nlet i = 0;\nPromise.resolve('resolved promise').then(() => {\n i += 2\n})\nconsole.log(i) // 0\n```\n\n\n## 文章推荐\n* [TypeScript 入门指南](http://www.oschina.net/question/12_72250)\n TypeScript入门指南,适合入门了解。\n\n\n\n* [别再拿奇技淫巧搬砖了](https://juejin.im/post/5a0b29756fb9a045167cb643)\n技巧性的知识大家都有掌握,使用场景及方式是否合理也是个问题。\n文章总结了一些常见的编程技巧的利弊,希望对大家有所帮助。\n\n\n\n* [抓住数据的小尾巴 - JS浮点数陷阱及解法](https://zhuanlan.zhihu.com/p/30703042?utm_medium=social&utm_source=wechat_session)\n推荐:众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004、1-0.9=0.09999999999999998,很多人知道这是浮点数误差问题,但具体原因就说不清楚了。本文帮你理清这背后的原理以及解决方案,还会向你解释JS中的大数危机和四则运算中会遇到的坑。\n\n\n\n* [打造自己的JavaScript武器库](https://juejin.im/post/5a091afe6fb9a044ff30f402)\n作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率。这里提一个小点,我们在业务开发过程中,经常会重复用到日期格式化、url参数转对象、浏览器类型判断、节流函数等一类函数,这些工具类函数,基本上在每个项目都会用到,为避免不同项目多次复制粘贴的麻烦,我们可以统一封装,发布到npm,以提高开发效率。\n\n\n\n* [浏览器渲染引擎](https://juejin.im/post/59f5bbdb6fb9a0451968d851)\n浏览器基础是前端知识网中的一个小分支,也是前端开发人员必须掌握的基础知识点。他贯穿着前端的整个网络体系,项目优化也是围绕着浏览器进行的。\n\n\n\n* [美化表单的CSS高级技巧](https://www.w3cplus.com/css/advanced-css-form-styling.html)\n\t通常前端业务离不开表单,而其本身的UI确实不太美观,文章通过一些选择器实现常用表单的美化,相信对有定制化表单需求的小伙伴有所帮助。\n\n\n\n* [websocket服务器监控](http://blog.fens.me/nodejs-websocket-monitor/)\n\t这篇文章解释了一个简单的例子,用NodeJS搭建一个服务器监控程序,核心是socket.io实现的real time通信,另外还有node.js的child_process模块来实现进程管理。从这个简单而有用的例子出发,可以去研究socket.io和child_process的深层用法。\n\n\n\n* [Web应用程序和Git的双向同步](https://ponyfoo.com/articles/two-way-synchronization-for-a-web-app-and-git)\n通过钩子函数实现数据库与git仓库之间的双向同步,当数据库发生变化时,git仓库也进行相应同步操作。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","source":"_posts/weekly-21.md","raw":"---\ntitle: 大前端周刊 第21期 (本期小编:李凡)\ndate: 2017-11-17 12:52:13\ntags:\n---\n## Show me the code\n\n### 关于Promise对象容易忽视的几个问题\n\n1.resolve后的执行情况\n\n无论是 resolve, reject,都会将函数剩余的代码执行完\n``` javascript\nconst promise = new Promise((resolve, reject) => {\n console.log('mark 1');\n resolve('hello world'); // reject('hello world');\n console.log('mark 2');\n});\n\npromise.then(result => {\n console.log(result);\n}).catch(err => {\n console.log(err);\n});\n```\n2.调用 then 方法返回新的 Promise 对象\n``` javascript\nlet promise1 = new Promise((resolve) => {\n resolve('Hello world')\n})\n\nlet promise2 = promise1.then()\n\nconsole.log(promise1 === promise2) // false\nconsole.log(promise1 instanceof Promise) // true\nconsole.log(promise2 instanceof Promise) // true\n```\n3.串行执行和并行执行\n- 串行执行:有一堆 Promise 对象,它们的执行顺序是固定的,前一个 promise 执行完后,后一个 promise 才开始执行,比如数据库查询,它们往往有前后的因果关系。\n- 并行执行:有一堆 Promise 对象,它们的执行顺序是不固定的,没有前后因果关系,可以并发地去执行。\n\n\n```javascript\n//串行方式一\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\nlet serial = Promise.resolve();\n\nfor(let i of datum) {\n serial = serial.then(data => {\n console.log(data);\n\treturn new Promise((resolve, reject) => {\n\t setTimeout(() => {\n\t\tconsole.log(i * 200 + \" ms 后执行结束\");\n\t\tresolve(\"第 \" + (i + 1) + \" 个 Promise 执行结束\");\n\t }, i * 200);\n\t})\t\n });\n}\n\n//串行方式二 使用reduce\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\ndatum.reduce((prev, cur) => {\n return prev.then(data => {\n\tconsole.log(data);\n\treturn new Promise((resolve, reject) => {\n\t setTimeout(() => {\n\t\tconsole.log(cur * 200 + \" ms 后执行结束\");\n\t\tresolve(\"第 \" + (cur + 1) + \" 个 Promise 执行结束\");\n\t }, cur * 200);\n\t})\t\n })\n}, Promise.resolve(true));\n```\n并行执行很好解决,在 Promise中有 all 这个函数支持, Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当多个 Promise 实例执行完后才去执行最后新的 Promise 实例。\n```javascript\nconst datum = [];\nfor(let i = 0; i < 10; i++) {\n datum.push(i);\n}\n\nPromise.all(datum.map(i => {\n return new Promise((resolve, reject) => {\n\tsetTimeout(() => {\n\t console.log(i * 200 + \" ms 后执行结束\");\n\t resolve(\"第 \" + (i + 1) + \" 个 Promise 执行结束\");\n\t}, i * 200);\n })\n})).then((data) => {\n console.log(data);\n});\n\n```\n如果不使用 Promise.all 这个方法的话,你也可以使用像 ES7 的 async/await\n\n```javascript\nconst asyncFun = async () => {\n const datum = []\n for(let i = 0; i < 10; i++) {\n datum.push(new Promise((resolve, reject) => {\n setTimeout(() => {\n console.log(i * 200 + 'ms 后执行结束')\n resolve('第 ' + (i + 1) + ' 个 Promise 执行结束')\n }, i * 200)\n }))\n }\n const result = []\n for(let promise of datum) {\n result.push(await promise)\n }\n console.log(result)\n}\nasyncFun()\n```\n\n4 . 结合 async/await 编写同步代码\n- async/await 函数可以帮助我们彻底摆脱回调地狱的烦恼,用一种同步的方式来编写异步函数。\n- await 后面可以接数值,如果是异步请求的话可以接 Thunk 函数和 Promise 对象。\n\n```javascript\nconst timeout = (ms) => {\n return new Promise((resolve) => {\n setTimeout(() => {\n resolve(ms + ' passed')\n }, ms)\n })\n}\n\nconst asyncFunc = async () => {\n const value1 = await timeout(2000)\n console.log(value1)\n const value2 = await timeout(2000)\n console.log(value2)\n}\n\nasyncFunc()\nconsole.log('now')\n```\n5 .resolved 状态的 Promise 不会立即执行\n\n```javascript\nlet i = 0;\nPromise.resolve('resolved promise').then(() => {\n i += 2\n})\nconsole.log(i) // 0\n```\n\n\n## 文章推荐\n* [TypeScript 入门指南](http://www.oschina.net/question/12_72250)\n TypeScript入门指南,适合入门了解。\n\n\n\n* [别再拿奇技淫巧搬砖了](https://juejin.im/post/5a0b29756fb9a045167cb643)\n技巧性的知识大家都有掌握,使用场景及方式是否合理也是个问题。\n文章总结了一些常见的编程技巧的利弊,希望对大家有所帮助。\n\n\n\n* [抓住数据的小尾巴 - JS浮点数陷阱及解法](https://zhuanlan.zhihu.com/p/30703042?utm_medium=social&utm_source=wechat_session)\n推荐:众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004、1-0.9=0.09999999999999998,很多人知道这是浮点数误差问题,但具体原因就说不清楚了。本文帮你理清这背后的原理以及解决方案,还会向你解释JS中的大数危机和四则运算中会遇到的坑。\n\n\n\n* [打造自己的JavaScript武器库](https://juejin.im/post/5a091afe6fb9a044ff30f402)\n作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率。这里提一个小点,我们在业务开发过程中,经常会重复用到日期格式化、url参数转对象、浏览器类型判断、节流函数等一类函数,这些工具类函数,基本上在每个项目都会用到,为避免不同项目多次复制粘贴的麻烦,我们可以统一封装,发布到npm,以提高开发效率。\n\n\n\n* [浏览器渲染引擎](https://juejin.im/post/59f5bbdb6fb9a0451968d851)\n浏览器基础是前端知识网中的一个小分支,也是前端开发人员必须掌握的基础知识点。他贯穿着前端的整个网络体系,项目优化也是围绕着浏览器进行的。\n\n\n\n* [美化表单的CSS高级技巧](https://www.w3cplus.com/css/advanced-css-form-styling.html)\n\t通常前端业务离不开表单,而其本身的UI确实不太美观,文章通过一些选择器实现常用表单的美化,相信对有定制化表单需求的小伙伴有所帮助。\n\n\n\n* [websocket服务器监控](http://blog.fens.me/nodejs-websocket-monitor/)\n\t这篇文章解释了一个简单的例子,用NodeJS搭建一个服务器监控程序,核心是socket.io实现的real time通信,另外还有node.js的child_process模块来实现进程管理。从这个简单而有用的例子出发,可以去研究socket.io和child_process的深层用法。\n\n\n\n* [Web应用程序和Git的双向同步](https://ponyfoo.com/articles/two-way-synchronization-for-a-web-app-and-git)\n通过钩子函数实现数据库与git仓库之间的双向同步,当数据库发生变化时,git仓库也进行相应同步操作。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```\n","slug":"weekly-21","published":1,"updated":"2019-03-01T16:26:16.529Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qky000mjrs68jfe0pjx","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"关于Promise对象容易忽视的几个问题\"><a href=\"#关于Promise对象容易忽视的几个问题\" class=\"headerlink\" title=\"关于Promise对象容易忽视的几个问题\"></a>关于Promise对象容易忽视的几个问题</h3><p>1.resolve后的执行情况</p>\n<p>无论是 resolve, reject,都会将函数剩余的代码执行完<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> promise = <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'mark 1'</span>);</span><br><span class=\"line\"> resolve(<span class=\"string\">'hello world'</span>); <span class=\"comment\">// reject('hello world');</span></span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'mark 2'</span>);</span><br><span class=\"line\">});</span><br><span class=\"line\"></span><br><span class=\"line\">promise.then(<span class=\"function\"><span class=\"params\">result</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(result);</span><br><span class=\"line\">}).catch(<span class=\"function\"><span class=\"params\">err</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(err);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>2.调用 then 方法返回新的 Promise 对象<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> promise1 = <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> resolve(<span class=\"string\">'Hello world'</span>)</span><br><span class=\"line\">})</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> promise2 = promise1.then()</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise1 === promise2) <span class=\"comment\">// false</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise1 <span class=\"keyword\">instanceof</span> <span class=\"built_in\">Promise</span>) <span class=\"comment\">// true</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise2 <span class=\"keyword\">instanceof</span> <span class=\"built_in\">Promise</span>) <span class=\"comment\">// true</span></span><br></pre></td></tr></table></figure></p>\n<p>3.串行执行和并行执行</p>\n<ul>\n<li>串行执行:有一堆 Promise 对象,它们的执行顺序是固定的,前一个 promise 执行完后,后一个 promise 才开始执行,比如数据库查询,它们往往有前后的因果关系。</li>\n<li>并行执行:有一堆 Promise 对象,它们的执行顺序是不固定的,没有前后因果关系,可以并发地去执行。</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//串行方式一</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> serial = <span class=\"built_in\">Promise</span>.resolve();</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i <span class=\"keyword\">of</span> datum) {</span><br><span class=\"line\"> serial = serial.then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\t setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t\t<span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t\tresolve(<span class=\"string\">\"第 \"</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t }, i * <span class=\"number\">200</span>);</span><br><span class=\"line\">\t})\t</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//串行方式二 使用reduce</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">datum.reduce(<span class=\"function\">(<span class=\"params\">prev, cur</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> prev.then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\">\t<span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\t setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t\t<span class=\"built_in\">console</span>.log(cur * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t\tresolve(<span class=\"string\">\"第 \"</span> + (cur + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t }, cur * <span class=\"number\">200</span>);</span><br><span class=\"line\">\t})\t</span><br><span class=\"line\"> })</span><br><span class=\"line\">}, <span class=\"built_in\">Promise</span>.resolve(<span class=\"literal\">true</span>));</span><br></pre></td></tr></table></figure>\n<p>并行执行很好解决,在 Promise中有 all 这个函数支持, Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当多个 Promise 实例执行完后才去执行最后新的 Promise 实例。<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">Promise</span>.all(datum.map(<span class=\"function\"><span class=\"params\">i</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\tsetTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t <span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t resolve(<span class=\"string\">\"第 \"</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t}, i * <span class=\"number\">200</span>);</span><br><span class=\"line\"> })</span><br><span class=\"line\">})).then(<span class=\"function\">(<span class=\"params\">data</span>) =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>如果不使用 Promise.all 这个方法的话,你也可以使用像 ES7 的 async/await</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> asyncFun = <span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> datum = []</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(<span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">'ms 后执行结束'</span>)</span><br><span class=\"line\"> resolve(<span class=\"string\">'第 '</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">' 个 Promise 执行结束'</span>)</span><br><span class=\"line\"> }, i * <span class=\"number\">200</span>)</span><br><span class=\"line\"> }))</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">const</span> result = []</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> promise <span class=\"keyword\">of</span> datum) {</span><br><span class=\"line\"> result.push(<span class=\"keyword\">await</span> promise)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(result)</span><br><span class=\"line\">}</span><br><span class=\"line\">asyncFun()</span><br></pre></td></tr></table></figure>\n<p>4 . 结合 async/await 编写同步代码</p>\n<ul>\n<li>async/await 函数可以帮助我们彻底摆脱回调地狱的烦恼,用一种同步的方式来编写异步函数。</li>\n<li>await 后面可以接数值,如果是异步请求的话可以接 Thunk 函数和 Promise 对象。</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> timeout = <span class=\"function\">(<span class=\"params\">ms</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> resolve(ms + <span class=\"string\">' passed'</span>)</span><br><span class=\"line\"> }, ms)</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> asyncFunc = <span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> value1 = <span class=\"keyword\">await</span> timeout(<span class=\"number\">2000</span>)</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(value1)</span><br><span class=\"line\"> <span class=\"keyword\">const</span> value2 = <span class=\"keyword\">await</span> timeout(<span class=\"number\">2000</span>)</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(value2)</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">asyncFunc()</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(<span class=\"string\">'now'</span>)</span><br></pre></td></tr></table></figure>\n<p>5 .resolved 状态的 Promise 不会立即执行</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> i = <span class=\"number\">0</span>;</span><br><span class=\"line\"><span class=\"built_in\">Promise</span>.resolve(<span class=\"string\">'resolved promise'</span>).then(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> i += <span class=\"number\">2</span></span><br><span class=\"line\">})</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(i) <span class=\"comment\">// 0</span></span><br></pre></td></tr></table></figure>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><a href=\"http://www.oschina.net/question/12_72250\" target=\"_blank\" rel=\"noopener\">TypeScript 入门指南</a><br>TypeScript入门指南,适合入门了解。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/5a0b29756fb9a045167cb643\" target=\"_blank\" rel=\"noopener\">别再拿奇技淫巧搬砖了</a><br>技巧性的知识大家都有掌握,使用场景及方式是否合理也是个问题。<br>文章总结了一些常见的编程技巧的利弊,希望对大家有所帮助。</li>\n</ul>\n<ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/30703042?utm_medium=social&utm_source=wechat_session\" target=\"_blank\" rel=\"noopener\">抓住数据的小尾巴 - JS浮点数陷阱及解法</a><br>推荐:众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004、1-0.9=0.09999999999999998,很多人知道这是浮点数误差问题,但具体原因就说不清楚了。本文帮你理清这背后的原理以及解决方案,还会向你解释JS中的大数危机和四则运算中会遇到的坑。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/5a091afe6fb9a044ff30f402\" target=\"_blank\" rel=\"noopener\">打造自己的JavaScript武器库</a><br>作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率。这里提一个小点,我们在业务开发过程中,经常会重复用到日期格式化、url参数转对象、浏览器类型判断、节流函数等一类函数,这些工具类函数,基本上在每个项目都会用到,为避免不同项目多次复制粘贴的麻烦,我们可以统一封装,发布到npm,以提高开发效率。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/59f5bbdb6fb9a0451968d851\" target=\"_blank\" rel=\"noopener\">浏览器渲染引擎</a><br>浏览器基础是前端知识网中的一个小分支,也是前端开发人员必须掌握的基础知识点。他贯穿着前端的整个网络体系,项目优化也是围绕着浏览器进行的。</li>\n</ul>\n<ul>\n<li><a href=\"https://www.w3cplus.com/css/advanced-css-form-styling.html\" target=\"_blank\" rel=\"noopener\">美化表单的CSS高级技巧</a><br> 通常前端业务离不开表单,而其本身的UI确实不太美观,文章通过一些选择器实现常用表单的美化,相信对有定制化表单需求的小伙伴有所帮助。</li>\n</ul>\n<ul>\n<li><a href=\"http://blog.fens.me/nodejs-websocket-monitor/\" target=\"_blank\" rel=\"noopener\">websocket服务器监控</a><br> 这篇文章解释了一个简单的例子,用NodeJS搭建一个服务器监控程序,核心是socket.io实现的real time通信,另外还有node.js的child_process模块来实现进程管理。从这个简单而有用的例子出发,可以去研究socket.io和child_process的深层用法。</li>\n</ul>\n<ul>\n<li><a href=\"https://ponyfoo.com/articles/two-way-synchronization-for-a-web-app-and-git\" target=\"_blank\" rel=\"noopener\">Web应用程序和Git的双向同步</a><br>通过钩子函数实现数据库与git仓库之间的双向同步,当数据库发生变化时,git仓库也进行相应同步操作。</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"关于Promise对象容易忽视的几个问题\"><a href=\"#关于Promise对象容易忽视的几个问题\" class=\"headerlink\" title=\"关于Promise对象容易忽视的几个问题\"></a>关于Promise对象容易忽视的几个问题</h3><p>1.resolve后的执行情况</p>\n<p>无论是 resolve, reject,都会将函数剩余的代码执行完<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> promise = <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'mark 1'</span>);</span><br><span class=\"line\"> resolve(<span class=\"string\">'hello world'</span>); <span class=\"comment\">// reject('hello world');</span></span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(<span class=\"string\">'mark 2'</span>);</span><br><span class=\"line\">});</span><br><span class=\"line\"></span><br><span class=\"line\">promise.then(<span class=\"function\"><span class=\"params\">result</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(result);</span><br><span class=\"line\">}).catch(<span class=\"function\"><span class=\"params\">err</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(err);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>2.调用 then 方法返回新的 Promise 对象<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> promise1 = <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> resolve(<span class=\"string\">'Hello world'</span>)</span><br><span class=\"line\">})</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> promise2 = promise1.then()</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise1 === promise2) <span class=\"comment\">// false</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise1 <span class=\"keyword\">instanceof</span> <span class=\"built_in\">Promise</span>) <span class=\"comment\">// true</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(promise2 <span class=\"keyword\">instanceof</span> <span class=\"built_in\">Promise</span>) <span class=\"comment\">// true</span></span><br></pre></td></tr></table></figure></p>\n<p>3.串行执行和并行执行</p>\n<ul>\n<li>串行执行:有一堆 Promise 对象,它们的执行顺序是固定的,前一个 promise 执行完后,后一个 promise 才开始执行,比如数据库查询,它们往往有前后的因果关系。</li>\n<li>并行执行:有一堆 Promise 对象,它们的执行顺序是不固定的,没有前后因果关系,可以并发地去执行。</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br><span class=\"line\">31</span><br><span class=\"line\">32</span><br><span class=\"line\">33</span><br><span class=\"line\">34</span><br><span class=\"line\">35</span><br><span class=\"line\">36</span><br><span class=\"line\">37</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//串行方式一</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> serial = <span class=\"built_in\">Promise</span>.resolve();</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i <span class=\"keyword\">of</span> datum) {</span><br><span class=\"line\"> serial = serial.then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\t setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t\t<span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t\tresolve(<span class=\"string\">\"第 \"</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t }, i * <span class=\"number\">200</span>);</span><br><span class=\"line\">\t})\t</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"comment\">//串行方式二 使用reduce</span></span><br><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">datum.reduce(<span class=\"function\">(<span class=\"params\">prev, cur</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> prev.then(<span class=\"function\"><span class=\"params\">data</span> =></span> {</span><br><span class=\"line\">\t<span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">\t<span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\t setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t\t<span class=\"built_in\">console</span>.log(cur * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t\tresolve(<span class=\"string\">\"第 \"</span> + (cur + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t }, cur * <span class=\"number\">200</span>);</span><br><span class=\"line\">\t})\t</span><br><span class=\"line\"> })</span><br><span class=\"line\">}, <span class=\"built_in\">Promise</span>.resolve(<span class=\"literal\">true</span>));</span><br></pre></td></tr></table></figure>\n<p>并行执行很好解决,在 Promise中有 all 这个函数支持, Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。当多个 Promise 实例执行完后才去执行最后新的 Promise 实例。<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> datum = [];</span><br><span class=\"line\"><span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(i);</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"built_in\">Promise</span>.all(datum.map(<span class=\"function\"><span class=\"params\">i</span> =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\">\tsetTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\">\t <span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">\" ms 后执行结束\"</span>);</span><br><span class=\"line\">\t resolve(<span class=\"string\">\"第 \"</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">\" 个 Promise 执行结束\"</span>);</span><br><span class=\"line\">\t}, i * <span class=\"number\">200</span>);</span><br><span class=\"line\"> })</span><br><span class=\"line\">})).then(<span class=\"function\">(<span class=\"params\">data</span>) =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(data);</span><br><span class=\"line\">});</span><br></pre></td></tr></table></figure></p>\n<p>如果不使用 Promise.all 这个方法的话,你也可以使用像 ES7 的 async/await</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> asyncFun = <span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> datum = []</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < <span class=\"number\">10</span>; i++) {</span><br><span class=\"line\"> datum.push(<span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve, reject</span>) =></span> {</span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(i * <span class=\"number\">200</span> + <span class=\"string\">'ms 后执行结束'</span>)</span><br><span class=\"line\"> resolve(<span class=\"string\">'第 '</span> + (i + <span class=\"number\">1</span>) + <span class=\"string\">' 个 Promise 执行结束'</span>)</span><br><span class=\"line\"> }, i * <span class=\"number\">200</span>)</span><br><span class=\"line\"> }))</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">const</span> result = []</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> promise <span class=\"keyword\">of</span> datum) {</span><br><span class=\"line\"> result.push(<span class=\"keyword\">await</span> promise)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(result)</span><br><span class=\"line\">}</span><br><span class=\"line\">asyncFun()</span><br></pre></td></tr></table></figure>\n<p>4 . 结合 async/await 编写同步代码</p>\n<ul>\n<li>async/await 函数可以帮助我们彻底摆脱回调地狱的烦恼,用一种同步的方式来编写异步函数。</li>\n<li>await 后面可以接数值,如果是异步请求的话可以接 Thunk 函数和 Promise 对象。</li>\n</ul>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> timeout = <span class=\"function\">(<span class=\"params\">ms</span>) =></span> {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"keyword\">new</span> <span class=\"built_in\">Promise</span>(<span class=\"function\">(<span class=\"params\">resolve</span>) =></span> {</span><br><span class=\"line\"> setTimeout(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> resolve(ms + <span class=\"string\">' passed'</span>)</span><br><span class=\"line\"> }, ms)</span><br><span class=\"line\"> })</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">const</span> asyncFunc = <span class=\"keyword\">async</span> () => {</span><br><span class=\"line\"> <span class=\"keyword\">const</span> value1 = <span class=\"keyword\">await</span> timeout(<span class=\"number\">2000</span>)</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(value1)</span><br><span class=\"line\"> <span class=\"keyword\">const</span> value2 = <span class=\"keyword\">await</span> timeout(<span class=\"number\">2000</span>)</span><br><span class=\"line\"> <span class=\"built_in\">console</span>.log(value2)</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\">asyncFunc()</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(<span class=\"string\">'now'</span>)</span><br></pre></td></tr></table></figure>\n<p>5 .resolved 状态的 Promise 不会立即执行</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">let</span> i = <span class=\"number\">0</span>;</span><br><span class=\"line\"><span class=\"built_in\">Promise</span>.resolve(<span class=\"string\">'resolved promise'</span>).then(<span class=\"function\"><span class=\"params\">()</span> =></span> {</span><br><span class=\"line\"> i += <span class=\"number\">2</span></span><br><span class=\"line\">})</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(i) <span class=\"comment\">// 0</span></span><br></pre></td></tr></table></figure>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><a href=\"http://www.oschina.net/question/12_72250\" target=\"_blank\" rel=\"noopener\">TypeScript 入门指南</a><br>TypeScript入门指南,适合入门了解。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/5a0b29756fb9a045167cb643\" target=\"_blank\" rel=\"noopener\">别再拿奇技淫巧搬砖了</a><br>技巧性的知识大家都有掌握,使用场景及方式是否合理也是个问题。<br>文章总结了一些常见的编程技巧的利弊,希望对大家有所帮助。</li>\n</ul>\n<ul>\n<li><a href=\"https://zhuanlan.zhihu.com/p/30703042?utm_medium=social&utm_source=wechat_session\" target=\"_blank\" rel=\"noopener\">抓住数据的小尾巴 - JS浮点数陷阱及解法</a><br>推荐:众所周知,JavaScript 浮点数运算时经常遇到会 0.000000001 和 0.999999999 这样奇怪的结果,如 0.1+0.2=0.30000000000000004、1-0.9=0.09999999999999998,很多人知道这是浮点数误差问题,但具体原因就说不清楚了。本文帮你理清这背后的原理以及解决方案,还会向你解释JS中的大数危机和四则运算中会遇到的坑。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/5a091afe6fb9a044ff30f402\" target=\"_blank\" rel=\"noopener\">打造自己的JavaScript武器库</a><br>作为战斗在业务一线的前端,要想少加班,就要想办法提高工作效率。这里提一个小点,我们在业务开发过程中,经常会重复用到日期格式化、url参数转对象、浏览器类型判断、节流函数等一类函数,这些工具类函数,基本上在每个项目都会用到,为避免不同项目多次复制粘贴的麻烦,我们可以统一封装,发布到npm,以提高开发效率。</li>\n</ul>\n<ul>\n<li><a href=\"https://juejin.im/post/59f5bbdb6fb9a0451968d851\" target=\"_blank\" rel=\"noopener\">浏览器渲染引擎</a><br>浏览器基础是前端知识网中的一个小分支,也是前端开发人员必须掌握的基础知识点。他贯穿着前端的整个网络体系,项目优化也是围绕着浏览器进行的。</li>\n</ul>\n<ul>\n<li><a href=\"https://www.w3cplus.com/css/advanced-css-form-styling.html\" target=\"_blank\" rel=\"noopener\">美化表单的CSS高级技巧</a><br> 通常前端业务离不开表单,而其本身的UI确实不太美观,文章通过一些选择器实现常用表单的美化,相信对有定制化表单需求的小伙伴有所帮助。</li>\n</ul>\n<ul>\n<li><a href=\"http://blog.fens.me/nodejs-websocket-monitor/\" target=\"_blank\" rel=\"noopener\">websocket服务器监控</a><br> 这篇文章解释了一个简单的例子,用NodeJS搭建一个服务器监控程序,核心是socket.io实现的real time通信,另外还有node.js的child_process模块来实现进程管理。从这个简单而有用的例子出发,可以去研究socket.io和child_process的深层用法。</li>\n</ul>\n<ul>\n<li><a href=\"https://ponyfoo.com/articles/two-way-synchronization-for-a-web-app-and-git\" target=\"_blank\" rel=\"noopener\">Web应用程序和Git的双向同步</a><br>通过钩子函数实现数据库与git仓库之间的双向同步,当数据库发生变化时,git仓库也进行相应同步操作。</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第5期 (本期小编:陶明)","date":"2017-07-21T06:21:43.000Z","_content":"\n## 基础\n* [JS中关于this](https://kongchenglc.github.io/blog/%E5%85%B3%E4%BA%8Ethis20170716/)\n**关于this的几种绑定规则以及优先级**\n\n* [跨域资源共享 CORS](http://www.ruanyifeng.com/blog/2016/04/cors.html)\n**一个option请求引发的疑惑**\n\n* [表单脚本的基础知识](http://www.jianshu.com/p/fc2017f18525)\n**详细的总结了表单的属性、方法及事件**\n\n## 文章\n* [五种事件驱动的API架构](https://talkingdata.github.io/fsd/2017/07/21/5-protocols-for-event-driven-api-architectures/)\n<small>*推荐人:王祥*</small>\n本文会介绍 5 种事件驱动的 API 架构:WebSockets、WebHooks、REST Hooks、Pub-Sub, 以及 Server Sent Events,并分别介绍这几种架构的基础功能、使用方式以及各自的优缺点。\n对于 Node.js 开发者来说,我们天生就在使用事件驱动的架构,业界也越来越认可事件驱动架构和异步系统的优势,了解本文介绍的 5 种事件驱动API 架构。\n\n* [推荐一篇Three.js入门文章](https://zhuanlan.zhihu.com/p/27296011)\n<small>*推荐人:张成斌*</small>\n文章把学习Three.js需要掌握的基本概念和知识点讲解的很详细。并且结合代码实现了一个demo。对于Three.js有兴趣的同学,是一篇不错的入门文章。\n\n* [推荐一篇介绍RESTful API的文章](https://segmentfault.com/a/1190000010261115)\n<small>*推荐人:李丽娇*</small>\n介绍了RESTful API的实现思想,并从http请求方式和相应内容等方面给出详细示例。\n在项目接口设计和接口对接中可做实质性参考。\n\n* [读 Zepto 源码之 Event 模块](https://juejin.im/post/596d45d96fb9a06ba2688e44/?utm_source=weixinqun&utm_medium=feZeptoEvent)\n<small>*推荐人:胡国伟*</small>\n如何自己实现事件处理,本文通过深入浅出解读 Zepto Event 模块源码,给我们提供了很好的答案。\n\n* [深入探究 eventloop 与浏览器渲染的时序问题](https://www.404forest.com/2017/07/18/how-javascript-actually-works-eventloop-and-uirendering/)\n<small>*推荐人:陶明*</small>\n文章通过对那些『延迟』执行的函数思考,深入的对event loop和task进行了拆分讲解,通过实例与图示详细讲解了整个执行渲染过程。\n\n* [vue的Virtual Dom实现- snabbdom解密](http://www.cnblogs.com/xuntu/p/6800547.html)\n<small>*推荐人:李志伟*</small>\n文章通过详细的图文对照、算法代码解析讲述了虚拟dom的实现,Virtual Node作为纯数据对象,patch创建或者更新DOM树,diff算法用来比较同层级,然后通过钩子和扩展模块创建有attribute、props、eventlistener的复杂dom。\n\n* [ES6数组的扩展(rest参数和扩展运算符)](https://github.com/ruanyf/es6tutorial/blob/8c8be74712a9e0d1a5dbcc855fe3e574b9fd4e6b/docs/array.md)\n<small>*推荐人:耿少真*</small>\nrest参数和扩展运算符都是ES6新增的特性。\nrest参数的形式为:...变量名;扩展运算符是三个点(...)。\n\n ##### rest参数:\n - rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了, rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中\n\n ##### 扩展运算符:\n - 扩展运算符可以看做是 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列\n\n* [程序员如何快速学习新的框架](https://mp.weixin.qq.com/s?__biz=MjM5Mjg4NDMwMA==&mid=2652975196&idx=1&sn=7775588a3e5a9cd44090f379766d2354&chksm=bd4ae37f8a3d6a69d00df95143c477440c4c494df56a101e4e076911a615e75f5b194cd4e182&mpshare=1&scene=1&srcid=0720soS6N4MjqELSisDoyamI#rd)\n<small>*推荐人:郭俊兵*</small>\n前端框架丰富多彩的今天,快速学习新的框架是每个前端程序员的必备技能。\n\n* [4种使用webpack提升vue应用的方式](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226710&idx=1&sn=3c6848e002aabeb55d6e9456b646d03d&chksm=bd495bd28a3ed2c43c34afb19a4fb0aedfb489b847f5e27348b9a021242e115d6ddb158c9e32&mpshare=1&scene=1&srcid=0721vFmgm9iqGHwNUyqboDb3&pass_ticket=E7F2%2BBqX9jvbMHf320yfzDVuT2rXz5tmHzjKDL3CgheMLCPvEi2MI8tlg%2FO3xRtu#rd)\n<small>*推荐人:包京京*</small>\n本篇文章所提到的几个措施大家可能都曾经在项目里用过,但是就如作者所言:你只是在用,并不知道为什么用,本文最大的价值在于提供了系统的优化方案并解释了原因\n\n## 其他\n* [pell](https://github.com/jaredreich/pell)\n**一个非常轻的开源WYSIWYG 编辑器**\n* [three.js](https://threejs.org/examples/#webgl_animation_cloth)\n**three.js的Demo**\n","source":"_posts/weekly-5.md","raw":"---\ntitle: 大前端周刊 第5期 (本期小编:陶明)\ndate: 2017-07-21 14:21:43\ntags: [weekly,three.js,Zepto,ES6,Vue,事件驱动]\n---\n\n## 基础\n* [JS中关于this](https://kongchenglc.github.io/blog/%E5%85%B3%E4%BA%8Ethis20170716/)\n**关于this的几种绑定规则以及优先级**\n\n* [跨域资源共享 CORS](http://www.ruanyifeng.com/blog/2016/04/cors.html)\n**一个option请求引发的疑惑**\n\n* [表单脚本的基础知识](http://www.jianshu.com/p/fc2017f18525)\n**详细的总结了表单的属性、方法及事件**\n\n## 文章\n* [五种事件驱动的API架构](https://talkingdata.github.io/fsd/2017/07/21/5-protocols-for-event-driven-api-architectures/)\n<small>*推荐人:王祥*</small>\n本文会介绍 5 种事件驱动的 API 架构:WebSockets、WebHooks、REST Hooks、Pub-Sub, 以及 Server Sent Events,并分别介绍这几种架构的基础功能、使用方式以及各自的优缺点。\n对于 Node.js 开发者来说,我们天生就在使用事件驱动的架构,业界也越来越认可事件驱动架构和异步系统的优势,了解本文介绍的 5 种事件驱动API 架构。\n\n* [推荐一篇Three.js入门文章](https://zhuanlan.zhihu.com/p/27296011)\n<small>*推荐人:张成斌*</small>\n文章把学习Three.js需要掌握的基本概念和知识点讲解的很详细。并且结合代码实现了一个demo。对于Three.js有兴趣的同学,是一篇不错的入门文章。\n\n* [推荐一篇介绍RESTful API的文章](https://segmentfault.com/a/1190000010261115)\n<small>*推荐人:李丽娇*</small>\n介绍了RESTful API的实现思想,并从http请求方式和相应内容等方面给出详细示例。\n在项目接口设计和接口对接中可做实质性参考。\n\n* [读 Zepto 源码之 Event 模块](https://juejin.im/post/596d45d96fb9a06ba2688e44/?utm_source=weixinqun&utm_medium=feZeptoEvent)\n<small>*推荐人:胡国伟*</small>\n如何自己实现事件处理,本文通过深入浅出解读 Zepto Event 模块源码,给我们提供了很好的答案。\n\n* [深入探究 eventloop 与浏览器渲染的时序问题](https://www.404forest.com/2017/07/18/how-javascript-actually-works-eventloop-and-uirendering/)\n<small>*推荐人:陶明*</small>\n文章通过对那些『延迟』执行的函数思考,深入的对event loop和task进行了拆分讲解,通过实例与图示详细讲解了整个执行渲染过程。\n\n* [vue的Virtual Dom实现- snabbdom解密](http://www.cnblogs.com/xuntu/p/6800547.html)\n<small>*推荐人:李志伟*</small>\n文章通过详细的图文对照、算法代码解析讲述了虚拟dom的实现,Virtual Node作为纯数据对象,patch创建或者更新DOM树,diff算法用来比较同层级,然后通过钩子和扩展模块创建有attribute、props、eventlistener的复杂dom。\n\n* [ES6数组的扩展(rest参数和扩展运算符)](https://github.com/ruanyf/es6tutorial/blob/8c8be74712a9e0d1a5dbcc855fe3e574b9fd4e6b/docs/array.md)\n<small>*推荐人:耿少真*</small>\nrest参数和扩展运算符都是ES6新增的特性。\nrest参数的形式为:...变量名;扩展运算符是三个点(...)。\n\n ##### rest参数:\n - rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了, rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中\n\n ##### 扩展运算符:\n - 扩展运算符可以看做是 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列\n\n* [程序员如何快速学习新的框架](https://mp.weixin.qq.com/s?__biz=MjM5Mjg4NDMwMA==&mid=2652975196&idx=1&sn=7775588a3e5a9cd44090f379766d2354&chksm=bd4ae37f8a3d6a69d00df95143c477440c4c494df56a101e4e076911a615e75f5b194cd4e182&mpshare=1&scene=1&srcid=0720soS6N4MjqELSisDoyamI#rd)\n<small>*推荐人:郭俊兵*</small>\n前端框架丰富多彩的今天,快速学习新的框架是每个前端程序员的必备技能。\n\n* [4种使用webpack提升vue应用的方式](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226710&idx=1&sn=3c6848e002aabeb55d6e9456b646d03d&chksm=bd495bd28a3ed2c43c34afb19a4fb0aedfb489b847f5e27348b9a021242e115d6ddb158c9e32&mpshare=1&scene=1&srcid=0721vFmgm9iqGHwNUyqboDb3&pass_ticket=E7F2%2BBqX9jvbMHf320yfzDVuT2rXz5tmHzjKDL3CgheMLCPvEi2MI8tlg%2FO3xRtu#rd)\n<small>*推荐人:包京京*</small>\n本篇文章所提到的几个措施大家可能都曾经在项目里用过,但是就如作者所言:你只是在用,并不知道为什么用,本文最大的价值在于提供了系统的优化方案并解释了原因\n\n## 其他\n* [pell](https://github.com/jaredreich/pell)\n**一个非常轻的开源WYSIWYG 编辑器**\n* [three.js](https://threejs.org/examples/#webgl_animation_cloth)\n**three.js的Demo**\n","slug":"weekly-5","published":1,"updated":"2017-08-25T02:32:17.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql0000njrs6c4erh5si","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://kongchenglc.github.io/blog/%E5%85%B3%E4%BA%8Ethis20170716/\" target=\"_blank\" rel=\"noopener\">JS中关于this</a><br><strong>关于this的几种绑定规则以及优先级</strong></p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2016/04/cors.html\" target=\"_blank\" rel=\"noopener\">跨域资源共享 CORS</a><br><strong>一个option请求引发的疑惑</strong></p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/fc2017f18525\" target=\"_blank\" rel=\"noopener\">表单脚本的基础知识</a><br><strong>详细的总结了表单的属性、方法及事件</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://talkingdata.github.io/fsd/2017/07/21/5-protocols-for-event-driven-api-architectures/\">五种事件驱动的API架构</a><br><small><em>推荐人:王祥</em></small><br>本文会介绍 5 种事件驱动的 API 架构:WebSockets、WebHooks、REST Hooks、Pub-Sub, 以及 Server Sent Events,并分别介绍这几种架构的基础功能、使用方式以及各自的优缺点。<br>对于 Node.js 开发者来说,我们天生就在使用事件驱动的架构,业界也越来越认可事件驱动架构和异步系统的优势,了解本文介绍的 5 种事件驱动API 架构。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27296011\" target=\"_blank\" rel=\"noopener\">推荐一篇Three.js入门文章</a><br><small><em>推荐人:张成斌</em></small><br>文章把学习Three.js需要掌握的基本概念和知识点讲解的很详细。并且结合代码实现了一个demo。对于Three.js有兴趣的同学,是一篇不错的入门文章。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010261115\" target=\"_blank\" rel=\"noopener\">推荐一篇介绍RESTful API的文章</a><br><small><em>推荐人:李丽娇</em></small><br>介绍了RESTful API的实现思想,并从http请求方式和相应内容等方面给出详细示例。<br>在项目接口设计和接口对接中可做实质性参考。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/596d45d96fb9a06ba2688e44/?utm_source=weixinqun&utm_medium=feZeptoEvent\" target=\"_blank\" rel=\"noopener\">读 Zepto 源码之 Event 模块</a><br><small><em>推荐人:胡国伟</em></small><br>如何自己实现事件处理,本文通过深入浅出解读 Zepto Event 模块源码,给我们提供了很好的答案。</p>\n</li>\n<li><p><a href=\"https://www.404forest.com/2017/07/18/how-javascript-actually-works-eventloop-and-uirendering/\" target=\"_blank\" rel=\"noopener\">深入探究 eventloop 与浏览器渲染的时序问题</a><br><small><em>推荐人:陶明</em></small><br>文章通过对那些『延迟』执行的函数思考,深入的对event loop和task进行了拆分讲解,通过实例与图示详细讲解了整个执行渲染过程。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/xuntu/p/6800547.html\" target=\"_blank\" rel=\"noopener\">vue的Virtual Dom实现- snabbdom解密</a><br><small><em>推荐人:李志伟</em></small><br>文章通过详细的图文对照、算法代码解析讲述了虚拟dom的实现,Virtual Node作为纯数据对象,patch创建或者更新DOM树,diff算法用来比较同层级,然后通过钩子和扩展模块创建有attribute、props、eventlistener的复杂dom。</p>\n</li>\n<li><p><a href=\"https://github.com/ruanyf/es6tutorial/blob/8c8be74712a9e0d1a5dbcc855fe3e574b9fd4e6b/docs/array.md\" target=\"_blank\" rel=\"noopener\">ES6数组的扩展(rest参数和扩展运算符)</a><br><small><em>推荐人:耿少真</em></small><br>rest参数和扩展运算符都是ES6新增的特性。<br>rest参数的形式为:…变量名;扩展运算符是三个点(…)。</p>\n<h5 id=\"rest参数\"><a href=\"#rest参数\" class=\"headerlink\" title=\"rest参数:\"></a>rest参数:</h5><ul>\n<li>rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了, rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中</li>\n</ul>\n<h5 id=\"扩展运算符\"><a href=\"#扩展运算符\" class=\"headerlink\" title=\"扩展运算符:\"></a>扩展运算符:</h5><ul>\n<li>扩展运算符可以看做是 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列</li>\n</ul>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5Mjg4NDMwMA==&mid=2652975196&idx=1&sn=7775588a3e5a9cd44090f379766d2354&chksm=bd4ae37f8a3d6a69d00df95143c477440c4c494df56a101e4e076911a615e75f5b194cd4e182&mpshare=1&scene=1&srcid=0720soS6N4MjqELSisDoyamI#rd\" target=\"_blank\" rel=\"noopener\">程序员如何快速学习新的框架</a><br><small><em>推荐人:郭俊兵</em></small><br>前端框架丰富多彩的今天,快速学习新的框架是每个前端程序员的必备技能。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226710&idx=1&sn=3c6848e002aabeb55d6e9456b646d03d&chksm=bd495bd28a3ed2c43c34afb19a4fb0aedfb489b847f5e27348b9a021242e115d6ddb158c9e32&mpshare=1&scene=1&srcid=0721vFmgm9iqGHwNUyqboDb3&pass_ticket=E7F2%2BBqX9jvbMHf320yfzDVuT2rXz5tmHzjKDL3CgheMLCPvEi2MI8tlg%2FO3xRtu#rd\" target=\"_blank\" rel=\"noopener\">4种使用webpack提升vue应用的方式</a><br><small><em>推荐人:包京京</em></small><br>本篇文章所提到的几个措施大家可能都曾经在项目里用过,但是就如作者所言:你只是在用,并不知道为什么用,本文最大的价值在于提供了系统的优化方案并解释了原因</p>\n</li>\n</ul>\n<h2 id=\"其他\"><a href=\"#其他\" class=\"headerlink\" title=\"其他\"></a>其他</h2><ul>\n<li><a href=\"https://github.com/jaredreich/pell\" target=\"_blank\" rel=\"noopener\">pell</a><br><strong>一个非常轻的开源WYSIWYG 编辑器</strong></li>\n<li><a href=\"https://threejs.org/examples/#webgl_animation_cloth\" target=\"_blank\" rel=\"noopener\">three.js</a><br><strong>three.js的Demo</strong></li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://kongchenglc.github.io/blog/%E5%85%B3%E4%BA%8Ethis20170716/\" target=\"_blank\" rel=\"noopener\">JS中关于this</a><br><strong>关于this的几种绑定规则以及优先级</strong></p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2016/04/cors.html\" target=\"_blank\" rel=\"noopener\">跨域资源共享 CORS</a><br><strong>一个option请求引发的疑惑</strong></p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/fc2017f18525\" target=\"_blank\" rel=\"noopener\">表单脚本的基础知识</a><br><strong>详细的总结了表单的属性、方法及事件</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://talkingdata.github.io/fsd/2017/07/21/5-protocols-for-event-driven-api-architectures/\">五种事件驱动的API架构</a><br><small><em>推荐人:王祥</em></small><br>本文会介绍 5 种事件驱动的 API 架构:WebSockets、WebHooks、REST Hooks、Pub-Sub, 以及 Server Sent Events,并分别介绍这几种架构的基础功能、使用方式以及各自的优缺点。<br>对于 Node.js 开发者来说,我们天生就在使用事件驱动的架构,业界也越来越认可事件驱动架构和异步系统的优势,了解本文介绍的 5 种事件驱动API 架构。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27296011\" target=\"_blank\" rel=\"noopener\">推荐一篇Three.js入门文章</a><br><small><em>推荐人:张成斌</em></small><br>文章把学习Three.js需要掌握的基本概念和知识点讲解的很详细。并且结合代码实现了一个demo。对于Three.js有兴趣的同学,是一篇不错的入门文章。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010261115\" target=\"_blank\" rel=\"noopener\">推荐一篇介绍RESTful API的文章</a><br><small><em>推荐人:李丽娇</em></small><br>介绍了RESTful API的实现思想,并从http请求方式和相应内容等方面给出详细示例。<br>在项目接口设计和接口对接中可做实质性参考。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/596d45d96fb9a06ba2688e44/?utm_source=weixinqun&utm_medium=feZeptoEvent\" target=\"_blank\" rel=\"noopener\">读 Zepto 源码之 Event 模块</a><br><small><em>推荐人:胡国伟</em></small><br>如何自己实现事件处理,本文通过深入浅出解读 Zepto Event 模块源码,给我们提供了很好的答案。</p>\n</li>\n<li><p><a href=\"https://www.404forest.com/2017/07/18/how-javascript-actually-works-eventloop-and-uirendering/\" target=\"_blank\" rel=\"noopener\">深入探究 eventloop 与浏览器渲染的时序问题</a><br><small><em>推荐人:陶明</em></small><br>文章通过对那些『延迟』执行的函数思考,深入的对event loop和task进行了拆分讲解,通过实例与图示详细讲解了整个执行渲染过程。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/xuntu/p/6800547.html\" target=\"_blank\" rel=\"noopener\">vue的Virtual Dom实现- snabbdom解密</a><br><small><em>推荐人:李志伟</em></small><br>文章通过详细的图文对照、算法代码解析讲述了虚拟dom的实现,Virtual Node作为纯数据对象,patch创建或者更新DOM树,diff算法用来比较同层级,然后通过钩子和扩展模块创建有attribute、props、eventlistener的复杂dom。</p>\n</li>\n<li><p><a href=\"https://github.com/ruanyf/es6tutorial/blob/8c8be74712a9e0d1a5dbcc855fe3e574b9fd4e6b/docs/array.md\" target=\"_blank\" rel=\"noopener\">ES6数组的扩展(rest参数和扩展运算符)</a><br><small><em>推荐人:耿少真</em></small><br>rest参数和扩展运算符都是ES6新增的特性。<br>rest参数的形式为:…变量名;扩展运算符是三个点(…)。</p>\n<h5 id=\"rest参数\"><a href=\"#rest参数\" class=\"headerlink\" title=\"rest参数:\"></a>rest参数:</h5><ul>\n<li>rest参数用于获取函数的多余参数,这样就不需要使用arguments对象了, rest参数搭配的变量是一个数组,该变量将多余的参数放入数组中</li>\n</ul>\n<h5 id=\"扩展运算符\"><a href=\"#扩展运算符\" class=\"headerlink\" title=\"扩展运算符:\"></a>扩展运算符:</h5><ul>\n<li>扩展运算符可以看做是 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列</li>\n</ul>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5Mjg4NDMwMA==&mid=2652975196&idx=1&sn=7775588a3e5a9cd44090f379766d2354&chksm=bd4ae37f8a3d6a69d00df95143c477440c4c494df56a101e4e076911a615e75f5b194cd4e182&mpshare=1&scene=1&srcid=0720soS6N4MjqELSisDoyamI#rd\" target=\"_blank\" rel=\"noopener\">程序员如何快速学习新的框架</a><br><small><em>推荐人:郭俊兵</em></small><br>前端框架丰富多彩的今天,快速学习新的框架是每个前端程序员的必备技能。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226710&idx=1&sn=3c6848e002aabeb55d6e9456b646d03d&chksm=bd495bd28a3ed2c43c34afb19a4fb0aedfb489b847f5e27348b9a021242e115d6ddb158c9e32&mpshare=1&scene=1&srcid=0721vFmgm9iqGHwNUyqboDb3&pass_ticket=E7F2%2BBqX9jvbMHf320yfzDVuT2rXz5tmHzjKDL3CgheMLCPvEi2MI8tlg%2FO3xRtu#rd\" target=\"_blank\" rel=\"noopener\">4种使用webpack提升vue应用的方式</a><br><small><em>推荐人:包京京</em></small><br>本篇文章所提到的几个措施大家可能都曾经在项目里用过,但是就如作者所言:你只是在用,并不知道为什么用,本文最大的价值在于提供了系统的优化方案并解释了原因</p>\n</li>\n</ul>\n<h2 id=\"其他\"><a href=\"#其他\" class=\"headerlink\" title=\"其他\"></a>其他</h2><ul>\n<li><a href=\"https://github.com/jaredreich/pell\" target=\"_blank\" rel=\"noopener\">pell</a><br><strong>一个非常轻的开源WYSIWYG 编辑器</strong></li>\n<li><a href=\"https://threejs.org/examples/#webgl_animation_cloth\" target=\"_blank\" rel=\"noopener\">three.js</a><br><strong>three.js的Demo</strong></li>\n</ul>\n"},{"title":"大前端周刊 第6期 (本期小编:郭俊兵)","date":"2017-07-28T04:09:40.000Z","_content":"\n## 基础\n* [CSS 样式书写规范](https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552360&idx=1&sn=8d2bc092405fc23379a786a6b7a36274&chksm=8025ada9b75224bfd372ce168cb0f9cb6959255e2a7e94556eacea5d1d8e4b559dd494704ae5&mpshare=1&scene=1&srcid=0720bFFOVROJ90Pe2ZutzpQz#rd)\n**不同的规范都有各自的长处与缺陷,对待所谓的规范最好的方式不是人云亦云,拿来就用,而是应该结合实际情况及需求,取长补短,取其精华去其糟粕。**\n\n* [bfc初探](https://segmentfault.com/a/1190000010150841)\n**bfc全称是块级格式化上下文(block formating context),是web可视化css渲染的一部分,它是块级盒子的布局发生,浮动互相交互的部分。**\n\n* [es6精简学习](https://segmentfault.com/a/1190000010279009)\n**秉着二八原则,掌握好常用的,有用的这个可以让我们快速起飞**\n\n## 文章\n* [推荐一个Vuex的介绍文章](https://github.com/chenbin92/blog/issues/1)\n<small>*推荐人:张成斌*</small>\n使用Vue做项目时,Vuex的使用与否和怎么使用始终是回避不了的一个问题。这篇文章或许能给你一些灵感。\n\n* [当我们学习 Node.js 时,我们在学习什么?](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0728VrhaVGLU4L9ednVFlmev&pass_ticket=UuoqCxRu07cu1Iw3Eo8nDcUi6ufOxbjgwdd0cRPXNFEztRXx6J2qpa2gAXxKir5f#rd)\n<small>*推荐人:包京京*</small>\n大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?\n\n* [推荐一篇关于WebSocket 的教程](http://www.ruanyifeng.com/blog/2017/05/websocket.html)\n<small>*推荐人:陶明*</small>\n文章介绍了WebSocket 的特性及与HTTP对比在服务器推送上的优势,通过一个简单的示例介绍了WebSocket 部分API。\n\n* [推荐一篇介绍git工作流程的文章](http://www.cnblogs.com/cnblogsfans/p/5075073.html)\n<small>*推荐人:李丽娇*</small>\ngit成为现在最火的代码管理工具,文中详细介绍了git在团队中的使用流程,这种思路在团队协作中很是受用。同时文中介绍了gitflow使用的方法。\n\n* [理解 async/await](https://juejin.im/post/596e142d5188254b532ce2da)\n<small>*推荐人:耿少真*</small>\nasync 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。\n\n* [http协议简介](http://www.jianshu.com/p/80e25cb1d81a)\n<small>*推荐人:郭俊兵*</small>\n大致了解下http协议相关内容,有利于了解前端开发时,调用后台接口,请求做了什么。\n\n* [Vue2.0 源码阅读:响应式原理](http://zhouweicsu.github.io/blog/2017/03/07/vue-2-0-reactivity/)\n<small>*推荐人:李志伟*</small>\n文章深入Vue源码,详细地解析了响应式原理。其原理大致可总结为:当数据发生改变后,相应的 setter 函数被触发,然后执行 notify 函数通知订阅者(Watcher)去更新相关视图,也会对新的数据重新 observe,更新相关的依赖关系。\n\n* [HTTP/2 Server Push 详解(原文)](https://www.smashingmagazine.com/2017/04/guide-http2-server-push/)\n<small>*推荐人:胡国伟*</small>\nServer Push可以将静态资源推送给客户端,实现多路复用,是HTTP/2众多协议优化中最令人振奋的特性,它大大降低了网络延迟对性能的影响。\n##### 翻译:\n - [HTTP/2 Server Push 详解(上)](http://www.alloyteam.com/2017/04/guide-http2-server-push-part1/)\n - [HTTP/2 Server Push 详解(下)](http://www.alloyteam.com/2017/04/guide-http2-server-push-part2/)\n\n* [深入vue2.0底层思想–模板渲染](http://mp.weixin.qq.com/s/L5VK5v3fmzdjLdT6Z6w-rA)\n<small>*推荐人:王俐*</small>\nVue 2.0 中模板渲染与 Vue 1.0的区别,1.0 中采用的 DocumentFragment (想了解可以观看这篇文章),而 2.0 中借鉴 React 的 Virtual DOM。基于 Virtual DOM,2.0 还可以支持服务端渲染(SSR),也支持 JSX 语法。\n\n* [iView 一周年了,同时发布了 2.0 正式版](https://zhuanlan.zhihu.com/p/28090879)\n<small>*推荐人:王祥*</small>\n一周年,两个大版本,很值得称赞的成绩!能跟梁灏这样优秀的前端生态贡献者共事,我感到非常荣幸!\n正如标题所言,2.0正式版将会是一个全新的开始,她将随着Vue社区的进步而快速迭代。\n期待vue社区和iView能有更好的发展,iView不会止于组件库,更期待iView deign、iView mobile…和更多优秀的开发者参与到开源生态的共建!\n","source":"_posts/weekly-6.md","raw":"---\ntitle: 大前端周刊 第6期 (本期小编:郭俊兵)\ndate: 2017-07-28 12:09:40\ntags: [weekly,Vuex,node,WebSocket,http,Vue,iView,Git]\n---\n\n## 基础\n* [CSS 样式书写规范](https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552360&idx=1&sn=8d2bc092405fc23379a786a6b7a36274&chksm=8025ada9b75224bfd372ce168cb0f9cb6959255e2a7e94556eacea5d1d8e4b559dd494704ae5&mpshare=1&scene=1&srcid=0720bFFOVROJ90Pe2ZutzpQz#rd)\n**不同的规范都有各自的长处与缺陷,对待所谓的规范最好的方式不是人云亦云,拿来就用,而是应该结合实际情况及需求,取长补短,取其精华去其糟粕。**\n\n* [bfc初探](https://segmentfault.com/a/1190000010150841)\n**bfc全称是块级格式化上下文(block formating context),是web可视化css渲染的一部分,它是块级盒子的布局发生,浮动互相交互的部分。**\n\n* [es6精简学习](https://segmentfault.com/a/1190000010279009)\n**秉着二八原则,掌握好常用的,有用的这个可以让我们快速起飞**\n\n## 文章\n* [推荐一个Vuex的介绍文章](https://github.com/chenbin92/blog/issues/1)\n<small>*推荐人:张成斌*</small>\n使用Vue做项目时,Vuex的使用与否和怎么使用始终是回避不了的一个问题。这篇文章或许能给你一些灵感。\n\n* [当我们学习 Node.js 时,我们在学习什么?](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0728VrhaVGLU4L9ednVFlmev&pass_ticket=UuoqCxRu07cu1Iw3Eo8nDcUi6ufOxbjgwdd0cRPXNFEztRXx6J2qpa2gAXxKir5f#rd)\n<small>*推荐人:包京京*</small>\n大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?\n\n* [推荐一篇关于WebSocket 的教程](http://www.ruanyifeng.com/blog/2017/05/websocket.html)\n<small>*推荐人:陶明*</small>\n文章介绍了WebSocket 的特性及与HTTP对比在服务器推送上的优势,通过一个简单的示例介绍了WebSocket 部分API。\n\n* [推荐一篇介绍git工作流程的文章](http://www.cnblogs.com/cnblogsfans/p/5075073.html)\n<small>*推荐人:李丽娇*</small>\ngit成为现在最火的代码管理工具,文中详细介绍了git在团队中的使用流程,这种思路在团队协作中很是受用。同时文中介绍了gitflow使用的方法。\n\n* [理解 async/await](https://juejin.im/post/596e142d5188254b532ce2da)\n<small>*推荐人:耿少真*</small>\nasync 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。\n\n* [http协议简介](http://www.jianshu.com/p/80e25cb1d81a)\n<small>*推荐人:郭俊兵*</small>\n大致了解下http协议相关内容,有利于了解前端开发时,调用后台接口,请求做了什么。\n\n* [Vue2.0 源码阅读:响应式原理](http://zhouweicsu.github.io/blog/2017/03/07/vue-2-0-reactivity/)\n<small>*推荐人:李志伟*</small>\n文章深入Vue源码,详细地解析了响应式原理。其原理大致可总结为:当数据发生改变后,相应的 setter 函数被触发,然后执行 notify 函数通知订阅者(Watcher)去更新相关视图,也会对新的数据重新 observe,更新相关的依赖关系。\n\n* [HTTP/2 Server Push 详解(原文)](https://www.smashingmagazine.com/2017/04/guide-http2-server-push/)\n<small>*推荐人:胡国伟*</small>\nServer Push可以将静态资源推送给客户端,实现多路复用,是HTTP/2众多协议优化中最令人振奋的特性,它大大降低了网络延迟对性能的影响。\n##### 翻译:\n - [HTTP/2 Server Push 详解(上)](http://www.alloyteam.com/2017/04/guide-http2-server-push-part1/)\n - [HTTP/2 Server Push 详解(下)](http://www.alloyteam.com/2017/04/guide-http2-server-push-part2/)\n\n* [深入vue2.0底层思想–模板渲染](http://mp.weixin.qq.com/s/L5VK5v3fmzdjLdT6Z6w-rA)\n<small>*推荐人:王俐*</small>\nVue 2.0 中模板渲染与 Vue 1.0的区别,1.0 中采用的 DocumentFragment (想了解可以观看这篇文章),而 2.0 中借鉴 React 的 Virtual DOM。基于 Virtual DOM,2.0 还可以支持服务端渲染(SSR),也支持 JSX 语法。\n\n* [iView 一周年了,同时发布了 2.0 正式版](https://zhuanlan.zhihu.com/p/28090879)\n<small>*推荐人:王祥*</small>\n一周年,两个大版本,很值得称赞的成绩!能跟梁灏这样优秀的前端生态贡献者共事,我感到非常荣幸!\n正如标题所言,2.0正式版将会是一个全新的开始,她将随着Vue社区的进步而快速迭代。\n期待vue社区和iView能有更好的发展,iView不会止于组件库,更期待iView deign、iView mobile…和更多优秀的开发者参与到开源生态的共建!\n","slug":"weekly-6","published":1,"updated":"2017-08-25T02:32:13.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql2000ojrs63mrpw29w","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552360&idx=1&sn=8d2bc092405fc23379a786a6b7a36274&chksm=8025ada9b75224bfd372ce168cb0f9cb6959255e2a7e94556eacea5d1d8e4b559dd494704ae5&mpshare=1&scene=1&srcid=0720bFFOVROJ90Pe2ZutzpQz#rd\" target=\"_blank\" rel=\"noopener\">CSS 样式书写规范</a><br><strong>不同的规范都有各自的长处与缺陷,对待所谓的规范最好的方式不是人云亦云,拿来就用,而是应该结合实际情况及需求,取长补短,取其精华去其糟粕。</strong></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010150841\" target=\"_blank\" rel=\"noopener\">bfc初探</a><br><strong>bfc全称是块级格式化上下文(block formating context),是web可视化css渲染的一部分,它是块级盒子的布局发生,浮动互相交互的部分。</strong></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010279009\" target=\"_blank\" rel=\"noopener\">es6精简学习</a><br><strong>秉着二八原则,掌握好常用的,有用的这个可以让我们快速起飞</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://github.com/chenbin92/blog/issues/1\" target=\"_blank\" rel=\"noopener\">推荐一个Vuex的介绍文章</a><br><small><em>推荐人:张成斌</em></small><br>使用Vue做项目时,Vuex的使用与否和怎么使用始终是回避不了的一个问题。这篇文章或许能给你一些灵感。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0728VrhaVGLU4L9ednVFlmev&pass_ticket=UuoqCxRu07cu1Iw3Eo8nDcUi6ufOxbjgwdd0cRPXNFEztRXx6J2qpa2gAXxKir5f#rd\" target=\"_blank\" rel=\"noopener\">当我们学习 Node.js 时,我们在学习什么?</a><br><small><em>推荐人:包京京</em></small><br>大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/05/websocket.html\" target=\"_blank\" rel=\"noopener\">推荐一篇关于WebSocket 的教程</a><br><small><em>推荐人:陶明</em></small><br>文章介绍了WebSocket 的特性及与HTTP对比在服务器推送上的优势,通过一个简单的示例介绍了WebSocket 部分API。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/cnblogsfans/p/5075073.html\" target=\"_blank\" rel=\"noopener\">推荐一篇介绍git工作流程的文章</a><br><small><em>推荐人:李丽娇</em></small><br>git成为现在最火的代码管理工具,文中详细介绍了git在团队中的使用流程,这种思路在团队协作中很是受用。同时文中介绍了gitflow使用的方法。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/596e142d5188254b532ce2da\" target=\"_blank\" rel=\"noopener\">理解 async/await</a><br><small><em>推荐人:耿少真</em></small><br>async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/80e25cb1d81a\" target=\"_blank\" rel=\"noopener\">http协议简介</a><br><small><em>推荐人:郭俊兵</em></small><br>大致了解下http协议相关内容,有利于了解前端开发时,调用后台接口,请求做了什么。</p>\n</li>\n<li><p><a href=\"http://zhouweicsu.github.io/blog/2017/03/07/vue-2-0-reactivity/\" target=\"_blank\" rel=\"noopener\">Vue2.0 源码阅读:响应式原理</a><br><small><em>推荐人:李志伟</em></small><br>文章深入Vue源码,详细地解析了响应式原理。其原理大致可总结为:当数据发生改变后,相应的 setter 函数被触发,然后执行 notify 函数通知订阅者(Watcher)去更新相关视图,也会对新的数据重新 observe,更新相关的依赖关系。</p>\n</li>\n<li><p><a href=\"https://www.smashingmagazine.com/2017/04/guide-http2-server-push/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(原文)</a><br><small><em>推荐人:胡国伟</em></small><br>Server Push可以将静态资源推送给客户端,实现多路复用,是HTTP/2众多协议优化中最令人振奋的特性,它大大降低了网络延迟对性能的影响。</p>\n<h5 id=\"翻译:\"><a href=\"#翻译:\" class=\"headerlink\" title=\"翻译:\"></a>翻译:</h5><ul>\n<li><a href=\"http://www.alloyteam.com/2017/04/guide-http2-server-push-part1/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(上)</a></li>\n<li><a href=\"http://www.alloyteam.com/2017/04/guide-http2-server-push-part2/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(下)</a></li>\n</ul>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/L5VK5v3fmzdjLdT6Z6w-rA\" target=\"_blank\" rel=\"noopener\">深入vue2.0底层思想–模板渲染</a><br><small><em>推荐人:王俐</em></small><br>Vue 2.0 中模板渲染与 Vue 1.0的区别,1.0 中采用的 DocumentFragment (想了解可以观看这篇文章),而 2.0 中借鉴 React 的 Virtual DOM。基于 Virtual DOM,2.0 还可以支持服务端渲染(SSR),也支持 JSX 语法。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28090879\" target=\"_blank\" rel=\"noopener\">iView 一周年了,同时发布了 2.0 正式版</a><br><small><em>推荐人:王祥</em></small><br>一周年,两个大版本,很值得称赞的成绩!能跟梁灏这样优秀的前端生态贡献者共事,我感到非常荣幸!<br>正如标题所言,2.0正式版将会是一个全新的开始,她将随着Vue社区的进步而快速迭代。<br>期待vue社区和iView能有更好的发展,iView不会止于组件库,更期待iView deign、iView mobile…和更多优秀的开发者参与到开源生态的共建!</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552360&idx=1&sn=8d2bc092405fc23379a786a6b7a36274&chksm=8025ada9b75224bfd372ce168cb0f9cb6959255e2a7e94556eacea5d1d8e4b559dd494704ae5&mpshare=1&scene=1&srcid=0720bFFOVROJ90Pe2ZutzpQz#rd\" target=\"_blank\" rel=\"noopener\">CSS 样式书写规范</a><br><strong>不同的规范都有各自的长处与缺陷,对待所谓的规范最好的方式不是人云亦云,拿来就用,而是应该结合实际情况及需求,取长补短,取其精华去其糟粕。</strong></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010150841\" target=\"_blank\" rel=\"noopener\">bfc初探</a><br><strong>bfc全称是块级格式化上下文(block formating context),是web可视化css渲染的一部分,它是块级盒子的布局发生,浮动互相交互的部分。</strong></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010279009\" target=\"_blank\" rel=\"noopener\">es6精简学习</a><br><strong>秉着二八原则,掌握好常用的,有用的这个可以让我们快速起飞</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://github.com/chenbin92/blog/issues/1\" target=\"_blank\" rel=\"noopener\">推荐一个Vuex的介绍文章</a><br><small><em>推荐人:张成斌</em></small><br>使用Vue做项目时,Vuex的使用与否和怎么使用始终是回避不了的一个问题。这篇文章或许能给你一些灵感。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=1&sn=9e7f6c0c5e6707c8b3d0a73b36bc00c1&chksm=e82be290df5c6b86e2be66f2eea6ee88be1449c3b40d8ebf40932798f95e651fbaf49ca698d0&mpshare=1&scene=1&srcid=0728VrhaVGLU4L9ednVFlmev&pass_ticket=UuoqCxRu07cu1Iw3Eo8nDcUi6ufOxbjgwdd0cRPXNFEztRXx6J2qpa2gAXxKir5f#rd\" target=\"_blank\" rel=\"noopener\">当我们学习 Node.js 时,我们在学习什么?</a><br><small><em>推荐人:包京京</em></small><br>大家都说学 Node.js 学 Node.js,到底是学它的什么呢?是学 JavaScript 这门语言,还是学 Node.js 的 API?还是学 Node.js 各种三方库?</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/05/websocket.html\" target=\"_blank\" rel=\"noopener\">推荐一篇关于WebSocket 的教程</a><br><small><em>推荐人:陶明</em></small><br>文章介绍了WebSocket 的特性及与HTTP对比在服务器推送上的优势,通过一个简单的示例介绍了WebSocket 部分API。</p>\n</li>\n<li><p><a href=\"http://www.cnblogs.com/cnblogsfans/p/5075073.html\" target=\"_blank\" rel=\"noopener\">推荐一篇介绍git工作流程的文章</a><br><small><em>推荐人:李丽娇</em></small><br>git成为现在最火的代码管理工具,文中详细介绍了git在团队中的使用流程,这种思路在团队协作中很是受用。同时文中介绍了gitflow使用的方法。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/596e142d5188254b532ce2da\" target=\"_blank\" rel=\"noopener\">理解 async/await</a><br><small><em>推荐人:耿少真</em></small><br>async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/80e25cb1d81a\" target=\"_blank\" rel=\"noopener\">http协议简介</a><br><small><em>推荐人:郭俊兵</em></small><br>大致了解下http协议相关内容,有利于了解前端开发时,调用后台接口,请求做了什么。</p>\n</li>\n<li><p><a href=\"http://zhouweicsu.github.io/blog/2017/03/07/vue-2-0-reactivity/\" target=\"_blank\" rel=\"noopener\">Vue2.0 源码阅读:响应式原理</a><br><small><em>推荐人:李志伟</em></small><br>文章深入Vue源码,详细地解析了响应式原理。其原理大致可总结为:当数据发生改变后,相应的 setter 函数被触发,然后执行 notify 函数通知订阅者(Watcher)去更新相关视图,也会对新的数据重新 observe,更新相关的依赖关系。</p>\n</li>\n<li><p><a href=\"https://www.smashingmagazine.com/2017/04/guide-http2-server-push/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(原文)</a><br><small><em>推荐人:胡国伟</em></small><br>Server Push可以将静态资源推送给客户端,实现多路复用,是HTTP/2众多协议优化中最令人振奋的特性,它大大降低了网络延迟对性能的影响。</p>\n<h5 id=\"翻译:\"><a href=\"#翻译:\" class=\"headerlink\" title=\"翻译:\"></a>翻译:</h5><ul>\n<li><a href=\"http://www.alloyteam.com/2017/04/guide-http2-server-push-part1/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(上)</a></li>\n<li><a href=\"http://www.alloyteam.com/2017/04/guide-http2-server-push-part2/\" target=\"_blank\" rel=\"noopener\">HTTP/2 Server Push 详解(下)</a></li>\n</ul>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/L5VK5v3fmzdjLdT6Z6w-rA\" target=\"_blank\" rel=\"noopener\">深入vue2.0底层思想–模板渲染</a><br><small><em>推荐人:王俐</em></small><br>Vue 2.0 中模板渲染与 Vue 1.0的区别,1.0 中采用的 DocumentFragment (想了解可以观看这篇文章),而 2.0 中借鉴 React 的 Virtual DOM。基于 Virtual DOM,2.0 还可以支持服务端渲染(SSR),也支持 JSX 语法。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28090879\" target=\"_blank\" rel=\"noopener\">iView 一周年了,同时发布了 2.0 正式版</a><br><small><em>推荐人:王祥</em></small><br>一周年,两个大版本,很值得称赞的成绩!能跟梁灏这样优秀的前端生态贡献者共事,我感到非常荣幸!<br>正如标题所言,2.0正式版将会是一个全新的开始,她将随着Vue社区的进步而快速迭代。<br>期待vue社区和iView能有更好的发展,iView不会止于组件库,更期待iView deign、iView mobile…和更多优秀的开发者参与到开源生态的共建!</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第9期 (本期小编:包京京)","date":"2017-08-18T06:57:34.000Z","_content":"## 基础\n\n* [javascript数据结构](http://blog.benoitvallon.com/data-structures-in-javascript/data-structures-in-javascript/)\n**用javascript创建并分析各种常见数据结构**\n\n* [理解Service Worker](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226809&idx=1&sn=514ca88902bc91840f363348d6c86c39&chksm=bd495b3d8a3ed22bcf78801f96ae5c8d9555792d599004a7dc47a5a528185b9734f78af565fb&mpshare=1&scene=1&srcid=08182YSPaUr4JxGj4iID40gs&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd)\n**PWA是最近前端最火热的一个概念之一,Service Worker是支持PWA的核心技术之一**\n\n* [常见排序算法之JavaScript实现](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226816&idx=1&sn=5c2de943a3ff61de10466bfe21f973c2&chksm=bd495b448a3ed2529d674d66eab367d3b2c9c1516f70206ea36aaa5439703288168a6305d48f&mpshare=1&scene=1&srcid=0818znt16EAbHf0IGrXO1guY&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd)\n**排序算法是基础算法。本文用javascript和算法可视化工具将各种排序算法实现了一遍**\n\n\n## 文章\n* [饿了么的 PWA 升级实践](https://zhuanlan.zhihu.com/p/27853228)\n<small>*推荐人: 胡国伟*</small>\n饿了吗本次分享了基于 vue.js 的升级实践,踩坑跳坑的过程非常精彩。阅读完本文之余也可了解下Lavas:百度推出的基于 Vue 的 PWA 解决方案,其号称帮助开发者快速搭建 PWA 应用,解决接入 PWA 的各种问题。\n\n* [Vuex框架原理与源码分析](https://tech.meituan.com/vuex-code-analysis.html)\n<small>*推荐人:李志伟*</small>\n文章首先抛出5个核心问题,然后介绍各模块核心流程,结合图解、代码示例更利于理解。理清store构造方法你也就大致明白Vuex的实现了。\n\n* [每个JavaScript开发者都该懂的Unicode](https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552440&idx=1&sn=01bdb132ed0383a47993d711120b4283&chksm=8025ad79b752246fef6761482dbace0d9899ac00982a238063749400e4b0aed38140005ac869&mpshare=1&scene=1&srcid=0809B7Mm0d6x7DCLtBzpQKer#)\n<small>*推荐人:郭俊兵*</small>\n如果你觉得理解Unicode很难,那么是时候来面对它了!其实它没你想的那么难。让我们进入抽象概念、字符、星光平面(辅助平面)和代理对的世界。\n\n* [Webpack 性能优化 (一)](http://code.oneapm.com/javascript/2015/07/07/webpack_performance_1/)\n<small>*推荐人:陶明*</small>\n文章通过项目打包场景,介绍了 resolve.alias 即利用别名做重定向的方法,在此基础上,配合module.noParse 忽略对某些模块的解析可以进一步加快速度。\n\n* [分享一篇介绍JS调试技巧的文章](http://web.jobbole.com/85503/)\n<small>*推荐人:李丽娇*</small>\n据说程序员不是在改bug就是在写bug的路上,由此可见调试问题这个技能的重要性。文中介绍了多种JS的调试工具和方法,并配有GIF图演示。快GET起来吧!\n\n* [Koa2进阶学习笔记](https://chenshenhai.github.io/koa2-note/)\n<small>*推荐人:耿少真*</small>\n基于async/await实现中间体系的koa2框架将会是是node.js web开发方向大势所趋的普及框架。基于generator/yield的koa1将会逐渐被koa2替代,毕竟使用co.js来处理generator是一种过渡的方式,虽然有其特定的应用场景,但是用async/await会更加优雅地实现同步写法。\n\n* [前端开发持续集成/持续部署(CI/CD)实例](http://annn.me/frontend-ci-cd/)\n<small>*推荐人:包京京*</small>\n近几年,前端项目也引入了编译,构建,单元测试等现代软件工程化的标准环节。这样大提高了前端的开发效率和业务交付能力。在项目部署阶段,我们还需要引入 CI / CD 等现代化的软件开发实践,来减少风险,自动化重复操作,节省我们的时间。本文主要分享一下如何基于 gitlab 、 jenkins 让 CI/CD 跑起来。\n\n* [滴滴 webapp 5.0 Vue 2.0 重构经验分享](https://github.com/DDFE/DDFE-blog/issues/13)\n<small>*推荐人:张成斌*</small>\n滴滴的 webapp 是运行在微信、支付宝、手 Q 以及其它第三方渠道的打车软件。借着产品层面的功能和视觉升级,我们用 Vue 2.0 对它进行了一次技术重构;本文即是本次重构中的经验分享。\n\n* [前端工程化实践](http://wxnet.me/2017/08/18/front-end-engineering-practice/)\n<small>*推荐人:王祥*</small>\n第一篇原创文章,总结了TalkingData DTU可视化团队,在2017年上半年的实践和尝试。内容包括git工作流、代码规范和大前端的目标确定,总结过往,才能更好的迎接未来。\n","source":"_posts/weekly-9.md","raw":"---\ntitle: 大前端周刊 第9期 (本期小编:包京京)\ndate: 2017-08-18 14:57:34\ntags: [weekly,工程化实践,Vuex,Webpack,PWA,持续部署]\n---\n## 基础\n\n* [javascript数据结构](http://blog.benoitvallon.com/data-structures-in-javascript/data-structures-in-javascript/)\n**用javascript创建并分析各种常见数据结构**\n\n* [理解Service Worker](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226809&idx=1&sn=514ca88902bc91840f363348d6c86c39&chksm=bd495b3d8a3ed22bcf78801f96ae5c8d9555792d599004a7dc47a5a528185b9734f78af565fb&mpshare=1&scene=1&srcid=08182YSPaUr4JxGj4iID40gs&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd)\n**PWA是最近前端最火热的一个概念之一,Service Worker是支持PWA的核心技术之一**\n\n* [常见排序算法之JavaScript实现](https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226816&idx=1&sn=5c2de943a3ff61de10466bfe21f973c2&chksm=bd495b448a3ed2529d674d66eab367d3b2c9c1516f70206ea36aaa5439703288168a6305d48f&mpshare=1&scene=1&srcid=0818znt16EAbHf0IGrXO1guY&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd)\n**排序算法是基础算法。本文用javascript和算法可视化工具将各种排序算法实现了一遍**\n\n\n## 文章\n* [饿了么的 PWA 升级实践](https://zhuanlan.zhihu.com/p/27853228)\n<small>*推荐人: 胡国伟*</small>\n饿了吗本次分享了基于 vue.js 的升级实践,踩坑跳坑的过程非常精彩。阅读完本文之余也可了解下Lavas:百度推出的基于 Vue 的 PWA 解决方案,其号称帮助开发者快速搭建 PWA 应用,解决接入 PWA 的各种问题。\n\n* [Vuex框架原理与源码分析](https://tech.meituan.com/vuex-code-analysis.html)\n<small>*推荐人:李志伟*</small>\n文章首先抛出5个核心问题,然后介绍各模块核心流程,结合图解、代码示例更利于理解。理清store构造方法你也就大致明白Vuex的实现了。\n\n* [每个JavaScript开发者都该懂的Unicode](https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552440&idx=1&sn=01bdb132ed0383a47993d711120b4283&chksm=8025ad79b752246fef6761482dbace0d9899ac00982a238063749400e4b0aed38140005ac869&mpshare=1&scene=1&srcid=0809B7Mm0d6x7DCLtBzpQKer#)\n<small>*推荐人:郭俊兵*</small>\n如果你觉得理解Unicode很难,那么是时候来面对它了!其实它没你想的那么难。让我们进入抽象概念、字符、星光平面(辅助平面)和代理对的世界。\n\n* [Webpack 性能优化 (一)](http://code.oneapm.com/javascript/2015/07/07/webpack_performance_1/)\n<small>*推荐人:陶明*</small>\n文章通过项目打包场景,介绍了 resolve.alias 即利用别名做重定向的方法,在此基础上,配合module.noParse 忽略对某些模块的解析可以进一步加快速度。\n\n* [分享一篇介绍JS调试技巧的文章](http://web.jobbole.com/85503/)\n<small>*推荐人:李丽娇*</small>\n据说程序员不是在改bug就是在写bug的路上,由此可见调试问题这个技能的重要性。文中介绍了多种JS的调试工具和方法,并配有GIF图演示。快GET起来吧!\n\n* [Koa2进阶学习笔记](https://chenshenhai.github.io/koa2-note/)\n<small>*推荐人:耿少真*</small>\n基于async/await实现中间体系的koa2框架将会是是node.js web开发方向大势所趋的普及框架。基于generator/yield的koa1将会逐渐被koa2替代,毕竟使用co.js来处理generator是一种过渡的方式,虽然有其特定的应用场景,但是用async/await会更加优雅地实现同步写法。\n\n* [前端开发持续集成/持续部署(CI/CD)实例](http://annn.me/frontend-ci-cd/)\n<small>*推荐人:包京京*</small>\n近几年,前端项目也引入了编译,构建,单元测试等现代软件工程化的标准环节。这样大提高了前端的开发效率和业务交付能力。在项目部署阶段,我们还需要引入 CI / CD 等现代化的软件开发实践,来减少风险,自动化重复操作,节省我们的时间。本文主要分享一下如何基于 gitlab 、 jenkins 让 CI/CD 跑起来。\n\n* [滴滴 webapp 5.0 Vue 2.0 重构经验分享](https://github.com/DDFE/DDFE-blog/issues/13)\n<small>*推荐人:张成斌*</small>\n滴滴的 webapp 是运行在微信、支付宝、手 Q 以及其它第三方渠道的打车软件。借着产品层面的功能和视觉升级,我们用 Vue 2.0 对它进行了一次技术重构;本文即是本次重构中的经验分享。\n\n* [前端工程化实践](http://wxnet.me/2017/08/18/front-end-engineering-practice/)\n<small>*推荐人:王祥*</small>\n第一篇原创文章,总结了TalkingData DTU可视化团队,在2017年上半年的实践和尝试。内容包括git工作流、代码规范和大前端的目标确定,总结过往,才能更好的迎接未来。\n","slug":"weekly-9","published":1,"updated":"2017-08-25T02:32:00.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql4000qjrs6nn6nyjwj","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://blog.benoitvallon.com/data-structures-in-javascript/data-structures-in-javascript/\" target=\"_blank\" rel=\"noopener\">javascript数据结构</a><br><strong>用javascript创建并分析各种常见数据结构</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226809&idx=1&sn=514ca88902bc91840f363348d6c86c39&chksm=bd495b3d8a3ed22bcf78801f96ae5c8d9555792d599004a7dc47a5a528185b9734f78af565fb&mpshare=1&scene=1&srcid=08182YSPaUr4JxGj4iID40gs&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd\" target=\"_blank\" rel=\"noopener\">理解Service Worker</a><br><strong>PWA是最近前端最火热的一个概念之一,Service Worker是支持PWA的核心技术之一</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226816&idx=1&sn=5c2de943a3ff61de10466bfe21f973c2&chksm=bd495b448a3ed2529d674d66eab367d3b2c9c1516f70206ea36aaa5439703288168a6305d48f&mpshare=1&scene=1&srcid=0818znt16EAbHf0IGrXO1guY&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd\" target=\"_blank\" rel=\"noopener\">常见排序算法之JavaScript实现</a><br><strong>排序算法是基础算法。本文用javascript和算法可视化工具将各种排序算法实现了一遍</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27853228\" target=\"_blank\" rel=\"noopener\">饿了么的 PWA 升级实践</a><br><small><em>推荐人: 胡国伟</em></small><br>饿了吗本次分享了基于 vue.js 的升级实践,踩坑跳坑的过程非常精彩。阅读完本文之余也可了解下Lavas:百度推出的基于 Vue 的 PWA 解决方案,其号称帮助开发者快速搭建 PWA 应用,解决接入 PWA 的各种问题。</p>\n</li>\n<li><p><a href=\"https://tech.meituan.com/vuex-code-analysis.html\" target=\"_blank\" rel=\"noopener\">Vuex框架原理与源码分析</a><br><small><em>推荐人:李志伟</em></small><br>文章首先抛出5个核心问题,然后介绍各模块核心流程,结合图解、代码示例更利于理解。理清store构造方法你也就大致明白Vuex的实现了。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552440&idx=1&sn=01bdb132ed0383a47993d711120b4283&chksm=8025ad79b752246fef6761482dbace0d9899ac00982a238063749400e4b0aed38140005ac869&mpshare=1&scene=1&srcid=0809B7Mm0d6x7DCLtBzpQKer#\" target=\"_blank\" rel=\"noopener\">每个JavaScript开发者都该懂的Unicode</a><br><small><em>推荐人:郭俊兵</em></small><br>如果你觉得理解Unicode很难,那么是时候来面对它了!其实它没你想的那么难。让我们进入抽象概念、字符、星光平面(辅助平面)和代理对的世界。</p>\n</li>\n<li><p><a href=\"http://code.oneapm.com/javascript/2015/07/07/webpack_performance_1/\" target=\"_blank\" rel=\"noopener\">Webpack 性能优化 (一)</a><br><small><em>推荐人:陶明</em></small><br>文章通过项目打包场景,介绍了 resolve.alias 即利用别名做重定向的方法,在此基础上,配合module.noParse 忽略对某些模块的解析可以进一步加快速度。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/85503/\" target=\"_blank\" rel=\"noopener\">分享一篇介绍JS调试技巧的文章</a><br><small><em>推荐人:李丽娇</em></small><br>据说程序员不是在改bug就是在写bug的路上,由此可见调试问题这个技能的重要性。文中介绍了多种JS的调试工具和方法,并配有GIF图演示。快GET起来吧!</p>\n</li>\n<li><p><a href=\"https://chenshenhai.github.io/koa2-note/\" target=\"_blank\" rel=\"noopener\">Koa2进阶学习笔记</a><br><small><em>推荐人:耿少真</em></small><br>基于async/await实现中间体系的koa2框架将会是是node.js web开发方向大势所趋的普及框架。基于generator/yield的koa1将会逐渐被koa2替代,毕竟使用co.js来处理generator是一种过渡的方式,虽然有其特定的应用场景,但是用async/await会更加优雅地实现同步写法。</p>\n</li>\n<li><p><a href=\"http://annn.me/frontend-ci-cd/\" target=\"_blank\" rel=\"noopener\">前端开发持续集成/持续部署(CI/CD)实例</a><br><small><em>推荐人:包京京</em></small><br>近几年,前端项目也引入了编译,构建,单元测试等现代软件工程化的标准环节。这样大提高了前端的开发效率和业务交付能力。在项目部署阶段,我们还需要引入 CI / CD 等现代化的软件开发实践,来减少风险,自动化重复操作,节省我们的时间。本文主要分享一下如何基于 gitlab 、 jenkins 让 CI/CD 跑起来。</p>\n</li>\n<li><p><a href=\"https://github.com/DDFE/DDFE-blog/issues/13\" target=\"_blank\" rel=\"noopener\">滴滴 webapp 5.0 Vue 2.0 重构经验分享</a><br><small><em>推荐人:张成斌</em></small><br>滴滴的 webapp 是运行在微信、支付宝、手 Q 以及其它第三方渠道的打车软件。借着产品层面的功能和视觉升级,我们用 Vue 2.0 对它进行了一次技术重构;本文即是本次重构中的经验分享。</p>\n</li>\n<li><p><a href=\"http://wxnet.me/2017/08/18/front-end-engineering-practice/\" target=\"_blank\" rel=\"noopener\">前端工程化实践</a><br><small><em>推荐人:王祥</em></small><br>第一篇原创文章,总结了TalkingData DTU可视化团队,在2017年上半年的实践和尝试。内容包括git工作流、代码规范和大前端的目标确定,总结过往,才能更好的迎接未来。</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://blog.benoitvallon.com/data-structures-in-javascript/data-structures-in-javascript/\" target=\"_blank\" rel=\"noopener\">javascript数据结构</a><br><strong>用javascript创建并分析各种常见数据结构</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226809&idx=1&sn=514ca88902bc91840f363348d6c86c39&chksm=bd495b3d8a3ed22bcf78801f96ae5c8d9555792d599004a7dc47a5a528185b9734f78af565fb&mpshare=1&scene=1&srcid=08182YSPaUr4JxGj4iID40gs&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd\" target=\"_blank\" rel=\"noopener\">理解Service Worker</a><br><strong>PWA是最近前端最火热的一个概念之一,Service Worker是支持PWA的核心技术之一</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226816&idx=1&sn=5c2de943a3ff61de10466bfe21f973c2&chksm=bd495b448a3ed2529d674d66eab367d3b2c9c1516f70206ea36aaa5439703288168a6305d48f&mpshare=1&scene=1&srcid=0818znt16EAbHf0IGrXO1guY&pass_ticket=0Et24OmYtRSLgA6Geno1MGBk5RujsQrVbaq%2FwZJ%2BzwtD%2F%2FbnV8lCXfDaw3Z5FpPr#rd\" target=\"_blank\" rel=\"noopener\">常见排序算法之JavaScript实现</a><br><strong>排序算法是基础算法。本文用javascript和算法可视化工具将各种排序算法实现了一遍</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27853228\" target=\"_blank\" rel=\"noopener\">饿了么的 PWA 升级实践</a><br><small><em>推荐人: 胡国伟</em></small><br>饿了吗本次分享了基于 vue.js 的升级实践,踩坑跳坑的过程非常精彩。阅读完本文之余也可了解下Lavas:百度推出的基于 Vue 的 PWA 解决方案,其号称帮助开发者快速搭建 PWA 应用,解决接入 PWA 的各种问题。</p>\n</li>\n<li><p><a href=\"https://tech.meituan.com/vuex-code-analysis.html\" target=\"_blank\" rel=\"noopener\">Vuex框架原理与源码分析</a><br><small><em>推荐人:李志伟</em></small><br>文章首先抛出5个核心问题,然后介绍各模块核心流程,结合图解、代码示例更利于理解。理清store构造方法你也就大致明白Vuex的实现了。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552440&idx=1&sn=01bdb132ed0383a47993d711120b4283&chksm=8025ad79b752246fef6761482dbace0d9899ac00982a238063749400e4b0aed38140005ac869&mpshare=1&scene=1&srcid=0809B7Mm0d6x7DCLtBzpQKer#\" target=\"_blank\" rel=\"noopener\">每个JavaScript开发者都该懂的Unicode</a><br><small><em>推荐人:郭俊兵</em></small><br>如果你觉得理解Unicode很难,那么是时候来面对它了!其实它没你想的那么难。让我们进入抽象概念、字符、星光平面(辅助平面)和代理对的世界。</p>\n</li>\n<li><p><a href=\"http://code.oneapm.com/javascript/2015/07/07/webpack_performance_1/\" target=\"_blank\" rel=\"noopener\">Webpack 性能优化 (一)</a><br><small><em>推荐人:陶明</em></small><br>文章通过项目打包场景,介绍了 resolve.alias 即利用别名做重定向的方法,在此基础上,配合module.noParse 忽略对某些模块的解析可以进一步加快速度。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/85503/\" target=\"_blank\" rel=\"noopener\">分享一篇介绍JS调试技巧的文章</a><br><small><em>推荐人:李丽娇</em></small><br>据说程序员不是在改bug就是在写bug的路上,由此可见调试问题这个技能的重要性。文中介绍了多种JS的调试工具和方法,并配有GIF图演示。快GET起来吧!</p>\n</li>\n<li><p><a href=\"https://chenshenhai.github.io/koa2-note/\" target=\"_blank\" rel=\"noopener\">Koa2进阶学习笔记</a><br><small><em>推荐人:耿少真</em></small><br>基于async/await实现中间体系的koa2框架将会是是node.js web开发方向大势所趋的普及框架。基于generator/yield的koa1将会逐渐被koa2替代,毕竟使用co.js来处理generator是一种过渡的方式,虽然有其特定的应用场景,但是用async/await会更加优雅地实现同步写法。</p>\n</li>\n<li><p><a href=\"http://annn.me/frontend-ci-cd/\" target=\"_blank\" rel=\"noopener\">前端开发持续集成/持续部署(CI/CD)实例</a><br><small><em>推荐人:包京京</em></small><br>近几年,前端项目也引入了编译,构建,单元测试等现代软件工程化的标准环节。这样大提高了前端的开发效率和业务交付能力。在项目部署阶段,我们还需要引入 CI / CD 等现代化的软件开发实践,来减少风险,自动化重复操作,节省我们的时间。本文主要分享一下如何基于 gitlab 、 jenkins 让 CI/CD 跑起来。</p>\n</li>\n<li><p><a href=\"https://github.com/DDFE/DDFE-blog/issues/13\" target=\"_blank\" rel=\"noopener\">滴滴 webapp 5.0 Vue 2.0 重构经验分享</a><br><small><em>推荐人:张成斌</em></small><br>滴滴的 webapp 是运行在微信、支付宝、手 Q 以及其它第三方渠道的打车软件。借着产品层面的功能和视觉升级,我们用 Vue 2.0 对它进行了一次技术重构;本文即是本次重构中的经验分享。</p>\n</li>\n<li><p><a href=\"http://wxnet.me/2017/08/18/front-end-engineering-practice/\" target=\"_blank\" rel=\"noopener\">前端工程化实践</a><br><small><em>推荐人:王祥</em></small><br>第一篇原创文章,总结了TalkingData DTU可视化团队,在2017年上半年的实践和尝试。内容包括git工作流、代码规范和大前端的目标确定,总结过往,才能更好的迎接未来。</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第8期 (本期小编:耿少真)","date":"2017-08-11T06:57:34.000Z","_content":"## 基础\n\n* [掌握Chrome开发工具](http://www.zcfy.cc/article/mastering-chrome-developer-tools-next-level-front-end-development-techniques-3722.html?t=selection)\n**熟悉Chrome开发工具的基本功能: DOM检查器、样式面板和JavaScript控制台和一些不太为人所知的特性**\n\n* [JS函数式编程指南](https://www.gitbook.com/book/llh911001/mostly-adequate-guide-chinese/details)\n**对函数式编程的目的有一个初步认识,对一个程序之所以是函数式程序的原因有一定了解**\n\n* [HTTP协议详解](https://mp.weixin.qq.com/s/27zpNIGhVbx-on9FDs_6dw)\n**Web服务器是基于HTTP(HyperText Transfer Protocol)协议实现的,所以要实现一个Web服务器就必须了解HTTP协议,本章主要介绍HTTP协议的相关知识,让我们对HTTP协议有个理性的认识。**\n\n## 资源整理\n* [编程书单](http://blog.didiaoyuan.com/2017/04/18/%E6%80%BB%E6%9C%89%E4%BD%A0%E8%A6%81%E7%9A%84%E7%BC%96%E7%A8%8B%E4%B9%A6%E5%8D%95%EF%BC%88GitHub-%EF%BC%89/)\n**一些 GitHub 上不错的文章或电子书列表与大家分享。不乏有不少经典,可以收起来慢慢阅览。**\n\n* [Web前端导航网站](http://www.alloyteam.com/nav/)\n**收录了前端开发需要的大部分网站,可以快速找到自己需要的网站**\n\n## 文章\n* [彻底弄懂CommonJS和AMD/CMD](http://www.cnblogs.com/chenguangliang/p/5856701.html)\n<small>*推荐人:李丽娇*</small>\n经常说的CommonJS、AMD、CMD规范具体指什么?实现原理是什么?这些规范有哪些具体实现?来看这篇文章找答案。\n\n* [使用Node.js实现文件流转存服务](https://zhuanlan.zhihu.com/p/25367269)\n<small>*推荐人:李志伟*</small>\n文章介绍了基于node实现分片上传大型文件,通过灵活使用Promise和递归,实现非异步模型看起来很复杂的事情。另外文章附有较为完整的单元测试,覆盖分片的缓存与切割、上传前后的md5值。\n\n* [API设计原则](http://coolshell.cn/articles/18024.html)\n<small>*推荐人:胡国伟*</small>\n我们平时在编写组件或者后端接口的时候都避免不了API 设计,你的API越容易使用,那么就会有越多的人去用它。那么问题来了,怎样才能设计出优秀的 API ?本文是虽然是以`C++`为例, 其中设计原则和思考是具有普适性的,是关于API设计一篇难得的好文章\n\n* [一道JS面试题所引发的\"血案\",透过现象寻本质,再从本质看现象](https://github.com/jawil/blog/issues/3)\n<small>*推荐人:张成斌*</small>\n对this、执行环境、作用域等概念进行了系统的讲解。加深对于这些易混淆概念的理解。\n\n* [karma+webpack搭建vue单元测试环境](http://www.jianshu.com/p/a515fbbdd1b2)\n<small>*推荐人:耿少真*</small>\nkarma+webpack搭建vue单元测试环境介绍了vue单元测试环境搭建及查看源文件的测试覆盖覆盖率。\n[Vue单元测试case写法](http://www.jianshu.com/p/45e8c2b26309)\n测试环境搭建完成后,在此基础上vue单元测试思路介绍和case的写法。测试框架使用jasmine。\n\n* [【源码拾遗】axios —— 极简封装的艺术](https://zhuanlan.zhihu.com/p/28396592)\n<small>*推荐人:陶明*</small>\n本文通过axios 功能的使用及源码分析详细说明了axios 对于功能的实现。\naxios是基于Promise的方式封装,所以分析axios源码也是对Promise的深入学习。\n\n* [Intro to Frontend Ops](https://rupl.github.io/frontend-ops/#/)\n<small>*推荐人:包京京*</small>\nFrontend Ops是这篇文章作者自己定义的一个概念,业界应该还没有统一这种叫法,不过文章作者的意思是,随着前端项目复杂程度的增加,需要类似于DevOps的工程化能力,来进行持续发布、自动化测试等等流程(本文是英文的材料,暂无译文)。\n\n* [Koa 框架教程](http://www.ruanyifeng.com/blog/2017/08/koa.html)\n<small>*推荐人:王祥*</small>\n本文从零开始,循序渐进,教会你如何使用 Koa 写出自己的 Web 应用。每一步都有简洁易懂的示例,希望让大家一看就懂。\n\n* [一行 JavaScript 代码的逆向工程](https://juejin.im/post/5988411251882526185d634a)\n<small>*推荐人:郭俊兵*</small>\n这一行代码会被渲染成一个矩阵效果,通过一次代码解读,享受理解它的过程。\n`<pre id=p><script>n=setInterval(\"for(n+=7,i=k,P='p.\\\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P\",k=64)</script>`\n","source":"_posts/weekly-8.md","raw":"---\ntitle: 大前端周刊 第8期 (本期小编:耿少真)\ndate: 2017-08-11 14:57:34\ntags: [weekly,模块,node,Vue,API设计,单元测试]\n---\n## 基础\n\n* [掌握Chrome开发工具](http://www.zcfy.cc/article/mastering-chrome-developer-tools-next-level-front-end-development-techniques-3722.html?t=selection)\n**熟悉Chrome开发工具的基本功能: DOM检查器、样式面板和JavaScript控制台和一些不太为人所知的特性**\n\n* [JS函数式编程指南](https://www.gitbook.com/book/llh911001/mostly-adequate-guide-chinese/details)\n**对函数式编程的目的有一个初步认识,对一个程序之所以是函数式程序的原因有一定了解**\n\n* [HTTP协议详解](https://mp.weixin.qq.com/s/27zpNIGhVbx-on9FDs_6dw)\n**Web服务器是基于HTTP(HyperText Transfer Protocol)协议实现的,所以要实现一个Web服务器就必须了解HTTP协议,本章主要介绍HTTP协议的相关知识,让我们对HTTP协议有个理性的认识。**\n\n## 资源整理\n* [编程书单](http://blog.didiaoyuan.com/2017/04/18/%E6%80%BB%E6%9C%89%E4%BD%A0%E8%A6%81%E7%9A%84%E7%BC%96%E7%A8%8B%E4%B9%A6%E5%8D%95%EF%BC%88GitHub-%EF%BC%89/)\n**一些 GitHub 上不错的文章或电子书列表与大家分享。不乏有不少经典,可以收起来慢慢阅览。**\n\n* [Web前端导航网站](http://www.alloyteam.com/nav/)\n**收录了前端开发需要的大部分网站,可以快速找到自己需要的网站**\n\n## 文章\n* [彻底弄懂CommonJS和AMD/CMD](http://www.cnblogs.com/chenguangliang/p/5856701.html)\n<small>*推荐人:李丽娇*</small>\n经常说的CommonJS、AMD、CMD规范具体指什么?实现原理是什么?这些规范有哪些具体实现?来看这篇文章找答案。\n\n* [使用Node.js实现文件流转存服务](https://zhuanlan.zhihu.com/p/25367269)\n<small>*推荐人:李志伟*</small>\n文章介绍了基于node实现分片上传大型文件,通过灵活使用Promise和递归,实现非异步模型看起来很复杂的事情。另外文章附有较为完整的单元测试,覆盖分片的缓存与切割、上传前后的md5值。\n\n* [API设计原则](http://coolshell.cn/articles/18024.html)\n<small>*推荐人:胡国伟*</small>\n我们平时在编写组件或者后端接口的时候都避免不了API 设计,你的API越容易使用,那么就会有越多的人去用它。那么问题来了,怎样才能设计出优秀的 API ?本文是虽然是以`C++`为例, 其中设计原则和思考是具有普适性的,是关于API设计一篇难得的好文章\n\n* [一道JS面试题所引发的\"血案\",透过现象寻本质,再从本质看现象](https://github.com/jawil/blog/issues/3)\n<small>*推荐人:张成斌*</small>\n对this、执行环境、作用域等概念进行了系统的讲解。加深对于这些易混淆概念的理解。\n\n* [karma+webpack搭建vue单元测试环境](http://www.jianshu.com/p/a515fbbdd1b2)\n<small>*推荐人:耿少真*</small>\nkarma+webpack搭建vue单元测试环境介绍了vue单元测试环境搭建及查看源文件的测试覆盖覆盖率。\n[Vue单元测试case写法](http://www.jianshu.com/p/45e8c2b26309)\n测试环境搭建完成后,在此基础上vue单元测试思路介绍和case的写法。测试框架使用jasmine。\n\n* [【源码拾遗】axios —— 极简封装的艺术](https://zhuanlan.zhihu.com/p/28396592)\n<small>*推荐人:陶明*</small>\n本文通过axios 功能的使用及源码分析详细说明了axios 对于功能的实现。\naxios是基于Promise的方式封装,所以分析axios源码也是对Promise的深入学习。\n\n* [Intro to Frontend Ops](https://rupl.github.io/frontend-ops/#/)\n<small>*推荐人:包京京*</small>\nFrontend Ops是这篇文章作者自己定义的一个概念,业界应该还没有统一这种叫法,不过文章作者的意思是,随着前端项目复杂程度的增加,需要类似于DevOps的工程化能力,来进行持续发布、自动化测试等等流程(本文是英文的材料,暂无译文)。\n\n* [Koa 框架教程](http://www.ruanyifeng.com/blog/2017/08/koa.html)\n<small>*推荐人:王祥*</small>\n本文从零开始,循序渐进,教会你如何使用 Koa 写出自己的 Web 应用。每一步都有简洁易懂的示例,希望让大家一看就懂。\n\n* [一行 JavaScript 代码的逆向工程](https://juejin.im/post/5988411251882526185d634a)\n<small>*推荐人:郭俊兵*</small>\n这一行代码会被渲染成一个矩阵效果,通过一次代码解读,享受理解它的过程。\n`<pre id=p><script>n=setInterval(\"for(n+=7,i=k,P='p.\\\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P\",k=64)</script>`\n","slug":"weekly-8","published":1,"updated":"2017-08-25T02:32:05.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql7000rjrs6ovtjv5r6","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://www.zcfy.cc/article/mastering-chrome-developer-tools-next-level-front-end-development-techniques-3722.html?t=selection\" target=\"_blank\" rel=\"noopener\">掌握Chrome开发工具</a><br><strong>熟悉Chrome开发工具的基本功能: DOM检查器、样式面板和JavaScript控制台和一些不太为人所知的特性</strong></p>\n</li>\n<li><p><a href=\"https://www.gitbook.com/book/llh911001/mostly-adequate-guide-chinese/details\" target=\"_blank\" rel=\"noopener\">JS函数式编程指南</a><br><strong>对函数式编程的目的有一个初步认识,对一个程序之所以是函数式程序的原因有一定了解</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s/27zpNIGhVbx-on9FDs_6dw\" target=\"_blank\" rel=\"noopener\">HTTP协议详解</a><br><strong>Web服务器是基于HTTP(HyperText Transfer Protocol)协议实现的,所以要实现一个Web服务器就必须了解HTTP协议,本章主要介绍HTTP协议的相关知识,让我们对HTTP协议有个理性的认识。</strong></p>\n</li>\n</ul>\n<h2 id=\"资源整理\"><a href=\"#资源整理\" class=\"headerlink\" title=\"资源整理\"></a>资源整理</h2><ul>\n<li><p><a href=\"http://blog.didiaoyuan.com/2017/04/18/%E6%80%BB%E6%9C%89%E4%BD%A0%E8%A6%81%E7%9A%84%E7%BC%96%E7%A8%8B%E4%B9%A6%E5%8D%95%EF%BC%88GitHub-%EF%BC%89/\" target=\"_blank\" rel=\"noopener\">编程书单</a><br><strong>一些 GitHub 上不错的文章或电子书列表与大家分享。不乏有不少经典,可以收起来慢慢阅览。</strong></p>\n</li>\n<li><p><a href=\"http://www.alloyteam.com/nav/\" target=\"_blank\" rel=\"noopener\">Web前端导航网站</a><br><strong>收录了前端开发需要的大部分网站,可以快速找到自己需要的网站</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"http://www.cnblogs.com/chenguangliang/p/5856701.html\" target=\"_blank\" rel=\"noopener\">彻底弄懂CommonJS和AMD/CMD</a><br><small><em>推荐人:李丽娇</em></small><br>经常说的CommonJS、AMD、CMD规范具体指什么?实现原理是什么?这些规范有哪些具体实现?来看这篇文章找答案。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/25367269\" target=\"_blank\" rel=\"noopener\">使用Node.js实现文件流转存服务</a><br><small><em>推荐人:李志伟</em></small><br>文章介绍了基于node实现分片上传大型文件,通过灵活使用Promise和递归,实现非异步模型看起来很复杂的事情。另外文章附有较为完整的单元测试,覆盖分片的缓存与切割、上传前后的md5值。</p>\n</li>\n<li><p><a href=\"http://coolshell.cn/articles/18024.html\" target=\"_blank\" rel=\"noopener\">API设计原则</a><br><small><em>推荐人:胡国伟</em></small><br>我们平时在编写组件或者后端接口的时候都避免不了API 设计,你的API越容易使用,那么就会有越多的人去用它。那么问题来了,怎样才能设计出优秀的 API ?本文是虽然是以<code>C++</code>为例, 其中设计原则和思考是具有普适性的,是关于API设计一篇难得的好文章</p>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/3\" target=\"_blank\" rel=\"noopener\">一道JS面试题所引发的”血案”,透过现象寻本质,再从本质看现象</a><br><small><em>推荐人:张成斌</em></small><br>对this、执行环境、作用域等概念进行了系统的讲解。加深对于这些易混淆概念的理解。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/a515fbbdd1b2\" target=\"_blank\" rel=\"noopener\">karma+webpack搭建vue单元测试环境</a><br><small><em>推荐人:耿少真</em></small><br>karma+webpack搭建vue单元测试环境介绍了vue单元测试环境搭建及查看源文件的测试覆盖覆盖率。<br><a href=\"http://www.jianshu.com/p/45e8c2b26309\" target=\"_blank\" rel=\"noopener\">Vue单元测试case写法</a><br>测试环境搭建完成后,在此基础上vue单元测试思路介绍和case的写法。测试框架使用jasmine。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28396592\" target=\"_blank\" rel=\"noopener\">【源码拾遗】axios —— 极简封装的艺术</a><br><small><em>推荐人:陶明</em></small><br>本文通过axios 功能的使用及源码分析详细说明了axios 对于功能的实现。<br>axios是基于Promise的方式封装,所以分析axios源码也是对Promise的深入学习。</p>\n</li>\n<li><p><a href=\"https://rupl.github.io/frontend-ops/#/\" target=\"_blank\" rel=\"noopener\">Intro to Frontend Ops</a><br><small><em>推荐人:包京京</em></small><br>Frontend Ops是这篇文章作者自己定义的一个概念,业界应该还没有统一这种叫法,不过文章作者的意思是,随着前端项目复杂程度的增加,需要类似于DevOps的工程化能力,来进行持续发布、自动化测试等等流程(本文是英文的材料,暂无译文)。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/08/koa.html\" target=\"_blank\" rel=\"noopener\">Koa 框架教程</a><br><small><em>推荐人:王祥</em></small><br>本文从零开始,循序渐进,教会你如何使用 Koa 写出自己的 Web 应用。每一步都有简洁易懂的示例,希望让大家一看就懂。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5988411251882526185d634a\" target=\"_blank\" rel=\"noopener\">一行 JavaScript 代码的逆向工程</a><br><small><em>推荐人:郭俊兵</em></small><br>这一行代码会被渲染成一个矩阵效果,通过一次代码解读,享受理解它的过程。<br><code><pre id=p><script>n=setInterval("for(n+=7,i=k,P='p.\\\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P",k=64)</script></code></p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"http://www.zcfy.cc/article/mastering-chrome-developer-tools-next-level-front-end-development-techniques-3722.html?t=selection\" target=\"_blank\" rel=\"noopener\">掌握Chrome开发工具</a><br><strong>熟悉Chrome开发工具的基本功能: DOM检查器、样式面板和JavaScript控制台和一些不太为人所知的特性</strong></p>\n</li>\n<li><p><a href=\"https://www.gitbook.com/book/llh911001/mostly-adequate-guide-chinese/details\" target=\"_blank\" rel=\"noopener\">JS函数式编程指南</a><br><strong>对函数式编程的目的有一个初步认识,对一个程序之所以是函数式程序的原因有一定了解</strong></p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s/27zpNIGhVbx-on9FDs_6dw\" target=\"_blank\" rel=\"noopener\">HTTP协议详解</a><br><strong>Web服务器是基于HTTP(HyperText Transfer Protocol)协议实现的,所以要实现一个Web服务器就必须了解HTTP协议,本章主要介绍HTTP协议的相关知识,让我们对HTTP协议有个理性的认识。</strong></p>\n</li>\n</ul>\n<h2 id=\"资源整理\"><a href=\"#资源整理\" class=\"headerlink\" title=\"资源整理\"></a>资源整理</h2><ul>\n<li><p><a href=\"http://blog.didiaoyuan.com/2017/04/18/%E6%80%BB%E6%9C%89%E4%BD%A0%E8%A6%81%E7%9A%84%E7%BC%96%E7%A8%8B%E4%B9%A6%E5%8D%95%EF%BC%88GitHub-%EF%BC%89/\" target=\"_blank\" rel=\"noopener\">编程书单</a><br><strong>一些 GitHub 上不错的文章或电子书列表与大家分享。不乏有不少经典,可以收起来慢慢阅览。</strong></p>\n</li>\n<li><p><a href=\"http://www.alloyteam.com/nav/\" target=\"_blank\" rel=\"noopener\">Web前端导航网站</a><br><strong>收录了前端开发需要的大部分网站,可以快速找到自己需要的网站</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"http://www.cnblogs.com/chenguangliang/p/5856701.html\" target=\"_blank\" rel=\"noopener\">彻底弄懂CommonJS和AMD/CMD</a><br><small><em>推荐人:李丽娇</em></small><br>经常说的CommonJS、AMD、CMD规范具体指什么?实现原理是什么?这些规范有哪些具体实现?来看这篇文章找答案。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/25367269\" target=\"_blank\" rel=\"noopener\">使用Node.js实现文件流转存服务</a><br><small><em>推荐人:李志伟</em></small><br>文章介绍了基于node实现分片上传大型文件,通过灵活使用Promise和递归,实现非异步模型看起来很复杂的事情。另外文章附有较为完整的单元测试,覆盖分片的缓存与切割、上传前后的md5值。</p>\n</li>\n<li><p><a href=\"http://coolshell.cn/articles/18024.html\" target=\"_blank\" rel=\"noopener\">API设计原则</a><br><small><em>推荐人:胡国伟</em></small><br>我们平时在编写组件或者后端接口的时候都避免不了API 设计,你的API越容易使用,那么就会有越多的人去用它。那么问题来了,怎样才能设计出优秀的 API ?本文是虽然是以<code>C++</code>为例, 其中设计原则和思考是具有普适性的,是关于API设计一篇难得的好文章</p>\n</li>\n<li><p><a href=\"https://github.com/jawil/blog/issues/3\" target=\"_blank\" rel=\"noopener\">一道JS面试题所引发的”血案”,透过现象寻本质,再从本质看现象</a><br><small><em>推荐人:张成斌</em></small><br>对this、执行环境、作用域等概念进行了系统的讲解。加深对于这些易混淆概念的理解。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/a515fbbdd1b2\" target=\"_blank\" rel=\"noopener\">karma+webpack搭建vue单元测试环境</a><br><small><em>推荐人:耿少真</em></small><br>karma+webpack搭建vue单元测试环境介绍了vue单元测试环境搭建及查看源文件的测试覆盖覆盖率。<br><a href=\"http://www.jianshu.com/p/45e8c2b26309\" target=\"_blank\" rel=\"noopener\">Vue单元测试case写法</a><br>测试环境搭建完成后,在此基础上vue单元测试思路介绍和case的写法。测试框架使用jasmine。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/28396592\" target=\"_blank\" rel=\"noopener\">【源码拾遗】axios —— 极简封装的艺术</a><br><small><em>推荐人:陶明</em></small><br>本文通过axios 功能的使用及源码分析详细说明了axios 对于功能的实现。<br>axios是基于Promise的方式封装,所以分析axios源码也是对Promise的深入学习。</p>\n</li>\n<li><p><a href=\"https://rupl.github.io/frontend-ops/#/\" target=\"_blank\" rel=\"noopener\">Intro to Frontend Ops</a><br><small><em>推荐人:包京京</em></small><br>Frontend Ops是这篇文章作者自己定义的一个概念,业界应该还没有统一这种叫法,不过文章作者的意思是,随着前端项目复杂程度的增加,需要类似于DevOps的工程化能力,来进行持续发布、自动化测试等等流程(本文是英文的材料,暂无译文)。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/08/koa.html\" target=\"_blank\" rel=\"noopener\">Koa 框架教程</a><br><small><em>推荐人:王祥</em></small><br>本文从零开始,循序渐进,教会你如何使用 Koa 写出自己的 Web 应用。每一步都有简洁易懂的示例,希望让大家一看就懂。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5988411251882526185d634a\" target=\"_blank\" rel=\"noopener\">一行 JavaScript 代码的逆向工程</a><br><small><em>推荐人:郭俊兵</em></small><br>这一行代码会被渲染成一个矩阵效果,通过一次代码解读,享受理解它的过程。<br><code><pre id=p><script>n=setInterval("for(n+=7,i=k,P='p.\\\\n';i-=1/k;P+=P[i%2?(i%2*j-j+n/k^j)&1:2])j=k/i;p.innerHTML=P",k=64)</script></code></p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第7期 (本期小编:张成斌)","date":"2017-08-04T02:32:34.000Z","_content":"## 基础\n\n* [exports、module.exports 和 export、export default 到底是咋回事](https://juejin.im/post/597ec55a51882556a234fcef)\n**模块引入方式的一个梳理**\n\n* [Node.js 实践教程](https://github.com/ElemeFE/node-practice)\n**饿了么出的一个Node实践教程,还在施工中,有兴趣的小伙伴可以关注一下。前提背景是[如何通过饿了么 Node.js 面试](https://github.com/ElemeFE/node-interview/tree/master/sections/zh-cn)**\n\n* [浏览器是怎么看闭包的](https://juejin.im/post/5979b5755188253df1067397)\n**换个角度来理解闭包,从内存分配与回收的角度阐述,希望能帮助大家真正消化掉所看到的闭包知识**\n\n## 文章\n* [深入理解 JavaScript 数据双向绑定](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=2&sn=e1d9664d24d7b44bcece7464318a8369&chksm=e82be290df5c6b86f08fa80a5b33e4a3d46daa1093290610d63b47f86f5bdd7d21151b91dd8f&mpshare=1&scene=1&srcid=0804TnxBJbqO63wtfhcXPBra&pass_ticket=lctb96bPZ%2BUbaZfdgO9Bxo8p62cFUW61TN3xhm1p6zgF%2FxcmdmZtIzWeDN%2F7BnNZ#rd)\n<small>*推荐人:包京京*</small>\n首先讲解一下数据双向绑定的基本原理,介绍对比一下三大框架的不同实现方式,同时会一步步完成一个简单的mvvm示例。\n\n* [前端开发者指南(2017)](https://juejin.im/post/592faca42f301e006bc791e0)\n<small>*推荐人:郭俊兵*</small>\n内容偏向于 WEB 技术(HTML、CSS、DOM、JavaScript)和以这些技术为根基直接构建而成的开源技术。书中引用和讨论的材料要么就是同类翘楚,要么就是解决问题的流行方案。\n\n* [关于 Vue App 开发的一些思考](https://juejin.im/post/592faca42f301e006bc791e0)\n<small>*推荐人:张成斌*</small>\nTalkingData实习生写的一篇文章。作者回顾了自己经历三个项目的开发历程,发现了很多问题,也产生了很多思考。该文章有很多值得借鉴的地方。\n\n* [JavaScript专题之jQuery通用遍历方法each的实现](https://segmentfault.com/a/1190000010480396)\n<br>[系列目录地址](https://github.com/mqyqingfeng/Blog)\n<small>*推荐人:陶明*</small>\n文章从each 的功能实现入手不断完善,整体实现思路清晰,对于问题及解决也有详细的代码实现与解释。这是一个系列内容涵盖防抖、节流、去重、类型判断等。\n\n* [JavaScript 数据类型和数据结构](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures)\n<small>*推荐人:李丽娇*</small>\n作为js权威文档之一,mozilla网站除了对基础只是的介绍,还会有一些总结性的文章和使用注意事项。\n这篇文章总结性地介绍了Javascript的数据类型和数据结构,并有一些使用中的注意事项。\n\n* [函数式编程初探](http://www.ruanyifeng.com/blog/2012/04/functional_programming.html)\n<br>[函数式编程入门教程](http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html)\n<small>*推荐人:王祥*</small>\n推荐阮一峰老师的两篇函数式入门文章,大家可能无意识的使用函数式编程一段时间了。读这两篇文章,可以将思维里零散的函数式编码习惯系串联起来。\n\n* [Vue 全站服务器渲染 SSR 实践](http://gitbook.cn/m/mazi/article/5900675d2fde0e5078d4ed5e?readArticle=yes)\n<small>*推荐人:胡国伟*</small>\n掘金分享了`vue`实现SSR的实践,目前来看性能问题依然很严重,仅供大家参考。\n\n* [Vue开发常见问题集锦](http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ)\n<small>*推荐人:王俐*</small>\n附:[换个思路理解Javascript中的this](http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ)实际开发中会遇到的问题,主要涉及技术栈: Vue-CLI、 Element UI、 Pug(Jade)、 Less、ES6;\n1、涉及问题:ES6语法转换建议使用babel-polyfill;\n2、对于let和const的使用\n3、自定义路径别名的设置\n4、 在使用 Moment.js 遇到一些问题\n5、CSS 作用域与模块\n\n* [详解 Vue 2.4.0 带来的 4 个重大变化](https://mp.weixin.qq.com/s/qRAdgYxOfBW6xmQUdZcu_A)\n<small>*推荐人:李志伟*</small>\n“异步组件”让你的应用代码分离,使非必要组件在首页加载后延迟加载, 从而让用户更快的看到主页;组件内新增实现“属性继承”,使你的在每个中间组件属性定义变得相当简洁;异步组件支持webpack3,vue-loaderv13.0.0将.vue文件作为ES模块输出,这使得vue能够享受新的变量提升带来的便利;保留HTML注释,咳咳...聊胜于无。\n\n* [异步编程之async](https://i.jakeyu.top/2017/03/15/async/)\n<small>*推荐人:耿少真*</small>\n对async方法的深入理解。\n","source":"_posts/weekly-7.md","raw":"---\ntitle: 大前端周刊 第7期 (本期小编:张成斌)\ndate: 2017-08-04 10:32:34\ntags: [weekly,模块,node,Vue,函数式]\n---\n## 基础\n\n* [exports、module.exports 和 export、export default 到底是咋回事](https://juejin.im/post/597ec55a51882556a234fcef)\n**模块引入方式的一个梳理**\n\n* [Node.js 实践教程](https://github.com/ElemeFE/node-practice)\n**饿了么出的一个Node实践教程,还在施工中,有兴趣的小伙伴可以关注一下。前提背景是[如何通过饿了么 Node.js 面试](https://github.com/ElemeFE/node-interview/tree/master/sections/zh-cn)**\n\n* [浏览器是怎么看闭包的](https://juejin.im/post/5979b5755188253df1067397)\n**换个角度来理解闭包,从内存分配与回收的角度阐述,希望能帮助大家真正消化掉所看到的闭包知识**\n\n## 文章\n* [深入理解 JavaScript 数据双向绑定](https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=2&sn=e1d9664d24d7b44bcece7464318a8369&chksm=e82be290df5c6b86f08fa80a5b33e4a3d46daa1093290610d63b47f86f5bdd7d21151b91dd8f&mpshare=1&scene=1&srcid=0804TnxBJbqO63wtfhcXPBra&pass_ticket=lctb96bPZ%2BUbaZfdgO9Bxo8p62cFUW61TN3xhm1p6zgF%2FxcmdmZtIzWeDN%2F7BnNZ#rd)\n<small>*推荐人:包京京*</small>\n首先讲解一下数据双向绑定的基本原理,介绍对比一下三大框架的不同实现方式,同时会一步步完成一个简单的mvvm示例。\n\n* [前端开发者指南(2017)](https://juejin.im/post/592faca42f301e006bc791e0)\n<small>*推荐人:郭俊兵*</small>\n内容偏向于 WEB 技术(HTML、CSS、DOM、JavaScript)和以这些技术为根基直接构建而成的开源技术。书中引用和讨论的材料要么就是同类翘楚,要么就是解决问题的流行方案。\n\n* [关于 Vue App 开发的一些思考](https://juejin.im/post/592faca42f301e006bc791e0)\n<small>*推荐人:张成斌*</small>\nTalkingData实习生写的一篇文章。作者回顾了自己经历三个项目的开发历程,发现了很多问题,也产生了很多思考。该文章有很多值得借鉴的地方。\n\n* [JavaScript专题之jQuery通用遍历方法each的实现](https://segmentfault.com/a/1190000010480396)\n<br>[系列目录地址](https://github.com/mqyqingfeng/Blog)\n<small>*推荐人:陶明*</small>\n文章从each 的功能实现入手不断完善,整体实现思路清晰,对于问题及解决也有详细的代码实现与解释。这是一个系列内容涵盖防抖、节流、去重、类型判断等。\n\n* [JavaScript 数据类型和数据结构](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures)\n<small>*推荐人:李丽娇*</small>\n作为js权威文档之一,mozilla网站除了对基础只是的介绍,还会有一些总结性的文章和使用注意事项。\n这篇文章总结性地介绍了Javascript的数据类型和数据结构,并有一些使用中的注意事项。\n\n* [函数式编程初探](http://www.ruanyifeng.com/blog/2012/04/functional_programming.html)\n<br>[函数式编程入门教程](http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html)\n<small>*推荐人:王祥*</small>\n推荐阮一峰老师的两篇函数式入门文章,大家可能无意识的使用函数式编程一段时间了。读这两篇文章,可以将思维里零散的函数式编码习惯系串联起来。\n\n* [Vue 全站服务器渲染 SSR 实践](http://gitbook.cn/m/mazi/article/5900675d2fde0e5078d4ed5e?readArticle=yes)\n<small>*推荐人:胡国伟*</small>\n掘金分享了`vue`实现SSR的实践,目前来看性能问题依然很严重,仅供大家参考。\n\n* [Vue开发常见问题集锦](http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ)\n<small>*推荐人:王俐*</small>\n附:[换个思路理解Javascript中的this](http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ)实际开发中会遇到的问题,主要涉及技术栈: Vue-CLI、 Element UI、 Pug(Jade)、 Less、ES6;\n1、涉及问题:ES6语法转换建议使用babel-polyfill;\n2、对于let和const的使用\n3、自定义路径别名的设置\n4、 在使用 Moment.js 遇到一些问题\n5、CSS 作用域与模块\n\n* [详解 Vue 2.4.0 带来的 4 个重大变化](https://mp.weixin.qq.com/s/qRAdgYxOfBW6xmQUdZcu_A)\n<small>*推荐人:李志伟*</small>\n“异步组件”让你的应用代码分离,使非必要组件在首页加载后延迟加载, 从而让用户更快的看到主页;组件内新增实现“属性继承”,使你的在每个中间组件属性定义变得相当简洁;异步组件支持webpack3,vue-loaderv13.0.0将.vue文件作为ES模块输出,这使得vue能够享受新的变量提升带来的便利;保留HTML注释,咳咳...聊胜于无。\n\n* [异步编程之async](https://i.jakeyu.top/2017/03/15/async/)\n<small>*推荐人:耿少真*</small>\n对async方法的深入理解。\n","slug":"weekly-7","published":1,"updated":"2017-08-28T16:45:18.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql8000tjrs6lr0cx3u3","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://juejin.im/post/597ec55a51882556a234fcef\" target=\"_blank\" rel=\"noopener\">exports、module.exports 和 export、export default 到底是咋回事</a><br><strong>模块引入方式的一个梳理</strong></p>\n</li>\n<li><p><a href=\"https://github.com/ElemeFE/node-practice\" target=\"_blank\" rel=\"noopener\">Node.js 实践教程</a><br><strong>饿了么出的一个Node实践教程,还在施工中,有兴趣的小伙伴可以关注一下。前提背景是<a href=\"https://github.com/ElemeFE/node-interview/tree/master/sections/zh-cn\" target=\"_blank\" rel=\"noopener\">如何通过饿了么 Node.js 面试</a></strong></p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5979b5755188253df1067397\" target=\"_blank\" rel=\"noopener\">浏览器是怎么看闭包的</a><br><strong>换个角度来理解闭包,从内存分配与回收的角度阐述,希望能帮助大家真正消化掉所看到的闭包知识</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=2&sn=e1d9664d24d7b44bcece7464318a8369&chksm=e82be290df5c6b86f08fa80a5b33e4a3d46daa1093290610d63b47f86f5bdd7d21151b91dd8f&mpshare=1&scene=1&srcid=0804TnxBJbqO63wtfhcXPBra&pass_ticket=lctb96bPZ%2BUbaZfdgO9Bxo8p62cFUW61TN3xhm1p6zgF%2FxcmdmZtIzWeDN%2F7BnNZ#rd\" target=\"_blank\" rel=\"noopener\">深入理解 JavaScript 数据双向绑定</a><br><small><em>推荐人:包京京</em></small><br>首先讲解一下数据双向绑定的基本原理,介绍对比一下三大框架的不同实现方式,同时会一步步完成一个简单的mvvm示例。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/592faca42f301e006bc791e0\" target=\"_blank\" rel=\"noopener\">前端开发者指南(2017)</a><br><small><em>推荐人:郭俊兵</em></small><br>内容偏向于 WEB 技术(HTML、CSS、DOM、JavaScript)和以这些技术为根基直接构建而成的开源技术。书中引用和讨论的材料要么就是同类翘楚,要么就是解决问题的流行方案。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/592faca42f301e006bc791e0\" target=\"_blank\" rel=\"noopener\">关于 Vue App 开发的一些思考</a><br><small><em>推荐人:张成斌</em></small><br>TalkingData实习生写的一篇文章。作者回顾了自己经历三个项目的开发历程,发现了很多问题,也产生了很多思考。该文章有很多值得借鉴的地方。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010480396\" target=\"_blank\" rel=\"noopener\">JavaScript专题之jQuery通用遍历方法each的实现</a><br><br><a href=\"https://github.com/mqyqingfeng/Blog\" target=\"_blank\" rel=\"noopener\">系列目录地址</a><br><small><em>推荐人:陶明</em></small><br>文章从each 的功能实现入手不断完善,整体实现思路清晰,对于问题及解决也有详细的代码实现与解释。这是一个系列内容涵盖防抖、节流、去重、类型判断等。</p>\n</li>\n<li><p><a href=\"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures\" target=\"_blank\" rel=\"noopener\">JavaScript 数据类型和数据结构</a><br><small><em>推荐人:李丽娇</em></small><br>作为js权威文档之一,mozilla网站除了对基础只是的介绍,还会有一些总结性的文章和使用注意事项。<br>这篇文章总结性地介绍了Javascript的数据类型和数据结构,并有一些使用中的注意事项。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/04/functional_programming.html\" target=\"_blank\" rel=\"noopener\">函数式编程初探</a><br><br><a href=\"http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html\" target=\"_blank\" rel=\"noopener\">函数式编程入门教程</a><br><small><em>推荐人:王祥</em></small><br>推荐阮一峰老师的两篇函数式入门文章,大家可能无意识的使用函数式编程一段时间了。读这两篇文章,可以将思维里零散的函数式编码习惯系串联起来。</p>\n</li>\n<li><p><a href=\"http://gitbook.cn/m/mazi/article/5900675d2fde0e5078d4ed5e?readArticle=yes\" target=\"_blank\" rel=\"noopener\">Vue 全站服务器渲染 SSR 实践</a><br><small><em>推荐人:胡国伟</em></small><br>掘金分享了<code>vue</code>实现SSR的实践,目前来看性能问题依然很严重,仅供大家参考。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ\" target=\"_blank\" rel=\"noopener\">Vue开发常见问题集锦</a><br><small><em>推荐人:王俐</em></small><br>附:<a href=\"http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ\" target=\"_blank\" rel=\"noopener\">换个思路理解Javascript中的this</a>实际开发中会遇到的问题,主要涉及技术栈: Vue-CLI、 Element UI、 Pug(Jade)、 Less、ES6;<br>1、涉及问题:ES6语法转换建议使用babel-polyfill;<br>2、对于let和const的使用<br>3、自定义路径别名的设置<br>4、 在使用 Moment.js 遇到一些问题<br>5、CSS 作用域与模块</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s/qRAdgYxOfBW6xmQUdZcu_A\" target=\"_blank\" rel=\"noopener\">详解 Vue 2.4.0 带来的 4 个重大变化</a><br><small><em>推荐人:李志伟</em></small><br>“异步组件”让你的应用代码分离,使非必要组件在首页加载后延迟加载, 从而让用户更快的看到主页;组件内新增实现“属性继承”,使你的在每个中间组件属性定义变得相当简洁;异步组件支持webpack3,vue-loaderv13.0.0将.vue文件作为ES模块输出,这使得vue能够享受新的变量提升带来的便利;保留HTML注释,咳咳…聊胜于无。</p>\n</li>\n<li><p><a href=\"https://i.jakeyu.top/2017/03/15/async/\" target=\"_blank\" rel=\"noopener\">异步编程之async</a><br><small><em>推荐人:耿少真</em></small><br>对async方法的深入理解。</p>\n</li>\n</ul>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://juejin.im/post/597ec55a51882556a234fcef\" target=\"_blank\" rel=\"noopener\">exports、module.exports 和 export、export default 到底是咋回事</a><br><strong>模块引入方式的一个梳理</strong></p>\n</li>\n<li><p><a href=\"https://github.com/ElemeFE/node-practice\" target=\"_blank\" rel=\"noopener\">Node.js 实践教程</a><br><strong>饿了么出的一个Node实践教程,还在施工中,有兴趣的小伙伴可以关注一下。前提背景是<a href=\"https://github.com/ElemeFE/node-interview/tree/master/sections/zh-cn\" target=\"_blank\" rel=\"noopener\">如何通过饿了么 Node.js 面试</a></strong></p>\n</li>\n<li><p><a href=\"https://juejin.im/post/5979b5755188253df1067397\" target=\"_blank\" rel=\"noopener\">浏览器是怎么看闭包的</a><br><strong>换个角度来理解闭包,从内存分配与回收的角度阐述,希望能帮助大家真正消化掉所看到的闭包知识</strong></p>\n</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyMjYyMzg3MA==&mid=2247484289&idx=2&sn=e1d9664d24d7b44bcece7464318a8369&chksm=e82be290df5c6b86f08fa80a5b33e4a3d46daa1093290610d63b47f86f5bdd7d21151b91dd8f&mpshare=1&scene=1&srcid=0804TnxBJbqO63wtfhcXPBra&pass_ticket=lctb96bPZ%2BUbaZfdgO9Bxo8p62cFUW61TN3xhm1p6zgF%2FxcmdmZtIzWeDN%2F7BnNZ#rd\" target=\"_blank\" rel=\"noopener\">深入理解 JavaScript 数据双向绑定</a><br><small><em>推荐人:包京京</em></small><br>首先讲解一下数据双向绑定的基本原理,介绍对比一下三大框架的不同实现方式,同时会一步步完成一个简单的mvvm示例。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/592faca42f301e006bc791e0\" target=\"_blank\" rel=\"noopener\">前端开发者指南(2017)</a><br><small><em>推荐人:郭俊兵</em></small><br>内容偏向于 WEB 技术(HTML、CSS、DOM、JavaScript)和以这些技术为根基直接构建而成的开源技术。书中引用和讨论的材料要么就是同类翘楚,要么就是解决问题的流行方案。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/592faca42f301e006bc791e0\" target=\"_blank\" rel=\"noopener\">关于 Vue App 开发的一些思考</a><br><small><em>推荐人:张成斌</em></small><br>TalkingData实习生写的一篇文章。作者回顾了自己经历三个项目的开发历程,发现了很多问题,也产生了很多思考。该文章有很多值得借鉴的地方。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010480396\" target=\"_blank\" rel=\"noopener\">JavaScript专题之jQuery通用遍历方法each的实现</a><br><br><a href=\"https://github.com/mqyqingfeng/Blog\" target=\"_blank\" rel=\"noopener\">系列目录地址</a><br><small><em>推荐人:陶明</em></small><br>文章从each 的功能实现入手不断完善,整体实现思路清晰,对于问题及解决也有详细的代码实现与解释。这是一个系列内容涵盖防抖、节流、去重、类型判断等。</p>\n</li>\n<li><p><a href=\"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures\" target=\"_blank\" rel=\"noopener\">JavaScript 数据类型和数据结构</a><br><small><em>推荐人:李丽娇</em></small><br>作为js权威文档之一,mozilla网站除了对基础只是的介绍,还会有一些总结性的文章和使用注意事项。<br>这篇文章总结性地介绍了Javascript的数据类型和数据结构,并有一些使用中的注意事项。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2012/04/functional_programming.html\" target=\"_blank\" rel=\"noopener\">函数式编程初探</a><br><br><a href=\"http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html\" target=\"_blank\" rel=\"noopener\">函数式编程入门教程</a><br><small><em>推荐人:王祥</em></small><br>推荐阮一峰老师的两篇函数式入门文章,大家可能无意识的使用函数式编程一段时间了。读这两篇文章,可以将思维里零散的函数式编码习惯系串联起来。</p>\n</li>\n<li><p><a href=\"http://gitbook.cn/m/mazi/article/5900675d2fde0e5078d4ed5e?readArticle=yes\" target=\"_blank\" rel=\"noopener\">Vue 全站服务器渲染 SSR 实践</a><br><small><em>推荐人:胡国伟</em></small><br>掘金分享了<code>vue</code>实现SSR的实践,目前来看性能问题依然很严重,仅供大家参考。</p>\n</li>\n<li><p><a href=\"http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ\" target=\"_blank\" rel=\"noopener\">Vue开发常见问题集锦</a><br><small><em>推荐人:王俐</em></small><br>附:<a href=\"http://mp.weixin.qq.com/s/fgFOvWBC_P78hG154gyXYQ\" target=\"_blank\" rel=\"noopener\">换个思路理解Javascript中的this</a>实际开发中会遇到的问题,主要涉及技术栈: Vue-CLI、 Element UI、 Pug(Jade)、 Less、ES6;<br>1、涉及问题:ES6语法转换建议使用babel-polyfill;<br>2、对于let和const的使用<br>3、自定义路径别名的设置<br>4、 在使用 Moment.js 遇到一些问题<br>5、CSS 作用域与模块</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s/qRAdgYxOfBW6xmQUdZcu_A\" target=\"_blank\" rel=\"noopener\">详解 Vue 2.4.0 带来的 4 个重大变化</a><br><small><em>推荐人:李志伟</em></small><br>“异步组件”让你的应用代码分离,使非必要组件在首页加载后延迟加载, 从而让用户更快的看到主页;组件内新增实现“属性继承”,使你的在每个中间组件属性定义变得相当简洁;异步组件支持webpack3,vue-loaderv13.0.0将.vue文件作为ES模块输出,这使得vue能够享受新的变量提升带来的便利;保留HTML注释,咳咳…聊胜于无。</p>\n</li>\n<li><p><a href=\"https://i.jakeyu.top/2017/03/15/async/\" target=\"_blank\" rel=\"noopener\">异步编程之async</a><br><small><em>推荐人:耿少真</em></small><br>对async方法的深入理解。</p>\n</li>\n</ul>\n"},{"title":"大前端周刊 第3期 (本期小编:李志伟)","date":"2017-07-07T05:10:51.000Z","_content":"\n## 基础\n* [JavaScript系列](https://juejin.im/post/59278e312f301e006c2e1510)\n相信作为“前端程序猿(媛)”的你一定了解作用域、原型、原型链、继承、闭包……在前端框架的盛行之下,却让初学者忽略了JS基础的学习,但基础不稳必然限制你的发展空间,当你了解了底层,就能很轻松明白框架的原理。\n\n* [排序算法](https://juejin.im/post/57dcd394a22b9d00610c5ec8)\n什么?在这个“用数据说话”的时代,你不懂排序算法?那你算什么男人~算什么男人~ 不对不对 算什么猿人~算什么猿人...咳咳,言归正传,平时开发我们常用的快速排序、冒泡排序、选择排序你是否了解其利弊。除此之外还有什么排序算法呢?快来一起学习吧。\n\n* [Iterator 遍历器](http://es6.ruanyifeng.com/#docs/iterator)\nIterator为各种不同的数据结构提供了统一的访问机制。它可以提供统一的、简便的接口,使得数据结构的成员按某种次序排列,而es6新增for...of循环,就是由Iterator接口提供消费的。\n\n* [TCP协议简介](http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html)\nTCP作为互联网核心协议之一,“三次握手”“四次挥手”你是否有所了解?快来完善自己的知识体系吧。\nps:详解请参考[这里](http://www.jianshu.com/p/ef892323e68f)\n\n* [正则表达式](http://www.jianshu.com/p/e7bb97218946)\n业务中有很多复杂的逻辑判断?常常嵌套多个if?快来这里学习下吧,熟练掌握正则表达式会使得你的开发效率得到极大提升。\n\n## 资源整理\n* [前端知识点大百科全书](https://github.com/Wscats/Good-text-Share)\n* [前端资源汇集](http://www.jianshu.com/p/c3dae0951f74)\n如此之全的知识整理、资源汇集,都掌握的话你可以神挡杀神佛挡杀佛了。\n\n## 文章\n\n* [一劳永逸的搞定flex布局](https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb)\n你是否还在使用浮动布局?写各种line-height实现居中?不妨试试flexBox布局,它简单易用的写法可以轻松实现各种布局,让你的布局更快速高效。\n\n* [Vue的数据依赖实现原理简析](https://segmentfault.com/a/1190000010014281)\n主要从初始化的数据层面上分析了Vue是如何管理依赖来到达数据的动态响应。\ninitState的过程中,将props,computed,data等属性通过Object.defineProperty来改造其getter/setter属性,并为每一个响应式属性实例化一个observer观察者。这个observer内部dep记录了这个响应式属性的所有依赖。\n当响应式属性调用setter函数时,通过dep.notify()方法去遍历所有的依赖,调用watcher.update()去完成数据的动态响应。\n\n* [靠谱程序员必备技能——重构](https://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&mid=2652558943&idx=1&sn=1516afcf876b9fb4a17ce048c5ade58d)\n当项目变得难以维护,重构便便迫在眉睫,但很多所谓重构仅仅算是重写,随着时间推移,项目再次变得难以维护,周而复始,陷入怪圈。如何避免重构变成重写,本文给了一些很好的建议。\n\n* [我接触过的前端数据结构与算法](https://zhuanlan.zhihu.com/p/27659059)\n只要是工程师就必须学好计算机基础,只有这样才能适应计算机技术的快速发展,前端工程师更是如此。\n\n* [Vuex 通俗版教程](https://yeaseonzhang.github.io/2017/03/16/Vuex-%E9%80%9A%E4%BF%97%E7%89%88/)\nVuex 类似 Redux 的状态管理器,用来管理Vue的所有组件状态。\n一般在你开发大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。\n遇到以上情况时候,可以考虑使用Vuex,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。\n\n* [学习Vue.js源码](https://stffe.github.io/vue/2017/03/03/%E5%AD%A6%E4%B9%A0Vue%E6%BA%90%E7%A0%81.html)\n文中介绍了vue项目目录结构和数据绑定实现,没有太深入,但可以作为初步了解。\n\n* [GitHub —— 你不得不上的交友网站](https://segmentfault.com/a/1190000009985489#articleHeader9)\n文章整理了GitHub入门,搭建发布个人博客及个人项目发布,还介绍了一些工具,插件及开源项目;内容比较丰富。\n\n* [彻底搞清楚javascript中的require、import和export](http://meiminjun.github.io/import%E5%92%8Cexport%E7%AC%94%E8%AE%B0/)\n通过介绍CMD、AMD、ES6的模块规范,来引申出平时业务中经常用到require、import和export的用法以及含义。\n\n* [工具推荐](https://github.com/istanbuljs/nyc)\n覆盖率工具 istanbul 替换为 nyc,多进程覆盖率的测试速度提升了几倍。都是同一作者的作品,后者目前活跃度高,并支持前端很多新特性。\n\n```\n$ npm i nyc --save-dev\n$ ./node_modules/.bin/nyc ./node_modules/.bin/mocha\n```\n执行单元测试命令后,还会直观的给出代码覆盖率报告,以[Flclover](http://flcloverjs.org/)为例:\n```\n------------------------------------|----------|----------|----------|----------|----------------|\nFile | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |\n------------------------------------|----------|----------|----------|----------|----------------|\nAll files | 79.41 | 66.67 | 61.11 | 81.82 | |\n flclover | 100 | 100 | 100 | 100 | |\n index.js | 100 | 100 | 100 | 100 | |\n flclover/lib | 88.52 | 82.35 | 81.82 | 88.52 | |\n application.js | 100 | 100 | 100 | 100 | |\n flclover.js | 30 | 0 | 0 | 30 |... 13,14,17,19 |\n flclover/lib/middleware/bodyparser | 100 | 100 | 100 | 100 | |\n index.js | 100 | 100 | 100 | 100 | |\n flclover/lib/middleware/logger | 55.56 | 50 | 50 | 55.56 | |\n index.js | 55.56 | 50 | 50 | 55.56 |... 39,42,45,48 |\n flclover/lib/utils | 71.43 | 33.33 | 0 | 83.33 | |\n index.js | 81.25 | 33.33 | 0 | 100 | 7,10 |\n logger.js | 40 | 100 | 0 | 40 | 4,9,13 |\n------------------------------------|----------|----------|----------|----------|----------------|\n```\n","source":"_posts/weekly-3.md","raw":"---\ntitle: 大前端周刊 第3期 (本期小编:李志伟)\ndate: 2017-07-07 13:10:51\ntags: [weekly,es6,vue,算法,工具,必备技能]\n---\n\n## 基础\n* [JavaScript系列](https://juejin.im/post/59278e312f301e006c2e1510)\n相信作为“前端程序猿(媛)”的你一定了解作用域、原型、原型链、继承、闭包……在前端框架的盛行之下,却让初学者忽略了JS基础的学习,但基础不稳必然限制你的发展空间,当你了解了底层,就能很轻松明白框架的原理。\n\n* [排序算法](https://juejin.im/post/57dcd394a22b9d00610c5ec8)\n什么?在这个“用数据说话”的时代,你不懂排序算法?那你算什么男人~算什么男人~ 不对不对 算什么猿人~算什么猿人...咳咳,言归正传,平时开发我们常用的快速排序、冒泡排序、选择排序你是否了解其利弊。除此之外还有什么排序算法呢?快来一起学习吧。\n\n* [Iterator 遍历器](http://es6.ruanyifeng.com/#docs/iterator)\nIterator为各种不同的数据结构提供了统一的访问机制。它可以提供统一的、简便的接口,使得数据结构的成员按某种次序排列,而es6新增for...of循环,就是由Iterator接口提供消费的。\n\n* [TCP协议简介](http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html)\nTCP作为互联网核心协议之一,“三次握手”“四次挥手”你是否有所了解?快来完善自己的知识体系吧。\nps:详解请参考[这里](http://www.jianshu.com/p/ef892323e68f)\n\n* [正则表达式](http://www.jianshu.com/p/e7bb97218946)\n业务中有很多复杂的逻辑判断?常常嵌套多个if?快来这里学习下吧,熟练掌握正则表达式会使得你的开发效率得到极大提升。\n\n## 资源整理\n* [前端知识点大百科全书](https://github.com/Wscats/Good-text-Share)\n* [前端资源汇集](http://www.jianshu.com/p/c3dae0951f74)\n如此之全的知识整理、资源汇集,都掌握的话你可以神挡杀神佛挡杀佛了。\n\n## 文章\n\n* [一劳永逸的搞定flex布局](https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb)\n你是否还在使用浮动布局?写各种line-height实现居中?不妨试试flexBox布局,它简单易用的写法可以轻松实现各种布局,让你的布局更快速高效。\n\n* [Vue的数据依赖实现原理简析](https://segmentfault.com/a/1190000010014281)\n主要从初始化的数据层面上分析了Vue是如何管理依赖来到达数据的动态响应。\ninitState的过程中,将props,computed,data等属性通过Object.defineProperty来改造其getter/setter属性,并为每一个响应式属性实例化一个observer观察者。这个observer内部dep记录了这个响应式属性的所有依赖。\n当响应式属性调用setter函数时,通过dep.notify()方法去遍历所有的依赖,调用watcher.update()去完成数据的动态响应。\n\n* [靠谱程序员必备技能——重构](https://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&mid=2652558943&idx=1&sn=1516afcf876b9fb4a17ce048c5ade58d)\n当项目变得难以维护,重构便便迫在眉睫,但很多所谓重构仅仅算是重写,随着时间推移,项目再次变得难以维护,周而复始,陷入怪圈。如何避免重构变成重写,本文给了一些很好的建议。\n\n* [我接触过的前端数据结构与算法](https://zhuanlan.zhihu.com/p/27659059)\n只要是工程师就必须学好计算机基础,只有这样才能适应计算机技术的快速发展,前端工程师更是如此。\n\n* [Vuex 通俗版教程](https://yeaseonzhang.github.io/2017/03/16/Vuex-%E9%80%9A%E4%BF%97%E7%89%88/)\nVuex 类似 Redux 的状态管理器,用来管理Vue的所有组件状态。\n一般在你开发大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。\n遇到以上情况时候,可以考虑使用Vuex,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。\n\n* [学习Vue.js源码](https://stffe.github.io/vue/2017/03/03/%E5%AD%A6%E4%B9%A0Vue%E6%BA%90%E7%A0%81.html)\n文中介绍了vue项目目录结构和数据绑定实现,没有太深入,但可以作为初步了解。\n\n* [GitHub —— 你不得不上的交友网站](https://segmentfault.com/a/1190000009985489#articleHeader9)\n文章整理了GitHub入门,搭建发布个人博客及个人项目发布,还介绍了一些工具,插件及开源项目;内容比较丰富。\n\n* [彻底搞清楚javascript中的require、import和export](http://meiminjun.github.io/import%E5%92%8Cexport%E7%AC%94%E8%AE%B0/)\n通过介绍CMD、AMD、ES6的模块规范,来引申出平时业务中经常用到require、import和export的用法以及含义。\n\n* [工具推荐](https://github.com/istanbuljs/nyc)\n覆盖率工具 istanbul 替换为 nyc,多进程覆盖率的测试速度提升了几倍。都是同一作者的作品,后者目前活跃度高,并支持前端很多新特性。\n\n```\n$ npm i nyc --save-dev\n$ ./node_modules/.bin/nyc ./node_modules/.bin/mocha\n```\n执行单元测试命令后,还会直观的给出代码覆盖率报告,以[Flclover](http://flcloverjs.org/)为例:\n```\n------------------------------------|----------|----------|----------|----------|----------------|\nFile | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |\n------------------------------------|----------|----------|----------|----------|----------------|\nAll files | 79.41 | 66.67 | 61.11 | 81.82 | |\n flclover | 100 | 100 | 100 | 100 | |\n index.js | 100 | 100 | 100 | 100 | |\n flclover/lib | 88.52 | 82.35 | 81.82 | 88.52 | |\n application.js | 100 | 100 | 100 | 100 | |\n flclover.js | 30 | 0 | 0 | 30 |... 13,14,17,19 |\n flclover/lib/middleware/bodyparser | 100 | 100 | 100 | 100 | |\n index.js | 100 | 100 | 100 | 100 | |\n flclover/lib/middleware/logger | 55.56 | 50 | 50 | 55.56 | |\n index.js | 55.56 | 50 | 50 | 55.56 |... 39,42,45,48 |\n flclover/lib/utils | 71.43 | 33.33 | 0 | 83.33 | |\n index.js | 81.25 | 33.33 | 0 | 100 | 7,10 |\n logger.js | 40 | 100 | 0 | 40 | 4,9,13 |\n------------------------------------|----------|----------|----------|----------|----------------|\n```\n","slug":"weekly-3","published":1,"updated":"2017-08-25T02:32:23.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1ql9000ujrs6g5pi0rwr","content":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://juejin.im/post/59278e312f301e006c2e1510\" target=\"_blank\" rel=\"noopener\">JavaScript系列</a><br>相信作为“前端程序猿(媛)”的你一定了解作用域、原型、原型链、继承、闭包……在前端框架的盛行之下,却让初学者忽略了JS基础的学习,但基础不稳必然限制你的发展空间,当你了解了底层,就能很轻松明白框架的原理。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/57dcd394a22b9d00610c5ec8\" target=\"_blank\" rel=\"noopener\">排序算法</a><br>什么?在这个“用数据说话”的时代,你不懂排序算法?那你算什么男人~算什么男人~ 不对不对 算什么猿人~算什么猿人…咳咳,言归正传,平时开发我们常用的快速排序、冒泡排序、选择排序你是否了解其利弊。除此之外还有什么排序算法呢?快来一起学习吧。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/iterator\" target=\"_blank\" rel=\"noopener\">Iterator 遍历器</a><br>Iterator为各种不同的数据结构提供了统一的访问机制。它可以提供统一的、简便的接口,使得数据结构的成员按某种次序排列,而es6新增for…of循环,就是由Iterator接口提供消费的。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html\" target=\"_blank\" rel=\"noopener\">TCP协议简介</a><br>TCP作为互联网核心协议之一,“三次握手”“四次挥手”你是否有所了解?快来完善自己的知识体系吧。<br>ps:详解请参考<a href=\"http://www.jianshu.com/p/ef892323e68f\" target=\"_blank\" rel=\"noopener\">这里</a></p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/e7bb97218946\" target=\"_blank\" rel=\"noopener\">正则表达式</a><br>业务中有很多复杂的逻辑判断?常常嵌套多个if?快来这里学习下吧,熟练掌握正则表达式会使得你的开发效率得到极大提升。</p>\n</li>\n</ul>\n<h2 id=\"资源整理\"><a href=\"#资源整理\" class=\"headerlink\" title=\"资源整理\"></a>资源整理</h2><ul>\n<li><a href=\"https://github.com/Wscats/Good-text-Share\" target=\"_blank\" rel=\"noopener\">前端知识点大百科全书</a></li>\n<li><a href=\"http://www.jianshu.com/p/c3dae0951f74\" target=\"_blank\" rel=\"noopener\">前端资源汇集</a><br>如此之全的知识整理、资源汇集,都掌握的话你可以神挡杀神佛挡杀佛了。</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb\" target=\"_blank\" rel=\"noopener\">一劳永逸的搞定flex布局</a><br>你是否还在使用浮动布局?写各种line-height实现居中?不妨试试flexBox布局,它简单易用的写法可以轻松实现各种布局,让你的布局更快速高效。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010014281\" target=\"_blank\" rel=\"noopener\">Vue的数据依赖实现原理简析</a><br>主要从初始化的数据层面上分析了Vue是如何管理依赖来到达数据的动态响应。<br>initState的过程中,将props,computed,data等属性通过Object.defineProperty来改造其getter/setter属性,并为每一个响应式属性实例化一个observer观察者。这个observer内部dep记录了这个响应式属性的所有依赖。<br>当响应式属性调用setter函数时,通过dep.notify()方法去遍历所有的依赖,调用watcher.update()去完成数据的动态响应。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&mid=2652558943&idx=1&sn=1516afcf876b9fb4a17ce048c5ade58d\" target=\"_blank\" rel=\"noopener\">靠谱程序员必备技能——重构</a><br>当项目变得难以维护,重构便便迫在眉睫,但很多所谓重构仅仅算是重写,随着时间推移,项目再次变得难以维护,周而复始,陷入怪圈。如何避免重构变成重写,本文给了一些很好的建议。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27659059\" target=\"_blank\" rel=\"noopener\">我接触过的前端数据结构与算法</a><br>只要是工程师就必须学好计算机基础,只有这样才能适应计算机技术的快速发展,前端工程师更是如此。</p>\n</li>\n<li><p><a href=\"https://yeaseonzhang.github.io/2017/03/16/Vuex-%E9%80%9A%E4%BF%97%E7%89%88/\" target=\"_blank\" rel=\"noopener\">Vuex 通俗版教程</a><br>Vuex 类似 Redux 的状态管理器,用来管理Vue的所有组件状态。<br>一般在你开发大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。<br>遇到以上情况时候,可以考虑使用Vuex,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。</p>\n</li>\n<li><p><a href=\"https://stffe.github.io/vue/2017/03/03/%E5%AD%A6%E4%B9%A0Vue%E6%BA%90%E7%A0%81.html\" target=\"_blank\" rel=\"noopener\">学习Vue.js源码</a><br>文中介绍了vue项目目录结构和数据绑定实现,没有太深入,但可以作为初步了解。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000009985489#articleHeader9\" target=\"_blank\" rel=\"noopener\">GitHub —— 你不得不上的交友网站</a><br>文章整理了GitHub入门,搭建发布个人博客及个人项目发布,还介绍了一些工具,插件及开源项目;内容比较丰富。</p>\n</li>\n<li><p><a href=\"http://meiminjun.github.io/import%E5%92%8Cexport%E7%AC%94%E8%AE%B0/\" target=\"_blank\" rel=\"noopener\">彻底搞清楚javascript中的require、import和export</a><br>通过介绍CMD、AMD、ES6的模块规范,来引申出平时业务中经常用到require、import和export的用法以及含义。</p>\n</li>\n<li><p><a href=\"https://github.com/istanbuljs/nyc\" target=\"_blank\" rel=\"noopener\">工具推荐</a><br>覆盖率工具 istanbul 替换为 nyc,多进程覆盖率的测试速度提升了几倍。都是同一作者的作品,后者目前活跃度高,并支持前端很多新特性。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ npm i nyc --save-dev</span><br><span class=\"line\">$ ./node_modules/.bin/nyc ./node_modules/.bin/mocha</span><br></pre></td></tr></table></figure>\n<p>执行单元测试命令后,还会直观的给出代码覆盖率报告,以<a href=\"http://flcloverjs.org/\" target=\"_blank\" rel=\"noopener\">Flclover</a>为例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br><span class=\"line\">File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |</span><br><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br><span class=\"line\">All files | 79.41 | 66.67 | 61.11 | 81.82 | |</span><br><span class=\"line\"> flclover | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> index.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover/lib | 88.52 | 82.35 | 81.82 | 88.52 | |</span><br><span class=\"line\"> application.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover.js | 30 | 0 | 0 | 30 |... 13,14,17,19 |</span><br><span class=\"line\"> flclover/lib/middleware/bodyparser | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> index.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover/lib/middleware/logger | 55.56 | 50 | 50 | 55.56 | |</span><br><span class=\"line\"> index.js | 55.56 | 50 | 50 | 55.56 |... 39,42,45,48 |</span><br><span class=\"line\"> flclover/lib/utils | 71.43 | 33.33 | 0 | 83.33 | |</span><br><span class=\"line\"> index.js | 81.25 | 33.33 | 0 | 100 | 7,10 |</span><br><span class=\"line\"> logger.js | 40 | 100 | 0 | 40 | 4,9,13 |</span><br><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"基础\"><a href=\"#基础\" class=\"headerlink\" title=\"基础\"></a>基础</h2><ul>\n<li><p><a href=\"https://juejin.im/post/59278e312f301e006c2e1510\" target=\"_blank\" rel=\"noopener\">JavaScript系列</a><br>相信作为“前端程序猿(媛)”的你一定了解作用域、原型、原型链、继承、闭包……在前端框架的盛行之下,却让初学者忽略了JS基础的学习,但基础不稳必然限制你的发展空间,当你了解了底层,就能很轻松明白框架的原理。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/57dcd394a22b9d00610c5ec8\" target=\"_blank\" rel=\"noopener\">排序算法</a><br>什么?在这个“用数据说话”的时代,你不懂排序算法?那你算什么男人~算什么男人~ 不对不对 算什么猿人~算什么猿人…咳咳,言归正传,平时开发我们常用的快速排序、冒泡排序、选择排序你是否了解其利弊。除此之外还有什么排序算法呢?快来一起学习吧。</p>\n</li>\n<li><p><a href=\"http://es6.ruanyifeng.com/#docs/iterator\" target=\"_blank\" rel=\"noopener\">Iterator 遍历器</a><br>Iterator为各种不同的数据结构提供了统一的访问机制。它可以提供统一的、简便的接口,使得数据结构的成员按某种次序排列,而es6新增for…of循环,就是由Iterator接口提供消费的。</p>\n</li>\n<li><p><a href=\"http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html\" target=\"_blank\" rel=\"noopener\">TCP协议简介</a><br>TCP作为互联网核心协议之一,“三次握手”“四次挥手”你是否有所了解?快来完善自己的知识体系吧。<br>ps:详解请参考<a href=\"http://www.jianshu.com/p/ef892323e68f\" target=\"_blank\" rel=\"noopener\">这里</a></p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/e7bb97218946\" target=\"_blank\" rel=\"noopener\">正则表达式</a><br>业务中有很多复杂的逻辑判断?常常嵌套多个if?快来这里学习下吧,熟练掌握正则表达式会使得你的开发效率得到极大提升。</p>\n</li>\n</ul>\n<h2 id=\"资源整理\"><a href=\"#资源整理\" class=\"headerlink\" title=\"资源整理\"></a>资源整理</h2><ul>\n<li><a href=\"https://github.com/Wscats/Good-text-Share\" target=\"_blank\" rel=\"noopener\">前端知识点大百科全书</a></li>\n<li><a href=\"http://www.jianshu.com/p/c3dae0951f74\" target=\"_blank\" rel=\"noopener\">前端资源汇集</a><br>如此之全的知识整理、资源汇集,都掌握的话你可以神挡杀神佛挡杀佛了。</li>\n</ul>\n<h2 id=\"文章\"><a href=\"#文章\" class=\"headerlink\" title=\"文章\"></a>文章</h2><ul>\n<li><p><a href=\"https://juejin.im/post/58e3a5a0a0bb9f0069fc16bb\" target=\"_blank\" rel=\"noopener\">一劳永逸的搞定flex布局</a><br>你是否还在使用浮动布局?写各种line-height实现居中?不妨试试flexBox布局,它简单易用的写法可以轻松实现各种布局,让你的布局更快速高效。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000010014281\" target=\"_blank\" rel=\"noopener\">Vue的数据依赖实现原理简析</a><br>主要从初始化的数据层面上分析了Vue是如何管理依赖来到达数据的动态响应。<br>initState的过程中,将props,computed,data等属性通过Object.defineProperty来改造其getter/setter属性,并为每一个响应式属性实例化一个observer观察者。这个observer内部dep记录了这个响应式属性的所有依赖。<br>当响应式属性调用setter函数时,通过dep.notify()方法去遍历所有的依赖,调用watcher.update()去完成数据的动态响应。</p>\n</li>\n<li><p><a href=\"https://mp.weixin.qq.com/s?__biz=MzIyNjE4NjI2Nw==&mid=2652558943&idx=1&sn=1516afcf876b9fb4a17ce048c5ade58d\" target=\"_blank\" rel=\"noopener\">靠谱程序员必备技能——重构</a><br>当项目变得难以维护,重构便便迫在眉睫,但很多所谓重构仅仅算是重写,随着时间推移,项目再次变得难以维护,周而复始,陷入怪圈。如何避免重构变成重写,本文给了一些很好的建议。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/27659059\" target=\"_blank\" rel=\"noopener\">我接触过的前端数据结构与算法</a><br>只要是工程师就必须学好计算机基础,只有这样才能适应计算机技术的快速发展,前端工程师更是如此。</p>\n</li>\n<li><p><a href=\"https://yeaseonzhang.github.io/2017/03/16/Vuex-%E9%80%9A%E4%BF%97%E7%89%88/\" target=\"_blank\" rel=\"noopener\">Vuex 通俗版教程</a><br>Vuex 类似 Redux 的状态管理器,用来管理Vue的所有组件状态。<br>一般在你开发大型单页应用(SPA),会出现多个视图组件依赖同一个状态,来自不同视图的行为需要变更同一个状态。<br>遇到以上情况时候,可以考虑使用Vuex,它能把组件的共享状态抽取出来,当做一个全局单例模式进行管理。这样不管你在何处改变状态,都会通知使用该状态的组件做出相应修改。</p>\n</li>\n<li><p><a href=\"https://stffe.github.io/vue/2017/03/03/%E5%AD%A6%E4%B9%A0Vue%E6%BA%90%E7%A0%81.html\" target=\"_blank\" rel=\"noopener\">学习Vue.js源码</a><br>文中介绍了vue项目目录结构和数据绑定实现,没有太深入,但可以作为初步了解。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000009985489#articleHeader9\" target=\"_blank\" rel=\"noopener\">GitHub —— 你不得不上的交友网站</a><br>文章整理了GitHub入门,搭建发布个人博客及个人项目发布,还介绍了一些工具,插件及开源项目;内容比较丰富。</p>\n</li>\n<li><p><a href=\"http://meiminjun.github.io/import%E5%92%8Cexport%E7%AC%94%E8%AE%B0/\" target=\"_blank\" rel=\"noopener\">彻底搞清楚javascript中的require、import和export</a><br>通过介绍CMD、AMD、ES6的模块规范,来引申出平时业务中经常用到require、import和export的用法以及含义。</p>\n</li>\n<li><p><a href=\"https://github.com/istanbuljs/nyc\" target=\"_blank\" rel=\"noopener\">工具推荐</a><br>覆盖率工具 istanbul 替换为 nyc,多进程覆盖率的测试速度提升了几倍。都是同一作者的作品,后者目前活跃度高,并支持前端很多新特性。</p>\n</li>\n</ul>\n<figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">$ npm i nyc --save-dev</span><br><span class=\"line\">$ ./node_modules/.bin/nyc ./node_modules/.bin/mocha</span><br></pre></td></tr></table></figure>\n<p>执行单元测试命令后,还会直观的给出代码覆盖率报告,以<a href=\"http://flcloverjs.org/\" target=\"_blank\" rel=\"noopener\">Flclover</a>为例:<br><figure class=\"highlight plain\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br></pre></td><td class=\"code\"><pre><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br><span class=\"line\">File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |</span><br><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br><span class=\"line\">All files | 79.41 | 66.67 | 61.11 | 81.82 | |</span><br><span class=\"line\"> flclover | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> index.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover/lib | 88.52 | 82.35 | 81.82 | 88.52 | |</span><br><span class=\"line\"> application.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover.js | 30 | 0 | 0 | 30 |... 13,14,17,19 |</span><br><span class=\"line\"> flclover/lib/middleware/bodyparser | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> index.js | 100 | 100 | 100 | 100 | |</span><br><span class=\"line\"> flclover/lib/middleware/logger | 55.56 | 50 | 50 | 55.56 | |</span><br><span class=\"line\"> index.js | 55.56 | 50 | 50 | 55.56 |... 39,42,45,48 |</span><br><span class=\"line\"> flclover/lib/utils | 71.43 | 33.33 | 0 | 83.33 | |</span><br><span class=\"line\"> index.js | 81.25 | 33.33 | 0 | 100 | 7,10 |</span><br><span class=\"line\"> logger.js | 40 | 100 | 0 | 40 | 4,9,13 |</span><br><span class=\"line\">------------------------------------|----------|----------|----------|----------|----------------|</span><br></pre></td></tr></table></figure></p>\n"},{"title":"大前端周刊 第17期 (本期小编:耿少真)","date":"2017-10-20T02:24:12.000Z","_content":"\n## Show me the code \n \n### 柯里化\n\n柯里化就是函数和参数值结合产生一个新的函数,如下代码,假设有一个curry的函数:\n\n\n``` javascript\nfunction add(a, b) {\n return a + b;\n}\n\nlet add1 = add.curry(1);\nconsole.log(add1(5)); // 6\nconsole.log(add1(2)); // 3\n```\n\n怎么实现这样一个curry的函数?它的重点是要返回一个函数,这个函数有一些闭包的变量记录了创建时的默认参数,然后执行这个返回函数的时候,把新传进来的参数和默认参数拼一下变成完整参数列表去调原本的函数,所以有了以下代码:\n``` javascript\nFunction.prototype.curry = function() {\n let defaultArgs = arguments;\n let that = this;\n return function() {\n return that.apply(this, defaultArgs.concat(arguments)); \n }\n };\n```\n\n但是由于参数不是一个数组,没有concat函数,所以需要把伪数组转成一个伪数组,可以用Array.prototype.slice:\n\n``` javascript\nFunction.prototype.curry = function() {\n let slice = Array.prototype.slice;\n let defaultArgs = slice.call(arguments);\n let that = this;\n return function() {\n return that.apply(this, defaultArgs.concat(slice.call(arguments))); \n }\n };\n```\n\n### 复杂选择器的查DOM\n\n如实现一个document.querySelector:\n\n\n``` javascript\ndocument.querySelector(\".mls-info > div .copyright-content\")\n```\n\n首先把复杂选择器做一个解析,序列为以下格式:\n``` javascript\n//把selector解析为\nvar selectors = [\n{relation: \"descendant\", matchType: \"class\", value: \"copyright-content\"},\n{relation: \"child\", matchType: \"tag\", value: \"div\"},\n{relation: \"subSelector\", matchType: \"class\", value: \"mls-info\"}];\n\n```\n\n从右往左,第一个selector是.copyright-content,它是一个类选择器,所以它的matchType是class,它和第二个选择器是祖先和子孙关系,因此它的relation是descendant;同理第二个选择器的matchType是tag,而relation是child,表示是第三个选择器的直接子结点;第三个选择器也是class,但是它没有下一个选择器了,relation用subSelector表示。\n\nmatchType的作用就在于用来比较当前选择器是否match,如下代码所示:\n\n``` javascript\nfunction match(node, selector){\n if(node === document) return false;\n switch(selector.matchType){\n //如果是类选择器\n case \"class\":\n return node.className.trim().split(/ +/).indexOf(selector.value) >= 0;\n\n //如果是标签选择器\n case \"tag\":\n return node.tagName.toLowerCase() === selector.value. toLowerCase();\n\n default:\n throw \"unknown selector match type\";\n }\n}\n```\n\n根据不同的matchType做不同的匹配。\n\n在匹配的时候,从右往左,依次比较每个选择器是否match. 在比较下一个选择器的时候,需要找到相应的DOM结点,如果当前选择器是下一个选择器的子孙时,则需要比较当前选择器所有的祖先结点,一直往上直到document;而如果是直接子元素的关系,则比较它的父结点即可。所以需要有一个找到下一个目标结点的函数:\n``` javascript\nfunction nextTarget(node, selector){\n if(!node || node === document) return null;\n switch(selector.relation){\n case \"descendant\":\n return {node: node.parentNode, hasNext: true};\n case \"child\":\n return {node: node.parentNode, hasNext: false};\n case \"sibling\":\n return {node: node.previousSibling, hasNext: true};\n default:\n throw \"unknown selector relation type\";\n //hasNext表示当前选择器relation是否允许继续找下一个节点\n }\n}\n```\n有了nextTarge和match这两个函数就可以开始遍历DOM,如下代码所示:\n``` javascript\nfunction querySelector(node, selectors){\n while(node){ // 遍历节点\n var currentNode = node;\n if(!match(node, selectors[0])){\n node = nextElement(currentNode);\n continue;\n }\n var next = null;\n for(var i = 0;i < selectors.length;i++){\n var matchIt = false;\n do {\n next = nextTarget(node, selectors[i]);\n node = next.node;\n if(!node){\n break;\n }\n if(match(node, selectors[i+1])){\n matchIt = true; // 有一个符合就继续\n break;\n }\n } while (next.hasNext);\n if(!matchIt) break;\n }\n if(matchIt && i === selectors.length - 1){\n return currentNode; // 全部匹配完\n }\n node = nextElement(currentNode);\n }\n return null;\n}\n```\n\n最外层的while循环和简单选择器一样,都是要遍历所有DOM结点。对于每个结点,先判断第一个选择器是否match,如果不match的话,则继续下一个结点,如果不是标签选择器,对于绝大多数结点将会在这里判断不通过。如果第一个选择器match了,则根据第一个选择器的relation,找到下一个target,判断下一个targe是否match下一个selector,只要有一个target匹配上了,则退出里层的while循环,继续下一个选择器,如果所有的selector都能匹配上说明匹配成功。如果有一个selecotr的所有target都没有match,则说明匹配失败,退出selector的for循环,直接从头开始对下一个DOM结点进行匹配。\n\n\n## 插件推荐\n\n- [vue-area-linkage](https://dwqs.github.io/vue-area-linkage/)\n\nVue Area Linkage: 中国行政区联动选择器,省、市、区、街道联动选择\n\n\n## 文章推荐\n- [换种方式解读this](http://www.cnblogs.com/penghuwan/p/7356210.html) \n文中用一种全新的形式解读this的几种绑定形式,不论是新入门还是大牛都可以看看这种新的解读形式。\n\n- [谈谈 PostCSS](http://web.jobbole.com/92760/)\n现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?\n\n- [前端:常见的6种HTML5错误用法](http://geek.csdn.net/news/detail/240600)\n人们在标签使用中最常见到的错误之一就是随意将HTML5的<section>等价于<div>——具体地说,就是直接用作替代品(用于样式)。\n\n- [vuejs 路由基础入门实战操作详细指南](https://segmentfault.com/a/1190000011612365)\nVue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。\n\n- [JavaScript专题之解读 v8 排序源码](https://segmentfault.com/a/1190000011623637#articleHeader17)\n文章对于插入排序与快速排序原理、实现讲解非常详细,并且在 V8排序的源码进行了实例分析。\n\n- [从Vue.js源码看异步更新DOM策略及nextTick](https://juejin.im/post/59c7b25a5188257a125d7a98)\n文章以实际问题为引,从源码入手,吸收别人的思路,一步步得到解决问题方案。首先,我觉得作者这种解决问题的方式以及刨根问底的精神首先值得我们学习;其次,文章总结的很到位,配合代码示例,让人清晰理解nextTick的实现。\n\n- [更快速的Web应用程序I / O和流数据操作](https://www.sitepen.com/blog/2017/10/02/a-guide-to-faster-web-app-io-and-data-operations-with-streams/)\n使用流更改您读取,写入和处理数据的方式。根据您的用例,代码复杂度可能会增加。然而,流可以实现数据的高效处理,从而导致更好的存储器性能。\n\n- [使用Nuxt.js改善现有项目](https://qianduan.group/posts/59e8be1b0119753d067b40cc)\n`SPA` 应用有其天生的问题:搜索引擎爬虫抓不到,无法满足 `SEO` 的需求。这可以可以通过 `SSR` 解决,`Nuxt.js` 是由一对法国的兄弟基于 vue 2.0 提供的 ssr 能力开发的框架,基于恰到好处的约定与配置,可以显著的降低开发者创建服务端渲染 web app 的门槛。\n\n- [浅析nodejs的http模块](http://www.jianshu.com/p/ab2741f78858)\nHTTP模块是Node内置的核心模块之一,node入门的课程都会讲,通过createServer就可以得到一个server对象,关于它内部实现的理解,可以帮助你提高技能。本文讲解了HTTP模块的大致流程,对一些关键点进行了充分的分析。\n\n- [数据模拟神器 easy-mock](https://juejin.im/post/59a8f15ef265da246c4a3822)\n如何提高前端开发效率?当前端UI及逻辑都写完而后端接口还没有完成,怎样不打断开发进程? 因此一款简单、高效、可视化并能快速生成模拟数据 的在线mock服务诞生。\n\n- [如何使用koa2+es6/7打造高质量Restful API](https://zhuanlan.zhihu.com/p/26216336)\n如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。在过去,使用nodejs大家首先想到的是express.js,而发展到如今,更轻量,性能更好的koa已然成为主流不仅性能优异,它还支持async/await, 堪称回调地狱的终结者。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","source":"_posts/weekly-17.md","raw":"---\ntitle: 大前端周刊 第17期 (本期小编:耿少真)\ndate: 2017-10-20 10:24:12\ntags:\n---\n\n## Show me the code \n \n### 柯里化\n\n柯里化就是函数和参数值结合产生一个新的函数,如下代码,假设有一个curry的函数:\n\n\n``` javascript\nfunction add(a, b) {\n return a + b;\n}\n\nlet add1 = add.curry(1);\nconsole.log(add1(5)); // 6\nconsole.log(add1(2)); // 3\n```\n\n怎么实现这样一个curry的函数?它的重点是要返回一个函数,这个函数有一些闭包的变量记录了创建时的默认参数,然后执行这个返回函数的时候,把新传进来的参数和默认参数拼一下变成完整参数列表去调原本的函数,所以有了以下代码:\n``` javascript\nFunction.prototype.curry = function() {\n let defaultArgs = arguments;\n let that = this;\n return function() {\n return that.apply(this, defaultArgs.concat(arguments)); \n }\n };\n```\n\n但是由于参数不是一个数组,没有concat函数,所以需要把伪数组转成一个伪数组,可以用Array.prototype.slice:\n\n``` javascript\nFunction.prototype.curry = function() {\n let slice = Array.prototype.slice;\n let defaultArgs = slice.call(arguments);\n let that = this;\n return function() {\n return that.apply(this, defaultArgs.concat(slice.call(arguments))); \n }\n };\n```\n\n### 复杂选择器的查DOM\n\n如实现一个document.querySelector:\n\n\n``` javascript\ndocument.querySelector(\".mls-info > div .copyright-content\")\n```\n\n首先把复杂选择器做一个解析,序列为以下格式:\n``` javascript\n//把selector解析为\nvar selectors = [\n{relation: \"descendant\", matchType: \"class\", value: \"copyright-content\"},\n{relation: \"child\", matchType: \"tag\", value: \"div\"},\n{relation: \"subSelector\", matchType: \"class\", value: \"mls-info\"}];\n\n```\n\n从右往左,第一个selector是.copyright-content,它是一个类选择器,所以它的matchType是class,它和第二个选择器是祖先和子孙关系,因此它的relation是descendant;同理第二个选择器的matchType是tag,而relation是child,表示是第三个选择器的直接子结点;第三个选择器也是class,但是它没有下一个选择器了,relation用subSelector表示。\n\nmatchType的作用就在于用来比较当前选择器是否match,如下代码所示:\n\n``` javascript\nfunction match(node, selector){\n if(node === document) return false;\n switch(selector.matchType){\n //如果是类选择器\n case \"class\":\n return node.className.trim().split(/ +/).indexOf(selector.value) >= 0;\n\n //如果是标签选择器\n case \"tag\":\n return node.tagName.toLowerCase() === selector.value. toLowerCase();\n\n default:\n throw \"unknown selector match type\";\n }\n}\n```\n\n根据不同的matchType做不同的匹配。\n\n在匹配的时候,从右往左,依次比较每个选择器是否match. 在比较下一个选择器的时候,需要找到相应的DOM结点,如果当前选择器是下一个选择器的子孙时,则需要比较当前选择器所有的祖先结点,一直往上直到document;而如果是直接子元素的关系,则比较它的父结点即可。所以需要有一个找到下一个目标结点的函数:\n``` javascript\nfunction nextTarget(node, selector){\n if(!node || node === document) return null;\n switch(selector.relation){\n case \"descendant\":\n return {node: node.parentNode, hasNext: true};\n case \"child\":\n return {node: node.parentNode, hasNext: false};\n case \"sibling\":\n return {node: node.previousSibling, hasNext: true};\n default:\n throw \"unknown selector relation type\";\n //hasNext表示当前选择器relation是否允许继续找下一个节点\n }\n}\n```\n有了nextTarge和match这两个函数就可以开始遍历DOM,如下代码所示:\n``` javascript\nfunction querySelector(node, selectors){\n while(node){ // 遍历节点\n var currentNode = node;\n if(!match(node, selectors[0])){\n node = nextElement(currentNode);\n continue;\n }\n var next = null;\n for(var i = 0;i < selectors.length;i++){\n var matchIt = false;\n do {\n next = nextTarget(node, selectors[i]);\n node = next.node;\n if(!node){\n break;\n }\n if(match(node, selectors[i+1])){\n matchIt = true; // 有一个符合就继续\n break;\n }\n } while (next.hasNext);\n if(!matchIt) break;\n }\n if(matchIt && i === selectors.length - 1){\n return currentNode; // 全部匹配完\n }\n node = nextElement(currentNode);\n }\n return null;\n}\n```\n\n最外层的while循环和简单选择器一样,都是要遍历所有DOM结点。对于每个结点,先判断第一个选择器是否match,如果不match的话,则继续下一个结点,如果不是标签选择器,对于绝大多数结点将会在这里判断不通过。如果第一个选择器match了,则根据第一个选择器的relation,找到下一个target,判断下一个targe是否match下一个selector,只要有一个target匹配上了,则退出里层的while循环,继续下一个选择器,如果所有的selector都能匹配上说明匹配成功。如果有一个selecotr的所有target都没有match,则说明匹配失败,退出selector的for循环,直接从头开始对下一个DOM结点进行匹配。\n\n\n## 插件推荐\n\n- [vue-area-linkage](https://dwqs.github.io/vue-area-linkage/)\n\nVue Area Linkage: 中国行政区联动选择器,省、市、区、街道联动选择\n\n\n## 文章推荐\n- [换种方式解读this](http://www.cnblogs.com/penghuwan/p/7356210.html) \n文中用一种全新的形式解读this的几种绑定形式,不论是新入门还是大牛都可以看看这种新的解读形式。\n\n- [谈谈 PostCSS](http://web.jobbole.com/92760/)\n现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?\n\n- [前端:常见的6种HTML5错误用法](http://geek.csdn.net/news/detail/240600)\n人们在标签使用中最常见到的错误之一就是随意将HTML5的<section>等价于<div>——具体地说,就是直接用作替代品(用于样式)。\n\n- [vuejs 路由基础入门实战操作详细指南](https://segmentfault.com/a/1190000011612365)\nVue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。\n\n- [JavaScript专题之解读 v8 排序源码](https://segmentfault.com/a/1190000011623637#articleHeader17)\n文章对于插入排序与快速排序原理、实现讲解非常详细,并且在 V8排序的源码进行了实例分析。\n\n- [从Vue.js源码看异步更新DOM策略及nextTick](https://juejin.im/post/59c7b25a5188257a125d7a98)\n文章以实际问题为引,从源码入手,吸收别人的思路,一步步得到解决问题方案。首先,我觉得作者这种解决问题的方式以及刨根问底的精神首先值得我们学习;其次,文章总结的很到位,配合代码示例,让人清晰理解nextTick的实现。\n\n- [更快速的Web应用程序I / O和流数据操作](https://www.sitepen.com/blog/2017/10/02/a-guide-to-faster-web-app-io-and-data-operations-with-streams/)\n使用流更改您读取,写入和处理数据的方式。根据您的用例,代码复杂度可能会增加。然而,流可以实现数据的高效处理,从而导致更好的存储器性能。\n\n- [使用Nuxt.js改善现有项目](https://qianduan.group/posts/59e8be1b0119753d067b40cc)\n`SPA` 应用有其天生的问题:搜索引擎爬虫抓不到,无法满足 `SEO` 的需求。这可以可以通过 `SSR` 解决,`Nuxt.js` 是由一对法国的兄弟基于 vue 2.0 提供的 ssr 能力开发的框架,基于恰到好处的约定与配置,可以显著的降低开发者创建服务端渲染 web app 的门槛。\n\n- [浅析nodejs的http模块](http://www.jianshu.com/p/ab2741f78858)\nHTTP模块是Node内置的核心模块之一,node入门的课程都会讲,通过createServer就可以得到一个server对象,关于它内部实现的理解,可以帮助你提高技能。本文讲解了HTTP模块的大致流程,对一些关键点进行了充分的分析。\n\n- [数据模拟神器 easy-mock](https://juejin.im/post/59a8f15ef265da246c4a3822)\n如何提高前端开发效率?当前端UI及逻辑都写完而后端接口还没有完成,怎样不打断开发进程? 因此一款简单、高效、可视化并能快速生成模拟数据 的在线mock服务诞生。\n\n- [如何使用koa2+es6/7打造高质量Restful API](https://zhuanlan.zhihu.com/p/26216336)\n如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。在过去,使用nodejs大家首先想到的是express.js,而发展到如今,更轻量,性能更好的koa已然成为主流不仅性能优异,它还支持async/await, 堪称回调地狱的终结者。\n\n## 招聘\nTalkingData DTU 可视化团队招聘:\n* 资深前端工程师\n\n简历投递:\n``` javascript\nconst email = 'xiang.wang#tendcloud.com'.replace('#', '@');\nconsole.log(email);\n```","slug":"weekly-17","published":1,"updated":"2017-11-10T07:40:52.988Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qms005gjrs606p0o4vg","content":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"柯里化\"><a href=\"#柯里化\" class=\"headerlink\" title=\"柯里化\"></a>柯里化</h3><p>柯里化就是函数和参数值结合产生一个新的函数,如下代码,假设有一个curry的函数:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">add</span>(<span class=\"params\">a, b</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> a + b;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> add1 = add.curry(<span class=\"number\">1</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(add1(<span class=\"number\">5</span>)); <span class=\"comment\">// 6</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(add1(<span class=\"number\">2</span>)); <span class=\"comment\">// 3</span></span><br></pre></td></tr></table></figure>\n<p>怎么实现这样一个curry的函数?它的重点是要返回一个函数,这个函数有一些闭包的变量记录了创建时的默认参数,然后执行这个返回函数的时候,把新传进来的参数和默认参数拼一下变成完整参数列表去调原本的函数,所以有了以下代码:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">Function</span>.prototype.curry = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> defaultArgs = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\"> <span class=\"keyword\">let</span> that = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> that.apply(<span class=\"keyword\">this</span>, defaultArgs.concat(<span class=\"built_in\">arguments</span>)); </span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure></p>\n<p>但是由于参数不是一个数组,没有concat函数,所以需要把伪数组转成一个伪数组,可以用Array.prototype.slice:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">Function</span>.prototype.curry = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> slice = <span class=\"built_in\">Array</span>.prototype.slice;</span><br><span class=\"line\"> <span class=\"keyword\">let</span> defaultArgs = slice.call(<span class=\"built_in\">arguments</span>);</span><br><span class=\"line\"> <span class=\"keyword\">let</span> that = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> that.apply(<span class=\"keyword\">this</span>, defaultArgs.concat(slice.call(<span class=\"built_in\">arguments</span>))); </span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n<h3 id=\"复杂选择器的查DOM\"><a href=\"#复杂选择器的查DOM\" class=\"headerlink\" title=\"复杂选择器的查DOM\"></a>复杂选择器的查DOM</h3><p>如实现一个document.querySelector:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">document</span>.querySelector(<span class=\"string\">\".mls-info > div .copyright-content\"</span>)</span><br></pre></td></tr></table></figure>\n<p>首先把复杂选择器做一个解析,序列为以下格式:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//把selector解析为</span></span><br><span class=\"line\"><span class=\"keyword\">var</span> selectors = [</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"descendant\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"class\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"copyright-content\"</span>},</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"child\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"tag\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"div\"</span>},</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"subSelector\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"class\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"mls-info\"</span>}];</span><br></pre></td></tr></table></figure></p>\n<p>从右往左,第一个selector是.copyright-content,它是一个类选择器,所以它的matchType是class,它和第二个选择器是祖先和子孙关系,因此它的relation是descendant;同理第二个选择器的matchType是tag,而relation是child,表示是第三个选择器的直接子结点;第三个选择器也是class,但是它没有下一个选择器了,relation用subSelector表示。</p>\n<p>matchType的作用就在于用来比较当前选择器是否match,如下代码所示:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">match</span>(<span class=\"params\">node, selector</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(node === <span class=\"built_in\">document</span>) <span class=\"keyword\">return</span> <span class=\"literal\">false</span>;</span><br><span class=\"line\"> <span class=\"keyword\">switch</span>(selector.matchType){</span><br><span class=\"line\"> <span class=\"comment\">//如果是类选择器</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"class\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> node.className.trim().split(<span class=\"regexp\">/ +/</span>).indexOf(selector.value) >= <span class=\"number\">0</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">//如果是标签选择器</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"tag\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> node.tagName.toLowerCase() === selector.value. toLowerCase();</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">default</span>:</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"string\">\"unknown selector match type\"</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>根据不同的matchType做不同的匹配。</p>\n<p>在匹配的时候,从右往左,依次比较每个选择器是否match. 在比较下一个选择器的时候,需要找到相应的DOM结点,如果当前选择器是下一个选择器的子孙时,则需要比较当前选择器所有的祖先结点,一直往上直到document;而如果是直接子元素的关系,则比较它的父结点即可。所以需要有一个找到下一个目标结点的函数:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">nextTarget</span>(<span class=\"params\">node, selector</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!node || node === <span class=\"built_in\">document</span>) <span class=\"keyword\">return</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">switch</span>(selector.relation){</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"descendant\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.parentNode, <span class=\"attr\">hasNext</span>: <span class=\"literal\">true</span>};</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"child\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.parentNode, <span class=\"attr\">hasNext</span>: <span class=\"literal\">false</span>};</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"sibling\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.previousSibling, <span class=\"attr\">hasNext</span>: <span class=\"literal\">true</span>};</span><br><span class=\"line\"> <span class=\"keyword\">default</span>:</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"string\">\"unknown selector relation type\"</span>;</span><br><span class=\"line\"> <span class=\"comment\">//hasNext表示当前选择器relation是否允许继续找下一个节点</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>有了nextTarge和match这两个函数就可以开始遍历DOM,如下代码所示:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">querySelector</span>(<span class=\"params\">node, selectors</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">while</span>(node){ <span class=\"comment\">// 遍历节点</span></span><br><span class=\"line\"> <span class=\"keyword\">var</span> currentNode = node;</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!match(node, selectors[<span class=\"number\">0</span>])){</span><br><span class=\"line\"> node = nextElement(currentNode);</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">var</span> next = <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>;i < selectors.length;i++){</span><br><span class=\"line\"> <span class=\"keyword\">var</span> matchIt = <span class=\"literal\">false</span>;</span><br><span class=\"line\"> <span class=\"keyword\">do</span> {</span><br><span class=\"line\"> next = nextTarget(node, selectors[i]);</span><br><span class=\"line\"> node = next.node;</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!node){</span><br><span class=\"line\"> <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(match(node, selectors[i+<span class=\"number\">1</span>])){</span><br><span class=\"line\"> matchIt = <span class=\"literal\">true</span>; <span class=\"comment\">// 有一个符合就继续</span></span><br><span class=\"line\"> <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> } <span class=\"keyword\">while</span> (next.hasNext);</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!matchIt) <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(matchIt && i === selectors.length - <span class=\"number\">1</span>){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> currentNode; <span class=\"comment\">// 全部匹配完</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> node = nextElement(currentNode);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>最外层的while循环和简单选择器一样,都是要遍历所有DOM结点。对于每个结点,先判断第一个选择器是否match,如果不match的话,则继续下一个结点,如果不是标签选择器,对于绝大多数结点将会在这里判断不通过。如果第一个选择器match了,则根据第一个选择器的relation,找到下一个target,判断下一个targe是否match下一个selector,只要有一个target匹配上了,则退出里层的while循环,继续下一个选择器,如果所有的selector都能匹配上说明匹配成功。如果有一个selecotr的所有target都没有match,则说明匹配失败,退出selector的for循环,直接从头开始对下一个DOM结点进行匹配。</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://dwqs.github.io/vue-area-linkage/\" target=\"_blank\" rel=\"noopener\">vue-area-linkage</a></li>\n</ul>\n<p>Vue Area Linkage: 中国行政区联动选择器,省、市、区、街道联动选择</p>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.cnblogs.com/penghuwan/p/7356210.html\" target=\"_blank\" rel=\"noopener\">换种方式解读this</a><br>文中用一种全新的形式解读this的几种绑定形式,不论是新入门还是大牛都可以看看这种新的解读形式。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92760/\" target=\"_blank\" rel=\"noopener\">谈谈 PostCSS</a><br>现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?</p>\n</li>\n<li><p><a href=\"http://geek.csdn.net/news/detail/240600\" target=\"_blank\" rel=\"noopener\">前端:常见的6种HTML5错误用法</a><br>人们在标签使用中最常见到的错误之一就是随意将HTML5的<section>等价于<div>——具体地说,就是直接用作替代品(用于样式)。</div></section></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011612365\" target=\"_blank\" rel=\"noopener\">vuejs 路由基础入门实战操作详细指南</a><br>Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011623637#articleHeader17\" target=\"_blank\" rel=\"noopener\">JavaScript专题之解读 v8 排序源码</a><br>文章对于插入排序与快速排序原理、实现讲解非常详细,并且在 V8排序的源码进行了实例分析。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59c7b25a5188257a125d7a98\" target=\"_blank\" rel=\"noopener\">从Vue.js源码看异步更新DOM策略及nextTick</a><br>文章以实际问题为引,从源码入手,吸收别人的思路,一步步得到解决问题方案。首先,我觉得作者这种解决问题的方式以及刨根问底的精神首先值得我们学习;其次,文章总结的很到位,配合代码示例,让人清晰理解nextTick的实现。</p>\n</li>\n<li><p><a href=\"https://www.sitepen.com/blog/2017/10/02/a-guide-to-faster-web-app-io-and-data-operations-with-streams/\" target=\"_blank\" rel=\"noopener\">更快速的Web应用程序I / O和流数据操作</a><br>使用流更改您读取,写入和处理数据的方式。根据您的用例,代码复杂度可能会增加。然而,流可以实现数据的高效处理,从而导致更好的存储器性能。</p>\n</li>\n<li><p><a href=\"https://qianduan.group/posts/59e8be1b0119753d067b40cc\" target=\"_blank\" rel=\"noopener\">使用Nuxt.js改善现有项目</a><br><code>SPA</code> 应用有其天生的问题:搜索引擎爬虫抓不到,无法满足 <code>SEO</code> 的需求。这可以可以通过 <code>SSR</code> 解决,<code>Nuxt.js</code> 是由一对法国的兄弟基于 vue 2.0 提供的 ssr 能力开发的框架,基于恰到好处的约定与配置,可以显著的降低开发者创建服务端渲染 web app 的门槛。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/ab2741f78858\" target=\"_blank\" rel=\"noopener\">浅析nodejs的http模块</a><br>HTTP模块是Node内置的核心模块之一,node入门的课程都会讲,通过createServer就可以得到一个server对象,关于它内部实现的理解,可以帮助你提高技能。本文讲解了HTTP模块的大致流程,对一些关键点进行了充分的分析。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59a8f15ef265da246c4a3822\" target=\"_blank\" rel=\"noopener\">数据模拟神器 easy-mock</a><br>如何提高前端开发效率?当前端UI及逻辑都写完而后端接口还没有完成,怎样不打断开发进程? 因此一款简单、高效、可视化并能快速生成模拟数据 的在线mock服务诞生。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26216336\" target=\"_blank\" rel=\"noopener\">如何使用koa2+es6/7打造高质量Restful API</a><br>如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。在过去,使用nodejs大家首先想到的是express.js,而发展到如今,更轻量,性能更好的koa已然成为主流不仅性能优异,它还支持async/await, 堪称回调地狱的终结者。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n","site":{"data":{}},"excerpt":"","more":"<h2 id=\"Show-me-the-code\"><a href=\"#Show-me-the-code\" class=\"headerlink\" title=\"Show me the code\"></a>Show me the code</h2><h3 id=\"柯里化\"><a href=\"#柯里化\" class=\"headerlink\" title=\"柯里化\"></a>柯里化</h3><p>柯里化就是函数和参数值结合产生一个新的函数,如下代码,假设有一个curry的函数:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">add</span>(<span class=\"params\">a, b</span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> a + b;</span><br><span class=\"line\">}</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">let</span> add1 = add.curry(<span class=\"number\">1</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(add1(<span class=\"number\">5</span>)); <span class=\"comment\">// 6</span></span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(add1(<span class=\"number\">2</span>)); <span class=\"comment\">// 3</span></span><br></pre></td></tr></table></figure>\n<p>怎么实现这样一个curry的函数?它的重点是要返回一个函数,这个函数有一些闭包的变量记录了创建时的默认参数,然后执行这个返回函数的时候,把新传进来的参数和默认参数拼一下变成完整参数列表去调原本的函数,所以有了以下代码:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">Function</span>.prototype.curry = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> defaultArgs = <span class=\"built_in\">arguments</span>;</span><br><span class=\"line\"> <span class=\"keyword\">let</span> that = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> that.apply(<span class=\"keyword\">this</span>, defaultArgs.concat(<span class=\"built_in\">arguments</span>)); </span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure></p>\n<p>但是由于参数不是一个数组,没有concat函数,所以需要把伪数组转成一个伪数组,可以用Array.prototype.slice:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">Function</span>.prototype.curry = <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">let</span> slice = <span class=\"built_in\">Array</span>.prototype.slice;</span><br><span class=\"line\"> <span class=\"keyword\">let</span> defaultArgs = slice.call(<span class=\"built_in\">arguments</span>);</span><br><span class=\"line\"> <span class=\"keyword\">let</span> that = <span class=\"keyword\">this</span>;</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"function\"><span class=\"keyword\">function</span>(<span class=\"params\"></span>) </span>{</span><br><span class=\"line\"> <span class=\"keyword\">return</span> that.apply(<span class=\"keyword\">this</span>, defaultArgs.concat(slice.call(<span class=\"built_in\">arguments</span>))); </span><br><span class=\"line\"> }</span><br><span class=\"line\"> };</span><br></pre></td></tr></table></figure>\n<h3 id=\"复杂选择器的查DOM\"><a href=\"#复杂选择器的查DOM\" class=\"headerlink\" title=\"复杂选择器的查DOM\"></a>复杂选择器的查DOM</h3><p>如实现一个document.querySelector:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"built_in\">document</span>.querySelector(<span class=\"string\">\".mls-info > div .copyright-content\"</span>)</span><br></pre></td></tr></table></figure>\n<p>首先把复杂选择器做一个解析,序列为以下格式:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">//把selector解析为</span></span><br><span class=\"line\"><span class=\"keyword\">var</span> selectors = [</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"descendant\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"class\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"copyright-content\"</span>},</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"child\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"tag\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"div\"</span>},</span><br><span class=\"line\">{<span class=\"attr\">relation</span>: <span class=\"string\">\"subSelector\"</span>, <span class=\"attr\">matchType</span>: <span class=\"string\">\"class\"</span>, <span class=\"attr\">value</span>: <span class=\"string\">\"mls-info\"</span>}];</span><br></pre></td></tr></table></figure></p>\n<p>从右往左,第一个selector是.copyright-content,它是一个类选择器,所以它的matchType是class,它和第二个选择器是祖先和子孙关系,因此它的relation是descendant;同理第二个选择器的matchType是tag,而relation是child,表示是第三个选择器的直接子结点;第三个选择器也是class,但是它没有下一个选择器了,relation用subSelector表示。</p>\n<p>matchType的作用就在于用来比较当前选择器是否match,如下代码所示:</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">match</span>(<span class=\"params\">node, selector</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(node === <span class=\"built_in\">document</span>) <span class=\"keyword\">return</span> <span class=\"literal\">false</span>;</span><br><span class=\"line\"> <span class=\"keyword\">switch</span>(selector.matchType){</span><br><span class=\"line\"> <span class=\"comment\">//如果是类选择器</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"class\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> node.className.trim().split(<span class=\"regexp\">/ +/</span>).indexOf(selector.value) >= <span class=\"number\">0</span>;</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">//如果是标签选择器</span></span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"tag\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> node.tagName.toLowerCase() === selector.value. toLowerCase();</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">default</span>:</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"string\">\"unknown selector match type\"</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>根据不同的matchType做不同的匹配。</p>\n<p>在匹配的时候,从右往左,依次比较每个选择器是否match. 在比较下一个选择器的时候,需要找到相应的DOM结点,如果当前选择器是下一个选择器的子孙时,则需要比较当前选择器所有的祖先结点,一直往上直到document;而如果是直接子元素的关系,则比较它的父结点即可。所以需要有一个找到下一个目标结点的函数:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">nextTarget</span>(<span class=\"params\">node, selector</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!node || node === <span class=\"built_in\">document</span>) <span class=\"keyword\">return</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">switch</span>(selector.relation){</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"descendant\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.parentNode, <span class=\"attr\">hasNext</span>: <span class=\"literal\">true</span>};</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"child\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.parentNode, <span class=\"attr\">hasNext</span>: <span class=\"literal\">false</span>};</span><br><span class=\"line\"> <span class=\"keyword\">case</span> <span class=\"string\">\"sibling\"</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {<span class=\"attr\">node</span>: node.previousSibling, <span class=\"attr\">hasNext</span>: <span class=\"literal\">true</span>};</span><br><span class=\"line\"> <span class=\"keyword\">default</span>:</span><br><span class=\"line\"> <span class=\"keyword\">throw</span> <span class=\"string\">\"unknown selector relation type\"</span>;</span><br><span class=\"line\"> <span class=\"comment\">//hasNext表示当前选择器relation是否允许继续找下一个节点</span></span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>有了nextTarge和match这两个函数就可以开始遍历DOM,如下代码所示:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br><span class=\"line\">3</span><br><span class=\"line\">4</span><br><span class=\"line\">5</span><br><span class=\"line\">6</span><br><span class=\"line\">7</span><br><span class=\"line\">8</span><br><span class=\"line\">9</span><br><span class=\"line\">10</span><br><span class=\"line\">11</span><br><span class=\"line\">12</span><br><span class=\"line\">13</span><br><span class=\"line\">14</span><br><span class=\"line\">15</span><br><span class=\"line\">16</span><br><span class=\"line\">17</span><br><span class=\"line\">18</span><br><span class=\"line\">19</span><br><span class=\"line\">20</span><br><span class=\"line\">21</span><br><span class=\"line\">22</span><br><span class=\"line\">23</span><br><span class=\"line\">24</span><br><span class=\"line\">25</span><br><span class=\"line\">26</span><br><span class=\"line\">27</span><br><span class=\"line\">28</span><br><span class=\"line\">29</span><br><span class=\"line\">30</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"function\"><span class=\"keyword\">function</span> <span class=\"title\">querySelector</span>(<span class=\"params\">node, selectors</span>)</span>{</span><br><span class=\"line\"> <span class=\"keyword\">while</span>(node){ <span class=\"comment\">// 遍历节点</span></span><br><span class=\"line\"> <span class=\"keyword\">var</span> currentNode = node;</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!match(node, selectors[<span class=\"number\">0</span>])){</span><br><span class=\"line\"> node = nextElement(currentNode);</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">var</span> next = <span class=\"literal\">null</span>;</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">var</span> i = <span class=\"number\">0</span>;i < selectors.length;i++){</span><br><span class=\"line\"> <span class=\"keyword\">var</span> matchIt = <span class=\"literal\">false</span>;</span><br><span class=\"line\"> <span class=\"keyword\">do</span> {</span><br><span class=\"line\"> next = nextTarget(node, selectors[i]);</span><br><span class=\"line\"> node = next.node;</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!node){</span><br><span class=\"line\"> <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(match(node, selectors[i+<span class=\"number\">1</span>])){</span><br><span class=\"line\"> matchIt = <span class=\"literal\">true</span>; <span class=\"comment\">// 有一个符合就继续</span></span><br><span class=\"line\"> <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> } <span class=\"keyword\">while</span> (next.hasNext);</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(!matchIt) <span class=\"keyword\">break</span>;</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(matchIt && i === selectors.length - <span class=\"number\">1</span>){</span><br><span class=\"line\"> <span class=\"keyword\">return</span> currentNode; <span class=\"comment\">// 全部匹配完</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> node = nextElement(currentNode);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"literal\">null</span>;</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure></p>\n<p>最外层的while循环和简单选择器一样,都是要遍历所有DOM结点。对于每个结点,先判断第一个选择器是否match,如果不match的话,则继续下一个结点,如果不是标签选择器,对于绝大多数结点将会在这里判断不通过。如果第一个选择器match了,则根据第一个选择器的relation,找到下一个target,判断下一个targe是否match下一个selector,只要有一个target匹配上了,则退出里层的while循环,继续下一个选择器,如果所有的selector都能匹配上说明匹配成功。如果有一个selecotr的所有target都没有match,则说明匹配失败,退出selector的for循环,直接从头开始对下一个DOM结点进行匹配。</p>\n<h2 id=\"插件推荐\"><a href=\"#插件推荐\" class=\"headerlink\" title=\"插件推荐\"></a>插件推荐</h2><ul>\n<li><a href=\"https://dwqs.github.io/vue-area-linkage/\" target=\"_blank\" rel=\"noopener\">vue-area-linkage</a></li>\n</ul>\n<p>Vue Area Linkage: 中国行政区联动选择器,省、市、区、街道联动选择</p>\n<h2 id=\"文章推荐\"><a href=\"#文章推荐\" class=\"headerlink\" title=\"文章推荐\"></a>文章推荐</h2><ul>\n<li><p><a href=\"http://www.cnblogs.com/penghuwan/p/7356210.html\" target=\"_blank\" rel=\"noopener\">换种方式解读this</a><br>文中用一种全新的形式解读this的几种绑定形式,不论是新入门还是大牛都可以看看这种新的解读形式。</p>\n</li>\n<li><p><a href=\"http://web.jobbole.com/92760/\" target=\"_blank\" rel=\"noopener\">谈谈 PostCSS</a><br>现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?</p>\n</li>\n<li><p><a href=\"http://geek.csdn.net/news/detail/240600\" target=\"_blank\" rel=\"noopener\">前端:常见的6种HTML5错误用法</a><br>人们在标签使用中最常见到的错误之一就是随意将HTML5的<section>等价于<div>——具体地说,就是直接用作替代品(用于样式)。</div></section></p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011612365\" target=\"_blank\" rel=\"noopener\">vuejs 路由基础入门实战操作详细指南</a><br>Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们。</p>\n</li>\n<li><p><a href=\"https://segmentfault.com/a/1190000011623637#articleHeader17\" target=\"_blank\" rel=\"noopener\">JavaScript专题之解读 v8 排序源码</a><br>文章对于插入排序与快速排序原理、实现讲解非常详细,并且在 V8排序的源码进行了实例分析。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59c7b25a5188257a125d7a98\" target=\"_blank\" rel=\"noopener\">从Vue.js源码看异步更新DOM策略及nextTick</a><br>文章以实际问题为引,从源码入手,吸收别人的思路,一步步得到解决问题方案。首先,我觉得作者这种解决问题的方式以及刨根问底的精神首先值得我们学习;其次,文章总结的很到位,配合代码示例,让人清晰理解nextTick的实现。</p>\n</li>\n<li><p><a href=\"https://www.sitepen.com/blog/2017/10/02/a-guide-to-faster-web-app-io-and-data-operations-with-streams/\" target=\"_blank\" rel=\"noopener\">更快速的Web应用程序I / O和流数据操作</a><br>使用流更改您读取,写入和处理数据的方式。根据您的用例,代码复杂度可能会增加。然而,流可以实现数据的高效处理,从而导致更好的存储器性能。</p>\n</li>\n<li><p><a href=\"https://qianduan.group/posts/59e8be1b0119753d067b40cc\" target=\"_blank\" rel=\"noopener\">使用Nuxt.js改善现有项目</a><br><code>SPA</code> 应用有其天生的问题:搜索引擎爬虫抓不到,无法满足 <code>SEO</code> 的需求。这可以可以通过 <code>SSR</code> 解决,<code>Nuxt.js</code> 是由一对法国的兄弟基于 vue 2.0 提供的 ssr 能力开发的框架,基于恰到好处的约定与配置,可以显著的降低开发者创建服务端渲染 web app 的门槛。</p>\n</li>\n<li><p><a href=\"http://www.jianshu.com/p/ab2741f78858\" target=\"_blank\" rel=\"noopener\">浅析nodejs的http模块</a><br>HTTP模块是Node内置的核心模块之一,node入门的课程都会讲,通过createServer就可以得到一个server对象,关于它内部实现的理解,可以帮助你提高技能。本文讲解了HTTP模块的大致流程,对一些关键点进行了充分的分析。</p>\n</li>\n<li><p><a href=\"https://juejin.im/post/59a8f15ef265da246c4a3822\" target=\"_blank\" rel=\"noopener\">数据模拟神器 easy-mock</a><br>如何提高前端开发效率?当前端UI及逻辑都写完而后端接口还没有完成,怎样不打断开发进程? 因此一款简单、高效、可视化并能快速生成模拟数据 的在线mock服务诞生。</p>\n</li>\n<li><p><a href=\"https://zhuanlan.zhihu.com/p/26216336\" target=\"_blank\" rel=\"noopener\">如何使用koa2+es6/7打造高质量Restful API</a><br>如今nodejs变得越来越火热,采用nodejs实现前后端分离架构已被多数大公司所采用。在过去,使用nodejs大家首先想到的是express.js,而发展到如今,更轻量,性能更好的koa已然成为主流不仅性能优异,它还支持async/await, 堪称回调地狱的终结者。</p>\n</li>\n</ul>\n<h2 id=\"招聘\"><a href=\"#招聘\" class=\"headerlink\" title=\"招聘\"></a>招聘</h2><p>TalkingData DTU 可视化团队招聘:</p>\n<ul>\n<li>资深前端工程师</li>\n</ul>\n<p>简历投递:<br><figure class=\"highlight javascript\"><table><tr><td class=\"gutter\"><pre><span class=\"line\">1</span><br><span class=\"line\">2</span><br></pre></td><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">const</span> email = <span class=\"string\">'xiang.wang#tendcloud.com'</span>.replace(<span class=\"string\">'#'</span>, <span class=\"string\">'@'</span>);</span><br><span class=\"line\"><span class=\"built_in\">console</span>.log(email);</span><br></pre></td></tr></table></figure></p>\n"},{"title":"5 Protocols For Event-Driven API Architectures","date":"2017-07-21T04:00:00.000Z","_content":"\n原文:[5 Protocols For Event-Driven API Architectures](http://nordicapis.com/5-protocols-for-event-driven-api-architectures/)\n\nThe internet is a system of communication, and as such, the relationship between client and server, as well as server to server, is one of the most oft-discussed and hotly contested concepts. **event-driven architecture** is a methodology of defining these relationships, and creating systems within a specific set of relationships that allow for extensive functionality.\n\nIn this piece, we’re going to discuss 5 common event-driven methods — **WebSockets**, **WebHooks**, **REST Hooks**, **Pub-Sub**, and **Server Sent Events**. We’ll define what they fundamentally are and do, and how API providers go about using them. Additionally, we’ll provide some pros and cons on each to make choosing a solution for your platform easy and intuitive.\n\n## What is an Event-Driven Architecture?\n\nEvent-driven architectures establish an event that can be consumed and reacted to. But what is an event?\n\nAn event is essentially any significant **change** from one state to another, such as the change from having no messages in your inbox to have a new message in your inbox. This state can be reacted to **internally** (such as when the email program in question realizes a new message has been received), **externally** (when a user sees a notification for a new message), or used to **generate another event** (for instance, the message tally increases by one).\n\nEvent-driven architectures are appealing to API developers because they function very well in **asynchronous** environments. By crafting APIs that **trigger** certain functions on new event delivery, API systems don’t have to inherently wait for synchronous delivery or real time communication. This is hugely beneficial, as eliminating the need to constantly poll endpoints frees resources from otherwise wasteful purposes, reducing both general hardware requirements and call-specific overhead.\n\nFor this reason, event-driven architectures are very, very popular, and lead to improved power, bandwidth, and co-processing than other solutions and architectures such as polling and other poll-centric derivatives.\n\n## 5 Types of Event-Driven Protocols for APIs\n\n### 1: WebSockets\n\n**WebSockets** are an interesting event-driven solution, because, for most browsers, they’re actually baked into the application itself. Essentially, WebSocket is a protocol that provides full-duplex communication on a single TCP connection. It was standardized by the Internet Engineering Task Force as [RFC 6455](https://tools.ietf.org/html/rfc6455), and the WebSocket API in Web IDL was later standardized under the W3C banner.\n\nWhile the protocol itself is meant to be used between **web browsers** and **servers**, the protocol can be used in any case where there is a client-server relationship. The protocol itself is based upon TCP, with the additional HTTP interpretation statement that is considered an “Upgrade request” to allow for interoperability.\n\n#### Pros\nBecause WebSocket is expressly designed for browser operation, it boasts extremely **low overhead** for what it actually does. By establishing a **full-duplex** conversation using a standardized methodology, connection both to and from the two entities can take place simultaneously, resulting in lower overhead and better throughput.\n\nAdditionally, the fact that these communications take place over TCP 80/443 means that environments that traditionally block non-web based applications for security reasons can still handle this protocol, as firewalls allow communication to and from this port.\n\nPerhaps the strongest argument for the use of WebSockets are the fact that they are standardized and **natively supported** by all major browsers, ranging from Microsft Edge to Opera, from Firefox to Chrome. This means that any web application that ties into it will be interactable within the vast majority of both browser-based and browser-independent gateways and applications.\n\n#### Cons\nWebSockets have one distinct major failing — while it might have support for HTTP-like functionality, **it is not HTTP** whatsoever. This has implications, especially when considering optimizing in HTTP such as caching, proxying, etc., that haven’t quite become apparent.\n\nBecause WebSockets are relatively new, having been only officially standardized in 2011, the industry is still understanding what the side effects mean. Most applications that use WebSockets are designed specifically for everything that a WebSocket is — what has yet to be seen, however, is whether or not this solution is better in the long-run than any stateless solution currently available.\n\nThere is of course the fact that, as with other architectures on this list, WebSockets create an “always on” connection during the duration of data transfer. While this is fine for many uses such as media streaming and live stream calculations, it also essentially means that, for WebSockets, there is no scalability. Ports have hardcoded limitations and bandwidth, and thus in order to “scale”, you must add additional ports to match the maximum load. In stateless systems, this is less of an issue, as requests can wait and be made in such a way as to be independent on the state of the server itself.\n\n### 2: WebHooks\n**WebHooks** are a similar concept to the WebSocket. They primarily function using **custom callbacks**, or code that is passed as an argument to another chunk of code and executed at a specified point in time. Essentially, a WebHook is a glorified system of “if this, then do”, allowing for users independent of the event firing to craft a custom response to that event within their own system.\n\nThe term was coined by [Jeff Lindsay](https://twitter.com/progrium) in 2007, and quickly became popular amongst users who wished to create automated responses to exterior behaviors. A great example of this would be a developer pushing a new item to GitHub, which causes an event. A user has a system tied into the URI of a WebHook. When the push is published, the user’s system utilizes the URI of the WebHook to integrate the push into a larger build, thereby creating a compiled component.\n\n#### Pros\nWebHooks function a lot like WebSockets, but they’re different in some key areas. First and foremost, WebSockets are primarily designed for browser-based communications, and while they can be used regardless in any client-server communication, they do not behave well in a **server-to-server** setup.\n\nWebHooks, on the other hand, work very well in server-to-server systems due to how they operate. Because the system essentially functions as the aforementioned “if this then do”, servers can be configured to tie into pre-formed URIs at any time and execute a given function whenever that event is triggered.\n\nAdditionally, WebHooks have the unique benefit of being **based upon HTTP**, unlike WebSockets. This means that the system can be integrated without utilizing any new infrastructure, allowing speedy adoption and relatively simple setup.\n\n#### Cons\nThe problem with WebHooks is that a lot of their functionality can already be placed on the arguably more powerful REST architectural approach. While adopting event-driven architecture is often a requirement of the service being built, it’s a hard sell when it can be mirrored in REST while also giving the wealth of options that REST gives to the user.\n\nThese RESTful solutions such as [RestMS](http://www.restms.org/) are essentially simply message querying services, though, and do require additional infrastructure, which may or may not be doable considering the purpose of the application.\n\nAdditionally, WebHooks can be **resource intensive** to both the client and the server. If the client needs to notify many servers that an event has occurred, and a server needs to listen to a great deal of clients notifying of this change, you can very quickly run into a situation where your network grows uncontrollably. While HTTP does scale quite well, this is a definite negative to consider.\n\nHowever, there are also ways to build a [message queuing service](https://en.wikipedia.org/wiki/Message_queuing_service) on top of HTTP—some RESTful examples include [IronMQ](https://www.iron.io/platform/ironmq/) and RestMS.\n\n### 3: REST Hooks\nSpeaking of RESTful examples, **REST Hooks** is essentially “hooking” baked into REST itself. Defined as an initiative from [Zapier](http://resthooks.org/docs/), this is a subject [we’ve covered before](http://nordicapis.com/stop-polling-and-consider-using-rest-hooks/) — hooks are collated to a single target URL as a subscription, which pings the resource requester when a change is noted.\n\nThis approach is a response to the practice of **polling**, in which a client constantly checks for changes to a resource. Under the REST Hooks paradigm, the client instead waits for a change, and reacts to it. To put it simply, this is a WebHook in REST.\n\n#### Pros\nREST Hooks are obviously super powerful in the correct context — being able to passively receive a resource rather than dedicating processing power to constant polling frees up a lot of the client-side cost.\n\nPerhaps the strongest argument for REST Hooks though, is the fact that it’s **so easy** and **intuitive** to use. While WebHooks utilize HTTP and thus do not need new architecture to set up, they are also limited by the fact that they are built upon HTTP, and can thus be somewhat complex to set up properly and use effectively.\n\nREST Hooks, though, are **subscription based**, and as such, are simply usable by subscribing. This makes it a very easy to use solution while providing a lot of the usability and effectiveness of more complex systems.\n\n#### Cons\nOf course, every solution has its negatives, and REST Hooks are no different. It could be viewed that REST Hooks actually fly in the face of what REST is — [session free and stateless](http://nordicapis.com/defining-stateful-vs-stateless-web-services/). REST Hooks essentially create consistent polling, it’s just moved the polling from one side to another.\n\nThen, there’s the arguable problem that REST Hooks might be doing something that has already been solved. Some would argue that TCP already does most of what REST Hooks is trying to do, and simply layering more solutions on top of HTTP to get what TCP already does is a poor approach.\n\n### 4: Pub-Sub\n**Pub-Sub** is a slightly different approach. Referred to by its full name as **publish-subscribe**, the concept is where events are published to a class without knowledge of the client subscribing to the class. Basically, a user will join one or more classes, and then will receive event updates without regard or knowledge to the event publisher.\n\nThe main difference here is one of conscious choice of provider — in the other solutions noted herein, a user consciously communicates with a given server or provider and receives events as pre-determined. Under the Pub-Sub scheme, the user only specifies which class they wish to be part of and what events they are interested in receiving. From there, they receive these events when one is pushed out.\n\nA way this is often framed in internet discussions is in the frame of a **radio channel**. Record companies, or publishers, issue audio to the station, which then broadcasts this audio to listeners, or subscribers. Pub-sub is the middleman radio station here — listeners don’t know who gave the station the music, nor do the companies know who the listeners are. It is this segmentation that is baked into the pattern.\n\nWhen we talk about Pub-Sub, we need to keep in mind that we’re actually talking about two different things. Pub-Sub can mean the methodology and general concept in programming terms, but it can also mean specific provider solutions based upon that methodology. For instance, Google’s [Cloud Pub/Sub](https://cloud.google.com/pubsub/docs/overview) is an implementation of the general methodology within their cloud service, and allows for asynchronous many-to-many pub-sub relationships as stated above.\n\n#### Pros\nA huge benefit of Pub-Sub is the fact that it’s **loosely coupled**, and thus is extremely scalable and flexible. The only thing the event-provider is doing is generating the content — each other step is done through a separated middleman, and so the content is easily scaled and modulated to the architecture and design of the solution.\n\nAdditionally, Pub-Sub lends itself very well to **testing**. A subscriber is narrowly limited to a set of events that they have requested under a class, so if a failure occurs, this natural segmentation informs the provider as to where the fault is, and which class of users is experiencing the fault.\n\n#### Cons\nUnfortunately, decoupling is also a huge disadvantage for this pattern. By being a **middleman**, Pub-Sub cannot effectively notify the provider that a message has been sent, and the listener is separated from the event and thus may not know if a message wasn’t sent that should have been. Harkening back to the radio explanation, a listener will never know if a song was meant to play on a channel or if the channel is out of range, and once the record executives hand off the music, they’ve got no idea if the user received the songs without direct feedback from them.\n\nAdditionally, while the system is extensible and flexible, instability does occur with high traffic load as subclass after subclass might be constructed to handle further segmentation. This of course leads to the aforementioned instability in addition to increased complexity.\n\nYou must keep in mind that while the relationship between the publisher and subscriber in this model may be beneficial, it also comes with its own difficulties when these relationships need to be modulated. While you can certainly work around this, at this point, you’re fighting the very basis of the pattern, rather than any secondary natures — you’re trying to make dehydrated water, and fighting against the nature of a pattern suggests the pattern to be inherently poor.\n\n> Also read: [Building a Backend for Frontend (BFF) For Your Microservices](http://nordicapis.com/building-a-backend-for-frontend-shim-for-your-microservices/)\n\n### 5: Server Sent Events\n**Server Sent Events**, or SSE, is a communication protocol much like WebSockets, but with the implication of **unidirectional data**. In this architecture, the server is consistently sending updates to the client as an automatic process. This was standardized under HTML5 by the [W3C](https://www.w3.org/TR/2009/WD-eventsource-20091029/), and is thus compatible with any solution that is likewise compatible with HTML5.\n\n> Of note is that there is a competing standardization from the [Web Hypertext Application Technology Working Group](https://whatwg.org/) – this is a relic from movement away from “HTML5” and into what WHATWG is calling “HTML Living Standard”. The general working consensus is that, WHATWG’s standardization is prioritized in the rare cases of divergent standards. This could become more of an issue as time marches forward, given that WHATWG was created due to a perceived lack of interest from W3C towards evolving HTML, but for the time being, either standard is generally acceptable.\nWhile simple in theory, Server Sent Events are anything but simple when considering benefits and drawbacks.\n\n#### Pros\nSSE is **not bidirectional** in its communications — the server is issuing the events in a steady, predictable method. This is hugely beneficial to applications which do not need the two-way communications baked into WebSockets or other such solutions, as this means **lower bandwidth**, and an allowance for the connection to be temporary rather than always-on during the duration of data transfer. By its nature, the data is being transferred one way, and thus there is no need to wait for data to be returned.\n\nAdditionally, at least in theory, SSE is easier to set up in complex situations. You only have to worry about data traveling one direction via one system, thus reducing complexity dramatically. There is no need to define a message exchange protocol, no need to specify data duration or wait times, no need to support bilateral messaging — the single direction saves a lot of complexity.\n\n#### Cons\nThat simplicity could be where SSE fails for particular use cases. SSE is a very poor solution for situations that require **bidirectional communication**, and while this seems obvious, it would surprise many developers to see how many systems actually depend on bidirectional communication for simple functionality.\n\nWhile much of this can be fixed with workarounds, a developer’s goal in choosing an event-driven protocol should be to find one that works out of the box, not to find a solution that might work if configured properly and given secondary systems upon which to depend.\n\nThere is also the issue of **security** and authentication. While two-way systems can easily use authentication methodologies, SSE handles this using **header forwarding**. While headers can be manipulated and overridden in many languages and applications, the EventSource object in JavaScript does not natively support this, which would cause many adoptees some major headaches.\n\nFinally, there is a concern over loss of efficiency with **over transmitting** data. A two-direction system can determine when a client or server disconnects, but SSE can only determine that a client has disconnected after attempting a full data transmission and receiving a noted failure. Because of this, data can be lost rather quickly, and with many failed connections, this loss can mount dramatically over time.\n\n## Conclusion\nThere is no one event-driven solution that works in every use case. While many would argue that event-driven solutions should be REST based, which suggests REST Hooks as the answer, many others would argue that it is entirely situational, and that REST is not always the silver bullet it’s touted to be.\n\nIf you are building for scalability with low overhead in a browser environment, **WebSockets** are a great solution. Conversely, if you’d like those same benefits but are working in a non-browser system, then **WebHooks** should be your approach. **REST Hooks** are not only great for RESTful services, they’re also much easier to set up than either, and thus are great in low-time high-rush situations. **Pub-Sub** can be great if you need to enforce a division between client and server, and this can further be established and controlled in an even stronger way with **Server Sent**.\n\nSimply put, the best solution will be the one that fits your specific situation and build — any of these solutions, given the correct system, is a great solution. To that end, each solution has a very specific use case.\n\n## TLDR Comparison Table\n| PROTOCOL | RELATED TO | STANDARD BODY | NOTES |\n| ------ | ------ | ------ | ------ |\n| WebSockets | TCP, HTTP-like | IETF, W3C | Two-way communication over TCP<br>Designed for web browsers & web servers<br>Good for lower overhead scenarios<br>Supported in all major browsers |\n| Webhooks | URI, HTTP | - | User defined “HTTP callbacks”<br>Triggered by an event HTTP<br>Requests are made to Webhook URI<br>Enables real-time event triggering|\n| REST Hooks | HTTP | Zapier | Lightweight subscription layer<br>Manipulated by a REST API<br>Essentially a WebHook in REST |\n| Pub-Sub | - | - |Client subscribes to classes<br>Bidirectional<br>Middleman layer between client and server<br>Loose coupling|\n| Server Sent | HTTP, HTML5 , DOM | WHATWG, W3C |Server constantly sends updates to the client<br>Unidirectional push notifications as DOM events|\n","source":"_posts/5-protocols-for-event-driven-api-architectures.md","raw":"---\ntitle: 5 Protocols For Event-Driven API Architectures\ndate: 2017-07-21 12:00:00\ntags: [Event-Driven,全栈,Node]\n---\n\n原文:[5 Protocols For Event-Driven API Architectures](http://nordicapis.com/5-protocols-for-event-driven-api-architectures/)\n\nThe internet is a system of communication, and as such, the relationship between client and server, as well as server to server, is one of the most oft-discussed and hotly contested concepts. **event-driven architecture** is a methodology of defining these relationships, and creating systems within a specific set of relationships that allow for extensive functionality.\n\nIn this piece, we’re going to discuss 5 common event-driven methods — **WebSockets**, **WebHooks**, **REST Hooks**, **Pub-Sub**, and **Server Sent Events**. We’ll define what they fundamentally are and do, and how API providers go about using them. Additionally, we’ll provide some pros and cons on each to make choosing a solution for your platform easy and intuitive.\n\n## What is an Event-Driven Architecture?\n\nEvent-driven architectures establish an event that can be consumed and reacted to. But what is an event?\n\nAn event is essentially any significant **change** from one state to another, such as the change from having no messages in your inbox to have a new message in your inbox. This state can be reacted to **internally** (such as when the email program in question realizes a new message has been received), **externally** (when a user sees a notification for a new message), or used to **generate another event** (for instance, the message tally increases by one).\n\nEvent-driven architectures are appealing to API developers because they function very well in **asynchronous** environments. By crafting APIs that **trigger** certain functions on new event delivery, API systems don’t have to inherently wait for synchronous delivery or real time communication. This is hugely beneficial, as eliminating the need to constantly poll endpoints frees resources from otherwise wasteful purposes, reducing both general hardware requirements and call-specific overhead.\n\nFor this reason, event-driven architectures are very, very popular, and lead to improved power, bandwidth, and co-processing than other solutions and architectures such as polling and other poll-centric derivatives.\n\n## 5 Types of Event-Driven Protocols for APIs\n\n### 1: WebSockets\n\n**WebSockets** are an interesting event-driven solution, because, for most browsers, they’re actually baked into the application itself. Essentially, WebSocket is a protocol that provides full-duplex communication on a single TCP connection. It was standardized by the Internet Engineering Task Force as [RFC 6455](https://tools.ietf.org/html/rfc6455), and the WebSocket API in Web IDL was later standardized under the W3C banner.\n\nWhile the protocol itself is meant to be used between **web browsers** and **servers**, the protocol can be used in any case where there is a client-server relationship. The protocol itself is based upon TCP, with the additional HTTP interpretation statement that is considered an “Upgrade request” to allow for interoperability.\n\n#### Pros\nBecause WebSocket is expressly designed for browser operation, it boasts extremely **low overhead** for what it actually does. By establishing a **full-duplex** conversation using a standardized methodology, connection both to and from the two entities can take place simultaneously, resulting in lower overhead and better throughput.\n\nAdditionally, the fact that these communications take place over TCP 80/443 means that environments that traditionally block non-web based applications for security reasons can still handle this protocol, as firewalls allow communication to and from this port.\n\nPerhaps the strongest argument for the use of WebSockets are the fact that they are standardized and **natively supported** by all major browsers, ranging from Microsft Edge to Opera, from Firefox to Chrome. This means that any web application that ties into it will be interactable within the vast majority of both browser-based and browser-independent gateways and applications.\n\n#### Cons\nWebSockets have one distinct major failing — while it might have support for HTTP-like functionality, **it is not HTTP** whatsoever. This has implications, especially when considering optimizing in HTTP such as caching, proxying, etc., that haven’t quite become apparent.\n\nBecause WebSockets are relatively new, having been only officially standardized in 2011, the industry is still understanding what the side effects mean. Most applications that use WebSockets are designed specifically for everything that a WebSocket is — what has yet to be seen, however, is whether or not this solution is better in the long-run than any stateless solution currently available.\n\nThere is of course the fact that, as with other architectures on this list, WebSockets create an “always on” connection during the duration of data transfer. While this is fine for many uses such as media streaming and live stream calculations, it also essentially means that, for WebSockets, there is no scalability. Ports have hardcoded limitations and bandwidth, and thus in order to “scale”, you must add additional ports to match the maximum load. In stateless systems, this is less of an issue, as requests can wait and be made in such a way as to be independent on the state of the server itself.\n\n### 2: WebHooks\n**WebHooks** are a similar concept to the WebSocket. They primarily function using **custom callbacks**, or code that is passed as an argument to another chunk of code and executed at a specified point in time. Essentially, a WebHook is a glorified system of “if this, then do”, allowing for users independent of the event firing to craft a custom response to that event within their own system.\n\nThe term was coined by [Jeff Lindsay](https://twitter.com/progrium) in 2007, and quickly became popular amongst users who wished to create automated responses to exterior behaviors. A great example of this would be a developer pushing a new item to GitHub, which causes an event. A user has a system tied into the URI of a WebHook. When the push is published, the user’s system utilizes the URI of the WebHook to integrate the push into a larger build, thereby creating a compiled component.\n\n#### Pros\nWebHooks function a lot like WebSockets, but they’re different in some key areas. First and foremost, WebSockets are primarily designed for browser-based communications, and while they can be used regardless in any client-server communication, they do not behave well in a **server-to-server** setup.\n\nWebHooks, on the other hand, work very well in server-to-server systems due to how they operate. Because the system essentially functions as the aforementioned “if this then do”, servers can be configured to tie into pre-formed URIs at any time and execute a given function whenever that event is triggered.\n\nAdditionally, WebHooks have the unique benefit of being **based upon HTTP**, unlike WebSockets. This means that the system can be integrated without utilizing any new infrastructure, allowing speedy adoption and relatively simple setup.\n\n#### Cons\nThe problem with WebHooks is that a lot of their functionality can already be placed on the arguably more powerful REST architectural approach. While adopting event-driven architecture is often a requirement of the service being built, it’s a hard sell when it can be mirrored in REST while also giving the wealth of options that REST gives to the user.\n\nThese RESTful solutions such as [RestMS](http://www.restms.org/) are essentially simply message querying services, though, and do require additional infrastructure, which may or may not be doable considering the purpose of the application.\n\nAdditionally, WebHooks can be **resource intensive** to both the client and the server. If the client needs to notify many servers that an event has occurred, and a server needs to listen to a great deal of clients notifying of this change, you can very quickly run into a situation where your network grows uncontrollably. While HTTP does scale quite well, this is a definite negative to consider.\n\nHowever, there are also ways to build a [message queuing service](https://en.wikipedia.org/wiki/Message_queuing_service) on top of HTTP—some RESTful examples include [IronMQ](https://www.iron.io/platform/ironmq/) and RestMS.\n\n### 3: REST Hooks\nSpeaking of RESTful examples, **REST Hooks** is essentially “hooking” baked into REST itself. Defined as an initiative from [Zapier](http://resthooks.org/docs/), this is a subject [we’ve covered before](http://nordicapis.com/stop-polling-and-consider-using-rest-hooks/) — hooks are collated to a single target URL as a subscription, which pings the resource requester when a change is noted.\n\nThis approach is a response to the practice of **polling**, in which a client constantly checks for changes to a resource. Under the REST Hooks paradigm, the client instead waits for a change, and reacts to it. To put it simply, this is a WebHook in REST.\n\n#### Pros\nREST Hooks are obviously super powerful in the correct context — being able to passively receive a resource rather than dedicating processing power to constant polling frees up a lot of the client-side cost.\n\nPerhaps the strongest argument for REST Hooks though, is the fact that it’s **so easy** and **intuitive** to use. While WebHooks utilize HTTP and thus do not need new architecture to set up, they are also limited by the fact that they are built upon HTTP, and can thus be somewhat complex to set up properly and use effectively.\n\nREST Hooks, though, are **subscription based**, and as such, are simply usable by subscribing. This makes it a very easy to use solution while providing a lot of the usability and effectiveness of more complex systems.\n\n#### Cons\nOf course, every solution has its negatives, and REST Hooks are no different. It could be viewed that REST Hooks actually fly in the face of what REST is — [session free and stateless](http://nordicapis.com/defining-stateful-vs-stateless-web-services/). REST Hooks essentially create consistent polling, it’s just moved the polling from one side to another.\n\nThen, there’s the arguable problem that REST Hooks might be doing something that has already been solved. Some would argue that TCP already does most of what REST Hooks is trying to do, and simply layering more solutions on top of HTTP to get what TCP already does is a poor approach.\n\n### 4: Pub-Sub\n**Pub-Sub** is a slightly different approach. Referred to by its full name as **publish-subscribe**, the concept is where events are published to a class without knowledge of the client subscribing to the class. Basically, a user will join one or more classes, and then will receive event updates without regard or knowledge to the event publisher.\n\nThe main difference here is one of conscious choice of provider — in the other solutions noted herein, a user consciously communicates with a given server or provider and receives events as pre-determined. Under the Pub-Sub scheme, the user only specifies which class they wish to be part of and what events they are interested in receiving. From there, they receive these events when one is pushed out.\n\nA way this is often framed in internet discussions is in the frame of a **radio channel**. Record companies, or publishers, issue audio to the station, which then broadcasts this audio to listeners, or subscribers. Pub-sub is the middleman radio station here — listeners don’t know who gave the station the music, nor do the companies know who the listeners are. It is this segmentation that is baked into the pattern.\n\nWhen we talk about Pub-Sub, we need to keep in mind that we’re actually talking about two different things. Pub-Sub can mean the methodology and general concept in programming terms, but it can also mean specific provider solutions based upon that methodology. For instance, Google’s [Cloud Pub/Sub](https://cloud.google.com/pubsub/docs/overview) is an implementation of the general methodology within their cloud service, and allows for asynchronous many-to-many pub-sub relationships as stated above.\n\n#### Pros\nA huge benefit of Pub-Sub is the fact that it’s **loosely coupled**, and thus is extremely scalable and flexible. The only thing the event-provider is doing is generating the content — each other step is done through a separated middleman, and so the content is easily scaled and modulated to the architecture and design of the solution.\n\nAdditionally, Pub-Sub lends itself very well to **testing**. A subscriber is narrowly limited to a set of events that they have requested under a class, so if a failure occurs, this natural segmentation informs the provider as to where the fault is, and which class of users is experiencing the fault.\n\n#### Cons\nUnfortunately, decoupling is also a huge disadvantage for this pattern. By being a **middleman**, Pub-Sub cannot effectively notify the provider that a message has been sent, and the listener is separated from the event and thus may not know if a message wasn’t sent that should have been. Harkening back to the radio explanation, a listener will never know if a song was meant to play on a channel or if the channel is out of range, and once the record executives hand off the music, they’ve got no idea if the user received the songs without direct feedback from them.\n\nAdditionally, while the system is extensible and flexible, instability does occur with high traffic load as subclass after subclass might be constructed to handle further segmentation. This of course leads to the aforementioned instability in addition to increased complexity.\n\nYou must keep in mind that while the relationship between the publisher and subscriber in this model may be beneficial, it also comes with its own difficulties when these relationships need to be modulated. While you can certainly work around this, at this point, you’re fighting the very basis of the pattern, rather than any secondary natures — you’re trying to make dehydrated water, and fighting against the nature of a pattern suggests the pattern to be inherently poor.\n\n> Also read: [Building a Backend for Frontend (BFF) For Your Microservices](http://nordicapis.com/building-a-backend-for-frontend-shim-for-your-microservices/)\n\n### 5: Server Sent Events\n**Server Sent Events**, or SSE, is a communication protocol much like WebSockets, but with the implication of **unidirectional data**. In this architecture, the server is consistently sending updates to the client as an automatic process. This was standardized under HTML5 by the [W3C](https://www.w3.org/TR/2009/WD-eventsource-20091029/), and is thus compatible with any solution that is likewise compatible with HTML5.\n\n> Of note is that there is a competing standardization from the [Web Hypertext Application Technology Working Group](https://whatwg.org/) – this is a relic from movement away from “HTML5” and into what WHATWG is calling “HTML Living Standard”. The general working consensus is that, WHATWG’s standardization is prioritized in the rare cases of divergent standards. This could become more of an issue as time marches forward, given that WHATWG was created due to a perceived lack of interest from W3C towards evolving HTML, but for the time being, either standard is generally acceptable.\nWhile simple in theory, Server Sent Events are anything but simple when considering benefits and drawbacks.\n\n#### Pros\nSSE is **not bidirectional** in its communications — the server is issuing the events in a steady, predictable method. This is hugely beneficial to applications which do not need the two-way communications baked into WebSockets or other such solutions, as this means **lower bandwidth**, and an allowance for the connection to be temporary rather than always-on during the duration of data transfer. By its nature, the data is being transferred one way, and thus there is no need to wait for data to be returned.\n\nAdditionally, at least in theory, SSE is easier to set up in complex situations. You only have to worry about data traveling one direction via one system, thus reducing complexity dramatically. There is no need to define a message exchange protocol, no need to specify data duration or wait times, no need to support bilateral messaging — the single direction saves a lot of complexity.\n\n#### Cons\nThat simplicity could be where SSE fails for particular use cases. SSE is a very poor solution for situations that require **bidirectional communication**, and while this seems obvious, it would surprise many developers to see how many systems actually depend on bidirectional communication for simple functionality.\n\nWhile much of this can be fixed with workarounds, a developer’s goal in choosing an event-driven protocol should be to find one that works out of the box, not to find a solution that might work if configured properly and given secondary systems upon which to depend.\n\nThere is also the issue of **security** and authentication. While two-way systems can easily use authentication methodologies, SSE handles this using **header forwarding**. While headers can be manipulated and overridden in many languages and applications, the EventSource object in JavaScript does not natively support this, which would cause many adoptees some major headaches.\n\nFinally, there is a concern over loss of efficiency with **over transmitting** data. A two-direction system can determine when a client or server disconnects, but SSE can only determine that a client has disconnected after attempting a full data transmission and receiving a noted failure. Because of this, data can be lost rather quickly, and with many failed connections, this loss can mount dramatically over time.\n\n## Conclusion\nThere is no one event-driven solution that works in every use case. While many would argue that event-driven solutions should be REST based, which suggests REST Hooks as the answer, many others would argue that it is entirely situational, and that REST is not always the silver bullet it’s touted to be.\n\nIf you are building for scalability with low overhead in a browser environment, **WebSockets** are a great solution. Conversely, if you’d like those same benefits but are working in a non-browser system, then **WebHooks** should be your approach. **REST Hooks** are not only great for RESTful services, they’re also much easier to set up than either, and thus are great in low-time high-rush situations. **Pub-Sub** can be great if you need to enforce a division between client and server, and this can further be established and controlled in an even stronger way with **Server Sent**.\n\nSimply put, the best solution will be the one that fits your specific situation and build — any of these solutions, given the correct system, is a great solution. To that end, each solution has a very specific use case.\n\n## TLDR Comparison Table\n| PROTOCOL | RELATED TO | STANDARD BODY | NOTES |\n| ------ | ------ | ------ | ------ |\n| WebSockets | TCP, HTTP-like | IETF, W3C | Two-way communication over TCP<br>Designed for web browsers & web servers<br>Good for lower overhead scenarios<br>Supported in all major browsers |\n| Webhooks | URI, HTTP | - | User defined “HTTP callbacks”<br>Triggered by an event HTTP<br>Requests are made to Webhook URI<br>Enables real-time event triggering|\n| REST Hooks | HTTP | Zapier | Lightweight subscription layer<br>Manipulated by a REST API<br>Essentially a WebHook in REST |\n| Pub-Sub | - | - |Client subscribes to classes<br>Bidirectional<br>Middleman layer between client and server<br>Loose coupling|\n| Server Sent | HTTP, HTML5 , DOM | WHATWG, W3C |Server constantly sends updates to the client<br>Unidirectional push notifications as DOM events|\n","slug":"5-protocols-for-event-driven-api-architectures","published":1,"updated":"2017-07-21T03:28:42.000Z","comments":1,"layout":"post","photos":[],"link":"","_id":"cjsqa1qmx005hjrs6mqnbk8t0","content":"<p>原文:<a href=\"http://nordicapis.com/5-protocols-for-event-driven-api-architectures/\" target=\"_blank\" rel=\"noopener\">5 Protocols For Event-Driven API Architectures</a></p>\n<p>The internet is a system of communication, and as such, the relationship between client and server, as well as server to server, is one of the most oft-discussed and hotly contested concepts. <strong>event-driven architecture</strong> is a methodology of defining these relationships, and creating systems within a specific set of relationships that allow for extensive functionality.</p>\n<p>In this piece, we’re going to discuss 5 common event-driven methods — <strong>WebSockets</strong>, <strong>WebHooks</strong>, <strong>REST Hooks</strong>, <strong>Pub-Sub</strong>, and <strong>Server Sent Events</strong>. We’ll define what they fundamentally are and do, and how API providers go about using them. Additionally, we’ll provide some pros and cons on each to make choosing a solution for your platform easy and intuitive.</p>\n<h2 id=\"What-is-an-Event-Driven-Architecture\"><a href=\"#What-is-an-Event-Driven-Architecture\" class=\"headerlink\" title=\"What is an Event-Driven Architecture?\"></a>What is an Event-Driven Architecture?</h2><p>Event-driven architectures establish an event that can be consumed and reacted to. But what is an event?</p>\n<p>An event is essentially any significant <strong>change</strong> from one state to another, such as the change from having no messages in your inbox to have a new message in your inbox. This state can be reacted to <strong>internally</strong> (such as when the email program in question realizes a new message has been received), <strong>externally</strong> (when a user sees a notification for a new message), or used to <strong>generate another event</strong> (for instance, the message tally increases by one).</p>\n<p>Event-driven architectures are appealing to API developers because they function very well in <strong>asynchronous</strong> environments. By crafting APIs that <strong>trigger</strong> certain functions on new event delivery, API systems don’t have to inherently wait for synchronous delivery or real time communication. This is hugely beneficial, as eliminating the need to constantly poll endpoints frees resources from otherwise wasteful purposes, reducing both general hardware requirements and call-specific overhead.</p>\n<p>For this reason, event-driven architectures are very, very popular, and lead to improved power, bandwidth, and co-processing than other solutions and architectures such as polling and other poll-centric derivatives.</p>\n<h2 id=\"5-Types-of-Event-Driven-Protocols-for-APIs\"><a href=\"#5-Types-of-Event-Driven-Protocols-for-APIs\" class=\"headerlink\" title=\"5 Types of Event-Driven Protocols for APIs\"></a>5 Types of Event-Driven Protocols for APIs</h2><h3 id=\"1-WebSockets\"><a href=\"#1-WebSockets\" class=\"headerlink\" title=\"1: WebSockets\"></a>1: WebSockets</h3><p><strong>WebSockets</strong> are an interesting event-driven solution, because, for most browsers, they’re actually baked into the application itself. Essentially, WebSocket is a protocol that provides full-duplex communication on a single TCP connection. It was standardized by the Internet Engineering Task Force as <a href=\"https://tools.ietf.org/html/rfc6455\" target=\"_blank\" rel=\"noopener\">RFC 6455</a>, and the WebSocket API in Web IDL was later standardized under the W3C banner.</p>\n<p>While the protocol itself is meant to be used between <strong>web browsers</strong> and <strong>servers</strong>, the protocol can be used in any case where there is a client-server relationship. The protocol itself is based upon TCP, with the additional HTTP interpretation statement that is considered an “Upgrade request” to allow for interoperability.</p>\n<h4 id=\"Pros\"><a href=\"#Pros\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>Because WebSocket is expressly designed for browser operation, it boasts extremely <strong>low overhead</strong> for what it actually does. By establishing a <strong>full-duplex</strong> conversation using a standardized methodology, connection both to and from the two entities can take place simultaneously, resulting in lower overhead and better throughput.</p>\n<p>Additionally, the fact that these communications take place over TCP 80/443 means that environments that traditionally block non-web based applications for security reasons can still handle this protocol, as firewalls allow communication to and from this port.</p>\n<p>Perhaps the strongest argument for the use of WebSockets are the fact that they are standardized and <strong>natively supported</strong> by all major browsers, ranging from Microsft Edge to Opera, from Firefox to Chrome. This means that any web application that ties into it will be interactable within the vast majority of both browser-based and browser-independent gateways and applications.</p>\n<h4 id=\"Cons\"><a href=\"#Cons\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>WebSockets have one distinct major failing — while it might have support for HTTP-like functionality, <strong>it is not HTTP</strong> whatsoever. This has implications, especially when considering optimizing in HTTP such as caching, proxying, etc., that haven’t quite become apparent.</p>\n<p>Because WebSockets are relatively new, having been only officially standardized in 2011, the industry is still understanding what the side effects mean. Most applications that use WebSockets are designed specifically for everything that a WebSocket is — what has yet to be seen, however, is whether or not this solution is better in the long-run than any stateless solution currently available.</p>\n<p>There is of course the fact that, as with other architectures on this list, WebSockets create an “always on” connection during the duration of data transfer. While this is fine for many uses such as media streaming and live stream calculations, it also essentially means that, for WebSockets, there is no scalability. Ports have hardcoded limitations and bandwidth, and thus in order to “scale”, you must add additional ports to match the maximum load. In stateless systems, this is less of an issue, as requests can wait and be made in such a way as to be independent on the state of the server itself.</p>\n<h3 id=\"2-WebHooks\"><a href=\"#2-WebHooks\" class=\"headerlink\" title=\"2: WebHooks\"></a>2: WebHooks</h3><p><strong>WebHooks</strong> are a similar concept to the WebSocket. They primarily function using <strong>custom callbacks</strong>, or code that is passed as an argument to another chunk of code and executed at a specified point in time. Essentially, a WebHook is a glorified system of “if this, then do”, allowing for users independent of the event firing to craft a custom response to that event within their own system.</p>\n<p>The term was coined by <a href=\"https://twitter.com/progrium\" target=\"_blank\" rel=\"noopener\">Jeff Lindsay</a> in 2007, and quickly became popular amongst users who wished to create automated responses to exterior behaviors. A great example of this would be a developer pushing a new item to GitHub, which causes an event. A user has a system tied into the URI of a WebHook. When the push is published, the user’s system utilizes the URI of the WebHook to integrate the push into a larger build, thereby creating a compiled component.</p>\n<h4 id=\"Pros-1\"><a href=\"#Pros-1\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>WebHooks function a lot like WebSockets, but they’re different in some key areas. First and foremost, WebSockets are primarily designed for browser-based communications, and while they can be used regardless in any client-server communication, they do not behave well in a <strong>server-to-server</strong> setup.</p>\n<p>WebHooks, on the other hand, work very well in server-to-server systems due to how they operate. Because the system essentially functions as the aforementioned “if this then do”, servers can be configured to tie into pre-formed URIs at any time and execute a given function whenever that event is triggered.</p>\n<p>Additionally, WebHooks have the unique benefit of being <strong>based upon HTTP</strong>, unlike WebSockets. This means that the system can be integrated without utilizing any new infrastructure, allowing speedy adoption and relatively simple setup.</p>\n<h4 id=\"Cons-1\"><a href=\"#Cons-1\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>The problem with WebHooks is that a lot of their functionality can already be placed on the arguably more powerful REST architectural approach. While adopting event-driven architecture is often a requirement of the service being built, it’s a hard sell when it can be mirrored in REST while also giving the wealth of options that REST gives to the user.</p>\n<p>These RESTful solutions such as <a href=\"http://www.restms.org/\" target=\"_blank\" rel=\"noopener\">RestMS</a> are essentially simply message querying services, though, and do require additional infrastructure, which may or may not be doable considering the purpose of the application.</p>\n<p>Additionally, WebHooks can be <strong>resource intensive</strong> to both the client and the server. If the client needs to notify many servers that an event has occurred, and a server needs to listen to a great deal of clients notifying of this change, you can very quickly run into a situation where your network grows uncontrollably. While HTTP does scale quite well, this is a definite negative to consider.</p>\n<p>However, there are also ways to build a <a href=\"https://en.wikipedia.org/wiki/Message_queuing_service\" target=\"_blank\" rel=\"noopener\">message queuing service</a> on top of HTTP—some RESTful examples include <a href=\"https://www.iron.io/platform/ironmq/\" target=\"_blank\" rel=\"noopener\">IronMQ</a> and RestMS.</p>\n<h3 id=\"3-REST-Hooks\"><a href=\"#3-REST-Hooks\" class=\"headerlink\" title=\"3: REST Hooks\"></a>3: REST Hooks</h3><p>Speaking of RESTful examples, <strong>REST Hooks</strong> is essentially “hooking” baked into REST itself. Defined as an initiative from <a href=\"http://resthooks.org/docs/\" target=\"_blank\" rel=\"noopener\">Zapier</a>, this is a subject <a href=\"http://nordicapis.com/stop-polling-and-consider-using-rest-hooks/\" target=\"_blank\" rel=\"noopener\">we’ve covered before</a> — hooks are collated to a single target URL as a subscription, which pings the resource requester when a change is noted.</p>\n<p>This approach is a response to the practice of <strong>polling</strong>, in which a client constantly checks for changes to a resource. Under the REST Hooks paradigm, the client instead waits for a change, and reacts to it. To put it simply, this is a WebHook in REST.</p>\n<h4 id=\"Pros-2\"><a href=\"#Pros-2\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>REST Hooks are obviously super powerful in the correct context — being able to passively receive a resource rather than dedicating processing power to constant polling frees up a lot of the client-side cost.</p>\n<p>Perhaps the strongest argument for REST Hooks though, is the fact that it’s <strong>so easy</strong> and <strong>intuitive</strong> to use. While WebHooks utilize HTTP and thus do not need new architecture to set up, they are also limited by the fact that they are built upon HTTP, and can thus be somewhat complex to set up properly and use effectively.</p>\n<p>REST Hooks, though, are <strong>subscription based</strong>, and as such, are simply usable by subscribing. This makes it a very easy to use solution while providing a lot of the usability and effectiveness of more complex systems.</p>\n<h4 id=\"Cons-2\"><a href=\"#Cons-2\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>Of course, every solution has its negatives, and REST Hooks are no different. It could be viewed that REST Hooks actually fly in the face of what REST is — <a href=\"http://nordicapis.com/defining-stateful-vs-stateless-web-services/\" target=\"_blank\" rel=\"noopener\">session free and stateless</a>. REST Hooks essentially create consistent polling, it’s just moved the polling from one side to another.</p>\n<p>Then, there’s the arguable problem that REST Hooks might be doing something that has already been solved. Some would argue that TCP already does most of what REST Hooks is trying to do, and simply layering more solutions on top of HTTP to get what TCP already does is a poor approach.</p>\n<h3 id=\"4-Pub-Sub\"><a href=\"#4-Pub-Sub\" class=\"headerlink\" title=\"4: Pub-Sub\"></a>4: Pub-Sub</h3><p><strong>Pub-Sub</strong> is a slightly different approach. Referred to by its full name as <strong>publish-subscribe</strong>, the concept is where events are published to a class without knowledge of the client subscribing to the class. Basically, a user will join one or more classes, and then will receive event updates without regard or knowledge to the event publisher.</p>\n<p>The main difference here is one of conscious choice of provider — in the other solutions noted herein, a user consciously communicates with a given server or provider and receives events as pre-determined. Under the Pub-Sub scheme, the user only specifies which class they wish to be part of and what events they are interested in receiving. From there, they receive these events when one is pushed out.</p>\n<p>A way this is often framed in internet discussions is in the frame of a <strong>radio channel</strong>. Record companies, or publishers, issue audio to the station, which then broadcasts this audio to listeners, or subscribers. Pub-sub is the middleman radio station here — listeners don’t know who gave the station the music, nor do the companies know who the listeners are. It is this segmentation that is baked into the pattern.</p>\n<p>When we talk about Pub-Sub, we need to keep in mind that we’re actually talking about two different things. Pub-Sub can mean the methodology and general concept in programming terms, but it can also mean specific provider solutions based upon that methodology. For instance, Google’s <a href=\"https://cloud.google.com/pubsub/docs/overview\" target=\"_blank\" rel=\"noopener\">Cloud Pub/Sub</a> is an implementation of the general methodology within their cloud service, and allows for asynchronous many-to-many pub-sub relationships as stated above.</p>\n<h4 id=\"Pros-3\"><a href=\"#Pros-3\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>A huge benefit of Pub-Sub is the fact that it’s <strong>loosely coupled</strong>, and thus is extremely scalable and flexible. The only thing the event-provider is doing is generating the content — each other step is done through a separated middleman, and so the content is easily scaled and modulated to the architecture and design of the solution.</p>\n<p>Additionally, Pub-Sub lends itself very well to <strong>testing</strong>. A subscriber is narrowly limited to a set of events that they have requested under a class, so if a failure occurs, this natural segmentation informs the provider as to where the fault is, and which class of users is experiencing the fault.</p>\n<h4 id=\"Cons-3\"><a href=\"#Cons-3\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>Unfortunately, decoupling is also a huge disadvantage for this pattern. By being a <strong>middleman</strong>, Pub-Sub cannot effectively notify the provider that a message has been sent, and the listener is separated from the event and thus may not know if a message wasn’t sent that should have been. Harkening back to the radio explanation, a listener will never know if a song was meant to play on a channel or if the channel is out of range, and once the record executives hand off the music, they’ve got no idea if the user received the songs without direct feedback from them.</p>\n<p>Additionally, while the system is extensible and flexible, instability does occur with high traffic load as subclass after subclass might be constructed to handle further segmentation. This of course leads to the aforementioned instability in addition to increased complexity.</p>\n<p>You must keep in mind that while the relationship between the publisher and subscriber in this model may be beneficial, it also comes with its own difficulties when these relationships need to be modulated. While you can certainly work around this, at this point, you’re fighting the very basis of the pattern, rather than any secondary natures — you’re trying to make dehydrated water, and fighting against the nature of a pattern suggests the pattern to be inherently poor.</p>\n<blockquote>\n<p>Also read: <a href=\"http://nordicapis.com/building-a-backend-for-frontend-shim-for-your-microservices/\" target=\"_blank\" rel=\"noopener\">Building a Backend for Frontend (BFF) For Your Microservices</a></p>\n</blockquote>\n<h3 id=\"5-Server-Sent-Events\"><a href=\"#5-Server-Sent-Events\" class=\"headerlink\" title=\"5: Server Sent Events\"></a>5: Server Sent Events</h3><p><strong>Server Sent Events</strong>, or SSE, is a communication protocol much like WebSockets, but with the implication of <strong>unidirectional data</strong>. In this architecture, the server is consistently sending updates to the client as an automatic process. This was standardized under HTML5 by the <a href=\"https://www.w3.org/TR/2009/WD-eventsource-20091029/\" target=\"_blank\" rel=\"noopener\">W3C</a>, and is thus compatible with any solution that is likewise compatible with HTML5.</p>\n<blockquote>\n<p>Of note is that there is a competing standardization from the <a href=\"https://whatwg.org/\" target=\"_blank\" rel=\"noopener\">Web Hypertext Application Technology Working Group</a> – this is a relic from movement away from “HTML5” and into what WHATWG is calling “HTML Living Standard”. The general working consensus is that, WHATWG’s standardization is prioritized in the rare cases of divergent standards. This could become more of an issue as time marches forward, given that WHATWG was created due to a perceived lack of interest from W3C towards evolving HTML, but for the time being, either standard is generally acceptable.<br>While simple in theory, Server Sent Events are anything but simple when considering benefits and drawbacks.</p>\n</blockquote>\n<h4 id=\"Pros-4\"><a href=\"#Pros-4\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>SSE is <strong>not bidirectional</strong> in its communications — the server is issuing the events in a steady, predictable method. This is hugely beneficial to applications which do not need the two-way communications baked into WebSockets or other such solutions, as this means <strong>lower bandwidth</strong>, and an allowance for the connection to be temporary rather than always-on during the duration of data transfer. By its nature, the data is being transferred one way, and thus there is no need to wait for data to be returned.</p>\n<p>Additionally, at least in theory, SSE is easier to set up in complex situations. You only have to worry about data traveling one direction via one system, thus reducing complexity dramatically. There is no need to define a message exchange protocol, no need to specify data duration or wait times, no need to support bilateral messaging — the single direction saves a lot of complexity.</p>\n<h4 id=\"Cons-4\"><a href=\"#Cons-4\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>That simplicity could be where SSE fails for particular use cases. SSE is a very poor solution for situations that require <strong>bidirectional communication</strong>, and while this seems obvious, it would surprise many developers to see how many systems actually depend on bidirectional communication for simple functionality.</p>\n<p>While much of this can be fixed with workarounds, a developer’s goal in choosing an event-driven protocol should be to find one that works out of the box, not to find a solution that might work if configured properly and given secondary systems upon which to depend.</p>\n<p>There is also the issue of <strong>security</strong> and authentication. While two-way systems can easily use authentication methodologies, SSE handles this using <strong>header forwarding</strong>. While headers can be manipulated and overridden in many languages and applications, the EventSource object in JavaScript does not natively support this, which would cause many adoptees some major headaches.</p>\n<p>Finally, there is a concern over loss of efficiency with <strong>over transmitting</strong> data. A two-direction system can determine when a client or server disconnects, but SSE can only determine that a client has disconnected after attempting a full data transmission and receiving a noted failure. Because of this, data can be lost rather quickly, and with many failed connections, this loss can mount dramatically over time.</p>\n<h2 id=\"Conclusion\"><a href=\"#Conclusion\" class=\"headerlink\" title=\"Conclusion\"></a>Conclusion</h2><p>There is no one event-driven solution that works in every use case. While many would argue that event-driven solutions should be REST based, which suggests REST Hooks as the answer, many others would argue that it is entirely situational, and that REST is not always the silver bullet it’s touted to be.</p>\n<p>If you are building for scalability with low overhead in a browser environment, <strong>WebSockets</strong> are a great solution. Conversely, if you’d like those same benefits but are working in a non-browser system, then <strong>WebHooks</strong> should be your approach. <strong>REST Hooks</strong> are not only great for RESTful services, they’re also much easier to set up than either, and thus are great in low-time high-rush situations. <strong>Pub-Sub</strong> can be great if you need to enforce a division between client and server, and this can further be established and controlled in an even stronger way with <strong>Server Sent</strong>.</p>\n<p>Simply put, the best solution will be the one that fits your specific situation and build — any of these solutions, given the correct system, is a great solution. To that end, each solution has a very specific use case.</p>\n<h2 id=\"TLDR-Comparison-Table\"><a href=\"#TLDR-Comparison-Table\" class=\"headerlink\" title=\"TLDR Comparison Table\"></a>TLDR Comparison Table</h2><table>\n<thead>\n<tr>\n<th>PROTOCOL</th>\n<th>RELATED TO</th>\n<th>STANDARD BODY</th>\n<th>NOTES</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>WebSockets</td>\n<td>TCP, HTTP-like</td>\n<td>IETF, W3C</td>\n<td>Two-way communication over TCP<br>Designed for web browsers & web servers<br>Good for lower overhead scenarios<br>Supported in all major browsers</td>\n</tr>\n<tr>\n<td>Webhooks</td>\n<td>URI, HTTP</td>\n<td>-</td>\n<td>User defined “HTTP callbacks”<br>Triggered by an event HTTP<br>Requests are made to Webhook URI<br>Enables real-time event triggering</td>\n</tr>\n<tr>\n<td>REST Hooks</td>\n<td>HTTP</td>\n<td>Zapier</td>\n<td>Lightweight subscription layer<br>Manipulated by a REST API<br>Essentially a WebHook in REST</td>\n</tr>\n<tr>\n<td>Pub-Sub</td>\n<td>-</td>\n<td>-</td>\n<td>Client subscribes to classes<br>Bidirectional<br>Middleman layer between client and server<br>Loose coupling</td>\n</tr>\n<tr>\n<td>Server Sent</td>\n<td>HTTP, HTML5 , DOM</td>\n<td>WHATWG, W3C</td>\n<td>Server constantly sends updates to the client<br>Unidirectional push notifications as DOM events</td>\n</tr>\n</tbody>\n</table>\n","site":{"data":{}},"excerpt":"","more":"<p>原文:<a href=\"http://nordicapis.com/5-protocols-for-event-driven-api-architectures/\" target=\"_blank\" rel=\"noopener\">5 Protocols For Event-Driven API Architectures</a></p>\n<p>The internet is a system of communication, and as such, the relationship between client and server, as well as server to server, is one of the most oft-discussed and hotly contested concepts. <strong>event-driven architecture</strong> is a methodology of defining these relationships, and creating systems within a specific set of relationships that allow for extensive functionality.</p>\n<p>In this piece, we’re going to discuss 5 common event-driven methods — <strong>WebSockets</strong>, <strong>WebHooks</strong>, <strong>REST Hooks</strong>, <strong>Pub-Sub</strong>, and <strong>Server Sent Events</strong>. We’ll define what they fundamentally are and do, and how API providers go about using them. Additionally, we’ll provide some pros and cons on each to make choosing a solution for your platform easy and intuitive.</p>\n<h2 id=\"What-is-an-Event-Driven-Architecture\"><a href=\"#What-is-an-Event-Driven-Architecture\" class=\"headerlink\" title=\"What is an Event-Driven Architecture?\"></a>What is an Event-Driven Architecture?</h2><p>Event-driven architectures establish an event that can be consumed and reacted to. But what is an event?</p>\n<p>An event is essentially any significant <strong>change</strong> from one state to another, such as the change from having no messages in your inbox to have a new message in your inbox. This state can be reacted to <strong>internally</strong> (such as when the email program in question realizes a new message has been received), <strong>externally</strong> (when a user sees a notification for a new message), or used to <strong>generate another event</strong> (for instance, the message tally increases by one).</p>\n<p>Event-driven architectures are appealing to API developers because they function very well in <strong>asynchronous</strong> environments. By crafting APIs that <strong>trigger</strong> certain functions on new event delivery, API systems don’t have to inherently wait for synchronous delivery or real time communication. This is hugely beneficial, as eliminating the need to constantly poll endpoints frees resources from otherwise wasteful purposes, reducing both general hardware requirements and call-specific overhead.</p>\n<p>For this reason, event-driven architectures are very, very popular, and lead to improved power, bandwidth, and co-processing than other solutions and architectures such as polling and other poll-centric derivatives.</p>\n<h2 id=\"5-Types-of-Event-Driven-Protocols-for-APIs\"><a href=\"#5-Types-of-Event-Driven-Protocols-for-APIs\" class=\"headerlink\" title=\"5 Types of Event-Driven Protocols for APIs\"></a>5 Types of Event-Driven Protocols for APIs</h2><h3 id=\"1-WebSockets\"><a href=\"#1-WebSockets\" class=\"headerlink\" title=\"1: WebSockets\"></a>1: WebSockets</h3><p><strong>WebSockets</strong> are an interesting event-driven solution, because, for most browsers, they’re actually baked into the application itself. Essentially, WebSocket is a protocol that provides full-duplex communication on a single TCP connection. It was standardized by the Internet Engineering Task Force as <a href=\"https://tools.ietf.org/html/rfc6455\" target=\"_blank\" rel=\"noopener\">RFC 6455</a>, and the WebSocket API in Web IDL was later standardized under the W3C banner.</p>\n<p>While the protocol itself is meant to be used between <strong>web browsers</strong> and <strong>servers</strong>, the protocol can be used in any case where there is a client-server relationship. The protocol itself is based upon TCP, with the additional HTTP interpretation statement that is considered an “Upgrade request” to allow for interoperability.</p>\n<h4 id=\"Pros\"><a href=\"#Pros\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>Because WebSocket is expressly designed for browser operation, it boasts extremely <strong>low overhead</strong> for what it actually does. By establishing a <strong>full-duplex</strong> conversation using a standardized methodology, connection both to and from the two entities can take place simultaneously, resulting in lower overhead and better throughput.</p>\n<p>Additionally, the fact that these communications take place over TCP 80/443 means that environments that traditionally block non-web based applications for security reasons can still handle this protocol, as firewalls allow communication to and from this port.</p>\n<p>Perhaps the strongest argument for the use of WebSockets are the fact that they are standardized and <strong>natively supported</strong> by all major browsers, ranging from Microsft Edge to Opera, from Firefox to Chrome. This means that any web application that ties into it will be interactable within the vast majority of both browser-based and browser-independent gateways and applications.</p>\n<h4 id=\"Cons\"><a href=\"#Cons\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>WebSockets have one distinct major failing — while it might have support for HTTP-like functionality, <strong>it is not HTTP</strong> whatsoever. This has implications, especially when considering optimizing in HTTP such as caching, proxying, etc., that haven’t quite become apparent.</p>\n<p>Because WebSockets are relatively new, having been only officially standardized in 2011, the industry is still understanding what the side effects mean. Most applications that use WebSockets are designed specifically for everything that a WebSocket is — what has yet to be seen, however, is whether or not this solution is better in the long-run than any stateless solution currently available.</p>\n<p>There is of course the fact that, as with other architectures on this list, WebSockets create an “always on” connection during the duration of data transfer. While this is fine for many uses such as media streaming and live stream calculations, it also essentially means that, for WebSockets, there is no scalability. Ports have hardcoded limitations and bandwidth, and thus in order to “scale”, you must add additional ports to match the maximum load. In stateless systems, this is less of an issue, as requests can wait and be made in such a way as to be independent on the state of the server itself.</p>\n<h3 id=\"2-WebHooks\"><a href=\"#2-WebHooks\" class=\"headerlink\" title=\"2: WebHooks\"></a>2: WebHooks</h3><p><strong>WebHooks</strong> are a similar concept to the WebSocket. They primarily function using <strong>custom callbacks</strong>, or code that is passed as an argument to another chunk of code and executed at a specified point in time. Essentially, a WebHook is a glorified system of “if this, then do”, allowing for users independent of the event firing to craft a custom response to that event within their own system.</p>\n<p>The term was coined by <a href=\"https://twitter.com/progrium\" target=\"_blank\" rel=\"noopener\">Jeff Lindsay</a> in 2007, and quickly became popular amongst users who wished to create automated responses to exterior behaviors. A great example of this would be a developer pushing a new item to GitHub, which causes an event. A user has a system tied into the URI of a WebHook. When the push is published, the user’s system utilizes the URI of the WebHook to integrate the push into a larger build, thereby creating a compiled component.</p>\n<h4 id=\"Pros-1\"><a href=\"#Pros-1\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>WebHooks function a lot like WebSockets, but they’re different in some key areas. First and foremost, WebSockets are primarily designed for browser-based communications, and while they can be used regardless in any client-server communication, they do not behave well in a <strong>server-to-server</strong> setup.</p>\n<p>WebHooks, on the other hand, work very well in server-to-server systems due to how they operate. Because the system essentially functions as the aforementioned “if this then do”, servers can be configured to tie into pre-formed URIs at any time and execute a given function whenever that event is triggered.</p>\n<p>Additionally, WebHooks have the unique benefit of being <strong>based upon HTTP</strong>, unlike WebSockets. This means that the system can be integrated without utilizing any new infrastructure, allowing speedy adoption and relatively simple setup.</p>\n<h4 id=\"Cons-1\"><a href=\"#Cons-1\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>The problem with WebHooks is that a lot of their functionality can already be placed on the arguably more powerful REST architectural approach. While adopting event-driven architecture is often a requirement of the service being built, it’s a hard sell when it can be mirrored in REST while also giving the wealth of options that REST gives to the user.</p>\n<p>These RESTful solutions such as <a href=\"http://www.restms.org/\" target=\"_blank\" rel=\"noopener\">RestMS</a> are essentially simply message querying services, though, and do require additional infrastructure, which may or may not be doable considering the purpose of the application.</p>\n<p>Additionally, WebHooks can be <strong>resource intensive</strong> to both the client and the server. If the client needs to notify many servers that an event has occurred, and a server needs to listen to a great deal of clients notifying of this change, you can very quickly run into a situation where your network grows uncontrollably. While HTTP does scale quite well, this is a definite negative to consider.</p>\n<p>However, there are also ways to build a <a href=\"https://en.wikipedia.org/wiki/Message_queuing_service\" target=\"_blank\" rel=\"noopener\">message queuing service</a> on top of HTTP—some RESTful examples include <a href=\"https://www.iron.io/platform/ironmq/\" target=\"_blank\" rel=\"noopener\">IronMQ</a> and RestMS.</p>\n<h3 id=\"3-REST-Hooks\"><a href=\"#3-REST-Hooks\" class=\"headerlink\" title=\"3: REST Hooks\"></a>3: REST Hooks</h3><p>Speaking of RESTful examples, <strong>REST Hooks</strong> is essentially “hooking” baked into REST itself. Defined as an initiative from <a href=\"http://resthooks.org/docs/\" target=\"_blank\" rel=\"noopener\">Zapier</a>, this is a subject <a href=\"http://nordicapis.com/stop-polling-and-consider-using-rest-hooks/\" target=\"_blank\" rel=\"noopener\">we’ve covered before</a> — hooks are collated to a single target URL as a subscription, which pings the resource requester when a change is noted.</p>\n<p>This approach is a response to the practice of <strong>polling</strong>, in which a client constantly checks for changes to a resource. Under the REST Hooks paradigm, the client instead waits for a change, and reacts to it. To put it simply, this is a WebHook in REST.</p>\n<h4 id=\"Pros-2\"><a href=\"#Pros-2\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>REST Hooks are obviously super powerful in the correct context — being able to passively receive a resource rather than dedicating processing power to constant polling frees up a lot of the client-side cost.</p>\n<p>Perhaps the strongest argument for REST Hooks though, is the fact that it’s <strong>so easy</strong> and <strong>intuitive</strong> to use. While WebHooks utilize HTTP and thus do not need new architecture to set up, they are also limited by the fact that they are built upon HTTP, and can thus be somewhat complex to set up properly and use effectively.</p>\n<p>REST Hooks, though, are <strong>subscription based</strong>, and as such, are simply usable by subscribing. This makes it a very easy to use solution while providing a lot of the usability and effectiveness of more complex systems.</p>\n<h4 id=\"Cons-2\"><a href=\"#Cons-2\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>Of course, every solution has its negatives, and REST Hooks are no different. It could be viewed that REST Hooks actually fly in the face of what REST is — <a href=\"http://nordicapis.com/defining-stateful-vs-stateless-web-services/\" target=\"_blank\" rel=\"noopener\">session free and stateless</a>. REST Hooks essentially create consistent polling, it’s just moved the polling from one side to another.</p>\n<p>Then, there’s the arguable problem that REST Hooks might be doing something that has already been solved. Some would argue that TCP already does most of what REST Hooks is trying to do, and simply layering more solutions on top of HTTP to get what TCP already does is a poor approach.</p>\n<h3 id=\"4-Pub-Sub\"><a href=\"#4-Pub-Sub\" class=\"headerlink\" title=\"4: Pub-Sub\"></a>4: Pub-Sub</h3><p><strong>Pub-Sub</strong> is a slightly different approach. Referred to by its full name as <strong>publish-subscribe</strong>, the concept is where events are published to a class without knowledge of the client subscribing to the class. Basically, a user will join one or more classes, and then will receive event updates without regard or knowledge to the event publisher.</p>\n<p>The main difference here is one of conscious choice of provider — in the other solutions noted herein, a user consciously communicates with a given server or provider and receives events as pre-determined. Under the Pub-Sub scheme, the user only specifies which class they wish to be part of and what events they are interested in receiving. From there, they receive these events when one is pushed out.</p>\n<p>A way this is often framed in internet discussions is in the frame of a <strong>radio channel</strong>. Record companies, or publishers, issue audio to the station, which then broadcasts this audio to listeners, or subscribers. Pub-sub is the middleman radio station here — listeners don’t know who gave the station the music, nor do the companies know who the listeners are. It is this segmentation that is baked into the pattern.</p>\n<p>When we talk about Pub-Sub, we need to keep in mind that we’re actually talking about two different things. Pub-Sub can mean the methodology and general concept in programming terms, but it can also mean specific provider solutions based upon that methodology. For instance, Google’s <a href=\"https://cloud.google.com/pubsub/docs/overview\" target=\"_blank\" rel=\"noopener\">Cloud Pub/Sub</a> is an implementation of the general methodology within their cloud service, and allows for asynchronous many-to-many pub-sub relationships as stated above.</p>\n<h4 id=\"Pros-3\"><a href=\"#Pros-3\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>A huge benefit of Pub-Sub is the fact that it’s <strong>loosely coupled</strong>, and thus is extremely scalable and flexible. The only thing the event-provider is doing is generating the content — each other step is done through a separated middleman, and so the content is easily scaled and modulated to the architecture and design of the solution.</p>\n<p>Additionally, Pub-Sub lends itself very well to <strong>testing</strong>. A subscriber is narrowly limited to a set of events that they have requested under a class, so if a failure occurs, this natural segmentation informs the provider as to where the fault is, and which class of users is experiencing the fault.</p>\n<h4 id=\"Cons-3\"><a href=\"#Cons-3\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>Unfortunately, decoupling is also a huge disadvantage for this pattern. By being a <strong>middleman</strong>, Pub-Sub cannot effectively notify the provider that a message has been sent, and the listener is separated from the event and thus may not know if a message wasn’t sent that should have been. Harkening back to the radio explanation, a listener will never know if a song was meant to play on a channel or if the channel is out of range, and once the record executives hand off the music, they’ve got no idea if the user received the songs without direct feedback from them.</p>\n<p>Additionally, while the system is extensible and flexible, instability does occur with high traffic load as subclass after subclass might be constructed to handle further segmentation. This of course leads to the aforementioned instability in addition to increased complexity.</p>\n<p>You must keep in mind that while the relationship between the publisher and subscriber in this model may be beneficial, it also comes with its own difficulties when these relationships need to be modulated. While you can certainly work around this, at this point, you’re fighting the very basis of the pattern, rather than any secondary natures — you’re trying to make dehydrated water, and fighting against the nature of a pattern suggests the pattern to be inherently poor.</p>\n<blockquote>\n<p>Also read: <a href=\"http://nordicapis.com/building-a-backend-for-frontend-shim-for-your-microservices/\" target=\"_blank\" rel=\"noopener\">Building a Backend for Frontend (BFF) For Your Microservices</a></p>\n</blockquote>\n<h3 id=\"5-Server-Sent-Events\"><a href=\"#5-Server-Sent-Events\" class=\"headerlink\" title=\"5: Server Sent Events\"></a>5: Server Sent Events</h3><p><strong>Server Sent Events</strong>, or SSE, is a communication protocol much like WebSockets, but with the implication of <strong>unidirectional data</strong>. In this architecture, the server is consistently sending updates to the client as an automatic process. This was standardized under HTML5 by the <a href=\"https://www.w3.org/TR/2009/WD-eventsource-20091029/\" target=\"_blank\" rel=\"noopener\">W3C</a>, and is thus compatible with any solution that is likewise compatible with HTML5.</p>\n<blockquote>\n<p>Of note is that there is a competing standardization from the <a href=\"https://whatwg.org/\" target=\"_blank\" rel=\"noopener\">Web Hypertext Application Technology Working Group</a> – this is a relic from movement away from “HTML5” and into what WHATWG is calling “HTML Living Standard”. The general working consensus is that, WHATWG’s standardization is prioritized in the rare cases of divergent standards. This could become more of an issue as time marches forward, given that WHATWG was created due to a perceived lack of interest from W3C towards evolving HTML, but for the time being, either standard is generally acceptable.<br>While simple in theory, Server Sent Events are anything but simple when considering benefits and drawbacks.</p>\n</blockquote>\n<h4 id=\"Pros-4\"><a href=\"#Pros-4\" class=\"headerlink\" title=\"Pros\"></a>Pros</h4><p>SSE is <strong>not bidirectional</strong> in its communications — the server is issuing the events in a steady, predictable method. This is hugely beneficial to applications which do not need the two-way communications baked into WebSockets or other such solutions, as this means <strong>lower bandwidth</strong>, and an allowance for the connection to be temporary rather than always-on during the duration of data transfer. By its nature, the data is being transferred one way, and thus there is no need to wait for data to be returned.</p>\n<p>Additionally, at least in theory, SSE is easier to set up in complex situations. You only have to worry about data traveling one direction via one system, thus reducing complexity dramatically. There is no need to define a message exchange protocol, no need to specify data duration or wait times, no need to support bilateral messaging — the single direction saves a lot of complexity.</p>\n<h4 id=\"Cons-4\"><a href=\"#Cons-4\" class=\"headerlink\" title=\"Cons\"></a>Cons</h4><p>That simplicity could be where SSE fails for particular use cases. SSE is a very poor solution for situations that require <strong>bidirectional communication</strong>, and while this seems obvious, it would surprise many developers to see how many systems actually depend on bidirectional communication for simple functionality.</p>\n<p>While much of this can be fixed with workarounds, a developer’s goal in choosing an event-driven protocol should be to find one that works out of the box, not to find a solution that might work if configured properly and given secondary systems upon which to depend.</p>\n<p>There is also the issue of <strong>security</strong> and authentication. While two-way systems can easily use authentication methodologies, SSE handles this using <strong>header forwarding</strong>. While headers can be manipulated and overridden in many languages and applications, the EventSource object in JavaScript does not natively support this, which would cause many adoptees some major headaches.</p>\n<p>Finally, there is a concern over loss of efficiency with <strong>over transmitting</strong> data. A two-direction system can determine when a client or server disconnects, but SSE can only determine that a client has disconnected after attempting a full data transmission and receiving a noted failure. Because of this, data can be lost rather quickly, and with many failed connections, this loss can mount dramatically over time.</p>\n<h2 id=\"Conclusion\"><a href=\"#Conclusion\" class=\"headerlink\" title=\"Conclusion\"></a>Conclusion</h2><p>There is no one event-driven solution that works in every use case. While many would argue that event-driven solutions should be REST based, which suggests REST Hooks as the answer, many others would argue that it is entirely situational, and that REST is not always the silver bullet it’s touted to be.</p>\n<p>If you are building for scalability with low overhead in a browser environment, <strong>WebSockets</strong> are a great solution. Conversely, if you’d like those same benefits but are working in a non-browser system, then <strong>WebHooks</strong> should be your approach. <strong>REST Hooks</strong> are not only great for RESTful services, they’re also much easier to set up than either, and thus are great in low-time high-rush situations. <strong>Pub-Sub</strong> can be great if you need to enforce a division between client and server, and this can further be established and controlled in an even stronger way with <strong>Server Sent</strong>.</p>\n<p>Simply put, the best solution will be the one that fits your specific situation and build — any of these solutions, given the correct system, is a great solution. To that end, each solution has a very specific use case.</p>\n<h2 id=\"TLDR-Comparison-Table\"><a href=\"#TLDR-Comparison-Table\" class=\"headerlink\" title=\"TLDR Comparison Table\"></a>TLDR Comparison Table</h2><table>\n<thead>\n<tr>\n<th>PROTOCOL</th>\n<th>RELATED TO</th>\n<th>STANDARD BODY</th>\n<th>NOTES</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>WebSockets</td>\n<td>TCP, HTTP-like</td>\n<td>IETF, W3C</td>\n<td>Two-way communication over TCP<br>Designed for web browsers & web servers<br>Good for lower overhead scenarios<br>Supported in all major browsers</td>\n</tr>\n<tr>\n<td>Webhooks</td>\n<td>URI, HTTP</td>\n<td>-</td>\n<td>User defined “HTTP callbacks”<br>Triggered by an event HTTP<br>Requests are made to Webhook URI<br>Enables real-time event triggering</td>\n</tr>\n<tr>\n<td>REST Hooks</td>\n<td>HTTP</td>\n<td>Zapier</td>\n<td>Lightweight subscription layer<br>Manipulated by a REST API<br>Essentially a WebHook in REST</td>\n</tr>\n<tr>\n<td>Pub-Sub</td>\n<td>-</td>\n<td>-</td>\n<td>Client subscribes to classes<br>Bidirectional<br>Middleman layer between client and server<br>Loose coupling</td>\n</tr>\n<tr>\n<td>Server Sent</td>\n<td>HTTP, HTML5 , DOM</td>\n<td>WHATWG, W3C</td>\n<td>Server constantly sends updates to the client<br>Unidirectional push notifications as DOM events</td>\n</tr>\n</tbody>\n</table>\n"}],"PostAsset":[],"PostCategory":[],"PostTag":[{"post_id":"cjsqa1qk90000jrs697rh4rca","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qku000ejrs6xh31kj3v"},{"post_id":"cjsqa1qk90000jrs697rh4rca","tag_id":"cjsqa1qkl0006jrs6dnmld8ur","_id":"cjsqa1qkv000gjrs68af9pom2"},{"post_id":"cjsqa1qk90000jrs697rh4rca","tag_id":"cjsqa1qkn0009jrs6i13dt7h2","_id":"cjsqa1qkw000jjrs6ofsrkxuk"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qlc000xjrs6axusrrer"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1qkv000hjrs65j4sf7ft","_id":"cjsqa1qlc000yjrs60yfouipa"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1qky000ljrs6vrdluiwn","_id":"cjsqa1qlc0010jrs69ixwguvd"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1ql3000pjrs68dkhll0w","_id":"cjsqa1qlc0011jrs601zz11rn"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1ql8000sjrs67737rn5l","_id":"cjsqa1qld0013jrs6rqfec0tg"},{"post_id":"cjsqa1qke0001jrs62g3pkxfj","tag_id":"cjsqa1qlb000vjrs6gcjpc1t9","_id":"cjsqa1qld0014jrs6x5jmynlm"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qle0019jrs623kyv16i"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qlc000zjrs6fbz5jt0b","_id":"cjsqa1qle001ajrs6c5s2arm3"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qld0012jrs6jlulm2a9","_id":"cjsqa1qle001cjrs6qwkhv9ji"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qle001djrs6gzhct51y"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qld0016jrs6d1vmk6u8","_id":"cjsqa1qle001fjrs6uznwxh5y"},{"post_id":"cjsqa1qkj0003jrs6v6e7m0lp","tag_id":"cjsqa1qld0017jrs6oh3etkqj","_id":"cjsqa1qlf001gjrs6llpvw3o0"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qlg001kjrs634iimt2f"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qld0018jrs6h3phl6oq","_id":"cjsqa1qlg001ljrs6tl80but8"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qle001bjrs6x38c8sz8","_id":"cjsqa1qlg001njrs6rl1vns2k"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qle001ejrs6zflnlgej","_id":"cjsqa1qlg001ojrs6bas7nddv"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qld0016jrs6d1vmk6u8","_id":"cjsqa1qlg001qjrs6833ewe0q"},{"post_id":"cjsqa1qkk0004jrs6aqqwpeu9","tag_id":"cjsqa1qlf001ijrs6wgia62z0","_id":"cjsqa1qlg001rjrs6z426pv3o"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qlj0020jrs6pql31zo0"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlf001jjrs6ncdcotqz","_id":"cjsqa1qlj0021jrs622g2zb2i"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlg001mjrs6uwgv4j26","_id":"cjsqa1qlj0023jrs616852zbi"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlg001pjrs63t3zvmkw","_id":"cjsqa1qlj0024jrs61hom90mw"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlh001sjrs6omdg0omo","_id":"cjsqa1qlk0026jrs6311khv1q"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlh001tjrs69thctpkq","_id":"cjsqa1qlk0027jrs6ezxn8j5s"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlh001ujrs6wccn5s9g","_id":"cjsqa1qlk0029jrs66j86vrz5"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qlh001vjrs6iw3gy0nf","_id":"cjsqa1qlk002ajrs6qm0htglj"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qli001wjrs6mv43zwbl","_id":"cjsqa1qlk002bjrs6kms4hakh"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qli001xjrs6bbfqx11e","_id":"cjsqa1qll002djrs6zli6er37"},{"post_id":"cjsqa1qkk0005jrs63sdwu1kx","tag_id":"cjsqa1qli001yjrs6ftc8ceul","_id":"cjsqa1qll002ejrs623c65nou"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qli001zjrs6v24vull9","_id":"cjsqa1qlm002ijrs6s08s2x1s"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qlj0022jrs61brxb5l6","_id":"cjsqa1qlm002jjrs6lgvgj1kt"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qlj0025jrs6r5t6ia6t","_id":"cjsqa1qln002ljrs6z4479hby"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qlk0028jrs6o7nz5a4y","_id":"cjsqa1qln002mjrs66tazkjgt"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1ql3000pjrs68dkhll0w","_id":"cjsqa1qln002ojrs6tbi4aep9"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qll002fjrs6zrdntv76","_id":"cjsqa1qln002pjrs67vuwkvsy"},{"post_id":"cjsqa1qkm0007jrs64f4k2hpz","tag_id":"cjsqa1qll002gjrs6sydkbvl1","_id":"cjsqa1qln002rjrs6rlw58aj5"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qll002hjrs6mdg83ugm","_id":"cjsqa1qlr002wjrs6wy6mzlax"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qkn0009jrs6i13dt7h2","_id":"cjsqa1qlr002xjrs6smx35iea"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qln002njrs6r3v6aisk","_id":"cjsqa1qlt002zjrs6rzf8ja6t"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qln002qjrs6zfdspgpt","_id":"cjsqa1qlt0030jrs6fvx4ws6a"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qlo002sjrs6z87o754u","_id":"cjsqa1qlt0032jrs660ym9snh"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qlo002tjrs6fe6yx7ow","_id":"cjsqa1qlu0033jrs6ntfzfh0a"},{"post_id":"cjsqa1qkn0008jrs67pwmuobx","tag_id":"cjsqa1qlo002ujrs665hvlmpb","_id":"cjsqa1qlu0035jrs6x3xrmsum"},{"post_id":"cjsqa1qkp000bjrs6ta6bve1y","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qlv0037jrs68eo1fah2"},{"post_id":"cjsqa1qkp000bjrs6ta6bve1y","tag_id":"cjsqa1qlp002vjrs6uq0qj7an","_id":"cjsqa1qlv0038jrs6w3prknr2"},{"post_id":"cjsqa1qkp000bjrs6ta6bve1y","tag_id":"cjsqa1qlr002yjrs6zujcs9cr","_id":"cjsqa1qlw003ajrs6srz6nesx"},{"post_id":"cjsqa1qkp000bjrs6ta6bve1y","tag_id":"cjsqa1qld0017jrs6oh3etkqj","_id":"cjsqa1qlw003bjrs6k58fh6w4"},{"post_id":"cjsqa1qkp000bjrs6ta6bve1y","tag_id":"cjsqa1qlu0034jrs68h14q1mp","_id":"cjsqa1qlx003djrs62w9ukouw"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qm1003jjrs67q7wbde7"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qlu0036jrs66rnb3yjb","_id":"cjsqa1qm1003kjrs6iqwqz4bm"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qld0016jrs6d1vmk6u8","_id":"cjsqa1qm2003mjrs6ileglqxm"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qm2003njrs66kxeibot"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qlx003ejrs6zd36ewoz","_id":"cjsqa1qm2003pjrs6vi5eew01"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qly003fjrs6t7e73vlc","_id":"cjsqa1qm2003qjrs6tjh795xu"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qly003gjrs69xf2322a","_id":"cjsqa1qm3003sjrs60eufb2ms"},{"post_id":"cjsqa1qkx000kjrs6twvxrcgr","tag_id":"cjsqa1qlz003hjrs6tx3ixdko","_id":"cjsqa1qm3003tjrs6ju4kme4h"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qm4003wjrs6ipizr3ak"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qlu0034jrs68h14q1mp","_id":"cjsqa1qm4003xjrs6e6lonc4f"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qm1003ljrs6r5ului6y","_id":"cjsqa1qm4003zjrs6bciue4ew"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qld0016jrs6d1vmk6u8","_id":"cjsqa1qm40040jrs646jzadwt"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qm50042jrs6xqmmjv96"},{"post_id":"cjsqa1ql0000njrs6c4erh5si","tag_id":"cjsqa1qm3003ujrs6i2ngy29f","_id":"cjsqa1qm50043jrs6mrtcls2f"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qma0048jrs6u6xjsyif"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qky000ljrs6vrdluiwn","_id":"cjsqa1qma0049jrs6afoqrsiz"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qm3003vjrs6aiowf0a9","_id":"cjsqa1qmc004bjrs6y0j8f77i"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qm4003yjrs60j86lokg","_id":"cjsqa1qmc004cjrs6n4h55s0s"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qlf001ijrs6wgia62z0","_id":"cjsqa1qmd004ejrs6eo1emcsd"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qmd004fjrs6e81ay2u7"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qm60045jrs6nzffcimf","_id":"cjsqa1qmd004hjrs6pt0nzp7r"},{"post_id":"cjsqa1ql2000ojrs63mrpw29w","tag_id":"cjsqa1qm90046jrs6vsyowh4x","_id":"cjsqa1qmd004ijrs6ja4884iv"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qme004kjrs6ymk3leyf"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1qkv000hjrs65j4sf7ft","_id":"cjsqa1qme004ljrs6ntco6xe6"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1qky000ljrs6vrdluiwn","_id":"cjsqa1qme004njrs6o8c06411"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1ql3000pjrs68dkhll0w","_id":"cjsqa1qmf004ojrs61qsiuvsw"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1ql8000sjrs67737rn5l","_id":"cjsqa1qmf004qjrs66plz490s"},{"post_id":"cjsqa1ql4000qjrs6nn6nyjwj","tag_id":"cjsqa1qlb000vjrs6gcjpc1t9","_id":"cjsqa1qmg004rjrs6y5hlgj0v"},{"post_id":"cjsqa1ql7000rjrs6ovtjv5r6","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qmg004tjrs6rwphezgl"},{"post_id":"cjsqa1ql7000rjrs6ovtjv5r6","tag_id":"cjsqa1qmc004djrs6bzme6u4i","_id":"cjsqa1qmg004ujrs6vjnkrzg6"},{"post_id":"cjsqa1ql7000rjrs6ovtjv5r6","tag_id":"cjsqa1qm3003vjrs6aiowf0a9","_id":"cjsqa1qmh004wjrs6eukflzb7"},{"post_id":"cjsqa1ql7000rjrs6ovtjv5r6","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qmh004xjrs6s9in5e8k"},{"post_id":"cjsqa1ql7000rjrs6ovtjv5r6","tag_id":"cjsqa1qme004mjrs6zxcluf2t","_id":"cjsqa1qmh004zjrs63iu3zlsa"},{"post_id":"cjsqa1ql8000tjrs6lr0cx3u3","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qmi0051jrs634ivlxlg"},{"post_id":"cjsqa1ql8000tjrs6lr0cx3u3","tag_id":"cjsqa1qmc004djrs6bzme6u4i","_id":"cjsqa1qmi0052jrs6qb8u2oc7"},{"post_id":"cjsqa1ql8000tjrs6lr0cx3u3","tag_id":"cjsqa1qm3003vjrs6aiowf0a9","_id":"cjsqa1qmj0054jrs6mnuuviak"},{"post_id":"cjsqa1ql8000tjrs6lr0cx3u3","tag_id":"cjsqa1qld0015jrs60vgddzvp","_id":"cjsqa1qmj0055jrs61rw8i6gt"},{"post_id":"cjsqa1ql8000tjrs6lr0cx3u3","tag_id":"cjsqa1qmh004yjrs61no78xkw","_id":"cjsqa1qmj0057jrs6xcklhkn1"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qkh0002jrs6a1k82mb6","_id":"cjsqa1qml005ajrs6ph8608pz"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qmi0050jrs6kpymt291","_id":"cjsqa1qml005bjrs645k3xly4"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qmi0053jrs6bh5f3mvj","_id":"cjsqa1qml005cjrs68aql0sll"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qly003fjrs6t7e73vlc","_id":"cjsqa1qml005djrs6o18ylldn"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qmk0058jrs60seq5a87","_id":"cjsqa1qml005ejrs6cjg5tz2q"},{"post_id":"cjsqa1ql9000ujrs6g5pi0rwr","tag_id":"cjsqa1qmk0059jrs62xno2ooa","_id":"cjsqa1qml005fjrs6h5b2ejur"},{"post_id":"cjsqa1qmx005hjrs6mqnbk8t0","tag_id":"cjsqa1qmy005ijrs6ndwspjcd","_id":"cjsqa1qmz005jjrs6tofidw0e"},{"post_id":"cjsqa1qmx005hjrs6mqnbk8t0","tag_id":"cjsqa1qkl0006jrs6dnmld8ur","_id":"cjsqa1qmz005kjrs6191ngo2w"},{"post_id":"cjsqa1qmx005hjrs6mqnbk8t0","tag_id":"cjsqa1qkn0009jrs6i13dt7h2","_id":"cjsqa1qmz005ljrs6c0rml3nv"}],"Tag":[{"name":"weekly","_id":"cjsqa1qkh0002jrs6a1k82mb6"},{"name":"全栈","_id":"cjsqa1qkl0006jrs6dnmld8ur"},{"name":"Node","_id":"cjsqa1qkn0009jrs6i13dt7h2"},{"name":"工程化实践","_id":"cjsqa1qkv000hjrs65j4sf7ft"},{"name":"Vuex","_id":"cjsqa1qky000ljrs6vrdluiwn"},{"name":"Webpack","_id":"cjsqa1ql3000pjrs68dkhll0w"},{"name":"PWA","_id":"cjsqa1ql8000sjrs67737rn5l"},{"name":"持续部署","_id":"cjsqa1qlb000vjrs6gcjpc1t9"},{"name":"开发工具","_id":"cjsqa1qlc000zjrs6fbz5jt0b"},{"name":"测试工具","_id":"cjsqa1qld0012jrs6jlulm2a9"},{"name":"Vue","_id":"cjsqa1qld0015jrs60vgddzvp"},{"name":"ES6","_id":"cjsqa1qld0016jrs6d1vmk6u8"},{"name":"设计模式","_id":"cjsqa1qld0017jrs6oh3etkqj"},{"name":"webpack","_id":"cjsqa1qld0018jrs6h3phl6oq"},{"name":"koa","_id":"cjsqa1qle001bjrs6x38c8sz8"},{"name":"web安全","_id":"cjsqa1qle001ejrs6zflnlgej"},{"name":"http","_id":"cjsqa1qlf001ijrs6wgia62z0"},{"name":"Trackingjs","_id":"cjsqa1qlf001jjrs6ncdcotqz"},{"name":"flex","_id":"cjsqa1qlg001mjrs6uwgv4j26"},{"name":"postman","_id":"cjsqa1qlg001pjrs63t3zvmkw"},{"name":"神经网络","_id":"cjsqa1qlh001sjrs6omdg0omo"},{"name":"DOM","_id":"cjsqa1qlh001tjrs69thctpkq"},{"name":"Nodejs","_id":"cjsqa1qlh001ujrs6wccn5s9g"},{"name":"Web Worker","_id":"cjsqa1qlh001vjrs6iw3gy0nf"},{"name":"GitHub插件","_id":"cjsqa1qli001wjrs6mv43zwbl"},{"name":"人脸识别","_id":"cjsqa1qli001xjrs6bbfqx11e"},{"name":"流体排版","_id":"cjsqa1qli001yjrs6ftc8ceul"},{"name":"内存管理","_id":"cjsqa1qli001zjrs6v24vull9"},{"name":"散点图","_id":"cjsqa1qlj0022jrs61brxb5l6"},{"name":"正则","_id":"cjsqa1qlj0025jrs6r5t6ia6t"},{"name":"AR","_id":"cjsqa1qlk0028jrs6o7nz5a4y"},{"name":"IOT","_id":"cjsqa1qll002fjrs6zrdntv76"},{"name":"虚拟DOM","_id":"cjsqa1qll002gjrs6sydkbvl1"},{"name":"动画","_id":"cjsqa1qll002hjrs6mdg83ugm"},{"name":"Babels","_id":"cjsqa1qln002njrs6r3v6aisk"},{"name":"渲染性能","_id":"cjsqa1qln002qjrs6zfdspgpt"},{"name":"this关键字","_id":"cjsqa1qlo002sjrs6z87o754u"},{"name":"http/2升级","_id":"cjsqa1qlo002tjrs6fe6yx7ow"},{"name":"CSS黑魔法","_id":"cjsqa1qlo002ujrs665hvlmpb"},{"name":"框架","_id":"cjsqa1qlp002vjrs6uq0qj7an"},{"name":"测试","_id":"cjsqa1qlr002yjrs6zujcs9cr"},{"name":"three.js","_id":"cjsqa1qlu0034jrs68h14q1mp"},{"name":"Echarts","_id":"cjsqa1qlu0036jrs66rnb3yjb"},{"name":"SVG","_id":"cjsqa1qlx003ejrs6zd36ewoz"},{"name":"算法","_id":"cjsqa1qly003fjrs6t7e73vlc"},{"name":"模块化","_id":"cjsqa1qly003gjrs69xf2322a"},{"name":"性能优化","_id":"cjsqa1qlz003hjrs6tx3ixdko"},{"name":"Zepto","_id":"cjsqa1qm1003ljrs6r5ului6y"},{"name":"事件驱动","_id":"cjsqa1qm3003ujrs6i2ngy29f"},{"name":"node","_id":"cjsqa1qm3003vjrs6aiowf0a9"},{"name":"WebSocket","_id":"cjsqa1qm4003yjrs60j86lokg"},{"name":"iView","_id":"cjsqa1qm60045jrs6nzffcimf"},{"name":"Git","_id":"cjsqa1qm90046jrs6vsyowh4x"},{"name":"模块","_id":"cjsqa1qmc004djrs6bzme6u4i"},{"name":"API设计,单元测试","_id":"cjsqa1qme004mjrs6zxcluf2t"},{"name":"函数式","_id":"cjsqa1qmh004yjrs61no78xkw"},{"name":"es6","_id":"cjsqa1qmi0050jrs6kpymt291"},{"name":"vue","_id":"cjsqa1qmi0053jrs6bh5f3mvj"},{"name":"工具","_id":"cjsqa1qmk0058jrs60seq5a87"},{"name":"必备技能","_id":"cjsqa1qmk0059jrs62xno2ooa"},{"name":"Event-Driven","_id":"cjsqa1qmy005ijrs6ndwspjcd"}]}}