[
  {
    "path": ".gitignore",
    "content": "node_modules\n.vscode\ndist\n.idea\ntest"
  },
  {
    "path": "README.md",
    "content": "# 前端思维宫殿3.0\n\n> 关于前端工程项目管理的经验分享\n\n- [x] [代码格式的选择，ESM可以使用了么？](https://www.yuque.com/bayes-otxkg/ua5839/ha7r1r)\n\n- [ ] [如何管理项目中的CSS？](https://github.com/coconilu/Blog/issues/174)\n\n- [ ] [如何管理项目中的TypeScript？](https://github.com/coconilu/Blog/issues/175)\n\n## 归档\n[前端思维宫殿1.0](https://github.com/coconilu/Blog/issues/171)\n\n[前端思维宫殿2.0](https://github.com/coconilu/Blog/issues/173)\n\n# 勘误与改进\n\n如果博客对您有所帮助或启发，期待您的star，同时对作者也是一种鼓励。\n\n# License\n\n所有文章采用[知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/)进行许可。\n"
  },
  {
    "path": "README.old.md",
    "content": "# Bayes 的博客\n\n每个人都应该有自己的思维宫殿，它有利于我们面对复杂系统的时候，可以游刃有余地去理解它们。\n这些年来我收集了很多文章、博客，但我也是最近才想要仔细去把它们整理并串联起来，希望能组成一个有层次感的知识宫殿。\n\n<!--\n<p align=\"right\">—— 致敬《断舍离》</p>\n-->\n\n## :books: 思维宫殿\n\n### [从“浏览器输入URL后”说起](https://github.com/coconilu/Blog/issues/120)\n\n### 关于网络和安全\n1. - [x] [网络模型](https://github.com/coconilu/Blog/issues/97)\n2. - [ ] [数据链路层](https://github.com/coconilu/Blog/issues/140)\n3. - [ ] [IP 协议](https://github.com/coconilu/Blog/issues/139)\n4. - [ ] [TCP 协议](https://github.com/coconilu/Blog/issues/138)\n5. - [x] [HTTP 协议](https://github.com/coconilu/Blog/issues/135)\n6. - [x] [HTTPS 协议](https://github.com/coconilu/Blog/issues/137)\n7. - [x] [HTTP2 协议](https://github.com/coconilu/Blog/issues/134)\n6. - [ ] [网络模型中的其它协议（持续更新）](https://github.com/coconilu/Blog/issues/141)\n8. - [x] [认证用户身份](https://github.com/coconilu/Blog/issues/136)\n9. - [x] [Web 安全专题](https://github.com/coconilu/Blog/issues/38)\n10. - [x] [OAUTH 2.0](https://github.com/coconilu/Blog/issues/58)\n11. - [x] [JSON Web Token](https://github.com/coconilu/Blog/issues/110)\n\n### 关于专业基本功\n\n#### 计算机组成\n\n#### 操作系统\n\n#### 数据库\n\n#### 数据结构与算法\n\n##### 1. JavaScript实现的排序算法\n1. - [x] [校验排序算法的算法](https://gist.github.com/coconilu/f4d7c22f8056eecf7b4376f688389073)\n2. - [x] [冒泡排序](https://gist.github.com/coconilu/e2bb8340729dfc3fa89a2e00fd76ffb9)\n3. - [x] [插入排序](https://gist.github.com/coconilu/328a84764b15ec359d143fbd1a614a51)\n4. - [x] [选择排序](https://gist.github.com/coconilu/cdd13940a6bd8f28c4bd6ab0d226b8dd)\n5. - [x] [希尔排序](https://gist.github.com/coconilu/8cc56b37479070c6b6edacfd2eea995a)\n6. - [x] [递归排序](https://gist.github.com/coconilu/0bc68ea5099292bbc1aca7d48e0d5e40)\n7. - [x] [快速排序](https://gist.github.com/coconilu/8e814ac4238ac2fe3a6bf5113a685237)\n\n##### 2. 其他有意思的算法\n1. - [ ] 数组洗牌效果\n\n### 关于“浏览器运行原理”的系列博客\n\n1. [浏览器运行原理概述](https://github.com/coconilu/Blog/issues/47)\n2. [资源加载和页面渲染](https://github.com/coconilu/Blog/issues/48)\n3. [浏览器缓存机制](https://github.com/coconilu/Blog/issues/113)\n4. [同源策略与跨域请求](https://github.com/coconilu/Blog/issues/59)\n5. [JavaScript 引擎](https://github.com/coconilu/Blog/issues/45)\n   - [V8 引擎](https://github.com/coconilu/Blog/issues/49)\n6. [异步编程与事件循环](https://github.com/coconilu/Blog/issues/7)\n\n### 关于 “进阶的JavaScript”系列博客\n\n- - [x] [类相关](https://github.com/coconilu/Blog/issues/9)\n- - [x] [JS 常用对象和全局对象的常用方法](https://github.com/coconilu/Blog/issues/70)\n- - [x] [JS 常用操作符](https://github.com/coconilu/Blog/issues/72)\n- - [x] [JS 常用数据结构](https://github.com/coconilu/Blog/issues/71)\n- - [x] [JS 可迭代对象、迭代器、生成器](https://github.com/coconilu/Blog/issues/73)\n- - [x] [防抖和节流](https://github.com/coconilu/Blog/issues/64)\n- - [x] [ES6 要点](https://github.com/coconilu/Blog/issues/60)\n- - [x] [JS 函数式编程](https://github.com/coconilu/Blog/issues/62)\n- - [x] [JS 元编程](https://github.com/coconilu/Blog/issues/68)\n- - [x] [JS 设计模式](https://github.com/coconilu/Blog/issues/69)\n- - [x] [用代码讲述Promise原理——每个人都应该有自己的Promise](https://github.com/coconilu/myPromise)\n- - [X] [深究Function.prototype.bind](https://github.com/coconilu/Blog/issues/12)\n- - [x] [JS 编程技巧（持续更新）](https://github.com/coconilu/Blog/issues/46)\n\n### 关于 “前沿的JavaScript”系列博客\n\n- - [x] [虚拟DOM与diff算法](https://github.com/coconilu/Blog/issues/65)\n- - [x] [Snabbdom 官方文档翻译](https://github.com/coconilu/Blog/issues/152)\n- - [ ] [抽象语法树](https://github.com/coconilu/Blog/issues/145)\n- - [ ] [JS 切面编程](https://github.com/coconilu/Blog/issues/148)\n\n### 关于 “Web编程模型” 的系列博客\n\n- [x] [Web编程模型概述](https://github.com/coconilu/Blog/issues/23)\n\n#### 1. HTML模块\n\n1. - [x] [HTML概述](https://github.com/coconilu/Blog/issues/34)\n2. - [x] [HTML标签及属性](https://github.com/coconilu/Blog/issues/20)\n\n#### 2. CSS 模块\n\n1. - [x] [CSS 概述](https://github.com/coconilu/Blog/issues/28)\n2. - [x] [CSS 基础](https://github.com/coconilu/Blog/issues/26)\n3. - [x] [CSS 收集解析模型](https://github.com/coconilu/Blog/issues/18)\n4. - [x] [CSS 盒模型](https://github.com/coconilu/Blog/issues/25)\n5. - [x] [CSS 布局相关](https://github.com/coconilu/Blog/issues/17)\n6. - [x] [CSS 行内元素排版原理](https://github.com/coconilu/Blog/issues/61)\n6. - [x] [CSS 样式检索](https://github.com/coconilu/Blog/issues/27)\n7. - [x] [CSS 进阶内容（持续更新）](https://github.com/coconilu/Blog/issues/29)\n7. - [x] [CSS 工程化](https://github.com/coconilu/Blog/issues/144)\n\n#### 3. WebAPI 模块\n\n1. - [X] [WebAPI 概述](https://github.com/coconilu/Blog/issues/35)\n2. - [X] [DOM 模型](https://github.com/coconilu/Blog/issues/21)\n3. - [x] [DOM的事件模型](https://github.com/coconilu/Blog/issues/22)\n4. - [x] [Web API参考](https://github.com/coconilu/Blog/issues/24)\n5. - [x] [WebAPI 字节处理能力](https://github.com/coconilu/Blog/issues/154)\n\n#### 4. 综合模块\n\n1. - [X] [Web交互的关键：提交表单](https://github.com/coconilu/Blog/issues/30)\n2. - [x] [上传文件](https://github.com/coconilu/Blog/issues/109)\n2. - [x] [position: sticky的polyfill](https://github.com/coconilu/Blog/issues/31)\n3. - [x] [实现缓慢回到顶部](https://github.com/coconilu/Blog/issues/44)\n4. - [x] [网页关键数据与坐标](https://github.com/coconilu/Blog/issues/63)\n5. - [x] [响应式布局](https://github.com/coconilu/Blog/issues/74)\n6. - [x] [FLIP 动画](https://github.com/coconilu/Blog/issues/105)\n7. - [x] [动画队列](https://github.com/coconilu/Blog/issues/106)\n8. - [x] [页面生命周期](https://github.com/coconilu/Blog/issues/121)\n9. - [x] [前端开发需要注意的一些细节（持续更新）](https://github.com/coconilu/Blog/issues/98)\n\n#### 5. 优化指南\n\n1. 网络方面\n2. 浏览器方面\n3. 服务器方面\n\n### 前端业务场景\n\n1. - [x] [懒加载图片](https://github.com/coconilu/my-lazyload-picture)\n2. - [x] [预加载图片](https://github.com/coconilu/Blog/issues/85)\n3. - [x] [弹幕效果](https://github.com/coconilu/Blog/issues/86)\n4. - [x] [翻牌效果](https://github.com/coconilu/Blog/issues/107)\n5. - [x] [拖拽专题](https://github.com/coconilu/Blog/issues/108)\n6. - [x] [雪碧图](https://github.com/coconilu/Blog/issues/114)\n7. - [x] [Canvas 经典案例（持续更新）](https://github.com/coconilu/Blog/issues/37)\n8. 借助history api优化浏览器前进后退\n9. - [ ] [JS生成图片方案](https://github.com/coconilu/Blog/issues/146)\n\n### 关于VueJS\n1. - [x] [VueJS 运行过程](https://github.com/coconilu/Blog/issues/19)\n2. - [x] [VueJS 响应式原理及简单实现](https://github.com/coconilu/Blog/issues/75)\n3. - [x] [VueJS 的编译阶段到挂载节点](https://github.com/coconilu/Blog/issues/92)\n4. - [x] [VueJS 的模板引擎](https://github.com/coconilu/Blog/issues/91)\n5. - [x] [VueJS 的VNode](https://github.com/coconilu/Blog/issues/94)\n6. - [x] [VueJs 的组件化](https://github.com/coconilu/Blog/issues/93)\n6. - [x] [VueJS 的调试](https://github.com/coconilu/Blog/issues/96)\n7. - [x] [VueJS API](https://github.com/coconilu/Blog/issues/67)\n8. - [x] [VueJS 全家桶](https://github.com/coconilu/Blog/issues/111)\n\n### 关于React\n1. - [x] [React 运行过程](https://github.com/coconilu/Blog/issues/99)\n2. - [x] [React 进阶](https://github.com/coconilu/Blog/issues/100)\n3. - [ ] [React 原理部分](https://github.com/coconilu/Blog/issues/112)\n\n### 关于NodeJS\n1. - [x] [NodeJS 运行原理](https://github.com/coconilu/Blog/issues/43)\n2. - [x] [NodeJS 编程模型](https://github.com/coconilu/Blog/issues/41)\n3. - [x] [基础模块](https://github.com/coconilu/Blog/issues/42)\n4. - [x] [网络模块](https://github.com/coconilu/Blog/issues/50)\n5. - [x] [系统模块](https://github.com/coconilu/Blog/issues/51)\n6. - [x] [工具模块](https://github.com/coconilu/Blog/issues/53)\n7. - [x] [Express源码解析](https://github.com/coconilu/Blog/issues/82)\n8. - [x] [Koa源码解析](https://github.com/coconilu/Blog/issues/81)\n9. - [x] [Express和Koa的对比](https://github.com/coconilu/Blog/issues/83)\n10. - [ ] [NodeJS 集群](https://github.com/coconilu/Blog/issues/117)\n11. - [ ] [Node 与视频流媒体](https://github.com/coconilu/Blog/issues/149)\n12. - [ ] [pm2 使用手册](https://github.com/coconilu/Blog/issues/151)\n\n### 关于包管理器\n\n1. - [x] [NPM 指令大全](https://github.com/coconilu/Blog/issues/78)\n1. - [x] [配置 NPM](https://github.com/coconilu/Blog/issues/143)\n2. - [x] [NPM 上传自己的项目](https://github.com/coconilu/Blog/issues/79)\n3. - [x] [NPM与工作流](https://github.com/coconilu/Blog/issues/77)\n4. - [x] [NPM技巧收集（持续更新）](https://github.com/coconilu/Blog/issues/88)\n5. - [x] [Yarn 使用手册](https://github.com/coconilu/Blog/issues/142)\n\n### 关于GraphQL\n\n- [x] [GraphQL 速记手册](https://github.com/coconilu/Blog/issues/104)\n\n### 关于JS第三方工具库\n\n- [x] [axios 核心源码解读](https://github.com/coconilu/Blog/issues/116)\n- [ ] lodash\n\n## :video_game: 工具\n\n### 1. 设计工具\n\n#### Ant Design\n\n#### Fusion Design\n\n#### NG-ZORRO\n\n### 2. 版本管理工具\n\n#### Git\n\n- [x] [git模型](https://github.com/coconilu/Blog/issues/54)\n- [x] [git常用API](https://github.com/coconilu/Blog/issues/55)\n- [ ] [git 场景](https://github.com/coconilu/Blog/issues/157)\n- [x] [GitHub Flow](https://github.com/coconilu/Blog/issues/56)\n\n### 3. 构建工具\n\n#### Webpack\n\n- [x] [WebPack模型](https://github.com/coconilu/Blog/issues/87)\n- [x] [Webpack 进阶功能](https://github.com/coconilu/Blog/issues/123)\n- [x] [webpack-dev-server 原理探讨](https://github.com/coconilu/Blog/issues/115)\n- [x] [Webpack相关课题（持续更新）](https://github.com/coconilu/Blog/issues/122)\n- [x] [常用Loaders和Plugins（持续更新）](https://github.com/coconilu/Blog/issues/89)\n- [x] [Webpack 与内存](https://github.com/coconilu/Blog/issues/147)\n- [ ] webpack 与定制化编译过程\n\n#### Babel\n\n- [x] [Babel 运行过程](https://github.com/coconilu/Blog/issues/102)\n- [x] [Babel API](https://github.com/coconilu/Blog/issues/156)\n\n#### Travis CI\n\n- [ ] [Travis CI 使用手册](https://github.com/coconilu/Blog/issues/118)\n\n#### 其它\n\n- [x] [source-map实践](https://github.com/coconilu/Blog/issues/160)\n\n### 4. 开发测试工具\n\n#### VScode\n\n- [x] [vscode 设置默认终端为bash](https://github.com/coconilu/Blog/issues/80)\n- [x] [vscode 开发插件](https://github.com/coconilu/Blog/issues/90)\n\n#### Jest\n\n- [x] [Jest 速记手册](https://github.com/coconilu/Blog/issues/103)\n\n#### TypeScript\n\n- [x] [TypeScript 速记手册](https://github.com/coconilu/Blog/issues/101)\n\n#### Google开发者工具\n\n- [x] [Google 开发者工具使用指南](https://github.com/coconilu/Blog/issues/119)\n- [x] [Devtools 设备模式](https://github.com/coconilu/Blog/issues/124)\n- [x] [Devtools 元素模板](https://github.com/coconilu/Blog/issues/125)\n- [x] [Devtools 控制台面板](https://github.com/coconilu/Blog/issues/126)\n- [x] [Devtools 源代码面板](https://github.com/coconilu/Blog/issues/127)\n- [x] [Devtools 网络面板](https://github.com/coconilu/Blog/issues/128)\n- [x] [Devtools 性能面板](https://github.com/coconilu/Blog/issues/129)\n- [ ] [Devtools 内存面板](https://github.com/coconilu/Blog/issues/130)\n- [ ] [Devtools 应用面板](https://github.com/coconilu/Blog/issues/131)\n- [ ] [Devtools 安全面板](https://github.com/coconilu/Blog/issues/132)\n\n#### 抓包工具\n\n- [ ] [wireshark 使用手册](https://github.com/coconilu/Blog/issues/133)\n- [ ] [Fiddler 使用手册](https://github.com/coconilu/Blog/issues/150)\n\n#### 代理工具\n\n- [ ] SwitchyOmega 使用手册\n\n### 5. 服务器相关\n\n#### Nginx\n\n- [x] [前端与Nginx](https://github.com/coconilu/Blog/issues/76)\n- [x] [Protocol Buffers原理解析](https://github.com/coconilu/Blog/issues/159)\n- [ ] [Nginx 配置小结](https://github.com/coconilu/Blog/issues/153)\n\n<!--\n## 关于 JavaScript 的系列读书笔记\n1. - [ ] 《JavaScript 语言精粹》\n2. - [ ] 《高性能 JavaScript》\n3. - [ ] 《数据结构与算法 JavaScript描述》\n4. - [ ] 《JavaScript 设计模式》\n5. - [ ] 《JavaScript 框架设计》\n6. - [ ] 《前端工程化：体系设计与实践》\n7. - [ ] 《深入浅出 Webpack》\n-->\n\n## :trophy: 开源贡献\n\n### 社区活动\n\n#### 翻译活动\n\n1. [参与MDN翻译](https://developer.mozilla.org/en-US/profiles/sunline.bucket)\n2. [掘金翻译计划](https://github.com/coconilu/Blog/issues/36)\n\n#### [NPM 开源共享库](https://www.npmjs.com/~coconilu)\n\n1. [@coconilu/mypromise](https://www.npmjs.com/package/@coconilu/mypromise)\n2. [my-lazyload-picture](https://www.npmjs.com/package/my-lazyload-picture)\n3. [my-flip-animation](https://www.npmjs.com/package/my-flip-animation)\n4. [sticky-polyfill](https://www.npmjs.com/package/sticky-polyfill)\n\n### 开源项目\n\n1. [管理GitHub的stars](https://github.com/coconilu/iGitStar)\n\n# 勘误与改进\n\n如果博客对您有所帮助或启发，期待您的star，同时对作者也是一种鼓励。\n\n# License\n\n所有文章采用[知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/)进行许可。\n"
  },
  {
    "path": "code/classLike.js",
    "content": "let person = {\n    name: 'Bar'\n}\n\nlet handler = {\n    get: function (target, name) {\n        if (name === 'getName') {\n            return () => target['name']\n        }\n    }\n}\n\nlet p = new Proxy(person, handler)\n\nconsole.log(p.getName())\n\n// 验证extend的原理\nclass Father {\n    constructor() {\n        this.fatherSelf = function () { }\n    }\n\n    fatherPrototype() { }\n}\n\nclass Child extends Father {\n    constructor() {\n        super()\n        this.childSelf = function () { }\n    }\n\n    childPrototype() { }\n}\n\nvar c = new Child()"
  },
  {
    "path": "code/event-loop.js",
    "content": "// 验证事件循环机制\n// setTimeout(() => {\n//     console.log('timeout 1')\n//     Promise.resolve().then(() => {\n//         console.log('Promise 3')\n//     })\n//     setTimeout(() => {\n//         console.log('timeout 3')\n//     })\n//     setImmediate(() => {\n//         console.log('immediate 3')\n//     })\n// })\n\n// setImmediate(() => {\n//     console.log('immediate 1')\n// })\n\n// Promise.resolve().then(() => {\n//     console.log('Promise 1')\n//     Promise.resolve().then(() => {\n//         console.log('Promise 2')\n//     })\n//     setTimeout(() => {\n//         console.log('timeout 2')\n//     })\n//     setTimeout(() => {\n//         console.log('timeout 4')\n//     })\n//     setTimeout(() => {\n//         console.log('timeout 5')\n//     })\n//     setImmediate(() => {\n//         console.log('immediate 2')\n//         setTimeout(() => {\n//             console.log('timeout 6')\n//         })\n//     })\n// })\n\n// 更新UI机制\n// var testTitle = document.getElementById('testTitle')\n\n// setTimeout(()=>{\n//     testTitle.textContent = 'wangyaohui'\n//     var t = +new Date();\n//     while(+new Date() - t < 3000) ;\n// })\n\n// 验证任务队列的执行逻辑\n// process.nextTick(()=>{\n//     console.log('process 1')\n// })\n\n// setTimeout(()=>{\n//     console.log('setTimeout 1')\n//     process.nextTick(()=>{\n//         console.log('process 2')\n//         setTimeout(()=>{\n//             console.log('setTimeout 4')\n//         })\n//     })\n// })\n\n// setTimeout(()=>{\n//     console.log('setTimeout 2')\n//     process.nextTick(()=>{\n//         console.log('process 4')\n//         setTimeout(()=>{\n//             console.log('setTimeout 5')\n//         })\n//     })\n// })\n\n// setTimeout(()=>{\n//     console.log('setTimeout 3')\n// })\n\n// process.nextTick(()=>{\n//     console.log('process 3')\n// })\n\n\n// 验证任务阻塞setTimeout执行的情况\n// 结果相差\n// var d1, d2, d3, d4\n// console.log(d1 = new Date())\n// setTimeout(() => {\n//     console.log(d2 = new Date())\n//     var d;\n//     setTimeout(() => {\n//         console.log(d3 = new Date())\n//     }, 1000)\n//     d = +new Date();\n//     while (+new Date() - d < 3000);// 延迟3秒\n//     console.log(d4 = new Date())\n// }, 1000)\n\n// 验证setInterval的覆盖情况，nodejs\n// console.log(new Date())\n// setTimeout(() => {\n//     var d, num = 0;\n//     setInterval(() => {\n//         var dd;\n//         console.log(new Date())\n//         console.log(num)\n//         ++num\n//         dd = +new Date();\n//         while (+new Date() - dd < 2000);// 延迟3秒\n//     }, 1000)\n//     d = +new Date();\n//     while (+new Date() - d < 3000);// 延迟3秒\n// })\n\n// 验证setInterval的覆盖情况，浏览器环境\n(function inter(num) {\n    setInterval(() => {\n        var t = +new Date();\n        ++num;\n        console.log(num, new Date());\n        while (+new Date() - t < 1000); // 阻塞两秒\n    }, 2000)\n})(0)\n\n\n\n// 异步编程，优先级测试\n// setImmediate(function(){\n//     console.log(1);\n// },0);\n// setTimeout(function(){\n//     console.log(2);\n// },0);\n// new Promise(function(resolve){\n//     console.log(3);\n//     resolve();\n//     console.log(4);\n// }).then(function(){\n//     console.log(5);\n// });\n// console.log(6);\n// process.nextTick(function(){\n//     console.log(7);\n// });\n// console.log(8);\n\n// 疑惑中\n// console.log('script start');\n\n// setTimeout(function() {\n//     console.log('setTimeout');\n// }, 0);\n\n// Promise.resolve().then(function(resolve) {\n//     console.log('promise1');\n//     setTimeout(function() {\n//         console.log('setTimeout in microtask');\n//     }, 0);\n// }).then(function() {\n//     console.log('promise2');\n// });\n\n// console.log('script end');\n\n// 疑惑中\n\n// setTimeout(() => {\n//     console.log('timeout');\n// });\n// setImmediate(() => {\n//     console.log('immediate');\n// });\n\n// const fs = require('fs');\n// fs.readFile(__filename, () => {\n//     setTimeout(() => {\n//         console.log('timeout');\n//     });\n//     setImmediate(() => {\n//         console.log('immediate');\n//     });\n// });\n\n"
  },
  {
    "path": "code/main.js",
    "content": "// hosting，提升\n// console.log(a)\n// var a = 1\n// function a () {}\n// console.log(a)\n\n// 类数组\n// var ao = {1:'a', 2:'b', length:3}\n// var ar = Array.prototype.slice.apply(ao)\n// var arr = Array.from(ao)\n// console.log(ar)\n// console.log(arr)\n\n\n\n\n// 验证提升\n// (function (a, b) {\n//     console.log(a, b)\n//     var a;\n//     function b() {};\n//     a = 1;\n//     console.log(a, b)\n// })(3, 4)\n\n// (() => {\n//     // 验证任务队列有没有插队的行为\n//     // 先让主线程生成两个setTimeout和两个process.nextTick\n//     setTimeout(() => {\n//         console.log('timeout 1')\n//         process.nextTick(() => {\n//             console.log('process 3')\n//         })\n//         setTimeout(() => {\n//             console.log('timeout 3')\n//         })\n//     });\n//     setTimeout(() => {\n//         console.log('timeout 2')\n//     });\n//     process.nextTick(() => {\n//         console.log('process 1')\n//         process.nextTick(() => {\n//             console.log('process 4')\n//         })\n//         setTimeout(() => {\n//             console.log('timeout 4')\n//         })\n//     });\n//     process.nextTick(() => {\n//         console.log('process 2')\n//     });\n// })()\n\n\n\n// 验证箭头函数的this指向，在浏览器环境下测试通过\n// var x = 'windows';\n// function fun1() {\n//     var fun2 = () => {\n//         console.log(this.x)\n//     }\n//     fun2()\n// }\n// fun1();\n\n// var obj = {\n//     x: 'obj',\n//     showX: fun1\n// }\n// obj.showX()\n\n// function constructorDemo(x){\n//     this.x = x\n//     this.showX = () => {\n//         console.log(this.x)\n//     }\n// }\n// new constructorDemo('new').showX()\n\n\n// 验证bind\n// function list() {\n//     console.log(this)\n//     return Array.prototype.slice.call(arguments);\n// }\n\n// var f1 = list.bind(undefined,37);\n// var f2 = f1.bind(undefined, 1, 2, 3);\n\n// console.log(f1(4))\n// console.log(f2(4,5))\n\n// 验证暂时性死区\n// var x = 0;\n// function f(x = 2) {\n//     console.log(x)\n//     console.log(y)\n//     let y = 1;\n// }\n// f()\n\n"
  },
  {
    "path": "code/next-tick.js",
    "content": "/* @flow */\n/* globals MessageChannel */\n\nimport { noop } from 'shared/util'\nimport { handleError } from './error'\nimport { isIOS, isNative } from './env'\n\nconst callbacks = []\nlet pending = false\n\nfunction flushCallbacks () {\n  pending = false\n  const copies = callbacks.slice(0)\n  callbacks.length = 0\n  for (let i = 0; i < copies.length; i++) {\n    copies[i]()\n  }\n}\n\n// Here we have async deferring wrappers using both microtasks and (macro) tasks.\n// In < 2.4 we used microtasks everywhere, but there are some scenarios where\n// microtasks have too high a priority and fire in between supposedly\n// sequential events (e.g. #4521, #6690) or even between bubbling of the same\n// event (#6566). However, using (macro) tasks everywhere also has subtle problems\n// when state is changed right before repaint (e.g. #6813, out-in transitions).\n// Here we use microtask by default, but expose a way to force (macro) task when\n// needed (e.g. in event handlers attached by v-on).\nlet microTimerFunc\nlet macroTimerFunc\nlet useMacroTask = false\n\n// Determine (macro) task defer implementation.\n// Technically setImmediate should be the ideal choice, but it's only available\n// in IE. The only polyfill that consistently queues the callback after all DOM\n// events triggered in the same loop is by using MessageChannel.\n/* istanbul ignore if */\nif (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {\n  macroTimerFunc = () => {\n    setImmediate(flushCallbacks)\n  }\n} else if (typeof MessageChannel !== 'undefined' && (\n  isNative(MessageChannel) ||\n  // PhantomJS\n  MessageChannel.toString() === '[object MessageChannelConstructor]'\n)) {\n  const channel = new MessageChannel()\n  const port = channel.port2\n  channel.port1.onmessage = flushCallbacks\n  macroTimerFunc = () => {\n    port.postMessage(1)\n  }\n} else {\n  /* istanbul ignore next */\n  macroTimerFunc = () => {\n    setTimeout(flushCallbacks, 0)\n  }\n}\n\n// Determine microtask defer implementation.\n/* istanbul ignore next, $flow-disable-line */\nif (typeof Promise !== 'undefined' && isNative(Promise)) {\n  const p = Promise.resolve()\n  microTimerFunc = () => {\n    p.then(flushCallbacks)\n    // in problematic UIWebViews, Promise.then doesn't completely break, but\n    // it can get stuck in a weird state where callbacks are pushed into the\n    // microtask queue but the queue isn't being flushed, until the browser\n    // needs to do some other work, e.g. handle a timer. Therefore we can\n    // \"force\" the microtask queue to be flushed by adding an empty timer.\n    if (isIOS) setTimeout(noop)\n  }\n} else {\n  // fallback to macro\n  microTimerFunc = macroTimerFunc\n}\n\n/**\n * Wrap a function so that if any code inside triggers state change,\n * the changes are queued using a (macro) task instead of a microtask.\n */\nexport function withMacroTask (fn: Function): Function {\n  return fn._withTask || (fn._withTask = function () {\n    useMacroTask = true\n    const res = fn.apply(null, arguments)\n    useMacroTask = false\n    return res\n  })\n}\n\nexport function nextTick (cb?: Function, ctx?: Object) {\n  let _resolve\n  callbacks.push(() => {\n    if (cb) {\n      try {\n        cb.call(ctx)\n      } catch (e) {\n        handleError(e, ctx, 'nextTick')\n      }\n    } else if (_resolve) {\n      _resolve(ctx)\n    }\n  })\n  if (!pending) {\n    pending = true\n    if (useMacroTask) {\n      macroTimerFunc()\n    } else {\n      microTimerFunc()\n    }\n  }\n  // $flow-disable-line\n  if (!cb && typeof Promise !== 'undefined') {\n    return new Promise(resolve => {\n      _resolve = resolve\n    })\n  }\n}\n"
  },
  {
    "path": "code/state.js",
    "content": "/* @flow */\n\nimport config from '../config'\nimport Watcher from '../observer/watcher'\nimport { pushTarget, popTarget } from '../observer/dep'\nimport { isUpdatingChildComponent } from './lifecycle'\n\nimport {\n  set,\n  del,\n  observe,\n  defineReactive,\n  toggleObserving\n} from '../observer/index'\n\nimport {\n  warn,\n  bind,\n  noop,\n  hasOwn,\n  hyphenate,\n  isReserved,\n  handleError,\n  nativeWatch,\n  validateProp,\n  isPlainObject,\n  isServerRendering,\n  isReservedAttribute\n} from '../util/index'\n\nconst sharedPropertyDefinition = {\n  enumerable: true,\n  configurable: true,\n  get: noop,\n  set: noop\n}\n\nexport function proxy (target: Object, sourceKey: string, key: string) {\n  sharedPropertyDefinition.get = function proxyGetter () {\n    return this[sourceKey][key]\n  }\n  sharedPropertyDefinition.set = function proxySetter (val) {\n    this[sourceKey][key] = val\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition)\n}\n\nexport function initState (vm: Component) {\n  vm._watchers = []\n  const opts = vm.$options\n  if (opts.props) initProps(vm, opts.props)\n  if (opts.methods) initMethods(vm, opts.methods)\n  if (opts.data) {\n    initData(vm)\n  } else {\n    observe(vm._data = {}, true /* asRootData */)\n  }\n  if (opts.computed) initComputed(vm, opts.computed)\n  if (opts.watch && opts.watch !== nativeWatch) {\n    initWatch(vm, opts.watch)\n  }\n}\n\nfunction initProps (vm: Component, propsOptions: Object) {\n  const propsData = vm.$options.propsData || {}\n  const props = vm._props = {}\n  // cache prop keys so that future props updates can iterate using Array\n  // instead of dynamic object key enumeration.\n  const keys = vm.$options._propKeys = []\n  const isRoot = !vm.$parent\n  // root instance props should be converted\n  if (!isRoot) {\n    toggleObserving(false)\n  }\n  for (const key in propsOptions) {\n    keys.push(key)\n    const value = validateProp(key, propsOptions, propsData, vm)\n    /* istanbul ignore else */\n    if (process.env.NODE_ENV !== 'production') {\n      const hyphenatedKey = hyphenate(key)\n      if (isReservedAttribute(hyphenatedKey) ||\n          config.isReservedAttr(hyphenatedKey)) {\n        warn(\n          `\"${hyphenatedKey}\" is a reserved attribute and cannot be used as component prop.`,\n          vm\n        )\n      }\n      defineReactive(props, key, value, () => {\n        if (vm.$parent && !isUpdatingChildComponent) {\n          warn(\n            `Avoid mutating a prop directly since the value will be ` +\n            `overwritten whenever the parent component re-renders. ` +\n            `Instead, use a data or computed property based on the prop's ` +\n            `value. Prop being mutated: \"${key}\"`,\n            vm\n          )\n        }\n      })\n    } else {\n      defineReactive(props, key, value)\n    }\n    // static props are already proxied on the component's prototype\n    // during Vue.extend(). We only need to proxy props defined at\n    // instantiation here.\n    if (!(key in vm)) {\n      proxy(vm, `_props`, key)\n    }\n  }\n  toggleObserving(true)\n}\n\nfunction initData (vm: Component) {\n  let data = vm.$options.data\n  data = vm._data = typeof data === 'function'\n    ? getData(data, vm)\n    : data || {}\n  if (!isPlainObject(data)) {\n    data = {}\n    process.env.NODE_ENV !== 'production' && warn(\n      'data functions should return an object:\\n' +\n      'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',\n      vm\n    )\n  }\n  // proxy data on instance\n  const keys = Object.keys(data)\n  const props = vm.$options.props\n  const methods = vm.$options.methods\n  let i = keys.length\n  while (i--) {\n    const key = keys[i]\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods && hasOwn(methods, key)) {\n        warn(\n          `Method \"${key}\" has already been defined as a data property.`,\n          vm\n        )\n      }\n    }\n    if (props && hasOwn(props, key)) {\n      process.env.NODE_ENV !== 'production' && warn(\n        `The data property \"${key}\" is already declared as a prop. ` +\n        `Use prop default value instead.`,\n        vm\n      )\n    } else if (!isReserved(key)) {\n      proxy(vm, `_data`, key)\n    }\n  }\n  // observe data\n  observe(data, true /* asRootData */)\n}\n\nexport function getData (data: Function, vm: Component): any {\n  // #7573 disable dep collection when invoking data getters\n  pushTarget()\n  try {\n    return data.call(vm, vm)\n  } catch (e) {\n    handleError(e, vm, `data()`)\n    return {}\n  } finally {\n    popTarget()\n  }\n}\n\nconst computedWatcherOptions = { computed: true }\n\nfunction initComputed (vm: Component, computed: Object) {\n  // $flow-disable-line\n  const watchers = vm._computedWatchers = Object.create(null)\n  // computed properties are just getters during SSR\n  const isSSR = isServerRendering()\n\n  for (const key in computed) {\n    const userDef = computed[key]\n    const getter = typeof userDef === 'function' ? userDef : userDef.get\n    if (process.env.NODE_ENV !== 'production' && getter == null) {\n      warn(\n        `Getter is missing for computed property \"${key}\".`,\n        vm\n      )\n    }\n\n    if (!isSSR) {\n      // create internal watcher for the computed property.\n      watchers[key] = new Watcher(\n        vm,\n        getter || noop,\n        noop,\n        computedWatcherOptions\n      )\n    }\n\n    // component-defined computed properties are already defined on the\n    // component prototype. We only need to define computed properties defined\n    // at instantiation here.\n    if (!(key in vm)) {\n      defineComputed(vm, key, userDef)\n    } else if (process.env.NODE_ENV !== 'production') {\n      if (key in vm.$data) {\n        warn(`The computed property \"${key}\" is already defined in data.`, vm)\n      } else if (vm.$options.props && key in vm.$options.props) {\n        warn(`The computed property \"${key}\" is already defined as a prop.`, vm)\n      }\n    }\n  }\n}\n\nexport function defineComputed (\n  target: any,\n  key: string,\n  userDef: Object | Function\n) {\n  const shouldCache = !isServerRendering()\n  if (typeof userDef === 'function') {\n    sharedPropertyDefinition.get = shouldCache\n      ? createComputedGetter(key)\n      : userDef\n    sharedPropertyDefinition.set = noop\n  } else {\n    sharedPropertyDefinition.get = userDef.get\n      ? shouldCache && userDef.cache !== false\n        ? createComputedGetter(key)\n        : userDef.get\n      : noop\n    sharedPropertyDefinition.set = userDef.set\n      ? userDef.set\n      : noop\n  }\n  if (process.env.NODE_ENV !== 'production' &&\n      sharedPropertyDefinition.set === noop) {\n    sharedPropertyDefinition.set = function () {\n      warn(\n        `Computed property \"${key}\" was assigned to but it has no setter.`,\n        this\n      )\n    }\n  }\n  Object.defineProperty(target, key, sharedPropertyDefinition)\n}\n\nfunction createComputedGetter (key) {\n  return function computedGetter () {\n    const watcher = this._computedWatchers && this._computedWatchers[key]\n    if (watcher) {\n      watcher.depend()\n      return watcher.evaluate()\n    }\n  }\n}\n\nfunction initMethods (vm: Component, methods: Object) {\n  const props = vm.$options.props\n  for (const key in methods) {\n    if (process.env.NODE_ENV !== 'production') {\n      if (methods[key] == null) {\n        warn(\n          `Method \"${key}\" has an undefined value in the component definition. ` +\n          `Did you reference the function correctly?`,\n          vm\n        )\n      }\n      if (props && hasOwn(props, key)) {\n        warn(\n          `Method \"${key}\" has already been defined as a prop.`,\n          vm\n        )\n      }\n      if ((key in vm) && isReserved(key)) {\n        warn(\n          `Method \"${key}\" conflicts with an existing Vue instance method. ` +\n          `Avoid defining component methods that start with _ or $.`\n        )\n      }\n    }\n    vm[key] = methods[key] == null ? noop : bind(methods[key], vm)\n  }\n}\n\nfunction initWatch (vm: Component, watch: Object) {\n  for (const key in watch) {\n    const handler = watch[key]\n    if (Array.isArray(handler)) {\n      for (let i = 0; i < handler.length; i++) {\n        createWatcher(vm, key, handler[i])\n      }\n    } else {\n      createWatcher(vm, key, handler)\n    }\n  }\n}\n\nfunction createWatcher (\n  vm: Component,\n  expOrFn: string | Function,\n  handler: any,\n  options?: Object\n) {\n  if (isPlainObject(handler)) {\n    options = handler\n    handler = handler.handler\n  }\n  if (typeof handler === 'string') {\n    handler = vm[handler]\n  }\n  return vm.$watch(expOrFn, handler, options)\n}\n\nexport function stateMixin (Vue: Class<Component>) {\n  // flow somehow has problems with directly declared definition object\n  // when using Object.defineProperty, so we have to procedurally build up\n  // the object here.\n  const dataDef = {}\n  dataDef.get = function () { return this._data }\n  const propsDef = {}\n  propsDef.get = function () { return this._props }\n  if (process.env.NODE_ENV !== 'production') {\n    dataDef.set = function (newData: Object) {\n      warn(\n        'Avoid replacing instance root $data. ' +\n        'Use nested data properties instead.',\n        this\n      )\n    }\n    propsDef.set = function () {\n      warn(`$props is readonly.`, this)\n    }\n  }\n  Object.defineProperty(Vue.prototype, '$data', dataDef)\n  Object.defineProperty(Vue.prototype, '$props', propsDef)\n\n  Vue.prototype.$set = set\n  Vue.prototype.$delete = del\n\n  Vue.prototype.$watch = function (\n    expOrFn: string | Function,\n    cb: any,\n    options?: Object\n  ): Function {\n    const vm: Component = this\n    if (isPlainObject(cb)) {\n      return createWatcher(vm, expOrFn, cb, options)\n    }\n    options = options || {}\n    options.user = true\n    const watcher = new Watcher(vm, expOrFn, cb, options)\n    if (options.immediate) {\n      cb.call(vm, watcher.value)\n    }\n    return function unwatchFn () {\n      watcher.teardown()\n    }\n  }\n}\n"
  },
  {
    "path": "coolFunction/compose.js",
    "content": "function compose() {\n    let args = arguments\n    let len = args.length\n    if (len === 0) {\n        return function () { }\n    }\n    return function () {\n        let result = args[0].apply(undefined, arguments)\n\n        for (let i = 1; i < len; ++i) {\n            result = args[i].call(undefined, result)\n        }\n\n        return result\n    }\n}\n\n// 测试\nfunction what(n) { return n }\n\nfunction addTree(n) { return n + 3 }\n\nfunction multipleFour(n) { return n * 4 }\n\nfunction minusTwo(n) { return n / 2 }\n\nlet com1 = compose(what, addTree, multipleFour)\nlet com2 = compose(what, multipleFour, minusTwo)\n\nconsole.log(com1(2)) // 20\nconsole.log(com2(2))// 4"
  },
  {
    "path": "coolFunction/currying.js",
    "content": ""
  }
]