├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── README.md ├── demos ├── css │ ├── main.css │ ├── main.min.css │ └── main.scss ├── fib.js ├── html │ ├── aVue.html │ ├── base64AndSrcImage.html │ ├── box-model.html │ ├── closure.html │ ├── curve.html │ ├── debug-sort.html │ ├── flex-left_center_right-layout.html │ ├── float-left_center_right-layout.html │ ├── index.html │ ├── input.html │ ├── maring-left_center_right-layout.html │ ├── promise.html │ ├── vue-demo.html │ └── waterfall.html ├── js │ ├── aVue.js │ ├── algorithm │ │ ├── normal │ │ │ ├── backtrack-combine.js │ │ │ ├── backtrack-full-sort.js │ │ │ ├── backtrack-solveSudoku.js │ │ │ ├── divide-maxSubArray.js │ │ │ ├── divide-merge-sort.js │ │ │ ├── divide-quick-sort.js │ │ │ ├── dynamic-climb-start.js │ │ │ ├── dynamic-fibonacci.js │ │ │ ├── dynamic-knapsack.js │ │ │ ├── greedy-activity-selection.js │ │ │ ├── greedy-coin-change.js │ │ │ └── greedy-cookie-index.js │ │ └── sort │ │ │ ├── counting-sort.js │ │ │ ├── fast-sort.js │ │ │ ├── heap-sort.js │ │ │ ├── insert-sort.js │ │ │ ├── merge-sort.js │ │ │ ├── pop-sort.js │ │ │ ├── select-sort.js │ │ │ └── shell-sort.js │ ├── binary-search-sort-2.js │ ├── call_apply_bind.js │ ├── currring.js │ ├── deep-copy.js │ ├── document.js │ ├── es6 │ │ ├── class.js │ │ ├── symbol.js │ │ └── this.js │ ├── extends │ │ └── prototype-extends.js │ ├── promise-class.js │ ├── promise-function.js │ ├── publish-subscribe.js │ ├── simulate │ │ ├── README.md │ │ ├── myApply.js │ │ ├── myBind.js │ │ ├── myCall.js │ │ ├── myClass.js │ │ ├── myCreate.js │ │ ├── myCurring.js │ │ ├── myDebounce.js │ │ ├── myDecoration.js │ │ ├── myEventEmitter.js │ │ ├── myGetPrototypeOf.js │ │ ├── myInstanceOf.js │ │ ├── myJSON-parse.js │ │ ├── myJSON-stringify.js │ │ ├── myLazy.js │ │ ├── myNew.js │ │ ├── mySubscribe.js │ │ ├── mySymbol.js │ │ ├── myThrottle.js │ │ ├── myWatcher.js │ │ └── promise-class-all.js │ └── test_function_name_anonymous_arrow.js ├── proxy.js ├── qij.js ├── reflect.js ├── tests │ └── promise-class-all.spec.js └── ts │ └── generics.ts ├── docs ├── .vuepress │ ├── README.md │ ├── config.js │ ├── enhanceApp.js │ ├── nav │ │ └── zh.js │ ├── public │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── html │ │ │ ├── border-box-children.png │ │ │ ├── border-box-parent.png │ │ │ ├── content-box-children.png │ │ │ └── content-box-parent.png │ │ ├── images │ │ │ ├── css │ │ │ │ ├── flex-right-center-right.png │ │ │ │ ├── float-left-center-right.png │ │ │ │ ├── margin(pref)-left-center-right-1.png │ │ │ │ ├── margin(pref)-left-center-right-2.png │ │ │ │ ├── margin(pref)-left-center-right.png │ │ │ │ └── position-left-center-right.png │ │ │ ├── fib.jpg │ │ │ ├── http │ │ │ │ ├── baidu-cache.png │ │ │ │ └── cache-304.png │ │ │ ├── ie-leak.GIF │ │ │ ├── isArray.jpg │ │ │ ├── isTypeSupported.jpg │ │ │ ├── src-2.jpg │ │ │ ├── src.jpg │ │ │ ├── time-complex.png │ │ │ └── vue-prototype.png │ │ └── pic-hospital-bg.png │ └── theme │ │ ├── LICENSE │ │ ├── components │ │ ├── AlgoliaSearchBox.vue │ │ ├── DropdownLink.vue │ │ ├── DropdownTransition.vue │ │ ├── Home.vue │ │ ├── Keyword.vue │ │ ├── NavLink.vue │ │ ├── NavLinks.vue │ │ ├── Navbar.vue │ │ ├── Page.vue │ │ ├── Sidebar.vue │ │ ├── SidebarButton.vue │ │ ├── SidebarGroup.vue │ │ ├── SidebarLink.vue │ │ └── SidebarLinks.vue │ │ ├── global-components │ │ ├── Badge.vue │ │ └── Catalog.vue │ │ ├── index.js │ │ ├── layouts │ │ ├── 404.vue │ │ └── Layout.vue │ │ ├── noopModule.js │ │ ├── styles │ │ ├── arrow.styl │ │ ├── code.styl │ │ ├── config.styl │ │ ├── custom-blocks.styl │ │ ├── index.styl │ │ ├── mobile.styl │ │ ├── toc.styl │ │ └── wrapper.styl │ │ └── util │ │ └── index.js ├── README.md ├── about.md ├── algorithm │ ├── README.md │ └── bubbing.md ├── canvas │ └── README.md ├── css │ ├── README.md │ ├── animation.md │ ├── css3.md │ └── left-center-right.md ├── deno │ └── README.md ├── es6 │ ├── README.md │ ├── proxy.md │ └── symbol.md ├── guide.md ├── highLight │ └── README.md ├── html │ ├── README.md │ ├── elements.md │ └── html5.md ├── http │ ├── README.md │ ├── http-cache.md │ ├── http-headers.md │ ├── http.md │ ├── http2.md │ ├── http3.md │ └── https.md ├── interview │ ├── 2018-12-interview-web.md │ ├── 2018-8-15-interview-web.md │ ├── 2018-8-17-interview-web.md │ ├── 2018-8-31-interview-web.md │ ├── 2018-9-11-interview-web.md │ ├── 2018-9-18-interview-web.md │ ├── 2018-9-19-interview-web.md │ ├── 2018-alibaba-senior-web.md │ ├── 2018-netease-high-web.md │ ├── 2018-other-mid-high-web.md │ ├── 2020-11-interview-web.md │ ├── 2020-12-interview-web.md │ ├── 2020-alibaba-interview-web.md │ ├── 2020-other-interview-web.md │ └── README.md ├── javascript │ ├── README.md │ ├── __proto__.md │ ├── base.md │ ├── bom.md │ ├── closure.md │ ├── common-use-api.md │ ├── debounce.md │ ├── design-model.md │ ├── dom.md │ ├── event.md │ ├── eventloop.md │ ├── inherit.md │ ├── module.md │ ├── promise.md │ ├── prototype.md │ ├── this.md │ └── throttle.md ├── keyword.md ├── nginx │ ├── README.md │ ├── config.md │ └── proxy.md ├── node │ ├── README.md │ └── fs.md ├── nuxt │ └── README.md ├── performance │ └── README.md ├── pop │ └── README.md ├── project │ └── rollup │ │ └── README.md ├── pwa │ └── README.md ├── reference.md ├── rust │ ├── README.md │ ├── actix-web │ │ └── README.md │ └── tokio │ │ └── README.md ├── security │ ├── README.md │ ├── cookie.md │ ├── csrf.md │ └── xss.md ├── self │ └── README.md ├── skill │ └── README.md ├── svg │ └── README.md ├── typescript │ ├── README.md │ └── generics.md ├── v8 │ ├── README.md │ ├── build-gn.md │ ├── garbage.md │ ├── source-code.md │ └── v8.md ├── vue │ ├── README.md │ ├── parser-vue.md │ ├── vue2-api.md │ ├── vue2.md │ └── vue3.md ├── webgl │ └── REAME.md └── webpack │ ├── README.md │ └── webpack-dev-server.md ├── package.json └── scripts └── deploy.sh /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: web-advanced-frond-end CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | 11 | strategy: 12 | matrix: 13 | node-version: [12.x] 14 | 15 | steps: 16 | - uses: actions/checkout@v1 17 | - name: 步骤:第一步 -> 设置环境 18 | uses: actions/setup-node@v1 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | 22 | - name: 步骤:第二步 -> 安装依赖 23 | run: | 24 | npm install 25 | npm run build 26 | env: 27 | CI: true 28 | 29 | - name: 步骤:第三步 -> 部署脚本 30 | env: 31 | ACCESS_TOKEN_DEPLOY: ${{secrets.ACTIONS_ACCESS_TOKEN_WEB_CI }} 32 | PUBLISH_BRANCH: gh-pages 33 | PUBLISH_DIR: ./docs/.vuepress/dist 34 | CNAME: web.veaba.me 35 | run: | 36 | chmod +x ./scripts/deploy.sh 37 | bash ./scripts/deploy.sh 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | .vscode 4 | dist 5 | debug.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | > 进阶web高级前端知识体系:来自个人的面试经历、学习笔记、参考大神们的blog,以及常见面试题!不代表内容的正确性!!!!有一部分还在带着问号!以下内容是随手记下的笔记,还在学习..。 by@veaba 3 | ----------------------------------------------------------------- 4 | 5 | ![web-advanced-frond-end CI](https://github.com/veaba/web-advanced-frond-end/workflows/web-advanced-frond-end%20CI/badge.svg) 6 | 7 | 8 | 使用Vuepress 重新构建静态网站,舒爽体验阅读,请访问:https://web.veaba.me 9 | 10 | 部分内容尚未补充完成!! 11 | 12 | ## todo翻译工具 13 | 14 | - [开发工具,同步官方数据-todo]() 15 | - https://nodejs.org/dist/latest-v14.x/docs/api/documentation.json 一些api 16 | - 自动生成node最新版文档目录 17 | - copy一份后,自动翻译 18 | - 参考以前的Tensorflow-docs项目 19 | - 使用vuepress自带的在本页面生成目录在文章前面 20 | - 扫描未翻译的段落、同步更新请求操作 21 | 22 | ## 目录指南 23 | 24 | - [指南](https://web.veaba.me/guide/) 25 | - [Node](https://web.veaba.me/node/) 26 | - [V8](https://web.veaba.me/v8/) 27 | - [Canvas](/canvas/) 28 | - [Css](https://web.veaba.me/css/) 29 | - [Es6](https://web.veaba.me/es6/) 30 | - [Proxy](https://web.veaba.me/es6/proxy/) 31 | - [Highlight](https://web.veaba.me/highlight/) 32 | - [HTML](https://web.veaba.me/html/) 33 | 34 | - [HTML5](https://web.veaba.me/html/html5/) 35 | - [HTTP](https://web.veaba.me/http/) 36 | - [http](https://web.veaba.me/http/) 37 | - [http2](https://web.veaba.me/http2/) 38 | - [http3](https://web.veaba.me/http3/) 39 | - [面试](https://web.veaba.me/interview/) 40 | - [2018年阿里资深web前端面试题](https://web.veaba.me/interview/2018alibaba-senior-web/) 41 | - [2018年网易高级web前端面试题](https://web.veaba.me/interview/2018netease-high-web/) 42 | - [2018年中级/高级web前端面试题](https://web.veaba.meinterview/interview/2018other-mid-high-web/) 43 | - [2018年8月15日面试题](https://web.veaba.me/interview2018-8-15-interview-web/) 44 | - [2018年8月17日面试题](https://web.veaba.me/interview/2018-8-17-interview-web/) 45 | - [2018年8月31日面试题](https://web.veaba.me/interview/2018-8-31-interview-web/) 46 | - [2018年9月11日面试题](https://web.veaba.me/interview/2018-9-11-interview-web/) 47 | - [2018年9月18日面试题](https://web.veaba.me/interview/2018-9-18-interview-web/) 48 | - [2018年9月19日面试题](https://web.veaba.me/interview/2018-9-19-interview-web/) 49 | - [2018年12月份面试题](https://web.veaba.me/interview/2018-12-interview-web/) 50 | - [2020年4月upyun高级前端面试](https://web.veaba.me/interview/2020-upyun-interview-web) 51 | - [2020年4月阿里巴巴前端专家面试题](https://web.veaba.me/interview/2020-alibaba-interview-web/) 52 | - [JavaScript](https://web.veaba.me/javascript/) 53 | - [__proto__](https://web.veaba.me/javascript/__proto__/) 54 | - [Prototype](https://web.veaba.me/javascript/prototype/) 55 | - [基础](https://web.veaba.me/javascript/base/) 56 | - [DOM](https://web.veaba.me/javascript/dom/) 57 | - [BOM](https://web.veaba.me/javascript/bom/) 58 | - [event](https://web.veaba.me/javascript/event/) 59 | - [继承](https://web.veaba.me/javascript/inherit/) 60 | - [常用API](https://web.veaba.me/javascript/common-use-api/) 61 | - [设计模式](https://web.veaba.me/javascript/design-mode/) 62 | - [Nginx](https://web.veaba.me/nginx/) 63 | - [Proxy](https://web.veaba.me/nginx/proxy/) 64 | - [Confit](https://web.veaba.me/nginx/proxy/) 65 | - [Nuxt](https://web.veaba.me/nuxt/) 66 | - [性能](https://web.veaba.me/performance/) 67 | - [流行常见前端面试技术题](https://web.veaba.me/pop/) 68 | - [PWA](https://web.veaba.me/pwa/) 69 | - [Web安全性问题](https://web.veaba.me/security/) 70 | - [业务技巧相关](https://web.veaba.me/skill/) 71 | - [TypeScript](https://web.veaba.me/typescript/) 72 | - [WebGL](https://web.veaba.me/webgl/) 73 | - [Webpack](https://web.veaba.me/webpack/) 74 | - [Vue](https://web.veaba.me/vue/) 75 | - [Vue2](https://web.veaba.me/vue/vue2/) 76 | - [Vue3](https://web.veaba.me/vue/vue3/) 77 | - [解析Vue.js文件](https://web.veaba.me/vue/parser-vue/) 78 | - [Vue2-api](https://web.veaba.me/vue/vue2-api/) 79 | - [引用](https://web.veaba.me/reference/) 80 | - [关于](https://web.veaba.me/about/) 81 | - [自我驱动](https://web.veaba.me/self/) 82 | -------------------------------------------------------------------------------- /demos/css/main.css: -------------------------------------------------------------------------------- 1 | @media screen and (min-width: 1200px) { 2 | .base64 { 3 | width: 32px; 4 | height: 32px; 5 | background: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAgAHADASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIEBQEDBv/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB+/qW6O83uRyca2WTE2PLJsGjLE2wABUtrFW0lqysCv33EJgAB//EACAQAAMAAQQCAwAAAAAAAAAAAAECAwAEEhMUECAyNED/2gAIAQEAAQUCxXbs4CCPK0m53Dd7L91vhEvOIs/PzvNGfUCXK8M0rDteyo3ZxNPKZGmkrLCalYTQJFJ5tG/8f//EABYRAQEBAAAAAAAAAAAAAAAAACABEf/aAAgBAwEBPwGvH//EABgRAAIDAAAAAAAAAAAAAAAAAAEgAhFB/9oACAECAQE/AY64NP8A/8QAJxAAAQMDAQcFAAAAAAAAAAAAAQIRIQASMQMEEBMgIkGBMkBxcsH/2gAIAQEABj8CpaHgDc4kchCVpURljimcOO3PqfUUfitnVxHCmFrRSGKzprLSA3jvWoV3cQB7CI8VqOFtblVv5VhSFdLpGmml+u5SQSSgjnWtoI3C1OMTigoJxIkxRjMSXogAtiS9dIPkvRX3Me0//8QAIhABAAIBBAICAwAAAAAAAAAAAREhADFBUXEgYTChQJGx/9oACAEBAAE/IcQylQzQlwEglib+Gm/EK9sFRa5lZ8EvusayM8UJNt/vGMyZF0v8N8nrJkZ3Rt2/rGaW1oh9T0xUiyeDRiIvkwE8rhFfJRx5gZSg4giOjjoxGAtOgsGMAl2MdCaxAGw1dOCdDrGKEUevF7YyshqVUcXtgYCoT6PxP//aAAwDAQACAAMAAAAQ5Iww8889MMcc88//xAAYEQADAQEAAAAAAAAAAAAAAAABESAhcf/aAAgBAwEBPxA9HbLK/wD/xAAZEQEAAgMAAAAAAAAAAAAAAAABESBBUcH/2gAIAQIBAT8QIktdLqEM3//EAB8QAQEAAwEAAgMBAAAAAAAAAAERACExUSBBYZHwQP/aAAgBAQABPxDKMJdNK7b3FEQA2r9Yb8ROgeI/Z8FBXHksgHXHvmAsAEEHinSx/Xz/AIHuf1PMhNEyGlQbELUd0ag2KbCCDHvqh3PrOJ+RQdDF2LR9whO5LnQjRIVqKTriP2oYArSfQnHWBMvjW75QIV0Ptvzgwt02jvXcNqhE/GaZkM+TeInUBa+uW8aKiiNkBroA/RiLN0Bj6DRPINHmXQvGjytn4EMl+YjYcC1B4ayPG03aKE59v+T/2Q=="); 6 | } 7 | .src { 8 | width: 32px; 9 | height: 32px; 10 | background: url("../../docs/.vuepress/public/images/src.jpg") no-repeat; 11 | } 12 | } 13 | 14 | @media screen and (max-width: 750px) { 15 | .base64 { 16 | width: 32px; 17 | height: 32px; 18 | background: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAxAEEDASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIDBgUEAf/EABkBAQADAQEAAAAAAAAAAAAAAAACAwQBBf/aAAwDAQACEAMQAAAB+e6u3RK32Y7R1Vyqz+g7wRlfJFxLRZ3XRhhuBu+BDzp63nd5fkKL/lu6lJWt7fE+2R1mU6N9ef1ce2nPu8kZNtIAAAAAH//EACMQAAIBBAIBBQEAAAAAAAAAAAECAwAEERIQExQVICElMEH/2gAIAQEAAQUCErsaWNnrw5aaNk9qJoCCFnTV/U/rrdNnAJWsis8NAGtpY9lwdoo9VWALbUy5fQ8KdlvYcHrHZYw5LHVazW44tJvh0Dr0t3vmGETSNFX95jvGWvKi2luRKokVR+n/xAAgEQACAgEDBQAAAAAAAAAAAAABAgADEgQQERMhMDFC/9oACAEDAQE/AbHCjmLblFuBbDbiN3gbpEqZp0+zFYqeRM9rac4hrFRU+/B//8QAHhEAAgICAgMAAAAAAAAAAAAAAAECEQMQEhMwMUH/2gAIAQIBAT8BnJfC2Xq0TE601Z1wGrOJLHl7VJevB//EACkQAAECBAQEBwAAAAAAAAAAAAEAAhESMUEDEBNhICFRgSIjMDJCceH/2gAIAQEABj8CgAMuS+K58UbFRsVXzvb+qNgibDKuYw9kWmqhdBgqjh7ZbXzB6rVHdTrVPZE9OHTNbItNCtK68DaBYjHHfig8TKaQzUUpaYbFUc779X//xAAjEAABBAEEAgMBAAAAAAAAAAABABEhMRBBUWFxkaEgMOGx/9oACAEBAAE/IXwBQdpvhGIDsllFfkjER2C/xHyalCjZGBR2/wCq10xX/wCqajIxODJCL4TNxipBEDymjsHorSbMyaK5eyo0EknPOCg3t4UujAA9A6aAwYXv2rlOAYEKAvQPggLIXfgRfw80AmBitIsz8bqDEYA5R8TjVd17x/IzRcINAb0Vx6lFIyAv7fSJBQZzFbfb/9oADAMBAAIAAwAAABCDogT773jnzpvv0333333/xAAeEQEAAgEEAwAAAAAAAAAAAAABABExITBB8FFhwf/aAAgBAwEBPxBO8EAWTy9AXEtCCnETE44crO6OmT3LRLg1XiEgWxp92P/EAB0RAAMAAgIDAAAAAAAAAAAAAAABESFhEDAxQfD/2gAIAQIBAT8Q9VEUyhZx8bjwhPBW0UmT6pBBsOXZ2pvHR//EACcQAQABAwIGAgIDAAAAAAAAAAERACExQVEQYXGBkaGx8CDRMMHx/9oACAEBAAE/EBrZyf3RgmOqEFRIhMQx7zWZf2nPxTIQTEMesfjBS77lTPiNCpn5pnLJI3tT9r3x/X35oHLJK3vSZtBoRZj44CGgOJPt5K/1uECQDlC897z1pZEcX0K1/td5282pUBcW1PpWRgFrlPa0dOCWGdfhc2c1v0rmcF8AIepRY4QNEw97eK07S2c3WLVcRlk1XL2v5pwISnocMWOrFfRHAfDynRt1+6UHRQFa22Tq9L0om7UkOBhz52zNLPCJMAiPkPEcM28zvxFBERkTSgISxPyb1kdsNSd6SOwwAw3lUUWrBUbkCpjXmRxj+L//2Q=="); 19 | } 20 | .src { 21 | width: 32px; 22 | height: 32px; 23 | background: url("../../docs/.vuepress/public/images/src-2.jpg") no-repeat; 24 | } 25 | } 26 | 27 | .a { 28 | width: 200px; 29 | height: 200px; 30 | padding: 50px; 31 | border: 1px solid yellow; 32 | } 33 | 34 | .a .b { 35 | width: 100%; 36 | height: 100%; 37 | border: 1px solid green; 38 | } 39 | 40 | .a .b:hover { 41 | background: #3f1b1b; 42 | } 43 | 44 | .a .c + .b:hover { 45 | background: yellowgreen; 46 | } 47 | -------------------------------------------------------------------------------- /demos/css/main.min.css: -------------------------------------------------------------------------------- 1 | @media screen and (min-width: 1200px){.base64{width:32px;height:32px;background:url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAgAHADASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIEBQEDBv/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB+/qW6O83uRyca2WTE2PLJsGjLE2wABUtrFW0lqysCv33EJgAB//EACAQAAMAAQQCAwAAAAAAAAAAAAECAwAEEhMUECAyNED/2gAIAQEAAQUCxXbs4CCPK0m53Dd7L91vhEvOIs/PzvNGfUCXK8M0rDteyo3ZxNPKZGmkrLCalYTQJFJ5tG/8f//EABYRAQEBAAAAAAAAAAAAAAAAACABEf/aAAgBAwEBPwGvH//EABgRAAIDAAAAAAAAAAAAAAAAAAEgAhFB/9oACAECAQE/AY64NP8A/8QAJxAAAQMDAQcFAAAAAAAAAAAAAQIRIQASMQMEEBMgIkGBMkBxcsH/2gAIAQEABj8CpaHgDc4kchCVpURljimcOO3PqfUUfitnVxHCmFrRSGKzprLSA3jvWoV3cQB7CI8VqOFtblVv5VhSFdLpGmml+u5SQSSgjnWtoI3C1OMTigoJxIkxRjMSXogAtiS9dIPkvRX3Me0//8QAIhABAAIBBAICAwAAAAAAAAAAAREhADFBUXEgYTChQJGx/9oACAEBAAE/IcQylQzQlwEglib+Gm/EK9sFRa5lZ8EvusayM8UJNt/vGMyZF0v8N8nrJkZ3Rt2/rGaW1oh9T0xUiyeDRiIvkwE8rhFfJRx5gZSg4giOjjoxGAtOgsGMAl2MdCaxAGw1dOCdDrGKEUevF7YyshqVUcXtgYCoT6PxP//aAAwDAQACAAMAAAAQ5Iww8889MMcc88//xAAYEQADAQEAAAAAAAAAAAAAAAABESAhcf/aAAgBAwEBPxA9HbLK/wD/xAAZEQEAAgMAAAAAAAAAAAAAAAABESBBUcH/2gAIAQIBAT8QIktdLqEM3//EAB8QAQEAAwEAAgMBAAAAAAAAAAERACExUSBBYZHwQP/aAAgBAQABPxDKMJdNK7b3FEQA2r9Yb8ROgeI/Z8FBXHksgHXHvmAsAEEHinSx/Xz/AIHuf1PMhNEyGlQbELUd0ag2KbCCDHvqh3PrOJ+RQdDF2LR9whO5LnQjRIVqKTriP2oYArSfQnHWBMvjW75QIV0Ptvzgwt02jvXcNqhE/GaZkM+TeInUBa+uW8aKiiNkBroA/RiLN0Bj6DRPINHmXQvGjytn4EMl+YjYcC1B4ayPG03aKE59v+T/2Q==")}.src{width:32px;height:32px;background:url("../../docs/.vuepress/public/images/src.jpg") no-repeat}}@media screen and (max-width: 750px){.base64{width:32px;height:32px;background:url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAxAEEDASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIDBgUEAf/EABkBAQADAQEAAAAAAAAAAAAAAAACAwQBBf/aAAwDAQACEAMQAAAB+e6u3RK32Y7R1Vyqz+g7wRlfJFxLRZ3XRhhuBu+BDzp63nd5fkKL/lu6lJWt7fE+2R1mU6N9ef1ce2nPu8kZNtIAAAAAH//EACMQAAIBBAIBBQEAAAAAAAAAAAECAwAEERIQExQVICElMEH/2gAIAQEAAQUCErsaWNnrw5aaNk9qJoCCFnTV/U/rrdNnAJWsis8NAGtpY9lwdoo9VWALbUy5fQ8KdlvYcHrHZYw5LHVazW44tJvh0Dr0t3vmGETSNFX95jvGWvKi2luRKokVR+n/xAAgEQACAgEDBQAAAAAAAAAAAAABAgADEgQQERMhMDFC/9oACAEDAQE/AbHCjmLblFuBbDbiN3gbpEqZp0+zFYqeRM9rac4hrFRU+/B//8QAHhEAAgICAgMAAAAAAAAAAAAAAAECEQMQEhMwMUH/2gAIAQIBAT8BnJfC2Xq0TE601Z1wGrOJLHl7VJevB//EACkQAAECBAQEBwAAAAAAAAAAAAEAAhESMUEDEBNhICFRgSIjMDJCceH/2gAIAQEABj8CgAMuS+K58UbFRsVXzvb+qNgibDKuYw9kWmqhdBgqjh7ZbXzB6rVHdTrVPZE9OHTNbItNCtK68DaBYjHHfig8TKaQzUUpaYbFUc779X//xAAjEAABBAEEAgMBAAAAAAAAAAABABEhMRBBUWFxkaEgMOGx/9oACAEBAAE/IXwBQdpvhGIDsllFfkjER2C/xHyalCjZGBR2/wCq10xX/wCqajIxODJCL4TNxipBEDymjsHorSbMyaK5eyo0EknPOCg3t4UujAA9A6aAwYXv2rlOAYEKAvQPggLIXfgRfw80AmBitIsz8bqDEYA5R8TjVd17x/IzRcINAb0Vx6lFIyAv7fSJBQZzFbfb/9oADAMBAAIAAwAAABCDogT773jnzpvv0333333/xAAeEQEAAgEEAwAAAAAAAAAAAAABABExITBB8FFhwf/aAAgBAwEBPxBO8EAWTy9AXEtCCnETE44crO6OmT3LRLg1XiEgWxp92P/EAB0RAAMAAgIDAAAAAAAAAAAAAAABESFhEDAxQfD/2gAIAQIBAT8Q9VEUyhZx8bjwhPBW0UmT6pBBsOXZ2pvHR//EACcQAQABAwIGAgIDAAAAAAAAAAERACExQVEQYXGBkaGx8CDRMMHx/9oACAEBAAE/EBrZyf3RgmOqEFRIhMQx7zWZf2nPxTIQTEMesfjBS77lTPiNCpn5pnLJI3tT9r3x/X35oHLJK3vSZtBoRZj44CGgOJPt5K/1uECQDlC897z1pZEcX0K1/td5282pUBcW1PpWRgFrlPa0dOCWGdfhc2c1v0rmcF8AIepRY4QNEw97eK07S2c3WLVcRlk1XL2v5pwISnocMWOrFfRHAfDynRt1+6UHRQFa22Tq9L0om7UkOBhz52zNLPCJMAiPkPEcM28zvxFBERkTSgISxPyb1kdsNSd6SOwwAw3lUUWrBUbkCpjXmRxj+L//2Q==")} .src{width:32px;height:32px;background:url("../../docs/.vuepress/public/images/src-2.jpg") no-repeat}}.a{width:200px;height:200px;padding:50px;border:1px solid yellow} .a .b{width:100%;height:100%;border:1px solid green} .a .b:hover{background:#3f1b1b} .a .c+.b:hover{background:yellowgreen} 2 | -------------------------------------------------------------------------------- /demos/css/main.scss: -------------------------------------------------------------------------------- 1 | @media screen and(min-width:1200px){ 2 | .base64{ 3 | width: 32px; 4 | height: 32px; 5 | background: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAgAHADASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIEBQEDBv/EABYBAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB+/qW6O83uRyca2WTE2PLJsGjLE2wABUtrFW0lqysCv33EJgAB//EACAQAAMAAQQCAwAAAAAAAAAAAAECAwAEEhMUECAyNED/2gAIAQEAAQUCxXbs4CCPK0m53Dd7L91vhEvOIs/PzvNGfUCXK8M0rDteyo3ZxNPKZGmkrLCalYTQJFJ5tG/8f//EABYRAQEBAAAAAAAAAAAAAAAAACABEf/aAAgBAwEBPwGvH//EABgRAAIDAAAAAAAAAAAAAAAAAAEgAhFB/9oACAECAQE/AY64NP8A/8QAJxAAAQMDAQcFAAAAAAAAAAAAAQIRIQASMQMEEBMgIkGBMkBxcsH/2gAIAQEABj8CpaHgDc4kchCVpURljimcOO3PqfUUfitnVxHCmFrRSGKzprLSA3jvWoV3cQB7CI8VqOFtblVv5VhSFdLpGmml+u5SQSSgjnWtoI3C1OMTigoJxIkxRjMSXogAtiS9dIPkvRX3Me0//8QAIhABAAIBBAICAwAAAAAAAAAAAREhADFBUXEgYTChQJGx/9oACAEBAAE/IcQylQzQlwEglib+Gm/EK9sFRa5lZ8EvusayM8UJNt/vGMyZF0v8N8nrJkZ3Rt2/rGaW1oh9T0xUiyeDRiIvkwE8rhFfJRx5gZSg4giOjjoxGAtOgsGMAl2MdCaxAGw1dOCdDrGKEUevF7YyshqVUcXtgYCoT6PxP//aAAwDAQACAAMAAAAQ5Iww8889MMcc88//xAAYEQADAQEAAAAAAAAAAAAAAAABESAhcf/aAAgBAwEBPxA9HbLK/wD/xAAZEQEAAgMAAAAAAAAAAAAAAAABESBBUcH/2gAIAQIBAT8QIktdLqEM3//EAB8QAQEAAwEAAgMBAAAAAAAAAAERACExUSBBYZHwQP/aAAgBAQABPxDKMJdNK7b3FEQA2r9Yb8ROgeI/Z8FBXHksgHXHvmAsAEEHinSx/Xz/AIHuf1PMhNEyGlQbELUd0ag2KbCCDHvqh3PrOJ+RQdDF2LR9whO5LnQjRIVqKTriP2oYArSfQnHWBMvjW75QIV0Ptvzgwt02jvXcNqhE/GaZkM+TeInUBa+uW8aKiiNkBroA/RiLN0Bj6DRPINHmXQvGjytn4EMl+YjYcC1B4ayPG03aKE59v+T/2Q=="); 6 | } 7 | .src{ 8 | width: 32px; 9 | height: 32px; 10 | background: url('../../docs/.vuepress/public/images/src.jpg') no-repeat 11 | } 12 | 13 | } 14 | 15 | @media screen and(max-width:750px){ 16 | .base64{ 17 | width: 32px; 18 | height: 32px; 19 | background: url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wgARCAAxAEEDASIAAhEBAxEB/8QAGgABAAMBAQEAAAAAAAAAAAAAAAIDBgUEAf/EABkBAQADAQEAAAAAAAAAAAAAAAACAwQBBf/aAAwDAQACEAMQAAAB+e6u3RK32Y7R1Vyqz+g7wRlfJFxLRZ3XRhhuBu+BDzp63nd5fkKL/lu6lJWt7fE+2R1mU6N9ef1ce2nPu8kZNtIAAAAAH//EACMQAAIBBAIBBQEAAAAAAAAAAAECAwAEERIQExQVICElMEH/2gAIAQEAAQUCErsaWNnrw5aaNk9qJoCCFnTV/U/rrdNnAJWsis8NAGtpY9lwdoo9VWALbUy5fQ8KdlvYcHrHZYw5LHVazW44tJvh0Dr0t3vmGETSNFX95jvGWvKi2luRKokVR+n/xAAgEQACAgEDBQAAAAAAAAAAAAABAgADEgQQERMhMDFC/9oACAEDAQE/AbHCjmLblFuBbDbiN3gbpEqZp0+zFYqeRM9rac4hrFRU+/B//8QAHhEAAgICAgMAAAAAAAAAAAAAAAECEQMQEhMwMUH/2gAIAQIBAT8BnJfC2Xq0TE601Z1wGrOJLHl7VJevB//EACkQAAECBAQEBwAAAAAAAAAAAAEAAhESMUEDEBNhICFRgSIjMDJCceH/2gAIAQEABj8CgAMuS+K58UbFRsVXzvb+qNgibDKuYw9kWmqhdBgqjh7ZbXzB6rVHdTrVPZE9OHTNbItNCtK68DaBYjHHfig8TKaQzUUpaYbFUc779X//xAAjEAABBAEEAgMBAAAAAAAAAAABABEhMRBBUWFxkaEgMOGx/9oACAEBAAE/IXwBQdpvhGIDsllFfkjER2C/xHyalCjZGBR2/wCq10xX/wCqajIxODJCL4TNxipBEDymjsHorSbMyaK5eyo0EknPOCg3t4UujAA9A6aAwYXv2rlOAYEKAvQPggLIXfgRfw80AmBitIsz8bqDEYA5R8TjVd17x/IzRcINAb0Vx6lFIyAv7fSJBQZzFbfb/9oADAMBAAIAAwAAABCDogT773jnzpvv0333333/xAAeEQEAAgEEAwAAAAAAAAAAAAABABExITBB8FFhwf/aAAgBAwEBPxBO8EAWTy9AXEtCCnETE44crO6OmT3LRLg1XiEgWxp92P/EAB0RAAMAAgIDAAAAAAAAAAAAAAABESFhEDAxQfD/2gAIAQIBAT8Q9VEUyhZx8bjwhPBW0UmT6pBBsOXZ2pvHR//EACcQAQABAwIGAgIDAAAAAAAAAAERACExQVEQYXGBkaGx8CDRMMHx/9oACAEBAAE/EBrZyf3RgmOqEFRIhMQx7zWZf2nPxTIQTEMesfjBS77lTPiNCpn5pnLJI3tT9r3x/X35oHLJK3vSZtBoRZj44CGgOJPt5K/1uECQDlC897z1pZEcX0K1/td5282pUBcW1PpWRgFrlPa0dOCWGdfhc2c1v0rmcF8AIepRY4QNEw97eK07S2c3WLVcRlk1XL2v5pwISnocMWOrFfRHAfDynRt1+6UHRQFa22Tq9L0om7UkOBhz52zNLPCJMAiPkPEcM28zvxFBERkTSgISxPyb1kdsNSd6SOwwAw3lUUWrBUbkCpjXmRxj+L//2Q=="); 20 | } 21 | .src{ 22 | width: 32px; 23 | height: 32px; 24 | background: url('../../docs/.vuepress/public/images/src-2.jpg') no-repeat 25 | } 26 | } 27 | 28 | .a{ 29 | width: 200px; 30 | height: 200px; 31 | padding: 50px; 32 | border: 1px solid yellow; 33 | .b{ 34 | width: 100%; 35 | height: 100%; 36 | border: 1px solid green; 37 | &:hover{ 38 | background: rgb(63, 27, 27); 39 | } 40 | } 41 | } 42 | .a .c + .b:hover{ 43 | background: yellowgreen 44 | } 45 | 46 | .p{ 47 | .top{ 48 | 49 | } 50 | .bottom{ 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demos/fib.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @desc 斐波那契数列 学习,递归函数解析 4 | * 5 | */ 6 | function fib(n){ 7 | if(n<2){ 8 | return 1 9 | } 10 | console.info(fib(n-1)+fib(n-2)); 11 | debugger 12 | return fib(n-1)+fib(n-2) 13 | }; 14 | fib(8) 15 | // 入参 8 16 | ```js 17 | 1 fib(7)+fib(6) 18 | 2 fib(6)+fib(5) + fib(5)+fib(4) 19 | 3 fib(5)+fib(4) + fib(4)+fib(3) + fib(4)+fib(3) + fib(3)+fib(2) 20 | 4 fib(4)+fib(3) + fib(3)+fib(2) + fib(3)+fib(2) + fib(2)+fib(1) + fib(3)+fib(2) + fib(2)+fib(1) + fib(2)+fib(1) + fib(1)+fib(0) 21 | 5 fib(3)+fib(2) + fib(2)+fib(1) + fib(2)+fib(1) + fib(1)+fib(0) + fib(2)+fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(2)+fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1)+ fib(1)+fib(0) + fib(1) + fib(1) + fib(0) 22 | 6 fib(2)+fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) +fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1)+ fib(1)+fib(0) + fib(1) + fib(1) + fib(0) 23 | 7 fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1) + fib(1)+fib(0) +fib(1) + fib(1)+fib(0) + fib(1)+fib(0) + fib(1)+ fib(1)+fib(0) + fib(1) + fib(1) + fib(0) 24 | 8 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 25 | 9 去掉空格之后 我们得到一个结果 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1 = 34 26 | ``` -------------------------------------------------------------------------------- /demos/html/aVue.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Title 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/html/base64AndSrcImage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | base64 与 src 引入图片的比较 7 | 8 | 9 | 10 | 11 | 12 | 13 |

比较 响应式 媒体查询情况下,base64 与 src 的区别

14 | 15 |
16 |
17 |
18 |
19 | 20 |

子级的focus 让父级产生变化

21 |
22 |
bbbbb child
23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /demos/html/box-model.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 24 | 25 | 26 |
27 |
28 |
29 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demos/html/closure.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demos/html/curve.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /demos/html/debug-sort.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 33 | 34 | -------------------------------------------------------------------------------- /demos/html/flex-left_center_right-layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 左中右布局 Flex 7 | 27 | 28 | 29 |
30 |
31 | Left 32 |
33 |
34 | Center Flex 35 | 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。 36 |
37 |
38 | Right 39 |
40 |
41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /demos/html/float-left_center_right-layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 左中右布局 7 | 31 | 32 | 33 |
34 |
35 | Left 36 |
37 |
38 | Center 39 | Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。 40 |
41 |
42 | Right 43 |
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /demos/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 | 13 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /demos/html/input.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 29 | 30 | 31 | 32 | 38 | 50 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /demos/html/maring-left_center_right-layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 38 | 39 | 40 |
41 |
中间
42 |
左边
43 |
右边
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /demos/html/promise.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /demos/html/vue-demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Title 8 | 9 | 10 | 11 |
12 | {{message}} 13 | 14 | 15 | {{title}} 16 | 17 | 18 | 19 | 22 | 23 | 24 |
{{who}}----
25 |
26 | 27 | 28 | 29 | 30 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /demos/html/waterfall.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 图片瀑布流 7 | 20 | 21 | 22 |
23 | 24 | 62 | 63 | -------------------------------------------------------------------------------- /demos/js/aVue.js: -------------------------------------------------------------------------------- 1 | /*********************** 2 | * @name JS 3 | * @author Jo.gel 4 | * @date 2019/8/14 0014 下午 4:08 5 | ***********************/ 6 | const Vue = function () { 7 | return function (options) { 8 | if ("development" !== 'production' && 9 | !(this instanceof Vue) 10 | ) { 11 | warn('Vue is a constructor and should be called with the `new` keyword'); 12 | } 13 | _init(options); 14 | }; 15 | 16 | }; 17 | 18 | Vue.prototype = { 19 | $delete: del, // $delete 删除响应式key函数 20 | $destroy: function () { 21 | 22 | } 23 | }; 24 | //疑问TODO?为什么这个destroy不用变量来声明函数 25 | Vue.prototype.$destroy = function () { 26 | 27 | }; 28 | Vue.prototype.$emit = function (...args) { 29 | console.info(args); 30 | }; 31 | // 强制更新Vue实例 32 | Vue.prototype.$forceUpdate = function () { 33 | 34 | }; 35 | Vue.prototype.$mount = function (el, hydrating) { 36 | 37 | }; 38 | 39 | Vue.prototype.$nextTick = function (fn) { 40 | }; 41 | 42 | Vue.prototype.$off = function (event, fn) { 43 | 44 | }; 45 | 46 | Vue.prototype.$on = function (event, fn) { 47 | }; 48 | Vue.prototype.$once = function (event, fn) { 49 | 50 | }; 51 | Vue.prototype.$set = function (target, key, val) { 52 | 53 | }; 54 | Vue.prototype.$watch = function (expOrn, cb, options) { 55 | 56 | }; 57 | Vue.prototype.__patch__ = patch; 58 | 59 | Vue.prototype._b = bindObjectProps; 60 | 61 | Vue.prototype._e = function (text) { 62 | 63 | }; 64 | Vue.prototype._f = resolveFilter; 65 | 66 | Vue.prototype._g = bindObjectListeners; 67 | 68 | Vue.prototype._i = looseIndexOf; 69 | 70 | Vue.prototype._init = _init; 71 | 72 | Vue.prototype._k = checkKeyCodes; 73 | 74 | Vue.prototype._l = renderList; 75 | 76 | Vue.prototype._m = renderStatic; 77 | 78 | Vue.prototype._n = toNumber; 79 | 80 | Vue.prototype._o = markOnce; 81 | 82 | Vue.prototype._q = looseEqual; 83 | 84 | Vue.prototype._render = function () { 85 | 86 | }; 87 | Vue.prototype._s = toString; 88 | 89 | Vue.prototype._t = renderSlot; 90 | 91 | Vue.prototype._u = resolveScopedSlots; 92 | 93 | Vue.prototype._update = function (vnode, hydrating) { 94 | 95 | }; 96 | Vue.prototype._v = createTextVNode; 97 | 98 | function _init(options) { 99 | 100 | } 101 | 102 | function del(target, key) { 103 | 104 | } 105 | 106 | function f() { 107 | 108 | } 109 | 110 | // 补丁 111 | function patch(oldVnode, vnode, hydrating, removeOnly, parentElm, refElm) { 112 | 113 | } 114 | 115 | function bindObjectProps(data, tag, value, arProp, isSync) { 116 | 117 | } 118 | 119 | function resolveFilter(id) { 120 | 121 | } 122 | 123 | function bindObjectListeners(data, value) { 124 | 125 | } 126 | 127 | function looseIndexOf(arr, val) { 128 | 129 | } 130 | 131 | function checkKeyCodes(eventKeyCode, key, builtInKeyCode, eventKeyName, builtInKeyName) { 132 | 133 | } 134 | 135 | function renderList(val, render) { 136 | 137 | } 138 | 139 | function renderStatic(index, isInFor) { 140 | 141 | } 142 | 143 | function toNumber(val) { 144 | 145 | } 146 | 147 | function markOnce(tree, index, key) { 148 | 149 | } 150 | 151 | function looseEqual(a, b) { 152 | 153 | } 154 | 155 | function toString(val) { 156 | 157 | } 158 | 159 | function renderSlot(name, fallback, props, bindObject) { 160 | 161 | } 162 | 163 | function resolveScopedSlots(fns, 164 | //see flow.vnode 165 | res) { 166 | 167 | } 168 | 169 | function createTextVNode(val) { 170 | 171 | } 172 | 173 | const dataDef={ 174 | get:function () { 175 | return this._data 176 | }, 177 | set:function (value) { 178 | console.info(value); 179 | } 180 | }; 181 | 182 | const propsDef={ 183 | get:function () { 184 | return this._props 185 | }, 186 | set:function (value) { 187 | console.info(value); 188 | } 189 | }; 190 | const isServerDef={ 191 | get:function () { 192 | return false 193 | }, 194 | set:function (value) { 195 | console.info(value); 196 | } 197 | }; 198 | const ssrContextDef ={ 199 | get:function () { 200 | return false 201 | }, 202 | set:function (value) { 203 | console.info(value); 204 | } 205 | }; 206 | Object.defineProperty(Vue.prototype, '$data', dataDef); 207 | Object.defineProperty(Vue.prototype, '$props', propsDef); 208 | Object.defineProperty(Vue.prototype, '$isServer', isServerDef); 209 | Object.defineProperty(Vue.prototype, '$ssrContext', ssrContextDef); 210 | 211 | // Vue的构造器指向他自己 212 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/backtrack-combine.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 回溯算法 -组合问题 3 | * 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, 4 | * 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 5 | */ 6 | function combine(n, k) { 7 | const result = []; 8 | const path = []; 9 | 10 | function backtrack(start) { 11 | if (path.length === k) { 12 | result.push([...path]); 13 | return; 14 | } 15 | for (let i = start; i <= n; i++) { 16 | path.push(i); 17 | backtrack(i + 1); 18 | path.pop(); 19 | } 20 | } 21 | 22 | backtrack(1); 23 | return result; 24 | } 25 | 26 | // 测试 27 | const n = 4; 28 | const k = 2; 29 | console.log(combine(n, k)); 30 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/backtrack-full-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 回溯算法 - 全排列 3 | * 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, 4 | * 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 5 | * 给定一个不包含重复数字的数组,返回所有可能的全排列。 6 | */ 7 | function permute(nums) { 8 | const result = []; 9 | const used = new Array(nums.length).fill(false); 10 | const path = []; 11 | 12 | function backtrack() { 13 | if (path.length === nums.length) { 14 | result.push([...path]); 15 | return; 16 | } 17 | for (let i = 0; i < nums.length; i++) { 18 | if (used[i]) continue; 19 | path.push(nums[i]); 20 | used[i] = true; 21 | backtrack(); 22 | path.pop(); 23 | used[i] = false; 24 | } 25 | } 26 | 27 | backtrack(); 28 | return result; 29 | } 30 | 31 | // 测试 32 | const nums = [1, 2, 3]; 33 | console.log(permute(nums)); 34 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/backtrack-solveSudoku.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 回溯算法 - 解数独 3 | * 回溯算法是一种通过尝试所有可能的路径来解决问题的算法策略。在遇到不可行的路径时, 4 | * 它会回退到上一个决策点,尝试其他路径,直到找到解决方案或遍历完所有可能的路径。 5 | */ 6 | function solveSudoku(board) { 7 | function isValid(row, col, num) { 8 | // 检查行 9 | for (let i = 0; i < 9; i++) { 10 | if (board[row][i] === num) return false; 11 | } 12 | // 检查列 13 | for (let i = 0; i < 9; i++) { 14 | if (board[i][col] === num) return false; 15 | } 16 | // 检查 3x3 子棋盘 17 | const startRow = Math.floor(row / 3) * 3; 18 | const startCol = Math.floor(col / 3) * 3; 19 | for (let i = startRow; i < startRow + 3; i++) { 20 | for (let j = startCol; j < startCol + 3; j++) { 21 | if (board[i][j] === num) return false; 22 | } 23 | } 24 | return true; 25 | } 26 | 27 | function backtrack() { 28 | for (let i = 0; i < 9; i++) { 29 | for (let j = 0; j < 9; j++) { 30 | if (board[i][j] === '.') { 31 | for (let num = 1; num <= 9; num++) { 32 | if (isValid(i, j, num)) { 33 | board[i][j] = num.toString(); 34 | if (backtrack()) return true; 35 | board[i][j] = '.'; 36 | } 37 | } 38 | return false; 39 | } 40 | } 41 | } 42 | return true; 43 | } 44 | 45 | backtrack(); 46 | return board; 47 | } 48 | 49 | // 测试 50 | const board = [ 51 | ['5', '3', '.', '.', '7', '.', '.', '.', '.'], 52 | ['6', '.', '.', '1', '9', '5', '.', '.', '.'], 53 | ['.', '9', '8', '.', '.', '.', '.', '6', '.'], 54 | ['8', '.', '.', '.', '6', '.', '.', '.', '3'], 55 | ['4', '.', '.', '8', '.', '3', '.', '.', '1'], 56 | ['7', '.', '.', '.', '2', '.', '.', '.', '6'], 57 | ['.', '6', '.', '.', '.', '.', '2', '8', '.'], 58 | ['.', '.', '.', '4', '1', '9', '.', '.', '5'], 59 | ['.', '.', '.', '.', '8', '.', '.', '7', '9'], 60 | ]; 61 | console.log(solveSudoku(board)); 62 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/divide-maxSubArray.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, 3 | * 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, 4 | * 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 5 | * 6 | * 给定一个整数数组 nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 7 | */ 8 | 9 | function maxSubArray(nums) { 10 | if (nums.length === 1) { 11 | return nums[0]; 12 | } 13 | 14 | let maxEndingHere = nums[0]; 15 | let maxSoFar = nums[0]; 16 | 17 | for (let i = 1; i < nums.length; i++) { 18 | maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]); 19 | maxSoFar = Math.max(maxSoFar, maxEndingHere); 20 | } 21 | 22 | return maxSoFar; 23 | } 24 | 25 | // 测试 26 | const nums = [-2, 1, -3, 4, -1, 2, 3, -5, 4]; 27 | console.log(maxSubArray(nums)); // 输出 6 28 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/divide-merge-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, 3 | * 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, 4 | * 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 5 | * 6 | * 归并排序是一种典型的分治算法,它将一个数组分成两个子数组,分别对这两个子数组进行排序,然后将排好序的子数组合并成一个有序的数组。 7 | */ 8 | 9 | function mergeSort(arr) { 10 | if (arr.length <= 1) { 11 | return arr; 12 | } 13 | 14 | // 分割数组 15 | const mid = Math.floor(arr.length / 2); 16 | const left = arr.slice(0, mid); 17 | const right = arr.slice(mid); 18 | 19 | // 递归排序子数组 20 | const sortedLeft = mergeSort(left); 21 | const sortedRight = mergeSort(right); 22 | 23 | // 合并两个有序子数组 24 | return merge(sortedLeft, sortedRight); 25 | } 26 | 27 | function merge(left, right) { 28 | let result = []; 29 | let leftIndex = 0; 30 | let rightIndex = 0; 31 | 32 | while (leftIndex < left.length && rightIndex < right.length) { 33 | if (left[leftIndex] < right[rightIndex]) { 34 | result.push(left[leftIndex]); 35 | leftIndex++; 36 | } else { 37 | result.push(right[rightIndex]); 38 | rightIndex++; 39 | } 40 | } 41 | 42 | return result.concat(left.slice(leftIndex)).concat(right.slice(rightIndex)); 43 | } 44 | 45 | // 测试 46 | const array = [38, 27, 43, 3, 9, 82, 10]; 47 | console.log(mergeSort(array)); 48 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/divide-quick-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 分治算法(Divide and Conquer Algorithm)是一种常用的算法策略, 3 | * 它将一个复杂的问题分解成多个规模较小、相互独立且形式相同的子问题, 4 | * 然后分别解决这些子问题,最后将子问题的解合并起来得到原问题的解。 5 | * 6 | * 快速排序也是基于分治思想,通过选择一个基准元素,将数组分为两部分,使得左边部分的元素都小于等于基准元素,右边部分的元素都大于等于基准元素,然后分别对左右两部分进行排序。 7 | */ 8 | 9 | function quickSort(arr) { 10 | if (arr.length <= 1) { 11 | return arr; 12 | } 13 | 14 | // 选择基准元素 15 | const pivot = arr[Math.floor(arr.length / 2)]; 16 | const left = []; 17 | const right = []; 18 | const equal = []; 19 | 20 | for (let num of arr) { 21 | if (num < pivot) { 22 | left.push(num); 23 | } else if (num > pivot) { 24 | right.push(num); 25 | } else { 26 | equal.push(num); 27 | } 28 | } 29 | 30 | return [...quickSort(left),...equal,...quickSort(right)]; 31 | } 32 | 33 | // 测试 34 | const array2 = [38, 27, 43, 3, 9, 82, 10]; 35 | console.log(quickSort(array2)); -------------------------------------------------------------------------------- /demos/js/algorithm/normal/dynamic-climb-start.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, 3 | * 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 4 | */ 5 | 6 | 7 | function climbStairs(n) { 8 | if (n <= 2) { 9 | return n; 10 | } 11 | let dp = new Array(n + 1); 12 | dp[1] = 1; 13 | dp[2] = 2; 14 | for (let i = 3; i <= n; i++) { 15 | dp[i] = dp[i - 1] + dp[i - 2]; 16 | } 17 | return dp[n]; 18 | } 19 | 20 | // 测试 21 | console.log(climbStairs(5)); -------------------------------------------------------------------------------- /demos/js/algorithm/normal/dynamic-fibonacci.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, 3 | * 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 4 | * 5 | * 0 - 1 背包问题:有 n 个物品,每个物品有重量 weights 和价值 values,背包的容量为 capacity。每个物品只能使用一次,求能装入背包的最大价值。 6 | */ 7 | 8 | 9 | function fibonacci(n) { 10 | if (n <= 1) { 11 | return n; 12 | } 13 | let dp = new Array(n + 1); 14 | dp[0] = 0; 15 | dp[1] = 1; 16 | for (let i = 2; i <= n; i++) { 17 | dp[i] = dp[i - 1] + dp[i - 2]; 18 | } 19 | return dp[n]; 20 | } 21 | 22 | // 测试 23 | console.log(fibonacci(10)); -------------------------------------------------------------------------------- /demos/js/algorithm/normal/dynamic-knapsack.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 动态规划(Dynamic Programming,DP)是一种通过把原问题分解为相对简单的子问题, 3 | * 并保存子问题的解来避免重复计算,从而解决复杂问题的算法策略。 4 | * 5 | * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 6 | */ 7 | 8 | function knapsack(capacity, weights, values) { 9 | let n = weights.length; 10 | let dp = new Array(n + 1).fill(0).map(() => new Array(capacity + 1).fill(0)); 11 | 12 | for (let i = 1; i <= n; i++) { 13 | for (let w = 0; w <= capacity; w++) { 14 | if (weights[i - 1] > w) { 15 | dp[i][w] = dp[i - 1][w]; 16 | } else { 17 | dp[i][w] = Math.max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1]); 18 | } 19 | } 20 | } 21 | return dp[n][capacity]; 22 | } 23 | 24 | // 测试 25 | let capacity = 5; 26 | let weights = [2, 3, 4, 5]; 27 | let values = [3, 4, 5, 6]; 28 | console.log(knapsack(capacity, weights, values)); 29 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/greedy-activity-selection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终得到全局最优解的算法策略。 3 | * 虽然贪心算法并不总是能得到全局最优解,但在许多问题上它可以提供高效且近似最优的解决方案。 4 | * 假设有一组活动,每个活动都有开始时间和结束时间,你需要选择尽可能多的活动,使得这些活动之间没有时间冲突。 5 | */ 6 | 7 | function activitySelection(activities) { 8 | activities.sort((a, b) => a.end - b.end); 9 | let selected = []; 10 | let lastEnd = -1; 11 | for (let activity of activities) { 12 | if (activity.start >= lastEnd) { 13 | selected.push(activity); 14 | lastEnd = activity.end; 15 | } 16 | } 17 | return selected; 18 | } 19 | 20 | // 测试 21 | const activities = [ 22 | { start: 1, end: 3 }, 23 | { start: 2, end: 4 }, 24 | { start: 3, end: 5 }, 25 | { start: 5, end: 7 }, 26 | { start: 3, end: 8 } 27 | ]; 28 | const result = activitySelection(activities); 29 | console.log(result); -------------------------------------------------------------------------------- /demos/js/algorithm/normal/greedy-coin-change.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终得到全局最优解的算法策略。 3 | * 虽然贪心算法并不总是能得到全局最优解,但在许多问题上它可以提供高效且近似最优的解决方案。 4 | * 假设你有无限数量的硬币,硬币面额为 [1, 5, 10, 25](美分),要找给顾客 amount 美分,求最少需要多少枚硬币。 5 | */ 6 | 7 | function coinChange(amount) { 8 | const coins = [25, 10, 5, 1]; 9 | let count = 0; 10 | for (let coin of coins) { 11 | count += Math.floor(amount / coin); 12 | amount %= coin; 13 | } 14 | return count; 15 | } 16 | 17 | // 测试 18 | const amount = 63; 19 | console.log(coinChange(amount)); // 输出 6 20 | -------------------------------------------------------------------------------- /demos/js/algorithm/normal/greedy-cookie-index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 贪心算法是一种在每一步选择中都采取当前状态下的最优决策,从而希望最终得到全局最优解的算法策略。 3 | * 虽然贪心算法并不总是能得到全局最优解,但在许多问题上它可以提供高效且近似最优的解决方案。 4 | * 5 | * 有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃一个饼干, 6 | * 且只有当饼干的大小大于等于孩子的饥饿度时,孩子才能吃饱。求最多能有多少个孩子吃饱。 7 | */ 8 | 9 | function findContentChildren(g, s) { 10 | g.sort((a, b) => a - b); 11 | s.sort((a, b) => a - b); 12 | let childIndex = 0; 13 | let cookieIndex = 0; 14 | while (childIndex < g.length && cookieIndex < s.length) { 15 | if (s[cookieIndex] >= g[childIndex]) { 16 | childIndex++; 17 | } 18 | cookieIndex++; 19 | } 20 | return childIndex; 21 | } 22 | 23 | // 测试 24 | const g = [1, 2, 3]; 25 | const s = [1, 1]; 26 | console.log(findContentChildren(g, s)); // 输出 1 27 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/counting-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 计数排序 3 | * 1. 该方法使用了一个额外的数组C,这意味着增加了内存空间, 4 | * 2. 第 i 个元素是待排序数组A中值,等于 i 的元素的个数 5 | * 3. 然后根据C数组 来将 A中的元素排到正确的位置 6 | * 4. 只能对整数进行排序 7 | */ 8 | function countingSort(data) { 9 | console.time("counting=>"); 10 | var len = data.length; 11 | var B = []; 12 | var C = []; 13 | var min = (max = data[0]); 14 | 15 | for (let i = 0; i < len; i++) { 16 | min = min <= data[i] ? min : data[i]; 17 | max = max >= data[i] ? max : data[i]; 18 | 19 | C[data[i]] = C[data[i]] ? C[data[i]] + 1 : 1; 20 | } 21 | 22 | 23 | for (let j = min; j < max; j++) { 24 | C[j + 1] = (C[j + 1] || 0) + (C[j] || 0); 25 | } 26 | 27 | for (let k = len - 1; k >= 0; k--) { 28 | debugger 29 | B[C[data[k]] - 1] = data[k]; 30 | C[data[k]]--; 31 | } 32 | console.timeEnd("counting=>"); 33 | return B 34 | } 35 | 36 | 37 | var arr = [9, 8, 6, 4, 5, 3, 2]; 38 | 39 | console.log("===>", countingSort(arr)); 40 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/fast-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 快速排序 3 | * 对冒泡算法的改进 4 | * 第一趟: 5 | * - 一部分: 比另外部分都要小,递归调用 6 | * - 另外一部分:递归调用 7 | * 在两边都实行快速排序 8 | * 9 | */ 10 | 11 | function fastSort(el) { 12 | if (el.length <= 1) return el; 13 | // 向下取整获得中间数 14 | const halfIndex = Math.floor(el.length / 2); 15 | const pivot = el.splice(halfIndex, 1)[0]; 16 | const left = []; 17 | const right = []; 18 | for (let i = 0; i < el.length; i++) { 19 | if (el[i] < pivot) { 20 | left.push(el[i]); 21 | } else { 22 | right.push(el[i]); 23 | } 24 | } 25 | console.log("===>", { halfIndex, pivot, left, right }); 26 | return fastSort(left).concat([pivot], fastSort(right)); 27 | } 28 | 29 | const arr = [12, 12, 15, 445, 451, 12, 123456, 61, 20, 136, 4856, 1, 0]; 30 | 31 | console.log(fastSort(arr)); 32 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/heap-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 堆排序 4 | * @TODO 以下代码会引发无限递归 5 | * 1. 利用堆这种数据结构所设计的一种排序算法 6 | * 2. 堆积是近似完全二叉树的结构 7 | * 3. 满足堆积的性质 8 | * 4. 子节点的键值或索引总是 小于(或大于)它的父节点 9 | * 10 | */ 11 | 12 | function heapSort(data){ 13 | console.time('heapSort') 14 | var heapSize = data.length,temp; 15 | 16 | for(let i = Math.floor(heapSize)/2-1;i>=0;i++){ 17 | heapify(data,i,heapSize) 18 | } 19 | 20 | // 堆排序 21 | for (let j=heapSize-1;j<=i;j--){ 22 | temp=data[0] 23 | data[0]=data[j] 24 | data[j]=temp 25 | heapity(data,0,--heapSize) 26 | } 27 | console.timeEnd('heapSort') 28 | return data 29 | } 30 | 31 | function heapify(data,x,len){ 32 | var l = 2*x+1 33 | var r = 2*x+2 34 | largest = x 35 | temp=null 36 | if(ldata[largest]){ 37 | largest=l 38 | } 39 | 40 | if(rdata[largest]){ 41 | largest=r 42 | } 43 | if(largest!=x){ 44 | temp=data[x] 45 | data[x]=data[largest] 46 | data[largest]=temp 47 | heapity(data,largest,len) 48 | } 49 | } 50 | 51 | 52 | var arr = [9, 8, 6, 4, 5, 3, 2]; 53 | 54 | console.log("===>", heapSort(arr)); 55 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/insert-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 插入排序 3 | * 4 | * 1. 从第一个元素开始,可以认为已被排序 5 | * 2. 取出下一个元素,在已排序的元素序列中从后往前扫描 6 | * 3. 如果该元素(已排序)大于新元素,则将该元素移到下一个位置 7 | * 4. 重复3,直到找到已排序的元素小于或者等于新元素的位置 8 | * 5. 新元素插入到下一个位置中 9 | * 6. 重复步骤2 10 | */ 11 | 12 | function insertSort(els) { 13 | // 从第二个元素开始,即i=1 14 | for (let i = 1; i < els.length; i++) { 15 | // 后一个小于前一个,当前的值小于前面的 16 | if (els[i] < els[i - 1]) { 17 | const currentItem = els[i]; 18 | let j = i - 1; 19 | els[i] = els[j]; // 把前面的值给当前的 20 | // 比大小,找到被插入元素所在的位置 21 | while (j >= 0 && currentItem < els[j]) { 22 | els[j + 1] = els[j]; 23 | j--; 24 | } 25 | els[j + 1] = currentItem; 26 | } 27 | } 28 | return els; 29 | } 30 | 31 | const arr = [12, 12, 15, 445, 451, 12, 123456, 61, 20, 136, 4856, 1, 0]; 32 | 33 | console.log(insertSort(arr)); 34 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/merge-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 归并排序,一种稳定的排序方法 3 | * 1. 已有序的子序列合并 4 | * 2. 得到完全有序的序列 5 | * 3. 先让每个子序列有序 6 | * 4. 在让子序列段间有序 7 | * 8 | */ 9 | 10 | function mergeSort(data) { 11 | let len = data.length; 12 | if (len < 2) { 13 | return data; 14 | } 15 | var middle = Math.floor(len / 2); 16 | var left = data.slice(0, middle); 17 | var right = data.slice(middle); 18 | return merge(mergeSort(left), mergeSort(right)); 19 | } 20 | 21 | function merge(left, right) { 22 | var result = []; 23 | console.time("mergeSort=>"); 24 | while (left.length && right.length) { 25 | if (left[0] <= right[0]) { 26 | result.push(left.shift()); 27 | } else { 28 | result.push(right.shift()); 29 | } 30 | } 31 | while (left.length) { 32 | result.push(left.shift()); 33 | } 34 | while (right.length) { 35 | result.push(right.shift()); 36 | } 37 | console.timeEnd("mergeSort=>"); 38 | return result; 39 | } 40 | var arr = [9, 8, 6, 4, 5, 3, 2]; 41 | 42 | console.log("===>", mergeSort(arr)); 43 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/pop-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 冒泡排序 3 | * 1. 比较相邻的两个元素,如果前者比后者大 4 | * 2. 第一轮结束,最后一个是最大值 5 | * 3. 开始第二轮,最后一个最大的了,可不参与比较,巧用 `arr.length-i-1` 6 | * 7 | * 8 | */ 9 | 10 | var arr = [12, 12, 15, 445, 451, 12, 123456, 61, 20, 136, 4856, 1, 0]; 11 | // 12, 12, 15,445, 12, 451,61, 20, 136,4856, 1, 0,123456 12 | //[12, 12, 15,451, 12, 445,61, 123456, 136,4856, 1, 0, 20] 13 | 14 | for (let i = 0; i < arr.length; i++) { 15 | for (let j = 0; j < arr.length - i - 1; j++) { 16 | console.log("j=>", i, j); 17 | if (arr[i] > arr[j]) { 18 | const temp = arr[i]; 19 | arr[i] = arr[j]; 20 | arr[j] = temp; 21 | } 22 | } 23 | } 24 | 25 | console.log("arr==>", arr); 26 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/select-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 选择排序 3 | * 4 | * 1. 在未排序的序列中找到最小(大)的元素, 5 | * 2. 存放到排序序列的起始位置 6 | * 3. 再从剩余的未排序元素中继续寻找最小(大) 7 | * 4. 排到已排序序列的末尾 8 | * 9 | */ 10 | 11 | function selectionSort(data) { 12 | console.time("selectionSort"); 13 | const len = data.length; 14 | let minIndex = null; 15 | let temp = null; 16 | for (let i = 0; i < len; i++) { 17 | minIndex = i; 18 | for (let j = i + 1; j < len; j++) { 19 | // 前者比后者 20 | if (arr[j] < arr[minIndex]) { 21 | // 寻找最小值 22 | minIndex = j; // 将最小的索引保存 23 | } 24 | } 25 | // 前后两个交换位置 26 | console.log( 27 | "交换位置的索引是:(", 28 | i, 29 | minIndex + ")======>", 30 | `所对应的值做交换:(${arr[i]},${arr[minIndex]})` 31 | ); 32 | temp = arr[i]; 33 | arr[i] = arr[minIndex]; 34 | // console.log("arr[minIndex]===>", minIndex, arr[minIndex]); 35 | arr[minIndex] = temp; 36 | console.info("此时arr==>", arr); 37 | } 38 | console.timeEnd("selectionSort"); 39 | return arr; 40 | } 41 | 42 | var arr = [9, 8, 6, 4, 5, 3, 2]; 43 | 44 | console.log("===>", selectionSort(arr)); 45 | -------------------------------------------------------------------------------- /demos/js/algorithm/sort/shell-sort.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 希尔排序 3 | * 4 | * 1. 先将整个待排序的记录序列分割成为若干子序列 5 | * 2. 分别直接插入序列 6 | * 希尔排序(Shell Sort)是插入排序的一种改进版本,也称为 “缩小增量排序”。 7 | * 它通过将原始数据集合分割成若干个较小的子序列, 8 | * 对每个子序列进行插入排序,从而使数据逐步变得有序。 9 | */ 10 | function shellSort(arr) { 11 | let n = arr.length; 12 | let gap = Math.floor(n / 2); // 初始增量 13 | 14 | while (gap > 0) { 15 | for (let i = gap; i < n; i++) { 16 | let temp = arr[i]; 17 | let j = i; 18 | while (j >= gap && arr[j - gap] > temp) { 19 | arr[j] = arr[j - gap]; 20 | j -= gap; 21 | } 22 | arr[j] = temp; 23 | } 24 | gap = Math.floor(gap / 2); // 缩小增量 25 | } 26 | return arr; 27 | } 28 | 29 | // 测试 30 | let array = [64, 34, 25, 12, 22, 11, 90]; 31 | console.log(shellSort(array)); 32 | -------------------------------------------------------------------------------- /demos/js/binary-search-sort-2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 二分查找方法1:通过非递归的方式, 3 | * 1. 先找到中间值 4 | * 2. 通过中间值比较,大的在右,小的放左 5 | * 3. 再在两边分别寻找中间值,吃持续以上操作 6 | * (最多Lon2N) 7 | * 根据, 8 | */ 9 | function binarySearchTwo(data, dest) { 10 | let low = 0; 11 | let high = data.length - 1; 12 | 13 | while (low <= high) { 14 | const mid = Math.floor((high + low) / 2); 15 | if (data[mid] == dest) { 16 | return mid; 17 | } 18 | if (dest > data[mid]) { 19 | low = mid + 1; 20 | } else { 21 | high = mid - 1; 22 | } 23 | } 24 | return undefined; 25 | } 26 | 27 | const arr = [1, 3, 5, 7, 9, 10]; 28 | 29 | console.log(binarySearchTwo(arr, 5)); 30 | -------------------------------------------------------------------------------- /demos/js/currring.js: -------------------------------------------------------------------------------- 1 | // 柯里化 Currying 2 | 3 | function add() { 4 | const args = Array.prototype.slice.call(arguments); 5 | 6 | console.log("args=>", args); 7 | 8 | // 闭包特性,收集所有参数值 9 | const adder = function() { 10 | args.push(...args); 11 | return adder; 12 | }; 13 | console.log("args2=>", args); 14 | 15 | // toString 隐式转换 16 | 17 | console.log("adder==>", adder); 18 | adder.toString = function() { 19 | return args.reduce((left, right) => { 20 | return left + right; 21 | }); 22 | }; 23 | return adder; 24 | } 25 | 26 | const a = add(1, 5454)(1); 27 | 28 | const b = add(2, 5454)(1)(8588); 29 | console.log(a, b); 30 | -------------------------------------------------------------------------------- /demos/js/deep-copy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * deep copy 3 | * target copy to source 4 | * 1. 假设都是对象 5 | */ 6 | function deepCopy(target) { 7 | let result; 8 | 9 | if (typeof target === "object") { 10 | // 数组 11 | if (Array.isArray(target)) { 12 | // null 13 | } else if (target == null) { 14 | result = null; 15 | 16 | // function 17 | } else if (Object.prototype.toString.call(target) == "[object Function]") { 18 | } else if (Object.prototype.toString.call(target) === "[object Object]") { 19 | result = {}; 20 | 21 | for (let key in target) { 22 | result[key] = deepCopy(target[key]) 23 | } 24 | } 25 | // Date 26 | // RegExp 27 | else { 28 | result = target; 29 | } 30 | // object 31 | } else { 32 | result = target; 33 | } 34 | 35 | return result; 36 | } 37 | 38 | var a = { 39 | a: "a object", 40 | name: "a", 41 | }; 42 | 43 | var b = { 44 | b: "b object", 45 | name: "b", 46 | }; 47 | 48 | const newOne = deepCopy(a); 49 | 50 | console.log("newOne=>", newOne); 51 | -------------------------------------------------------------------------------- /demos/js/document.js: -------------------------------------------------------------------------------- 1 | //document.close() 2 | function createDoc(){ 3 | var doc=document.open("text/html","replace"); 4 | var txt="学习 HTML DOM 很有趣!"; 5 | doc.write(txt); 6 | doc.close(); 7 | } 8 | 9 | // replaceChild() 10 | function replaceChild(){ 11 | var textnode=document.createTextNode("Water"); 12 | var item=document.getElementById("myList").childNodes[0]; 13 | item.replaceChild(textnode,item.childNodes[0]); 14 | } 15 | 16 | // appendChild 17 | function appendChild (){ 18 | var node=document.createElement("LI"); 19 | var textnode=document.createTextNode("Water"); 20 | node.appendChild(textnode); 21 | document.getElementById("myList").appendChild(node); 22 | } 23 | 24 | // insertBefore 25 | 26 | function insertBefore(){ 27 | var a=document.createElement('a'); 28 | a.href='sb'; 29 | a.textContent='sbsbsbbs' 30 | var sping= document.querySelector('li:nth-child(4)') 31 | document.querySelector('ul').insertBefore(a,sping) 32 | } -------------------------------------------------------------------------------- /demos/js/es6/class.js: -------------------------------------------------------------------------------- 1 | /*********************** 2 | * @name JS 3 | * @author Jo.gel 4 | * @date 2019/8/9 0009 上午 11:22 5 | ***********************/ 6 | -------------------------------------------------------------------------------- /demos/js/es6/this.js: -------------------------------------------------------------------------------- 1 | const x = () => { 2 | console.log(this.a); 3 | }; 4 | 5 | function t() { 6 | this.a = 22; 7 | x(); 8 | } 9 | 10 | t(); 11 | 12 | let person = { 13 | name: "jike", 14 | init: function() { 15 | //为body添加一个点击事件,看看这个点击后的this属性有什么不同 16 | document.body.onclick = () => { 17 | alert(this.name); //?? this在浏览器默认是调用时的对象,可变的? 18 | }; 19 | }, 20 | }; 21 | person.init(); 22 | -------------------------------------------------------------------------------- /demos/js/extends/prototype-extends.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 原型继承 3 | */ 4 | 5 | function Parent() { 6 | this.name = 'parent'; 7 | } 8 | 9 | Parent.prototype.say = function () { 10 | console.log('hello'); 11 | }; 12 | 13 | function Child() { 14 | this.age = 18; 15 | } 16 | 17 | Child.prototype = Object.create(Parent.prototype); // Child 继承 Parent 18 | Child.prototype.constructor = Child; // 重置 constructor 19 | Child.prototype.cook = function () { 20 | console.log('cook'); 21 | }; 22 | 23 | // 此时, child 函数将拥有 cook 和 say 方法 24 | let child = new Child(); 25 | child.cook(); 26 | child.say(); 27 | -------------------------------------------------------------------------------- /demos/js/promise-class.js: -------------------------------------------------------------------------------- 1 | // Reference :https://segmentfault.com/a/1190000038433512 2 | 3 | class PromiseClass { 4 | constructor(exec) { 5 | this.status = "pending"; // 等待中 6 | this.value = undefined; 7 | this.reason = undefined; 8 | this.onFulfilled = undefined; 9 | this.onRejected = undefined; 10 | this.onFulFilledList = []; // 等待的函数与列表? 11 | this.onRejectedList = []; // 拒绝的列表 12 | 13 | try { 14 | // todo 15 | exec(this.resolve, this.reject); 16 | } catch (error) { 17 | this.reject(error); 18 | } 19 | } 20 | 21 | // resolve 函数 22 | resolve(value) { 23 | if (this.status === "pending") { 24 | this.status = "fulfilled"; 25 | this.value = value; 26 | this.onFulFilledList.forEach((item) => item()); //每项函数都是执行 27 | } 28 | } 29 | // reject 函数 30 | reject(reason) { 31 | if (this.status === "pending") { 32 | this.status = "rejected"; 33 | this.reason = reason; 34 | this.onRejectedList.forEach((item) => item()); 35 | } 36 | } 37 | 38 | // then 39 | 40 | then(onFulfilled, onRejected) { 41 | let result = null; 42 | if (this.status === "fulfilled" && onFulfilled) { 43 | result = onFulfilled(this.value); 44 | return PromiseClass.resolve(result); //返回新的一个promise 45 | } 46 | 47 | if (this.status === "rejected" && onRejected) { 48 | result = onRejected(this.reason); 49 | return PromiseClass.resolve(result); 50 | } 51 | 52 | if (this.status === "pending") { 53 | onFulfilled && this.onFulFilledList.push(() => onFulfilled(this.value)); // 如果存在,则到栈里 54 | onRejected && this.onRejectedList.push(() => onRejected(this.reason)); 55 | } 56 | } 57 | } 58 | 59 | PromiseClass.resolve = function(value) { 60 | if (typeof value === "object" && value.then) { 61 | return value; 62 | } else { 63 | return new PromiseClass((resolve) => { 64 | resolve(value); 65 | }); 66 | } 67 | }; 68 | 69 | PromiseClass.all = function(list) { 70 | return new PromiseClass((resolve, reject) => { 71 | let result = []; 72 | let count = 0; 73 | for (let i = 0; i < list.length; i++) { 74 | if (typeof list[i] === "object" && list[i].then) { 75 | PromiseClass.resolve(list[i]).then((data) => { 76 | result[i] = data; 77 | count++; 78 | }, reject); 79 | } else { 80 | result[i] = list[i]; 81 | count++; 82 | } 83 | } 84 | 85 | if (count === list.length) { 86 | resolve(result); 87 | } 88 | }); 89 | }; 90 | 91 | // TODO:PromiseClass.race 只要一个成功,全部resolve 92 | 93 | // TODO:PromiseClass finally,不管成功失败,回调都执行,执行之后,依然可以then 94 | -------------------------------------------------------------------------------- /demos/js/promise-function.js: -------------------------------------------------------------------------------- 1 | /*********************** 2 | * @name JS 3 | * @author Jo.gel 4 | * @date 2018/4/2 5 | ***********************/ 6 | 7 | //P(fn) fn typeof 为function 手写简单的 promise 8 | 9 | // 1 3 4 2 5 10 | function P(fn) { 11 | console.info("P promise"); 12 | var value = null; 13 | var events = []; 14 | this.then = function(f) { 15 | events.push(f); 16 | return this; 17 | }; 18 | function resolve(newValue) { 19 | var f = events.shift(); 20 | f(newValue, resolve); 21 | } 22 | fn(resolve); 23 | } 24 | 25 | function a() { 26 | debugger; 27 | console.info("function a"); 28 | return new P(function(resolve) { 29 | console.log("ge1"); 30 | setTimeout(function() { 31 | console.log("get2"); 32 | resolve(1); 33 | }, 6000); 34 | }); 35 | } 36 | a() 37 | .then(function(value, resolve) { 38 | console.log("get3"); 39 | setTimeout(function() { 40 | console.log("get 4"); 41 | resolve(2); 42 | }, 3000); 43 | }) 44 | .then(function(value, resolve) { 45 | console.log("get 5:" + value); 46 | }); 47 | -------------------------------------------------------------------------------- /demos/js/publish-subscribe.js: -------------------------------------------------------------------------------- 1 | // 所有一切都在对象中完成 2 | const eventEmitter = {}; 3 | 4 | // 缓存列表,调度中心 5 | eventEmitter.list = {}; 6 | 7 | // on 方法添加fn 缓存 ==> 订阅者注册事件到调度中心 8 | // 订阅处理 9 | eventEmitter.on = function(eventName, fn) { 10 | eventEmitter.list[eventName] 11 | ? eventEmitter.list[eventName].push(fn) 12 | : (eventEmitter.list[eventName] = [fn]); 13 | 14 | console.log("订阅事件==>list", eventEmitter.list); 15 | }; 16 | 17 | // 发布者发布事件到调度中心,调度中心执行代码 18 | eventEmitter.emit = function(...args) { 19 | console.log("arg=>", args); 20 | const list = eventEmitter.list; 21 | const eventName = args[0]; 22 | const publishContent = args[args.length - 1]; 23 | 24 | if (list[eventName]) { 25 | const fns = list[eventName]; 26 | for (let i = 0; i < fns.length; i++) { 27 | fns[i].call(this, publishContent); 28 | } 29 | } 30 | }; 31 | 32 | // off 取消订阅 33 | eventEmitter.off = function() { 34 | eventEmitter.list = []; 35 | }; 36 | 37 | function user1(content) { 38 | console.log("user1 subscribe=>", content); 39 | } 40 | 41 | // 订阅 42 | 43 | eventEmitter.on("art", user1); 44 | 45 | eventEmitter.emit("art", "ddd"); 46 | -------------------------------------------------------------------------------- /demos/js/simulate/README.md: -------------------------------------------------------------------------------- 1 | # 手动实现 -------------------------------------------------------------------------------- /demos/js/simulate/myApply.js: -------------------------------------------------------------------------------- 1 | Function.prototype.myApply = function (context, ...args) { 2 | context = Object(context); // 如果不是对象类型?则转为对象,以此保证 this 是个 对象 3 | 4 | // context 创建一个 symbol 的key,并赋值 this 5 | const fn = Symbol('myApply'); 6 | context[fn] = this; 7 | // 然后 调用 context[fn]() 8 | let ret = undefined; 9 | 10 | if (args) { 11 | ret = context[fn](...args); 12 | } else { 13 | ret = context[fn](); 14 | } 15 | 16 | // 删除这个函数 17 | delete context[fn]; 18 | // 返回结果 19 | return ret; 20 | }; 21 | 22 | const fn = function (a, b) { 23 | console.info(a, b); 24 | }; 25 | 26 | fn.myApply(null, 1, 2); 27 | -------------------------------------------------------------------------------- /demos/js/simulate/myBind.js: -------------------------------------------------------------------------------- 1 | Function.prototype.myBind = function (context, ...args) { 2 | const self = this; 3 | return (...innerArgs) => { 4 | // new 关键字 5 | if (this instanceof self) { 6 | console.info('is new'); 7 | return new self(...args, ...innerArgs); 8 | } 9 | 10 | console.info('no new'); 11 | return self.call(context, ...args, ...innerArgs); 12 | }; 13 | }; 14 | const fn = function (a, b) { 15 | console.info(a, b); 16 | }; 17 | 18 | const fnBind = fn.myBind(null, 1, 2); 19 | 20 | fnBind(); 21 | -------------------------------------------------------------------------------- /demos/js/simulate/myCall.js: -------------------------------------------------------------------------------- 1 | Function.prototype.myCall = function (context, [...args]) { 2 | if (context === null || context === undefined) { 3 | context = this || window; 4 | } else { 5 | context = Object(context); // 如果不是对象类型?则转为对象,以此保证 this 是个 对象 6 | } 7 | const fn = Symbol('myCall'); 8 | context[fn] = this; 9 | 10 | let ret = context[fn](...args); 11 | delete context[fn]; 12 | return ret; 13 | }; 14 | 15 | const fn = function (a, b) { 16 | console.info(a, b); 17 | }; 18 | 19 | const fnBind = fn.myCall(null, [1, 2]); 20 | -------------------------------------------------------------------------------- /demos/js/simulate/myClass.js: -------------------------------------------------------------------------------- 1 | // 定义一个函数来模拟类 2 | function createClass(constructor, methods, staticMethods) { 3 | // 为构造函数添加原型方法 4 | if (methods) { 5 | Object.keys(methods).forEach((methodName) => { 6 | constructor.prototype[methodName] = methods[methodName]; 7 | }); 8 | } 9 | 10 | // 为构造函数添加静态方法 11 | if (staticMethods) { 12 | Object.keys(staticMethods).forEach((methodName) => { 13 | constructor[methodName] = staticMethods[methodName]; 14 | }); 15 | } 16 | 17 | return constructor; 18 | } 19 | 20 | // 模拟一个类 21 | function Person(name, age) { 22 | this.name = name; 23 | this.age = age; 24 | } 25 | 26 | // 类的实例方法 27 | const personMethods = { 28 | sayHello() { 29 | console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`); 30 | } 31 | }; 32 | 33 | // 类的静态方法 34 | const personStaticMethods = { 35 | fromJSON(json) { 36 | return new Person(json.name, json.age); 37 | } 38 | }; 39 | 40 | // 创建模拟的类 41 | const MyPerson = createClass(Person, personMethods, personStaticMethods); 42 | 43 | // 创建实例 44 | let person = new MyPerson('Alice', 30); 45 | person.sayHello(); // 输出: Hello, my name is Alice and I'm 30 years old. 46 | 47 | // 调用静态方法 48 | let newPerson = MyPerson.fromJSON({ name: 'Bob', age: 25 }); 49 | newPerson.sayHello(); // 输出: Hello, my name is Bob and I'm 25 years old. -------------------------------------------------------------------------------- /demos/js/simulate/myCreate.js: -------------------------------------------------------------------------------- 1 | function myObjectCreate(proto, propertiesObject) { 2 | if (typeof proto!== 'object' && typeof proto!== 'function') { 3 | throw new TypeError('The first argument must be an object or null'); 4 | } 5 | 6 | // 创建一个临时构造函数 7 | function F() {} 8 | 9 | // 将临时构造函数的原型指向 proto 10 | F.prototype = proto; 11 | 12 | // 使用临时构造函数创建新对象 13 | let obj = new F(); 14 | 15 | // 如果提供了 propertiesObject,则为新对象定义属性 16 | if (propertiesObject!== undefined) { 17 | Object.defineProperties(obj, propertiesObject); 18 | } 19 | 20 | // 如果 proto 为 null,则手动设置 obj 的 __proto__ 为 null 21 | if (proto === null) { 22 | Object.setPrototypeOf(obj, null); 23 | } 24 | 25 | return obj; 26 | } 27 | 28 | // 测试 29 | let parent = { 30 | name: 'parent', 31 | sayHello: function () { 32 | console.log('Hello from parent'); 33 | } 34 | }; 35 | 36 | let child = myObjectCreate(parent, { 37 | age: { 38 | value: 10, 39 | writable: true, 40 | enumerable: true, 41 | configurable: true 42 | } 43 | }); 44 | 45 | console.log(child.name); // 输出 'parent' 46 | child.sayHello(); // 输出 'Hello from parent' 47 | console.log(child.age); // 输出 10 -------------------------------------------------------------------------------- /demos/js/simulate/myCurring.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 柯里化 3 | */ 4 | 5 | /** 6 | * 参数复用 7 | * */ 8 | function multiply(a, b) { 9 | return a * b; 10 | } 11 | 12 | // 柯里化函数 13 | const curriedMultiply = (a) => (b) => a * b; 14 | 15 | // 固定第一个参数为 5 16 | const multiplyBy5 = curriedMultiply(5); 17 | 18 | // 多次使用 multiplyBy5 19 | console.log(multiplyBy5(3)); // 输出 15 20 | console.log(multiplyBy5(4)); // 输出 20 21 | 22 | 23 | /** 24 | * 柯里化函数 25 | * 使用场景 26 | * - 参数复用 27 | * - 延迟执行 28 | * - 函数组合 29 | * - 事件处理 30 | * - 提高代码可测试性 31 | */ -------------------------------------------------------------------------------- /demos/js/simulate/myDebounce.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc 无论多少次都是用最后一次 3 | * 4 | */ 5 | function debounce(fn, wait = 50) { 6 | let timer = null; 7 | return function (...args) { 8 | if (timer) clearTimeout(timer); 9 | timer = setTimeout(() => { 10 | fn.apply(this, args); 11 | }, wait); 12 | }; 13 | } 14 | 15 | const betterFn = debounce(() => { 16 | console.log('go to ==>'); 17 | }, 200); 18 | 19 | // document.addEventListener('scroll', betterFn); 20 | 21 | /** ***************** */ 22 | 23 | function myDebounce(fn, wait = 50) { 24 | let timer = null; 25 | 26 | debugger 27 | return (...args) => { 28 | debugger 29 | console.log('hah=>', args); 30 | if (timer) clearTimeout(timer); 31 | timer = setTimeout(() => { 32 | fn.apply(this, args); 33 | }, wait); 34 | }; 35 | } 36 | 37 | const betterFn1 = myDebounce(() => { 38 | console.log('go to ==>'); 39 | }, 200); 40 | 41 | betterFn1(111,222) -------------------------------------------------------------------------------- /demos/js/simulate/myDecoration.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 伪代码,需要转码才可以执行~ 3 | */ 4 | // 装饰器函数 5 | function log(target, name, descriptor) { 6 | const originalMethod = descriptor.value; 7 | descriptor.value = function (...args) { 8 | console.log(`调用方法 ${name},参数为:`, args); 9 | const result = originalMethod.apply(this, args); 10 | console.log(`方法 ${name} 执行完毕,结果为:`, result); 11 | return result; 12 | }; 13 | return descriptor; 14 | } 15 | 16 | class MyClass { 17 | @log 18 | add(a, b) { 19 | return a + b; 20 | } 21 | } 22 | 23 | // 使用 24 | const myClass = new MyClass(); 25 | myClass.add(2, 3); 26 | -------------------------------------------------------------------------------- /demos/js/simulate/myEventEmitter.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/demos/js/simulate/myEventEmitter.js -------------------------------------------------------------------------------- /demos/js/simulate/myGetPrototypeOf.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/demos/js/simulate/myGetPrototypeOf.js -------------------------------------------------------------------------------- /demos/js/simulate/myInstanceOf.js: -------------------------------------------------------------------------------- 1 | /* 2 | 当使用 a instanceof b 时,JavaScript 引擎会按照以下步骤进行判断: 3 | 首先获取 a 的原型,即 a.__proto__。 4 | 然后获取 b 的原型属性,即 b.prototype。 5 | 接着检查 a.__proto__ 是否与 b.prototype 相等。如果相等,则 a instanceof b 返回 true。 6 | 如果不相等,就继续沿着 a 的原型链向上查找,即检查 a.__proto__.__proto__ 是否与 b.prototype 相等,以此类推 7 | 直到找到相等的情况或者到达原型链的顶端(null)。如果到达原型链顶端仍未找到相等的情况,则 a instanceof b 返回 false。 8 | */ 9 | function myInstanceOf(a, b) { 10 | let proto = Object.getPrototypeOf(a); 11 | let prototype = b.prototype; 12 | 13 | while (true) { 14 | debugger 15 | if (proto === null) { 16 | return false; 17 | } 18 | if (proto === prototype) { 19 | return true; 20 | } 21 | debugger 22 | proto = Object.getPrototypeOf(proto); 23 | } 24 | } 25 | 26 | // 测试 27 | let arr = []; 28 | // console.log(myInstanceOf(arr, Array)); // true 29 | // console.log(myInstanceOf(arr, Object)); // true 30 | console.log(myInstanceOf(arr, Function)); // false 31 | -------------------------------------------------------------------------------- /demos/js/simulate/myJSON-parse.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/demos/js/simulate/myJSON-parse.js -------------------------------------------------------------------------------- /demos/js/simulate/myJSON-stringify.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/demos/js/simulate/myJSON-stringify.js -------------------------------------------------------------------------------- /demos/js/simulate/myLazy.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/demos/js/simulate/myLazy.js -------------------------------------------------------------------------------- /demos/js/simulate/myNew.js: -------------------------------------------------------------------------------- 1 | function myNew(fn, ...args) { 2 | const obj = Object.create(fn.prototype); 3 | const result = fn.apply(obj, args); 4 | return typeof result === 'object' ? result : obj; 5 | } 6 | 7 | function fn(name) { 8 | this.name = name; 9 | } 10 | 11 | const x = myNew(fn, '6666'); 12 | 13 | console.log(x.name); 14 | -------------------------------------------------------------------------------- /demos/js/simulate/mySubscribe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 手动订阅模式 3 | */ 4 | -------------------------------------------------------------------------------- /demos/js/simulate/mySymbol.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 核心逻辑:函数的 return 出参不一样 3 | */ 4 | // 创建一个计数器 5 | let symbolCounter = 0; 6 | 7 | // 创建一个函数来生成唯一的标识符 8 | function mySymbol() { 9 | const uniqueId = `mySymbol_${symbolCounter++}`; 10 | return { 11 | toString: function () { 12 | return uniqueId; 13 | }, 14 | valueOf: function () { 15 | return uniqueId; 16 | } 17 | }; 18 | } 19 | 20 | // 使用自定义的mySymbol 21 | let sym1 = mySymbol(); 22 | let sym2 = mySymbol(); 23 | 24 | console.log(sym1 === sym2); // false 25 | console.log(sym1.toString()); // mySymbol_0 26 | console.log(sym2.toString()); // mySymbol_1 27 | 28 | -------------------------------------------------------------------------------- /demos/js/simulate/myThrottle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 节流函数 3 | * - 一定时间才执行一次,无论多少次 4 | * - 上传文件进度 5 | * - windows.resize 6 | * - input 查询 7 | * 8 | * */ 9 | 10 | const throttle = (fn, wait = 50) => { 11 | let pre = 0; 12 | 13 | return function(...args) { 14 | let now = new Date(); 15 | if (now - pre > wait) { 16 | pre = now; 17 | fn.apply(this, args); 18 | } 19 | }; 20 | }; 21 | 22 | const fn = throttle(() => { 23 | console.log(new Date()); 24 | }); 25 | 26 | document.addEventListener("scroll", fn); 27 | -------------------------------------------------------------------------------- /demos/js/simulate/myWatcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 观察者模式 3 | */ 4 | -------------------------------------------------------------------------------- /demos/js/simulate/promise-class-all.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * 1. TODO 如何实现链式调用 4 | * 2. Promise 实例有三个方法 5 | * - then 6 | * - catch 7 | * - finally 8 | * 3. Promise 有6个静态方法 9 | * 4. 10 | * static #fns 私有静态 11 | * static fns 公有静态 12 | * 13 | */ 14 | class PromiseClass { 15 | static thenList = []; 16 | static catchList = []; 17 | constructor(fn) { 18 | this.fns = [fn]; 19 | this.thenList = []; 20 | // console.log("fn=>", fn); 21 | // console.log("typeof fn=>", typeof fn); 22 | // console.log("typeof fns=>", typeof this.fns); 23 | // console.log("this=>", this); 24 | 25 | fn.call(null, PromiseClass.resolved); // 通过call 显式转移内部的 param 26 | fn.call(null, PromiseClass.rejected); // 通过call 显式转移内部的 param 27 | } 28 | static resolved(...args) { 29 | const resolveParam = args[0]; 30 | // PromiseClass.then.call(this, resolveParam); 31 | 32 | PromiseClass.thenList.shift().call(this, resolveParam); 33 | 34 | for (let i = 0; i < PromiseClass.thenList.length; i++) { 35 | const returnThen = PromiseClass.thenList[i]; 36 | console.log("returnThen=>", returnThen.call(this, returnThen)); 37 | } 38 | } 39 | static rejected(...args) { 40 | const rejectParam = args[0]; 41 | for (let i = 0; i < PromiseClass.catchList.length; i++) { 42 | PromiseClass.catchList[i].call(this, rejectParam); 43 | } 44 | } 45 | 46 | /** 47 | * @desc promise instance method: then 48 | * @TODO 这个then 是在 resolve 里面异步后再被动执行的 49 | * 50 | */ 51 | then(...args) { 52 | const thenParam = args[0]; 53 | PromiseClass.thenList.push(thenParam); 54 | return this; 55 | } 56 | 57 | /** 58 | * @desc promise instance method: catch 59 | * @TODO 60 | * 61 | */ 62 | catch(...args) { 63 | const catchParam = args[0]; 64 | PromiseClass.catchList.push(catchParam); 65 | return this; 66 | } 67 | 68 | /** 69 | * @desc promise instance method: finally 70 | * @TODO 71 | * 72 | */ 73 | finally() {} 74 | 75 | /** 76 | * @TODO 77 | * 78 | */ 79 | static all(arg) { 80 | console.log("this", arg); 81 | } 82 | static resolve() {} 83 | /** 84 | * @TODO 85 | * 86 | */ 87 | static reject() {} 88 | /** 89 | * @TODO 90 | * 91 | */ 92 | static race() {} 93 | /** 94 | * @TODO 95 | * 96 | */ 97 | static any() {} 98 | /** 99 | * @TODO 100 | * 101 | */ 102 | static finally() {} 103 | /** 104 | * @TODO 105 | * 106 | */ 107 | static allSettled() {} 108 | } 109 | 110 | // PromiseClass.all(11); 111 | 112 | // console.log(PromiseClass); 113 | 114 | /** 115 | * Promise 内部的如何调用 resolve 这个两个参数? 116 | * @Test 如果then里不return res 为undefined 117 | * 118 | */ 119 | 120 | module.exports = PromiseClass; 121 | -------------------------------------------------------------------------------- /demos/js/test_function_name_anonymous_arrow.js: -------------------------------------------------------------------------------- 1 | /*********************** 2 | * @name JS 3 | * @author Jo.gel 4 | * @date 2019/8/20 0020 下午 5:38 5 | ***********************/ 6 | 7 | console.time('具名函数'); 8 | var a=[66,99,44].map(function hello(item) { 9 | return item*2 10 | }); 11 | console.timeEnd('具名函数'); 12 | 13 | 14 | // 不清楚和以下有什么区别: 15 | 16 | console.time('匿名函数'); 17 | var b =[66,99,44].map(function(item) { 18 | return item*2 19 | }); 20 | console.timeEnd('匿名函数'); 21 | 22 | 23 | // 而如果使用箭头函数,则为: 24 | 25 | console.time('箭头函数'); 26 | var c=[66,99,44].map(item=>item*2); 27 | console.timeEnd('箭头函数'); 28 | 29 | 30 | // 测试结果发现函数的执行时间: 箭头函数<匿名函数<具名函数 31 | // -9007199254710991——9007199254710991 -------------------------------------------------------------------------------- /demos/proxy.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc Proxy 代理 实验 3 | * @todo Proxy第一个参数是干啥的? 4 | * @param 5 | * 6 | */ 7 | 8 | // const targetObj = {}; 9 | // const handler = { 10 | // get: function(target, propKey, receiver) { 11 | // console.log('getting===>',propKey); 12 | // return Reflect.get(target, propKey, receiver); 13 | // }, 14 | // set: function(target, propKey, value, receiver) { 15 | // console.log('setting===>',propKey); 16 | // return Reflect.set(target, propKey, value, receiver); 17 | // /* 18 | // set(target,prop,value){ 19 | // target[prop] = value 20 | 21 | // } 22 | // */ 23 | // }, 24 | // }; 25 | 26 | // const obj = new Proxy(targetObj, handler); 27 | // obj.aa=22 28 | // console.log(obj); 29 | 30 | 31 | /** Handler array */ 32 | const arrayData = [ 33 | {name:"Lee"}, 34 | {name:"Lisa"}, 35 | {name:"rookie"}, 36 | ] 37 | 38 | const proxy = new Proxy(arrayData,{ 39 | get(target,prop){ 40 | return target[prop] 41 | }, 42 | set(target,prop,value){ 43 | target[prop]=value 44 | } 45 | }) 46 | 47 | console.log(arrayData[1]) 48 | console.log(proxy[2]) -------------------------------------------------------------------------------- /demos/qij.js: -------------------------------------------------------------------------------- 1 | 2 | // let ob = { 3 | // '1': '∞', 4 | // '2': 'abc', 5 | // '3': 'def', 6 | // '4': 'ghi', 7 | // '5': 'jkl', 8 | // '6': 'mno', 9 | // '7': 'pqrs', 10 | // '8': 'tuv', 11 | // '9': 'wxyz', 12 | // '0': '+', 13 | // '*': ' ', 14 | // '↑': '#' 15 | // } 16 | // let arrNum = [1, 2, 3, 4, 5, 6, 7, 8, 9, '*', '0', '↑'];//∞ + ' ' # 17 | // function func(string) { 18 | // let stringData = (string.toString()).split('') //切割为数组 19 | // let len = stringData.length || 1; 20 | // let arrCount = [] 21 | // // 入参多少次数据? 22 | // for (let i = 0; i < len; i++) { 23 | // let tempArr = ob[stringData[i]].split('')//值的数组 24 | // arrCount.push(tempArr) 25 | // } 26 | // console.info(arrCount) 27 | // return arrCount 28 | // } 29 | // func(194) 30 | 31 | 32 | 33 | /*********************************************/ 34 | // var arr = []; 35 | // var a = ['b', 'c']; var b = ['e', 'f', 'g','h']; 36 | // for (let i = 0; i < 2; i++) { 37 | // for (let k = 0; k < b.length; k++) { 38 | // arr.push(a[i]+b[k]) 39 | // }; 40 | // }; 41 | // console.info(arr) 42 | 43 | // ['a']、 ['b','c']、['d','e','f'] abd,abe,abf,acd,ace,acf= 2x3=6的长度 44 | 45 | let arr1 = [['∞'], ['w', 'x', 'y', 'z'], ['g', 'h', 'i']] 46 | let temp = [] 47 | function p1(arr) { 48 | let s = '' 49 | for (let i = 0; i < arr.length; i++) { 50 | s = s + arr[i] 51 | temp.push(s) 52 | return p1(arr[i]) 53 | } 54 | } 55 | p1(arr1) 56 | 57 | 58 | 59 | // Math.round(Math.random())?Math.round(Math.random()):Math.round(Math.random())-1 60 | 61 | /**数据动态绑定基本实现 **/ 62 | let obj = { 63 | key_1: 1, 64 | key_2: 2 65 | } 66 | function func(key) { 67 | console.info(key + '的值子发生变化' + this[key]) 68 | } 69 | 70 | function bindData(obj, func) { 71 | for (let item in obj) { 72 | Object.defineProperty(obj, item, { 73 | get: function () { 74 | return obj.item; 75 | }, 76 | set: function (value) { 77 | obj.item = value; 78 | func.bind(obj)(item); 79 | } 80 | }) 81 | } 82 | } 83 | bindData(obj, func) 84 | obj.key_1 = 2;//此时自动输出 变化为2 85 | obj.key_2 = 1 //此时自动输出变化为1 86 | 87 | /** 对json 数据结构进行处理,要求找到child 超过两个的name值 **/ 88 | 89 | let data={ 90 | name:'jack', 91 | child:[ 92 | {name:'jack1'}, 93 | {name:'jack2',child:[ 94 | {name:'jack2_1',child:{name:'jack2-1-1'}}, 95 | {name:'jack2_2'} 96 | ]}, 97 | {name:'jack3',child:{name:'jack3-1'}} 98 | ] 99 | }; 100 | Object.keys(data)//只能取同级的keys值 -------------------------------------------------------------------------------- /demos/reflect.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc Reflect 反射,可以使用Object安全性底层的方法 3 | * 4 | */ 5 | var obj=new Proxy(obj,{ 6 | get(target,name){ 7 | console.log('get',target,name) 8 | return Reflect.get(target,name) 9 | }, 10 | deleteProperty(target,name){ 11 | console.log('delete ',name) 12 | return Reflect.deleteProperty(target,name) 13 | }, 14 | has(target,name){ 15 | console.log('has',name) 16 | return Reflect.has(target,name) 17 | } 18 | }) -------------------------------------------------------------------------------- /demos/tests/promise-class-all.spec.js: -------------------------------------------------------------------------------- 1 | const PromiseClass = require("../html/promise-class-all"); 2 | describe("Promise/then", () => { 3 | it("1. Promise 实例第一个 then是可以执行", () => { 4 | const p = new PromiseClass(function(resolve, reject) { 5 | setTimeout(function() { 6 | resolve("success!", "这个是忽略的参数"); 7 | // resolve("failed!", "这个是忽略的参数"); 8 | }, 2000); 9 | }); 10 | p.then((one) => { 11 | expect(one).to("success!"); 12 | }); 13 | }); 14 | 15 | it("2. Promise 实例第二个 then 的值应该是undefined", () => { 16 | const p = new PromiseClass(function(resolve, reject) { 17 | setTimeout(function() { 18 | resolve("success!", "这个是忽略的参数"); 19 | // resolve("failed!", "这个是忽略的参数"); 20 | }, 2000); 21 | }); 22 | p.then((one) => { 23 | expect(one).to("success!"); 24 | }).then((two) => { 25 | expect(two).toBe(undefined); 26 | }); 27 | }); 28 | it("3. Promise 实例第二个 then 的值应该是 return 到下一个then", () => { 29 | const p = new PromiseClass(function(resolve, reject) { 30 | setTimeout(function() { 31 | resolve("success!", "这个是忽略的参数"); 32 | // resolve("failed!", "这个是忽略的参数"); 33 | }, 2000); 34 | }); 35 | p.then((one) => { 36 | expect(one).to("success!"); 37 | return 1; 38 | }).then((two) => { 39 | expect(two).toBe(1); 40 | }); 41 | }); 42 | 43 | // TODO 44 | it("4. Promise 实例第一个 then 的第二个参数为catch", () => { 45 | const p = new PromiseClass(function(resolve, reject) { 46 | setTimeout(function() { 47 | resolve("success!", "这个是忽略的参数"); 48 | // resolve("failed!", "这个是忽略的参数"); 49 | }, 2000); 50 | }); 51 | p.then((one) => { 52 | expect(one).to("success!"); 53 | return 1; 54 | }).then((two) => { 55 | expect(two).toBe(1); 56 | }); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /docs/.vuepress/README.md: -------------------------------------------------------------------------------- 1 | # 关于此Vuepress 主题的开发 2 | 3 | - [Emoji](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.json) 4 | - 支持自定义logo,比如实验icon(烧杯形状) 5 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // base: "/web-advanced-frond-end/", 3 | title: "进阶web高级前端知识体系", 4 | author: "veaba", 5 | description: "进阶web高级前端知识体系", 6 | displayAllHeaders: true, // 默认值:false 7 | // locales:{},//多语言支持 https://vuepress.vuejs.org/zh/guide/i18n.html 8 | scss: {}, 9 | locales: { 10 | "/": { 11 | lang: "zh-CN", 12 | title: "进阶web高级前端知识体系", 13 | description: "面对web技术全栈,来自@veaba 个人学习笔记以及公开博客文章整理" 14 | } 15 | }, 16 | themeConfig: { 17 | repo: "veaba/web-advanced-frond-end", 18 | logo: "/favicon.png", 19 | locales: { 20 | //主站是中文版 21 | "/": { 22 | label: "简体中文", 23 | selectText: "选择语言", 24 | editLinkText: "在Github上编辑此页", 25 | nav: require("./nav/zh"), 26 | // sidebar: 'auto' 27 | }, 28 | } 29 | }, 30 | // 修改内部webpack的配置 31 | chinWebpack: (config, isServer) => {}, 32 | // vuepress-plugin-container 容器 33 | plugins: [ 34 | // tip 35 | [ 36 | "container", 37 | { 38 | type: "tip", 39 | before: title => 40 | `

${title}

`, 41 | after: "
" 42 | } 43 | ], 44 | [ 45 | "container", 46 | { 47 | type: "warning", 48 | before: title => 49 | `

${title}

`, 50 | after: "
" 51 | } 52 | ], 53 | [ 54 | "container", 55 | { 56 | type: "danger", 57 | before: title => 58 | `

${title}

`, 59 | after: "
" 60 | } 61 | ] 62 | ], 63 | extraWatchFiles: [".vuepress/nav/zh.js"] 64 | }; 65 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | /*********************** 2 | * @desc 自定义主题根目录下进行拓展配置 3 | * @name JS 4 | * @author Jo.gel 5 | * @date 2019/8/1 0001 6 | ***********************/ 7 | export default ( 8 | { 9 | Vue, 10 | options, 11 | router, 12 | siteData, 13 | } 14 | ) => { 15 | // console.info(router); 16 | // console.info(siteData); 17 | // console.info(router.currentRoute); 18 | // console.info(options); 19 | // console.info(Vue.prototype); 20 | } 21 | -------------------------------------------------------------------------------- /docs/.vuepress/nav/zh.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | text: '指南', 4 | link: '/guide/' 5 | }, 6 | { 7 | text: 'actix-web', 8 | link: '/rust/actix-web/' 9 | }, 10 | { 11 | text: 'JavaScript', 12 | link: '/javascript/' 13 | }, 14 | { 15 | text: 'Node', 16 | link: '/node/' 17 | }, 18 | { 19 | text: '面试题', 20 | link: '/interview/' 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/favicon.ico -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/favicon.png -------------------------------------------------------------------------------- /docs/.vuepress/public/html/border-box-children.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/html/border-box-children.png -------------------------------------------------------------------------------- /docs/.vuepress/public/html/border-box-parent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/html/border-box-parent.png -------------------------------------------------------------------------------- /docs/.vuepress/public/html/content-box-children.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/html/content-box-children.png -------------------------------------------------------------------------------- /docs/.vuepress/public/html/content-box-parent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/html/content-box-parent.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/flex-right-center-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/flex-right-center-right.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/float-left-center-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/float-left-center-right.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/margin(pref)-left-center-right-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/margin(pref)-left-center-right-1.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/margin(pref)-left-center-right-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/margin(pref)-left-center-right-2.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/margin(pref)-left-center-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/margin(pref)-left-center-right.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/css/position-left-center-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/css/position-left-center-right.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/fib.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/fib.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/images/http/baidu-cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/http/baidu-cache.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/http/cache-304.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/http/cache-304.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/ie-leak.GIF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/ie-leak.GIF -------------------------------------------------------------------------------- /docs/.vuepress/public/images/isArray.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/isArray.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/images/isTypeSupported.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/isTypeSupported.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/images/src-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/src-2.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/images/src.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/src.jpg -------------------------------------------------------------------------------- /docs/.vuepress/public/images/time-complex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/time-complex.png -------------------------------------------------------------------------------- /docs/.vuepress/public/images/vue-prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/images/vue-prototype.png -------------------------------------------------------------------------------- /docs/.vuepress/public/pic-hospital-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/.vuepress/public/pic-hospital-bg.png -------------------------------------------------------------------------------- /docs/.vuepress/theme/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018-present, Yuxi (Evan) You 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/DropdownTransition.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Home.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 75 | 76 | 166 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Keyword.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/NavLink.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 50 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/NavLinks.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 117 | 118 | 150 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Navbar.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 87 | 88 | 129 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 22 | 23 | 60 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarButton.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarLink.vue: -------------------------------------------------------------------------------- 1 | 95 | 96 | 126 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/components/SidebarLinks.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 87 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/global-components/Badge.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 45 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/global-components/Catalog.vue: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 49 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | // Theme API. 4 | module.exports = (options, ctx) => ({ 5 | alias () { 6 | const { themeConfig, siteConfig } = ctx 7 | // resolve algolia 8 | const isAlgoliaSearch = ( 9 | themeConfig.algolia 10 | || Object.keys(siteConfig.locales && themeConfig.locales || {}) 11 | .some(base => themeConfig.locales[base].algolia) 12 | ) 13 | return { 14 | '@AlgoliaSearchBox': isAlgoliaSearch 15 | ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue') 16 | : path.resolve(__dirname, 'noopModule.js') 17 | } 18 | }, 19 | 20 | plugins: [ 21 | ['@vuepress/active-header-links', options.activeHeaderLinks], 22 | '@vuepress/search', 23 | '@vuepress/plugin-nprogress', 24 | ['container', { 25 | type: 'tip', 26 | defaultTitle: { 27 | '/zh/': '提示' 28 | } 29 | }], 30 | ['container', { 31 | type: 'warning', 32 | defaultTitle: { 33 | '/zh/': '注意' 34 | } 35 | }], 36 | ['container', { 37 | type: 'danger', 38 | defaultTitle: { 39 | '/zh/': '警告' 40 | } 41 | }] 42 | ] 43 | }) 44 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/404.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/layouts/Layout.vue: -------------------------------------------------------------------------------- 1 | 53 | 54 | 152 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/noopModule.js: -------------------------------------------------------------------------------- 1 | export default {} 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/arrow.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | .arrow 4 | display inline-block 5 | width 0 6 | height 0 7 | &.up 8 | border-left 4px solid transparent 9 | border-right 4px solid transparent 10 | border-bottom 6px solid $arrowBgColor 11 | &.down 12 | border-left 4px solid transparent 13 | border-right 4px solid transparent 14 | border-top 6px solid $arrowBgColor 15 | &.right 16 | border-top 4px solid transparent 17 | border-bottom 4px solid transparent 18 | border-left 6px solid $arrowBgColor 19 | &.left 20 | border-top 4px solid transparent 21 | border-bottom 4px solid transparent 22 | border-right 6px solid $arrowBgColor 23 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/code.styl: -------------------------------------------------------------------------------- 1 | {$contentClass} 2 | code 3 | color lighten($textColor, 20%) 4 | padding 0.25rem 0.5rem 5 | margin 0 6 | font-size 0.85em 7 | background-color rgba(27,31,35,0.05) 8 | border-radius 3px 9 | .token 10 | &.deleted 11 | color #EC5975 12 | &.inserted 13 | color $accentColor 14 | 15 | {$contentClass} 16 | pre, pre[class*="language-"] 17 | line-height 1.4 18 | padding 1.25rem 1.5rem 19 | margin 0.85rem 0 20 | background-color $codeBgColor 21 | border-radius 6px 22 | overflow auto 23 | code 24 | color #fff 25 | padding 0 26 | background-color transparent 27 | border-radius 0 28 | 29 | div[class*="language-"] 30 | position relative 31 | background-color $codeBgColor 32 | border-radius 6px 33 | .highlight-lines 34 | user-select none 35 | padding-top 1.3rem 36 | position absolute 37 | top 0 38 | left 0 39 | width 100% 40 | line-height 1.4 41 | .highlighted 42 | background-color rgba(0, 0, 0, 66%) 43 | pre, pre[class*="language-"] 44 | background transparent 45 | position relative 46 | z-index 1 47 | &::before 48 | position absolute 49 | z-index 3 50 | top 0.8em 51 | right 1em 52 | font-size 0.75rem 53 | color rgba(255, 255, 255, 0.4) 54 | &:not(.line-numbers-mode) 55 | .line-numbers-wrapper 56 | display none 57 | &.line-numbers-mode 58 | .highlight-lines .highlighted 59 | position relative 60 | &:before 61 | content ' ' 62 | position absolute 63 | z-index 3 64 | left 0 65 | top 0 66 | display block 67 | width $lineNumbersWrapperWidth 68 | height 100% 69 | background-color rgba(0, 0, 0, 66%) 70 | pre 71 | padding-left $lineNumbersWrapperWidth + 1 rem 72 | vertical-align middle 73 | .line-numbers-wrapper 74 | position absolute 75 | top 0 76 | width $lineNumbersWrapperWidth 77 | text-align center 78 | color rgba(255, 255, 255, 0.3) 79 | padding 1.25rem 0 80 | line-height 1.4 81 | br 82 | user-select none 83 | .line-number 84 | position relative 85 | z-index 4 86 | user-select none 87 | font-size 0.85em 88 | &::after 89 | content '' 90 | position absolute 91 | z-index 2 92 | top 0 93 | left 0 94 | width $lineNumbersWrapperWidth 95 | height 100% 96 | border-radius 6px 0 0 6px 97 | border-right 1px solid rgba(0, 0, 0, 66%) 98 | background-color $codeBgColor 99 | 100 | for lang in $codeLang 101 | div{'[class~="language-' + lang + '"]'} 102 | &:before 103 | content ('' + lang) 104 | 105 | div[class~="language-javascript"] 106 | &:before 107 | content "js" 108 | 109 | div[class~="language-typescript"] 110 | &:before 111 | content "ts" 112 | 113 | div[class~="language-markup"] 114 | &:before 115 | content "html" 116 | 117 | div[class~="language-markdown"] 118 | &:before 119 | content "md" 120 | 121 | div[class~="language-json"]:before 122 | content "json" 123 | 124 | div[class~="language-ruby"]:before 125 | content "rb" 126 | 127 | div[class~="language-python"]:before 128 | content "py" 129 | 130 | div[class~="language-bash"]:before 131 | content "sh" 132 | 133 | div[class~="language-php"]:before 134 | content "php" 135 | 136 | @import '~prismjs/themes/prism-tomorrow.css' 137 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/config.styl: -------------------------------------------------------------------------------- 1 | $contentClass = '.theme-default-content' 2 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/custom-blocks.styl: -------------------------------------------------------------------------------- 1 | .custom-block 2 | .custom-block-title 3 | font-weight 600 4 | margin-bottom -0.4rem 5 | &.tip, &.warning, &.danger 6 | padding .1rem 1.5rem 7 | border-left-width .5rem 8 | border-left-style solid 9 | margin 1rem 0 10 | &.tip 11 | background-color #f3f5f7 12 | border-color #42b983 13 | &.warning 14 | background-color rgba(255,229,100,.3) 15 | border-color darken(#ffe564, 35%) 16 | color darken(#ffe564, 70%) 17 | .custom-block-title 18 | color darken(#ffe564, 50%) 19 | a 20 | color $textColor 21 | &.danger 22 | background-color #ffe6e6 23 | border-color darken(red, 20%) 24 | color darken(red, 70%) 25 | .custom-block-title 26 | color darken(red, 40%) 27 | a 28 | color $textColor 29 | 30 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/mobile.styl: -------------------------------------------------------------------------------- 1 | @require './config' 2 | 3 | $mobileSidebarWidth = $sidebarWidth * 0.82 4 | 5 | // narrow desktop / iPad 6 | @media (max-width: $MQNarrow) 7 | .sidebar 8 | font-size 15px 9 | width $mobileSidebarWidth 10 | .page 11 | padding-left $mobileSidebarWidth 12 | 13 | // wide mobile 14 | @media (max-width: $MQMobile) 15 | .sidebar 16 | top 0 17 | padding-top $navbarHeight 18 | transform translateX(-100%) 19 | transition transform .2s ease 20 | .page 21 | padding-left 0 22 | .theme-container 23 | &.sidebar-open 24 | .sidebar 25 | transform translateX(0) 26 | &.no-navbar 27 | .sidebar 28 | padding-top: 0 29 | 30 | // narrow mobile 31 | @media (max-width: $MQMobileNarrow) 32 | h1 33 | font-size 1.9rem 34 | {$contentClass} 35 | div[class*="language-"] 36 | margin 0.85rem -1.5rem 37 | border-radius 0 38 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/toc.styl: -------------------------------------------------------------------------------- 1 | .table-of-contents 2 | .badge 3 | vertical-align middle 4 | -------------------------------------------------------------------------------- /docs/.vuepress/theme/styles/wrapper.styl: -------------------------------------------------------------------------------- 1 | $wrapper 2 | max-width $contentWidth 3 | margin 0 auto 4 | padding 2rem 2.5rem 5 | @media (max-width: $MQNarrow) 6 | padding 2rem 7 | @media (max-width: $MQMobileNarrow) 8 | padding 1.5rem 9 | 10 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | actionText: 立即阅读 → 4 | actionLink: /guide.html 5 | icpText: veaba/web-advanced-frond-end 6 | icpLink: https://github.com/veaba/web-advanced-frond-end 7 | footer: Copyright © 2020-present compile by 8 | --- 9 | 10 |
11 |
12 | 13 |
14 |
15 |

开源(Open Source)

16 |

Github开源文档

17 |
18 |
19 |

下载(Download)

20 |

免费,任何人都可以免费获得本文档

21 |
22 |
23 |

个人学习整理

24 |

有自己学习或参考别人的

25 |
26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 |

TODO

34 |

近期自我驱动项目

35 | 46 |
47 |
48 |

个人博客

49 |

来自@veaba

50 | 58 |
59 |
60 |

关键词

61 |

必须知道的概念

62 |
63 |
64 | -------------------------------------------------------------------------------- /docs/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 关于 6 | 7 | 此网站是[@veaba](https://github.com/veaba) 个人技术点笔记梳理. 8 | -------------------------------------------------------------------------------- /docs/algorithm/README.md: -------------------------------------------------------------------------------- 1 | # 算法 2 | 3 | ## 时间复杂度 4 | 5 | **量级**: 6 | 7 | - 常数阶 O(1) 8 | ↓ 9 | - 对数阶 O(logN) 10 | ↓ 11 | - 线性阶 O(n) 12 | ↓ 13 | - 平方阶 O(n2) 14 | ↓ 15 | - 立方阶 O(n3) 16 | ↓ 17 | - K 次方阶 O(n^k) 18 | ↓ 19 | - 指数阶 O(2^n) 20 | ↓ 21 | 22 | 越下面,执行的效率越低。 23 | 24 | ![](/images/time-complex.png) 25 | 26 | **常数节**:时间复杂度只有 O(1) 27 | 28 | ```js 29 | var a = 0; 30 | 31 | var b = 0; 32 | 33 | a++; 34 | 35 | // or 此处的时间复杂度也是 O(n) 常数阶 36 | 37 | function total() { 38 | let sum = 0; 39 | for (let i = 0; i < 100; i++) { 40 | sum++; 41 | } 42 | } 43 | 44 | // O(n2) 45 | 46 | function total() { 47 | let sum = 0; 48 | for (let i = 0; i < 100; i++) { 49 | for (let j = 0; j < 100; j++) { 50 | sum++; 51 | } 52 | } 53 | } 54 | 55 | // 特殊的比较 O(m+n),无法比较n 、m 大小 56 | 57 | function total3(n, m) { 58 | let sum = 0; 59 | for (let i = 0; i < n; i++) { 60 | sum += i; 61 | } 62 | let sum2 = 0; 63 | for (let j = 0; j < m; i++) { 64 | sum2 += i; 65 | } 66 | return sum + sum2; 67 | } 68 | 69 | // 特殊的比较 O(n*m) 70 | function total4(n, m) { 71 | let sumN = 0; 72 | let sumM = 0; 73 | for (let i = 0; i < n; i++) { 74 | sumN += i; 75 | for (let j = 0; j < m; j++) { 76 | sumM += j; 77 | } 78 | } 79 | return sumN * sumM; 80 | } 81 | ``` 82 | 83 | **线性阶 O(n)**: 84 | 85 | **对数阶 O(logN)**: 86 | 87 | ```js 88 | function total() { 89 | let sum = 0; 90 | let i = 1; 91 | while (i <= n) { 92 | sum += 1; 93 | i = i * 2; 94 | } 95 | } 96 | 97 | function total2() { 98 | let sum = 0; 99 | for (let i = 0; i < n; i = i * 2) { 100 | sum += 1; 101 | } 102 | } 103 | ``` 104 | 105 | `2x=n` => `x=log2n`,这两者的时间复杂度为 O(log2n) 106 | 107 | ## 空间复杂度 108 | 109 | 空间复杂度:表示算法的存储空间和数据规模之间的关系 110 | 111 | ```js 112 | // 根据时间复杂度推算,忽略常数量级,每次数组都申请一个空间存储量,此时的空间复杂度为 O(n) 113 | function initArray(n) { 114 | const arr = []; 115 | for (let i = 0; i < n; i++) { 116 | arr[i]; 117 | } 118 | } 119 | ``` 120 | 121 | **0(1) 空间复杂度**: 122 | **O(n) 空间复杂度**: 123 | 124 | ```js 125 | function total(n) { 126 | let sum = 0; 127 | for (let i = 0; i <= n; i++) { 128 | sum += i; 129 | } 130 | return sum; 131 | } 132 | 133 | total(10); //45 134 | ``` 135 | 136 | 时间复杂度:O(n),但是,显然这里的时间复杂度是高了。 137 | 138 | ```js 139 | // 通过调整算法后,时间复杂度仅为 0(1) 140 | function total(n) { 141 | const sum = (n * (n + 1)) / 2; 142 | return n; 143 | } 144 | ``` 145 | 146 | 显然可以比较 `O(n)` > `O(1)`,这是算法的魅力,提高效率。 147 | **O(n2) 空间复杂度**: 148 | -------------------------------------------------------------------------------- /docs/canvas/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Canvas 6 | 7 | - 依赖分辨率 8 | - 不支持事件处理器 9 | - 弱文本渲染能力 10 | - 能够以图片形式保存结果 11 | - 最适合图片密集型的游戏,对象被频繁重绘 12 | - 逐像素进行渲染 13 | - 图形被绘制完成,就不会继续被浏览器关注,如果位置发生变化,需要重新绘制 14 | - canvas 不可以通过浏览器提供的接口获取到 TODO 15 | - drawImage 贴图受跨域限制 16 | 17 | ## RequestAnimationFrame 18 | -------------------------------------------------------------------------------- /docs/css/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Css部分 6 | 7 | - zoom与transform scale区别 8 | - CSS IFC inline formatting context 9 | > 内联格式上下文 10 | - CSS BFC block formatting context 11 | > 块级格式上下文。里面子元素不会影响到外面的元素 12 | 13 | ## CSS实现水平垂直居中的1010种方式(史上最全) 14 | - [CSS实现水平垂直居中](https://segmentfault.com/a/1190000016389031) 15 | 16 | ## 知识点 17 | - 外边距坍塌问题。块级之间共享垂直外边距,margin取最大值 18 | - 解决办法,给第二个兄弟加个父级,且给原兄弟使用margin 19 | - 当 `margin-top`、`padding-top` 值是百分比时,将以*父级块级元素的 width*、*相对父级块级元素的 width* 分别计算 20 | - `background-position`: 21 | - 该属性可有两个取值,第一个取值为背景图像与其容器在水平方向上的距离,第二个取值为背景图像与其容器在垂直方向上的距离 22 | - 若只有一个取值,则其第二个取值默认为50%; 23 | - 如果第一个值取关键词,则第二个默认值为:center 24 | - 若属性取值用left、center、right、top、bottom表示,则该属性取值的顺序可以颠倒,否则其取值顺序不能颠倒 25 | - 关于`link` 和 `@import`: 26 | - 页面被加载时,`link` 会同时被加载 27 | - `@import` 引用的css 会等到页面被加载完再加载 28 | - `@import` 只能加载 css,`link` 标签还可以定义 RSS 等 29 | - `@import` 是 css2.1提出,IE5 以上可识别,link 无兼容性问题 30 | - css 伪元素 31 | - active 必须位于 hover 之后 32 | - 顺序: 33 | 34 | - inline-block 可以设置高度 35 | - inline 不可以设置高度 36 | 37 | ### BFC 问题 38 | - BFC(Block formatting context),块级格式化上下文 39 | - 满足以下都可以触发 BFC 40 | - body 根元素 41 | - float元素:除以 none 意外的值 42 | - display: `inline-block`、`table-cells`、`flex` 43 | - overflow: 非 visible 的值( `hidden`、`auto`、`scroll` ) 44 | - position: `absolute` 45 | - BFC 浮动子元素也参与计算 46 | - BFC 页面隔离独立容器,容器的子元素不会影响到外部 47 | 48 | 49 | ## 可被继承的 css 属性 50 | 51 | ### 字体 52 | - `font-family` 53 | - `font-size` 54 | - `font-style` 55 | - `font-weight` 56 | - `font-stretch` 57 | - `font-size-adjust` 58 | 59 | ### 列表相关 60 | - `list-style` 61 | - `list-style-image` 62 | - `list-style-position` 63 | - `list-style-type` 64 | - `list-style-color` 65 | 66 | ### 文本继承 67 | - `text-indent` 68 | - `text-align` 69 | - `lint-height` 70 | - `word-spaceing` 71 | - `letter-spacing` 72 | - `text-transfomr` 73 | - `direction` 74 | - `color` 75 | 76 | ### 元素可见性 77 | - `visibility` 78 | 79 | ### 表格布局 80 | - `caption-side` 81 | - `border-collapse` 82 | - `border-spacing` 83 | - `empty-cells` 84 | - `table-layout` 85 | 86 | ### 生成内容 87 | - `quotes` 88 | 89 | ### 光标属性 90 | - `cursor` 91 | 92 | ### 页面样式 93 | - `page` 94 | - `page-break-inside` 95 | - `windows` 96 | - `orphans` 97 | 98 | ### 声音样式 99 | - `speak` 100 | - `speak-puncatuation` 101 | - `speak-numreal` 102 | - `speack-header` 103 | - `volume` 104 | - `voice-family` 105 | - `pitch` 106 | - `pitch-range` 107 | - `stress` 108 | - `richness` 109 | - `azimuth` 110 | - `elevation` 111 | 112 | ## 不可被继承的 css 属性 113 | - `display` 114 | - `margin` 115 | - `border` 116 | - `padding` 117 | - `background` 118 | - `height` 119 | - `min-height` 120 | - `max-height` 121 | - `width` 122 | - `min-height` 123 | - `max-height` 124 | - `overflow` 125 | - `position` 126 | - `left` 127 | - `right` 128 | - `top` 129 | - `bottom` 130 | - `z-index` 131 | - `float` 132 | - `clear` 133 | - `table-layout` 134 | - `vertical-align` 135 | - `page-break-after` 136 | - `page-break-before` 137 | - `unicode-bidi` 138 | 139 | ## css 选择符优先级 140 | 141 | - `! important`: infinite 142 | - `inline` 1000 143 | - `id`: 100 144 | - `class`、`attr`、`伪类`: 10 145 | - `标签`: 1 146 | - `*`: 0 147 | 148 | ## 伪类元素 149 | 150 | - first-of-type 151 | - nth-child(2) 152 | - disabled 153 | 154 | ::: 155 | 本页内容为网络收集整理所得 156 | ::: 157 | -------------------------------------------------------------------------------- /docs/css/animation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Animation 6 | -------------------------------------------------------------------------------- /docs/css/css3.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # CSS3 5 | 6 | ### anination-timing-function 7 | 8 | - `linear` 匀速 9 | - `ease` 默认,低速开始,加快,结束前变慢 10 | - `ease-in` 低速开始 11 | - `ease-out` 低速结束 12 | - `ease-in-out` 动画以低速开始和结束 13 | - `cubic-bezier(n,n,n,n)` 可能值范围0 - 1 14 | 15 | ### padding-top 16 | - 默认值,0 17 | 18 | ### maring-top 19 | - 默认值 0 20 | 21 | ### border-top-width 22 | - 默认值 medium 定义中等上边框 23 | 24 | ### outline-width 25 | - 默认值 medium 定义中等上边框 -------------------------------------------------------------------------------- /docs/deno/README.md: -------------------------------------------------------------------------------- 1 | # Deno docs 2 | 3 | - [官网](https://deno.land/) 4 | - [说明书](https://github.com/denoland/deno/tree/master/docs) 5 | - [API](https://doc.deno.land/https/github.com/denoland/deno/releases/latest/download/lib.deno.d.ts) 6 | - [deno-docs](https://github.com/veaba/deno-docs) 7 | - 使用官方文档做i18n,并支持双语,vuepress架构 8 | - 自动更新文档,并将需要更新的片段文件推送到/veaba/deno-docs 仓库的issues里面让作者对应手动更新 9 | - 目前约定1周更新一次文档 10 | - 脚本可以使用deno或者python来写 11 | - 自动翻译自动部署 12 | - 模块 13 | - [标准库](https://deno.land/std/) 14 | - [第三方库](https://deno.land/x/) 15 | -------------------------------------------------------------------------------- /docs/es6/proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Proxy 6 | 7 | - 只能是针对Proxy实例,如直接访问原对象不会有变化 8 | 9 | > 用于修改某些操作的默认行为,等同于在语言层作出修改,属于 “元编程”,meta programming by 阮一峰 [es6-proxy](##索引__关于本作知识引用来源sub标签 ) 10 | 11 | 理解:每当去12306去买票,都找一下黄牛哥,至于他干了啥,我们心里是没点数的。形成一个“代理”的机制。 12 | 13 | 在JS语言世界中,如果我们想去访问一个对象A(Object类型、可能是一个Function),对象A前面搭建了一座桥,这座桥可以过滤访客和改写返回的结果 14 | 15 | ```js 16 | 17 | const obj=new Proxy({},{ 18 | get:function(target,propKey,receiver){ 19 | console.log(`getting ${propKey}!`) 20 | return Reflect.get(target,propKey,receiver) 21 | }, 22 | set:function(target,propKey,value,receiver){ 23 | console.log(`setting ${propKey}!`) 24 | return Reflect.set(target,propKey,value,receiver) 25 | } 26 | }) 27 | 28 | 29 | // obj.name="hello world" 30 | // obj.name 31 | ``` 32 | 33 | ## es6 Proxy 定义声明 34 | - this 执行proxy 35 | 36 | ```js 37 | var proxy = new Proxy(target,handler) 38 | ``` 39 | 40 | target 参数表示要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为 41 | 42 | #### 把proxy 实例作为其他对象的原型 43 | - 对象上的原型所有属性都会被改写,比如construstor、__proto__、 44 | - 一般都会不去改写 propKey: prototype、__proto__、constructor、apply、bind、call 45 | ```js 46 | const proxy= new Proxy({},{ 47 | get:function(target,propKey){ 48 | return 'yeeh,I proxy this!' 49 | } 50 | }) 51 | 52 | const obj= Object.create(proxy) 53 | ``` 54 | 55 | #### 同一个拦截函数,可以拦截多个操作 56 | 57 | ```js 58 | var handler= { 59 | // 代理 60 | get :function(target,prop){ 61 | if(prop==='prototype'){ 62 | return Object.prototype 63 | } 64 | return 'Hello, '+prop 65 | }, 66 | // 普通函数 67 | apply:function(target,thisBinding,args){ 68 | return args[0] 69 | }, 70 | // 构造器 71 | construct:function(target,args){ 72 | return {value:args[1]} 73 | } 74 | } 75 | 76 | var fproxy=new Proxy(function(x,y){ 77 | 78 | return x+y 79 | },handler) 80 | 81 | fproxy(1,2) //1 82 | new fproxy(1,2) // {value:1} 83 | fproxy.prototype===Object.prototype // true 84 | fproxy.foo // 85 | 86 | 87 | ``` 88 | ## 拦截属性 89 | 90 | - **get(target,propKey,receiver)**:拦截对象属性的读取,比如proxy.foo 91 | - **set(target,propKey,value,receiver)**:拦截对象属性的设置,比如 proxy.foo='hello',返回一个布尔值 92 | - **has(target,propKey)**:拦截propKey in proxy 的操作,返回一个布尔值 93 | ```js 94 | var obj=new Proxy({},{ 95 | get:function(target,propKey,receiver){ 96 | console.log(`getting ${propKey}!`) 97 | return Reflect.get(target,propKey,receiver) 98 | }, 99 | set:function(target,propKey,value,receiver){ 100 | console.log(`setting ${propKey}!`) 101 | return Reflect.set(target,propKey,value,receiver) 102 | }, 103 | has:function(target,propKey){ 104 | return true 105 | } 106 | }) 107 | 108 | '22' in obj //true 109 | ``` 110 | - **deleteProperty(target,propKey)**:拦截delete proxy[propKey] 的操作,返回一个布尔值 111 | - **ownKeys(target)**,拦截以下: 112 | - `Object.getOwnPropertyNames(proxy)` 113 | - `Object.getOwnPropertySymbols(proxy)` 114 | - `Object.keys(proxy)` 仅包括对象自身可遍历属性 115 | - `for ... in` 116 | - 返回一个数组, 117 | - **getOwnPropertyDescriptor(target,propKey)**拦截` Object.getOwnPropertyDescriptor(proxy,proxyKey)`,返回属性的描述对象 118 | - **defineProperty(target,propKey,propDesc)**,拦截 `Object.defineProperty(proxy,propKey,propDesc)`、`Object.definePropertries(proxy,propDescs)` 返回布尔值 119 | - **preventExtensions(target)**,拦截 `Object.preventExtensions(proxy)`,返回布尔值 120 | - **getPrototypeOf(target)**,拦截 `Object.getPrototypeOf(proxy)`返回一个对象 121 | - **isExtensible(target)**,拦截`Object.isExtensible(proxy)`,返回一个布尔值 122 | - **setPrototypeOf(target,proto)**,拦截`Object.setPrototypeOf(proxy,proto)`,返回一个布尔值,如目标对象是个函数,那么还有两种额外操作可以拦截 123 | - **apply(target,objet,args)** 拦截Proxy 实例作为函数调用的操作,比如`proxy(...args)`、`proxy.call(object,...args)`、`proxy.apply(...)` 124 | - **constuct(target,args)** 拦截Proxy 实例作为构造函数调用的操作,比如`new proxy(...args)` 125 | 126 | 127 | ## web服务的拦截Proxy 128 | 129 | 适合写web服务客户端,也可以实现数据库的ORM 层 130 | 131 | ```js 132 | function createWebServer(baseUrl){ 133 | return new Proxy({},{ 134 | get(target,propKey,receive){ 135 | return ()=> httpGet(baseUrl+'/'+propKey) 136 | } 137 | }) 138 | } 139 | 140 | const service = createWebServer('http://baidu.com') 141 | 142 | service.employees().then(res=>{ 143 | console.log(res) 144 | }) 145 | ``` 146 | -------------------------------------------------------------------------------- /docs/es6/symbol.md: -------------------------------------------------------------------------------- 1 | # ES6 Symbol 枚举 2 | 3 | ## 概念 4 | 5 | - 属于 ES6 新的数据类型,与 `null`、`undefined`、`boolean`、`string`、`number` 这个五个一起被称为 JS 六大基本数据类型。 6 | 7 | - `symbol` 是一种基本类型,不是对象,不用 `new` 产生。 8 | 9 | - 同时,它也不能被添加属性。 10 | 11 | **可通过`Object.prototype.toString.call()`** 来判断其类型:`[object Symbol]` 12 | 13 | ## 用途 14 | 15 | **原因**:`es5` 对象的属性名是字符串,这容易造成属性名冲突。 16 | 17 | **解决**:`es6` 引入一种新的方法,确保对象上的每个属性名都是独一无二的 18 | 19 | ## 用法 20 | 21 | 参数:`string`、`object`,会被始终转为字符串,这里的参数仅仅作为描述 22 | 23 | 相同的参数,它的返回值也是不相同的。 24 | 25 | ```js 26 | const s1 = Symbol("he"); 27 | const s2 = Symbol("he"); 28 | 29 | console.log(s1 == s2); // false 30 | console.log(s1 === s2); // false 31 | ``` 32 | 33 | ## 约束 34 | 35 | - 无法与其他类型计算 36 | 37 | ```js 38 | const pluSy = Symbol("plus"); 39 | 40 | console.log(pluSy + "?"); 41 | ``` 42 | 43 | - **可被显式转为字符** 44 | 45 | ```js 46 | const st = Symbol("hello"); 47 | console.log(String(st)); // Symbol(hello) 48 | console.log(st.toString()); // Symbol(hello) 49 | ``` 50 | 51 | - **symbol 值可被转为布尔值,但不能转为数值** 52 | 53 | ```js 54 | const sy = Symbol(); 55 | console.log(Boolean(sy)); // true 56 | console.log(!sy); // false 57 | 58 | console.log(Number(sy)); // error 59 | console.log(sy + 2020); // error 60 | ``` 61 | 62 | - **symbol 值作为对象属性名是,无法使用点运算符** 63 | 64 | ```js 65 | const sy = Symbol(); 66 | const obj = {}; 67 | obj.sy = "hello world"; 68 | 69 | console.log(obj["sy"]); // "hello world" 70 | console.log(obj[sy]); // undefined 71 | ``` 72 | 73 | - **始终放在中括号中** 74 | 75 | ## 场景 76 | 77 | **唯一属性值**: 78 | 79 | ```js 80 | const sy = Symbol(); 81 | 82 | // 写法 1 83 | const obj = { 84 | [sy]: "world", 85 | }; 86 | 87 | // 写法 2 88 | obj[sy] = "hello"; 89 | 90 | // 写法 3 91 | Object.defineProperty(obj, sy, { value: "define value" }); 92 | 93 | console.log(obj[sy]); 94 | ``` 95 | 96 | **消除魔术字符串**: 97 | 98 | 魔术字符串值得是,在代码中多次出现,与代码形成耦合的某个具体的字符或数值。 99 | 100 | ```js 101 | function getArea(shape, ops) { 102 | let area = 0; 103 | 104 | switch (shape) { 105 | case "Triangle": // 魔术字符串 106 | area = 0.5 * ops.width * ops.height; 107 | break; 108 | } 109 | return area; 110 | } 111 | 112 | console.log(getArea("Triangle", { width: 90, height: 60 })); // 两次都出现这个字符串 `Triangle` 113 | ``` 114 | 115 | 常用的办法就是写成一个变量。 116 | 117 | ```js 118 | const obj = { 119 | triangle: "Triangle", 120 | }; 121 | function getArea(shape, ops) { 122 | let area = 0; 123 | 124 | switch (shape) { 125 | case obj.triangle: // 魔术字符串 126 | area = 0.5 * ops.width * ops.height; 127 | break; 128 | } 129 | return area; 130 | } 131 | 132 | console.log(getArea(obj.triangle, { width: 90, height: 60 })); // 两次都出现这个字符串 `Triangle` 133 | ``` 134 | 135 | 此时,消除了强耦合。 136 | 137 | 但这里的 `obj.triangle` 等于那个值不重要,只要确保不和其他 `obj` 属性值冲突即可。 138 | 139 | 所以,这里特别适用 `Symbol` 140 | 141 | ```js 142 | const obj = { 143 | triangle: Symbol(), 144 | }; 145 | function getArea(shape, ops) { 146 | let area = 0; 147 | 148 | switch (shape) { 149 | case obj.triangle: // 魔术字符串 150 | area = 0.5 * ops.width * ops.height; 151 | break; 152 | } 153 | return area; 154 | } 155 | 156 | console.log(getArea(obj.triangle, { width: 90, height: 60 })); // 两次都出现这个字符串 `Triangle` 157 | ``` 158 | 159 | **属性名的遍历**: 160 | 161 | ## 方法或属性 162 | 163 | - `Symbol.prototype.description` 164 | 165 | - `Symbol.for()` 166 | 167 | - `Symbol.keyFor()` 168 | 169 | - `Symbol.hasInstance` 170 | 171 | - `Symbol.isConcatSpreadable` 172 | 173 | - `Symbol.species` 174 | 175 | - `Symbol.match` 176 | 177 | - `Symbol.replace` 178 | 179 | - `Symbol.search` 180 | 181 | - `Symbol.split` 182 | 183 | - `Symbol.iterator` 184 | 185 | - `Symbol.toPrimitive` 186 | 187 | - `Symbol.toStringTag` 188 | 189 | - `Symbol.unscopables` 190 | -------------------------------------------------------------------------------- /docs/guide.md: -------------------------------------------------------------------------------- 1 | # 目录指南 2 | 3 | -------------------------------------------------------------------------------- /docs/html/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # HTML 6 | 7 | - [Docs Glossary](https://developer.mozilla.org/zh-CN/docs/Glossary) 8 | 9 | ## 知识点 10 | 11 | - 带 id 属性的 DOM 元素有什么副作用? 12 | - 创建同名的全局变量 13 | - `clientWidth`:`height` + `padding` 14 | - `offsetHeight`: `height` + `padding` + `border` 15 | - w3c 标准盒模型中,默认情况下,块元素的总宽度 = content 16 | - HTML5 事件可以触发多次 17 | - `link` 与 `@import` 区别 18 | 19 | ## 盒子模型 20 | 21 | ### 标准盒子模型 22 | 23 | 标准盒子模型宽度: content 24 | 25 | - 默认使用 border-box 26 | 27 | ```html 28 | 29 | 30 | 31 | 32 | Document 33 | 50 | 51 | 52 |
53 |
54 |
55 | 56 | 57 | ``` 58 | 59 | - parent 60 | 61 | - 总 width: width + margin-left + margin-right 62 | - 总 height: width + margin-left + margin-right 63 | - 实际content: width - border*2- padding*2=160 64 | 65 | ![](/html/border-box-parent.png) 66 | 67 | - children 68 | - 总 width: width - border*2- padding*2= 200-40=160 69 | - 总 height: height - border*2- padding*2= 200-40=160 70 | 71 | ![](/html/border-box-children.png) 72 | ### IE 盒子模型 73 | 74 | - IE 盒子模型: (margin+padding+border)\*2+width 75 | - 默认使用 content-box 76 | 77 | ```html 78 | 79 | 80 | 81 | 82 | Document 83 | 100 | 101 | 102 |
103 |
104 |
105 | 106 | 107 | ``` 108 | 109 | - parent 110 | 111 | - 总 width: margin*2+border*2+padding*2+width=200+20*2+10*2+10*2=280 112 | - 总 height: margin*2+border*2+padding*2+height=200+20*2+10*2+10*2=280 113 | 114 | ![](/html/content-box-parent.png) 115 | 116 | - children 117 | - 总 width: parent width = 200 118 | - 总 height: parent height = 200 119 | 120 | ![](/html/content-box-children.png) -------------------------------------------------------------------------------- /docs/html/html5.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # HTML5 6 | ## 知识点 7 | - initial-scale 表示的是初始缩放比例 8 | - minimum-scale 表示允许用户缩放到最小比例 9 | - width=device-width 表示网页宽度为设备屏幕宽度 10 | 11 | ## 不支持 12 | - `rel` 13 | ## 标签 14 | ## 拖放 15 | ## 地理定位 16 | ## video 17 | ## audio 18 | ## input 19 | ## 表单元素 20 | ## 表单属性 21 | ## 语义元素 22 | ## web存储 23 | ## web SQL 24 | ## 应用程序缓存 25 | ## web Workers 26 | ## SSE 27 | ## Websocket 28 | ## 代码规范 29 | -------------------------------------------------------------------------------- /docs/http/http-headers.md: -------------------------------------------------------------------------------- 1 | # HTTP Headers 2 | 3 | - [HTTP Headers](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers) -------------------------------------------------------------------------------- /docs/http/http.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # HTTP 6 | 7 | -------------------------------------------------------------------------------- /docs/http/http2.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # HTTP2 5 | -------------------------------------------------------------------------------- /docs/http/http3.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # HTTP3 5 | -------------------------------------------------------------------------------- /docs/http/https.md: -------------------------------------------------------------------------------- 1 | # HTTPS 2 | -------------------------------------------------------------------------------- /docs/interview/2018-12-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年 12 月份面试题 6 | 7 | 1。阅读代码,立即执行函数 8 | > 运算符的优先级 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence 9 | ```js 10 | /**1*/ 11 | var name1 ='World!'; 12 | (function(){ 13 | console.log(this); 14 | if(typeof name1 === 'undefined'){ 15 | var name1 ='JACK'; 16 | console.log('hello,'+name1) 17 | }else{ 18 | console.log('Goodbye' + name1) 19 | } 20 | })(); 21 | 22 | /**2 运算符的优先级*/ 23 | var val= ‘smtg’; 24 | console.log (‘Value is’ +(val===‘smtg’)?‘Something’:‘Nothing’); 25 | 26 | ``` 27 | 28 | ## 为什么其他语言不能使用set? 29 | ## transform 和display none 回流问题 30 | -------------------------------------------------------------------------------- /docs/interview/2018-8-15-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # 2018年8月15日面试题 5 | -------------------------------------------------------------------------------- /docs/interview/2018-8-31-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年8月 31 日面试题 6 | 7 | ## 以下代码运行结果符合预期?(还是没看懂这道题目!) 8 | - 目前测试的结果是,入参大于 100 + 300 的时候,time span 的打印时间会在 0.0x 毫秒以下,否则 100ms 左右 9 | ```js 10 | /*demo1*/ 11 | function f1() { 12 | console.time('time span') 13 | } 14 | function f2() { 15 | console.timeEnd('time span') 16 | } 17 | setTimeout(f1,100); 18 | setTimeout(f2,200); 19 | function waitForMs1(n) { 20 | var now = Date.now(); 21 | while (Date.now()-now将消息通知给一个消息处理器 (Observable)->消息处理器将消息传递给 B 具体的调用过程变成: 99 | 100 | A.emit('message',data); 101 | B.on('message',function(data){}) 102 | 103 | 请实现,消息代理功能。补充完成function EventEmitter(){} 104 | 105 | ## js 写一个 ajax get 请求 106 | 107 | > emm,无数次都会被问到的面试题。 108 | 109 | ```js 110 | const xhr = new XMLHttpRequest(); 111 | xhr.open('GET','http://baidu.com',false); 112 | xhr.send('hello'); 113 | console.log(xhr.responseText) 114 | ``` 115 | -------------------------------------------------------------------------------- /docs/interview/2018-9-11-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年9月11日面试题 6 | 7 | > 首先,这次面试印象很浅,其次对方需求,说不上来,怎么讲,就是有点鄙视对方的意思。有些术语,问到的,看出来对方不严谨。但部分面试题,还是可以学习的 8 | 9 | ## https://www.cnblogs.com/chenguangliang/p/5856701.html CommonJS AMD CMD 10 | 11 | ## 前端工程化 12 | - 模块化 13 | 1. JS 模块化:CommonJS/AMD/CMD/es6 module 14 | 2. CSS模块化:Sass/Less/Stylus/css module 15 | 3. 资源模块化:JS 管理文件关系 16 | - 组件化 17 | 1. UI组件 18 | 2. 业务组件 19 | - 规范化 20 | 1. 编码规范。 21 | 2. 联调规范。 22 | 3. 文件命名。 23 | 4. 样式管理规范。 24 | 5. git规范 25 | 6. code review 26 | - 自动化 27 | 1. webpack 28 | 2. Jenkins 29 | 30 | ## 前端自动化 31 | ## vue/的生命周期 32 | ## vue/props 是怎么实现的?跨域 33 | ## 如何处理文件上传的进度条 34 | ## 从零开始构建项目 35 | ## webpack了解 36 | ## node.js的stream 流? 37 | ## 跨域 38 | ## http/https/http2.0 39 | >用node.js 启动https 服务 40 | ```js 41 | const https = require('https'); 42 | const fs = require('fs'); 43 | 44 | const options = { 45 | key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'), 46 | cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem') 47 | }; 48 | 49 | https.createServer(options, (req, res) => { 50 | res.writeHead(200); 51 | res.end('hello world\n'); 52 | }).listen(8000); 53 | ``` 54 | >用node.js启动http2服务 55 | ```js 56 | const http2 = require('http2'); 57 | const fs = require('fs'); 58 | const server = http2.createSecureServer({ 59 | key: fs.readFileSync('./localhost-privkey.pem'), 60 | cert: fs.readFileSync('./localhost-cert.pem') 61 | }); 62 | server.on('error', (err) => console.error(err)); 63 | 64 | server.on('stream', (stream, headers) => { 65 | // stream is a Duplex 66 | stream.respond({ 67 | 'content-type': 'text/html', 68 | ':status': 200 69 | }); 70 | stream.end('

Hello world

') 71 | }); 72 | 73 | server.listen(8443); 74 | ``` 75 | ## 普通函数和构造函数的区别 76 | ## web前端安全和常见的web安全问题 77 | -------------------------------------------------------------------------------- /docs/interview/2018-9-18-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年9月18日面试题 6 | 7 | > 这一次面试经历让我大吃一惊,这不是个人能力有问题,是我的记忆出现了严重问题,截止至今,待业了两个月了。有些问题都重复,再重复,结果一面试就是忘记。比如一个请求头有哪些?我记忆力,好像没有一个key 为header,想了想还是没印象,干脆说不知道。而实际上,header就是一个大对象啊!日了狗。很绝望这一天。 8 | -------------------------------------------------------------------------------- /docs/interview/2018-9-19-interview-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年9月19日面试题 6 | -------------------------------------------------------------------------------- /docs/interview/2018-alibaba-senior-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年阿里资深web前端面试试题 6 | -------------------------------------------------------------------------------- /docs/interview/2018-netease-high-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年网易高级web前端面试题 6 | -------------------------------------------------------------------------------- /docs/interview/2018-other-mid-high-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 2018年中级/高级web前端面试题 6 | -------------------------------------------------------------------------------- /docs/interview/2020-12-interview-web.md: -------------------------------------------------------------------------------- 1 | # 2020年12月面试题 2 | 3 | 4 | ## 原型与原型链的关系 5 | 6 | 7 | ## APP Hybrid 中原生应用与 JS bridge 通信原理是什么? 8 | 9 | > 实际上,我不太懂这个题目的出题人是什么居心。 10 | 11 | 于是回答:通过共享浏览器 window 作用域,H5 给 window 放数据,原生调用浏览器 window 来获取。 12 | 13 | 搜了下大致的描述: 14 | 15 | 1. H5 中的 JS 发起请求,在 android 的 WebViewClient.shouldOverrideUrlLoading 方法中拦截 URL 请求,判断是否为接口调用 16 | 17 | 2. android 通过 webView.addJavascriptInterface 方法向 windows 对象中注入原生代码,然后 H5 在 JS 中调用相应的方法 18 | 19 | 3. 选择 prompt,console.log,alert 等方法作为通信的接口 -------------------------------------------------------------------------------- /docs/interview/2020-alibaba-interview-web.md: -------------------------------------------------------------------------------- 1 | # 一次阿里巴巴面试经历的总结 2 | 3 | 实在是没有准备这一次,太被动了。 4 | 5 | > 做一下理论知识可能比较好,尽快实践能力很棒,但也只是入职之后才体现出来。(实践能力优于理论能力或许不是一次正确的表达方式) 6 | 7 | > 还是老老实实去看Vue3源码吧 8 | ## V8引擎的垃圾回收机制 9 | 10 | - [浅谈Chrome V8引擎中的垃圾回收机制-参考一些文档](https://www.cnblogs.com/liangdaye/p/4654734.html) 11 | ### 遇到什么问题 12 | 13 | ### 怎么解决 14 | 15 | ### 还有什么问题 16 | 17 | ## vue相关 18 | 19 | ### get 、set 20 | ### vue的get set 的依赖收集,依赖是在get 上做的还是set上做 21 | 22 | 23 | ## 客户端Vue与SSR有什么区别 24 | 25 | ### 如何实习SSR组件渲染 26 | 27 | ### 路由怎么找到组件来渲染 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/interview/2020-other-interview-web.md: -------------------------------------------------------------------------------- 1 | # 2020 其他面试题常见题 2 | 3 | ## 快速创建 100 个 1 的数组 4 | 5 | > 确实没有想到可以 Array(100) 这样使用, [empty × 100] 6 | 7 | ```js 8 | Array(100).fill(1); 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/interview/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 面试题 6 | 7 | ## 个人总结 8 | 9 | - 知所以然,不知所以然。(必须在常见的问题上,得到深入的理解和应用) 10 | 11 | - 必须需要作足准备(几次的面试都很被动,打个措手不及) 12 | 13 | - 深入你使用主流框架的源码来理解 14 | 15 | ## css 16 | 17 | - 两种盒子模型分别说一下 18 | 19 | - 如何垂直居中 20 | 21 | - flex 怎么用?常用属性有什么? 22 | 23 | - BFC 是什么? 24 | 25 | - css 选择器优先级 26 | 27 | - 清除浮动 28 | - 原因? 29 | - 解决方案 30 | 31 | ## js 32 | 33 | - ES6 语法有什么?分别怎么用? 34 | - 必考:ES 6 语法知道哪些,分别怎么用? 35 | - 必考 Promise、Promise.all、Promise.race 分别怎么用? 36 | - 必考:手写函数防抖和函数节流 37 | - 必考:手写 AJAX 38 | - 必考:这段代码里的 this 是什么?6.必考:闭包/立即执行函数是什么? 39 | - 必考:什么是 JSONP,什么是 CORS,什么是跨域?8.常考: async/await 怎么用,如何捕获异常? 40 | - 常考:如何实现深拷贝? 41 | - 常考:如何用正则实现 trim()? 42 | - 常考:不用 class 如何实现继承?用 class 又如何实现?12.常考:如何实现数组去重? 43 | - 放弃:==相关题目(反着答) 44 | - 送命题:手写一个 Promise 45 | - (a==1&&a==2&&a==3) 可能为 true 吗?为什么 46 | - js 垃圾回收机制 47 | - EventLoop 48 | - apply call bind 49 | - [『JS 方法的源码实现』更新完毕](https://www.bilibili.com/read/cv7903371) 50 | - 手写原生 call bind apply 51 | - defineProperty 和 Proxy 区别 ? - defineProperty 劫持数据 -> 对象做拓展 - obj 是空对象 - 单个处理 property - proxy 返回代理对象 数据劫持 -> 代理 - target 是已有的 property - 无属性名 - 全局性处理 property - 代理改,被代理也会被改 - 支持对数组的代理 - 支持对函数的代理 52 | 53 | - [【前端面试必备】Vue2 与 Vue3 核心之『响应式原理』 ](https://www.bilibili.com/video/BV1Dk4y127Ha?p=1) 54 | - [前端进阶之道](https://yuchengkai.cn/docs/frontend/#%E5%86%85%E7%BD%AE%E7%B1%BB%E5%9E%8B) 55 | 56 | ## DOM 57 | 58 | 1.必考:事件委托 59 | ⒉ 曾考:用 mouse 事件写一个可拖曳的 div 60 | 61 | ## HTTP 62 | 63 | 1.必考:HTTP 状态码知道哪些?分别什么意思?2.大公司必考:HTTP 缓存有哪几种? 3.必考:GET 和 POST 的区别 64 | 4.Cookie v.s.LocalStorage v.s. SessionStorage V.S. Session 65 | 66 | ## 框架 Vue 67 | 68 | 1.必考: watch 和 computed 和 methods 区别是什么? 2.必考: Vue 有哪些生命周期钩子函数?分别有什么用? 3.必考: Vue 如何实现组件间通信? 4.必考: Vue 数据响应式怎么做到的? 5.必考:Vue.set 是做什么用的? 69 | 6.Vuex 你怎么用的? 70 | 7.VueRouter 你怎么用的?8.路由守卫是什么? 71 | 72 | ## 框架 React 73 | 74 | 1.必考:受控组件 v.S.非受控组件 75 | ⒉ 必考: React 有哪些生命周期函数?分别有什么用?(Ajax 请求放在哪个阶段?) 3.必考:React 如何实现组件间通信? 4.必考: shouldComponentUpdate 有什么用? 5.必考:虚拟 DOM 是什么? 6.必考:什么是高阶组件? 76 | 7.React diff 的原理是什么? 8.必考 Redux 是什么? 77 | 78 | ## TypeScript 79 | 80 | - 说一下泛类型 81 | 1.never 类型是什么? 82 | 2.TypeScript 比起 JavaScript 有什么优点? 83 | 84 | ## Webpack 85 | 86 | 1.必考:有哪些常见 loader 和 plugin,你用过哪些?2.英语题:loader 和 plugin 的区别是什么? 3.必考:如何按需加载代码? 4.必考:如何提高构建速度?5.转义出的文件过大怎么办? 87 | 上面五题请看这个不错的参考: https://zhuanlan.zhihu.com/p/44438844 88 | 89 | ## 安全 90 | 91 | - 什么是 XSS ? 92 | - 解决: 93 | 94 | - 什么是 CSRF 95 | - 解决: 96 | 97 | ## Promise 98 | 99 | [Reference](https://segmentfault.com/a/1190000038433512) 100 | 101 | ```js 102 | 103 | ``` 104 | -------------------------------------------------------------------------------- /docs/javascript/__proto__.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # `__proto__` 6 | 7 | ```js 8 | const obj = { 9 | a: 2, 10 | b: 3, 11 | }; 12 | ``` 13 | 14 | ## 1. 获取原型 [[getPropertyOf]] 15 | 16 | - console.log(obj.`__proto__`) 17 | - console.log(Object.getPropertyOf(obj)) 18 | - console.log(Object.prototype) 19 | 20 | ## 2. 设置原型 [[setPropertyOf]] 21 | 22 | - console.log(Object.setPropertyOf(obj,{c:22})) 23 | 24 | ## 3. 获取对象的可拓展性 [[isExtensible]] 25 | 26 | ```js 27 | console.log(Object.isExtensible(obj)); // true 28 | 29 | Object.freeze(obj); 30 | console.log(Object.isExtensible(obj)); // false 31 | 32 | // seal 不可修改、不可删除,可复写,可枚举 33 | Object.seal(obj); //封闭对象 34 | obj.c = 22; 35 | console.log(obj); 36 | 37 | // freeze 不可写 只读 38 | ``` 39 | 40 | ## 4. 获取自有属性 [[getOwnProperty]] 41 | 42 | - 返回自有属性 43 | 44 | ```js 45 | const obj = { 46 | a: 2, 47 | b: 3, 48 | }; 49 | Object.setPropertyOf(obj, { c: 22 }); 50 | console.log(Object.getOwnPropertyNames(obj)); // ['a','b'] 51 | ``` 52 | 53 | ## 5. 禁止拓展对象 [[preventExtensions]] 54 | 55 | ```js 56 | const obj = { 57 | a: 2, 58 | b: 3, 59 | }; 60 | Object.preventExtensions(obj); // 禁止添加,可删,可改 61 | obj.d = 2; 62 | console.log(obj); 63 | ``` 64 | 65 | ## 6. 拦截对象操作 [[defineProperty]] 66 | 67 | ```js 68 | const obj = { 69 | a: 2, 70 | b: 3, 71 | }; 72 | Object.defineProperty(obj); 73 | ``` 74 | 75 | ## 7. 判断是否是自身属性 [[hasOwnProperty]] 76 | 77 | ```js 78 | console.log(obj.hasOwnProperty("a")); // 返回布尔值,可用于深拷贝 79 | ``` 80 | 81 | ## 8. [[get]] 82 | 83 | ```js 84 | console.log("c" in obj); // 方法 1 85 | console.log(obj.c); // 方法 2 86 | ``` 87 | 88 | ## 9. [[set]] 89 | 90 | ```js 91 | obj.a = 2; // 方法 1 92 | obj["a"] = 2; // 方法 2 93 | ``` 94 | 95 | ## 10. delete 96 | ```js 97 | delete obj.a 98 | ``` 99 | 100 | ## 11. enum 101 | 102 | ```js 103 | for (let k in obj){ 104 | console.log(k) 105 | } 106 | ``` 107 | 108 | ## 12. 获取键集合 [[ownPropertyKeys]] 109 | ```js 110 | Object.keys(obj) 111 | ``` 112 | 113 | ## 13. 声明过程 114 | ```js 115 | function a (){} 116 | 117 | const a = function(){} 118 | ``` 119 | ## 14. new 过程 120 | 121 | ```js 122 | function T {} 123 | const t = new T() 124 | ``` -------------------------------------------------------------------------------- /docs/javascript/bom.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # BOM 对象 6 | 7 | ## window 对象 8 | 9 | - 浏览器窗口 10 | 11 | ## location 对象 12 | 13 | > 是 window 对象也是 document 对象。其中 search 不实用,需要改造函数来实现 14 | 15 | > 可以去往这个对象增加新属性,但无法对原来的属性值作出随意变更赋值 16 | 17 | | 属性 | 方法 | 值 | 描述 | 18 | | --------------- | ----------- | ------------------------------------- | ------------------------ | 19 | | ancestorOrigins | | | | 20 | | hash | | | | 21 | | hostname | | `www.baidu.com` | | 22 | | href | | `https://www.baidu.com/#dsad?dsd=dsd` | | 23 | | origin | | `https://www.baidu.com` | | 24 | | pathname | | `/` | | 25 | | protocol | | `https` | | 26 | | search | | | | 27 | | | assign(url) | | `生成一个location并跳转` | 28 | | | reload() | | | 29 | | | replace() | | `传递true,则强制刷新` | 30 | | | toString() | | | 31 | 32 | ## Navigator 对象 33 | 34 | > 可以去往这个对象增加新属性,但无法对原来的属性值作出随意变更赋值。可以使用 `Object.defineProperty(navigator,'userAgent',{value:'foo'})` 来修改 35 | 36 | - chrome 和 firefox 参数都有自己的,相同的属性或者同属性的值挺少的。 37 | 38 | - TODO 制作 node 去判断用户代理字段的特征值 39 | 40 | - 红宝石书中有一段检查浏览器、厂商、平台、操作系统的完全代码 41 | 42 | ## Screen 对象 43 | 44 | > 用处不大,表明客户端的能力,DPI 之类 屏幕像素宽高等 45 | 46 | ## History 对象 47 | 48 | > 无法得知浏览过的 url,但可以通过实现前进和后退 49 | 50 | - go(-) 51 | 52 | | 属性 | 方法 | 值 | 描述 | 53 | | ------ | --------- | -------------------------- | ---------------------- | 54 | | | go(1) | 整数 | 整数,前进,负数,后退 | 55 | | | back() | | 等同于 go(负数) | 56 | | | forward() | | 等同于 go(正数) | 57 | | length | | 整数,0 就是第一个目标页面 | 表示历史记录有几条 | 58 | | | | | | 59 | 60 | ## 存储对象 `sessionStorage` 回话存储 localStorage 本地存储 61 | 62 | | 属性 | 方法 | 描述 | 实例 | 63 | | ------ | ---------------------- | ---- | ---- | 64 | | length | | | | 65 | | | key(n) | | | 66 | | | getItem(keyName) | | | 67 | | | setItem(keyName,value) | | | 68 | | | removeItem(keyName) | | | 69 | | | clear() | | | 70 | | | | | | 71 | 72 | ## Cookie 与 Session +localStorage 73 | 74 | | 差异 | Cookie | Session | LocalStorage | 75 | | -------- | -------------- | -------------- | ------------ | 76 | | 存储 | 5K | 5M | 5M | 77 | | 生命周期 | 浏览器访问期间 | 浏览器访问期间 | 永久有效 | 78 | | | | | | 79 | -------------------------------------------------------------------------------- /docs/javascript/closure.md: -------------------------------------------------------------------------------- 1 | # 闭包 2 | 3 | - 如何调试闭包函数中返回的变量值,假设已上线,不可更改原始代码 4 | 5 | ```js 6 | const fn = (function() { 7 | const closeData = { 8 | age: 28, 9 | job: "web", 10 | }; 11 | return { 12 | run: function(key) { 13 | return closeData[key]; 14 | }, 15 | }; 16 | })(); 17 | 18 | // 如果获取完整的 closeData呢? 19 | fn.run("web"); 20 | 21 | // 劫持原始对象的get 22 | Object.defineProperty(Object.prototype, "all", { 23 | get: function() { 24 | return this; 25 | }, 26 | }); 27 | 28 | // 获取所有 29 | fn.run("all"); 30 | ``` 31 | 32 | 或: 33 | 34 | ```js 35 | Object.prototype.__defineGetter__("get", function() { 36 | return this; 37 | }); 38 | 39 | console.log(o.run("get")); 40 | ``` 41 | 42 | - JavaScript 语言中,只有函数内部的子函数才能读取局部变量。 43 | 44 | - JS 特有链式作用域(chain scope )有关系,子对象会父级以上查找作用域变量。 45 | - 父作用域对子对象可见,反之不行 46 | 47 | - 闭包能够读取其他函数内部变量的函数 48 | 49 | ## 定义 50 | 51 | A 函数返回函数 B,且返回的函数调用 A 的变量 52 | 53 | ```js 54 | function A() { 55 | const a = 1; 56 | return function B() { 57 | console.log(a); 58 | }; 59 | } 60 | 61 | // A()() 62 | ``` 63 | 64 | ## 常见 65 | 66 | ```js 67 | for (var i = 1; i <= 5; i++) { 68 | setTimeout(() => { 69 | console.log(i); 70 | }, i * 1000); 71 | } 72 | ``` 73 | 74 | setTimeout 是异步函数,会先把循环全部执行完毕。 75 | 76 | **1. 使用闭包解决:** 77 | 78 | ```js 79 | for (var i = 1; i <= 5; i++) { 80 | ((j) => { 81 | setTimeout(() => { 82 | console.log(j); 83 | }, j * 1000); 84 | })(i); 85 | } 86 | ``` 87 | 88 | **2. setTimeout 第三个参数:** 89 | 90 | ```js 91 | for (var i = 1; i <= 5; i++) { 92 | setTimeout( 93 | (i) => { 94 | console.log(i); 95 | }, 96 | i * 1000, 97 | i 98 | ); 99 | } 100 | ``` 101 | 102 | **3. 使用 let 声明,形成块级作用域:** 103 | 104 | ```js 105 | for (let i = 1; i <= 5; i++) { 106 | setTimeout(() => { 107 | console.log(i); 108 | }, i * 1000); 109 | } 110 | ``` 111 | 112 | ## 解决与避免 113 | 114 | ## 场景 115 | 116 | 1. 允许不带参数的函数 `setTimeout` 调用 117 | 118 | ```js 119 | function fn(a) { 120 | function f2() { 121 | console.log(a); 122 | } 123 | } 124 | const fun = fn(2); 125 | 126 | setTimeout(fn, 2000); 127 | ``` 128 | 129 | 2. 回调 130 | 131 | ```js 132 | function onSize(size) { 133 | return function() { 134 | document.border.style.fontSize = size + "px"; 135 | }; 136 | } 137 | 138 | const size16 = onSize(16); 139 | document.body.onclick = size16; 140 | ``` 141 | 142 | ## 如何消除闭包? 143 | 144 | - TODO 接触变量的引用? 145 | 146 | ```js 147 | const arrayDeepLevel = (function() { 148 | let level = -1; 149 | return function(array) { 150 | if (Array.isArray(array)) { 151 | for (let item of array) { 152 | if (Array.isArray(item)) { 153 | arrayDeepLevel(item); 154 | } 155 | } 156 | level++; 157 | return level; 158 | } 159 | }; 160 | })(); 161 | ``` 162 | 163 | ## 引用 164 | 165 | - [阮一峰 - 学习 Javascript 闭包(Closure)](http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html) 166 | -------------------------------------------------------------------------------- /docs/javascript/common-use-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 一些常用的 API 6 | 7 | ## document.querySelector API 8 | 9 | >2018年11月29日,在一家面试到这个API,我清晰的笃定说其实这个API是可以像JQuery一样使用css的选择器的,去选择第四的li标签,然后被驳回了,说只能用document.querySelectorAll 10 | 但通过测试来看,其实是可以的。 11 | 12 | ```js 13 | document.querySelector('#app > div > ul > li:nth-child(4)') 14 | /*或者*/ 15 | document.querySelector('li:nth-child(3)') 16 | ``` 17 | ## XMLHttpRequest 18 | 19 | 属于Http API 的一个范畴,使用的时候,需要实例化XMLHttpRequest对象 20 | 21 | - 如何发起http请求,在通用js环境下?步骤如下: 22 | 1. new XMLHttpRequest 一个对象 23 | 2. open 24 | 1. methods 25 | 2. 路径 26 | 27 | ```js 28 | //一段通过纯文本发送请求个服务器 29 | function send(){ 30 | var request = new XMLHttpRequst ; 31 | request.open("POST","/login.php");//post 数据 32 | request.setRequestHeader('Content-Type','text/plain;charset=UTF-8') 33 | request.send('say hello world') 34 | 35 | } 36 | 37 | // 一段超时的代码 38 | //js权威指南p503 39 | 40 | /*XMLHttpRequest 兼容ie6*/ 41 | 42 | /*如果不存在,判断IE下不支持非标准的xmlHttpRequest*/ 43 | if(window.XMLHttpRequest===undefined){ 44 | window.XMLHttpRequest=function() { 45 | try { 46 | //可用,则返回ActiveX对象的最新版本 47 | return new ActiveXObject('Msxml3.XMLHTTP.6.0') 48 | } 49 | catch (e1) { 50 | try { 51 | // 否则,退回到较旧的版本 52 | return new ActiveXObject('Msxml3.XMLHTTP.3.0') 53 | } 54 | catch (e2) { 55 | //否则,都没有的话,抛出错误 56 | throw new Error('不支持XMLHttpRequest') 57 | } 58 | } 59 | } 60 | } 61 | 62 | ``` 63 | 64 | 65 | - 可以实现上传文件进度的监控,在js权威指南/p501有写道,可以监控HTTP上传的进度 66 | - 设置超时 67 | - 同源策略不允许XMLHttpRequest 进行跨域请求 68 | - withCredentitails boolean值,该值的存在是为了测试是否支持CORS@2特性一种方法 69 | -------------------------------------------------------------------------------- /docs/javascript/debounce.md: -------------------------------------------------------------------------------- 1 | # 防抖函数 debounce 2 | 3 | ## 概念 4 | 5 | - 无论触发多少次回调,都只执行最后一次 6 | 7 | - 通俗说,抖掉,等新的一次,重新计算的意思 8 | 9 | - 注意:这里的抖动停止表示你停止了触发这个函数,从这个时间点开始计算,当间隔时间等于你设定时间,才会执行里面的回调函数。 10 | 11 | - 如果你一直在触发这个函数并且两次触发间隔小于设定时间,则一定不会到回调函数那一步。 12 | 13 | - 延滞性,最后一个函数触发后,过指定时间才开始执行 14 | 15 | ## 场景 16 | 17 | 1. 懒加载监听计算 `Scroll` 位置,按一定时间频率获取 18 | 19 | 2. input 查询,确保只有最后一次的更改有效 20 | 21 | ## 实现 22 | 23 | 重点是在 clearTimeout` 24 | 25 | **方案 1**: 26 | 27 | ```js 28 | function debounce(fn, wait = 50) { 29 | let timer = null; 30 | return function(...args) { 31 | if (timer) clearTimeout(timer); 32 | timer = setTimeout(() => { 33 | fn.apply(this, args); 34 | }, wait); 35 | }; 36 | } 37 | 38 | const betterFn = debounce(() => { 39 | console.log("go to ==>"); 40 | }, 200); 41 | 42 | document.addEventListener("scroll", betterFn); 43 | ``` 44 | 45 | **方案 2**: 46 | 47 | - 具备立即执行的特性 48 | 49 | ```js 50 | function debounce(fn, wait = 50, im) { 51 | let timer = null; 52 | return function(...args) { 53 | if (timer) clearTimeout(timer); 54 | if (!timer && im) { 55 | fn.apply(this, args); 56 | } 57 | timer = setTimeout(() => { 58 | fn.apply(this, args); 59 | }, wait); 60 | }; 61 | } 62 | 63 | const betterFn = debounce( 64 | () => { 65 | console.log("go to ==>"); 66 | }, 67 | 200, 68 | true 69 | ); 70 | 71 | document.addEventListener("scroll", betterFn); 72 | ``` 73 | -------------------------------------------------------------------------------- /docs/javascript/design-model.md: -------------------------------------------------------------------------------- 1 | # JavaScript 2 | 3 | ## 发布订阅模式(观察者模式) 4 | 5 | - 一种对象间一对多的依赖关系 6 | - 当一个对象的状态发送改变时,所有依赖它的对象都得到状态改变的通知 7 | 8 | ### 订阅+发布过程 9 | 10 | - 把自己想订阅的**事件**注册(subscribe) 到调度中心(event channel) 11 | 12 | - 发布者(publisher) 发布该事件到(publish event) 到调度中心 13 | 14 | - 事件触发时,调度中心统一调度订阅者注册到调度中心的处理代码 15 | 16 | ### 问题 17 | 18 | 1. 订阅者是如何订阅? 19 | 20 | > 调用事件对象中的注册事件,将自己事件名和执行函数,注册到注册中心中。然后出发事件发布即可执行订阅上的事件代码块 21 | -------------------------------------------------------------------------------- /docs/javascript/eventloop.md: -------------------------------------------------------------------------------- 1 | # EventLoop 2 | 3 | ## JavaScript 事件 4 | 5 | 分为两种事件类型: 6 | 7 | - 宏任务(macro-task)/Task 中的异步任务: 8 | 9 | - setTimeout 10 | - setInterval 11 | - setImmediate (Node) 12 | - requestAnimationFrame(browser) 13 | - I/O 14 | - UI rendering(browser) 15 | 16 | - 微任务(micro-task)/jobs 中的异步任务: 17 | - process.nextTick(node,limit=1000) 18 | - Promise 19 | - Object.observe 20 | - MutationObserve 21 | 22 | 事件的执行顺序:先`宏任务` ——> `微任务`。 23 | 24 | 任务中有`同步任务`和`异步任务`: 25 | 26 | - ——> 同步的进入主线程 27 | - ——> 异步进入 event table 并注册函数 28 | - ——> 异步完成后 29 | - ——> 将回调放入 event queue(宏任务和微任务是不同的 event queue),此时不执行异步快里的代码 30 | - ——> 同步任务完成后,从 event queue 读取事件放入主线程 31 | - ——> 回调函数可能包含不同的任务,因此循环执行上述 32 | 33 | ## Node 34 | - 略 35 | 36 | ## reference: 37 | 38 | - [带你彻底弄懂Event Loop](https://segmentfault.com/a/1190000016278115) 39 | 40 | -------------------------------------------------------------------------------- /docs/javascript/module.md: -------------------------------------------------------------------------------- 1 | # 模块化 2 | 3 | - [参考](https://yuchengkai.cn/docs/frontend/#%E6%A8%A1%E5%9D%97%E5%8C%96) 4 | 5 | ## CommonJS 6 | 7 | `CommonJS` Node 独有规范 8 | 9 | ## AMD 10 | -------------------------------------------------------------------------------- /docs/javascript/promise.md: -------------------------------------------------------------------------------- 1 | # Promise 2 | 3 | [promise-class](https://github.com/veaba/web-advanced/blob/master/demos/js/promise-class.js) 4 | 5 | ```js 6 | // Reference :https://segmentfault.com/a/1190000038433512 7 | 8 | class PromiseClass { 9 | constructor(exec) { 10 | this.status = "pending"; // 等待中 11 | this.value = undefined; 12 | this.reason = undefined; 13 | this.onFulfilled = undefined; 14 | this.onRejected = undefined; 15 | this.onFulFilledList = []; // 等待的函数与列表? 16 | this.onRejectedList = []; // 拒绝的列表 17 | 18 | try { 19 | // todo 20 | exec(this.resolve, this.reject); 21 | } catch (error) { 22 | this.reject(error); 23 | } 24 | } 25 | 26 | // resolve 函数 27 | resolve(value) { 28 | if (this.status === "pending") { 29 | this.status = "fulfilled"; 30 | this.value = value; 31 | this.onFulFilledList.forEach((item) => item()); //每项函数都是执行 32 | } 33 | } 34 | // reject 函数 35 | reject(reason) { 36 | if (this.status === "pending") { 37 | this.status = "rejected"; 38 | this.reason = reason; 39 | this.onRejectedList.forEach((item) => item()); 40 | } 41 | } 42 | 43 | // then 44 | 45 | then(onFulfilled, onRejected) { 46 | let result = null; 47 | if (this.status === "fulfilled" && onFulfilled) { 48 | result = onFulfilled(this.value); 49 | return PromiseClass.resolve(result); //返回新的一个promise 50 | } 51 | 52 | if (this.status === "rejected" && onRejected) { 53 | result = onRejected(this.reason); 54 | return PromiseClass.resolve(result); 55 | } 56 | 57 | if (this.status === "pending") { 58 | onFulfilled && this.onFulFilledList.push(() => onFulfilled(this.value)); // 如果存在,则到栈里 59 | onRejected && this.onRejectedList.push(() => onRejected(this.reason)); 60 | } 61 | } 62 | } 63 | 64 | PromiseClass.resolve = function(value) { 65 | if (typeof value === "object" && value.then) { 66 | return value; 67 | } else { 68 | return new PromiseClass((resolve) => { 69 | resolve(value); 70 | }); 71 | } 72 | }; 73 | 74 | PromiseClass.all = function(list) { 75 | return new PromiseClass((resolve, reject) => { 76 | let result = []; 77 | let count = 0; 78 | for (let i = 0; i < list.length; i++) { 79 | if (typeof list[i] === "object" && list[i].then) { 80 | PromiseClass.resolve(list[i]).then((data) => { 81 | result[i] = data; 82 | count++; 83 | }, reject); 84 | } else { 85 | result[i] = list[i]; 86 | count++; 87 | } 88 | } 89 | 90 | if (count === list.length) { 91 | resolve(result); 92 | } 93 | }); 94 | }; 95 | 96 | // TODO:PromiseClass.race 只要一个成功,全部resolve 97 | 98 | // TODO:PromiseClass finally,不管成功失败,回调都执行,执行之后,依然可以then 99 | ``` 100 | -------------------------------------------------------------------------------- /docs/javascript/this.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # This 6 | 7 | ## 立即执行函数中的 this 指向问题 8 | 9 | ```js 10 | var obj = { 11 | a: function() { 12 | console.log("this==>", this); 13 | return this.b; 14 | }, 15 | b: 2020, 16 | }; 17 | (function() { 18 | console.log("=======>", typeof arguments[0]()); // 因为这里的this 是windows,windows 没有变量b,所以是undefined 19 | })(obj.a); 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/javascript/throttle.md: -------------------------------------------------------------------------------- 1 | # 节流函数 Throttle 2 | 3 | ## 概念 4 | 5 | - 节省的意思 6 | 7 | - 跟水龙头一个概念,开一次,流水,关一次,停水,不管后面来了多少 8 | 9 | - 某个函数一定时间间隔内(如 3s )执行一次,在 3s 内无视后来产生的**函数调用请求** 10 | 11 | - 马老师被叫去打闪电五连鞭,3s 内打一次,不管叫多少次,他只能 3s 内打一次 12 | 13 | ## 场景 14 | 15 | 1. window.onresize() 16 | 17 | 2. mousemove() 18 | 19 | 3. 上传进度 20 | 21 | 4. input 实时查询,每隔 x s 发送一次请求,服务端是限流(Rate limit) 22 | 23 | ## 实现 24 | 25 | ```js 26 | const throttle = (fn, wait = 50) => { 27 | let pre = 0; 28 | 29 | return function(...args) { 30 | let now = new Date(); 31 | if (now - pre > wait) { 32 | pre = now; 33 | fn.apply(this, args); 34 | } 35 | }; 36 | }; 37 | 38 | const betterFn = throttle(() => { 39 | console.log("log"); 40 | }, 1000); 41 | 42 | // 每 10 毫秒执行一次 betterFn 函数,但是只有时间差大于 1000 时才会执行 fn 43 | setInterval(betterFn, 10); 44 | ``` 45 | 46 | 或者方案 2: 47 | 48 | ```js 49 | // 50 | function throttle(f, wait) { 51 | let timer; 52 | return (...args) => { 53 | if (timer) { 54 | return; 55 | } 56 | timer = setTimeout(() => { 57 | f(...args); 58 | timer = null; 59 | }, wait); 60 | }; 61 | } 62 | ``` 63 | -------------------------------------------------------------------------------- /docs/keyword.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # 关键词 5 | ## 未来需要了解的内容 6 | 7 | - [this](/javascript/this) 8 | - [冒泡算法](/algorithm/bubbing) 9 | - [继承](/javascript/inherit) 10 | - react 11 | - 小程序/微信/百度/快应用/支付宝 12 | - [闭包](javascript/closure.md) 13 | - [js 垃圾回收机制]() 14 | - [深拷贝](/javascript/#深拷贝) 15 | - [浅拷贝](/javascript/#浅拷贝) 16 | - class 17 | - Generator 18 | - webGl 19 | - [防抖](/javascript/debounce) 20 | - [节流](/javascript/throttle) 21 | - canvas 22 | - [proxy](/es6/proxy) 23 | - node 中 commonJs 与 ES6 module 24 | - node eventLoop 25 | - BFC 26 | - 词法作用域 27 | - 执行上下文 28 | - 全局执行上下文 29 | - 函数执行上下文 30 | - `eval` 执行上下文 31 | 32 | `@1` AST :抽象语法树。(abstract syntax tree) 33 | 34 | `@2` CORS:跨域资源共享。(Cross-Origin Resource Sharing) 35 | -------------------------------------------------------------------------------- /docs/nginx/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Nginx 6 | > https://blog.csdn.net/tsummerb/article/details/79248015 对nginx 正向、反向带来写的比较好的文章 7 | ## nginx 的正向代理? 8 | > 我忘记是2018年在哪一家公司面试了,面试官问我,你知道什么是nginx 正向代理?我楞了下,说不知道,后面想一直知道这个知识点。直到我直到这个知识点后,傻楞了,我一个前端知道个锤子nginx 正向代理啊,我去! 算了,本着学习的心态,不想回忆起这个沙雕面试官了。 9 | - 正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。 10 | - 内网服务 主动要求请求外网的地址服务, 内网服务->访问->外网 。((⊙_⊙)?,所以我ssh 到服务器 curl 百度 ,也算了) 11 | - (`应该可以本来按着a 页面返回给用户,结果我让百度页面返回给用户?恩?`) 12 | - 以 通过代理软件访问facebook 这样的例子,比较形象 13 | ```txt 14 | server{ 15 | resolver 8.8.8.8 16 | } 17 | ``` 18 | ## nginx 的反向代理? 19 | - proxy_pass 20 | - upstream 21 | - 外网 主动请求内网服务, 外网->请求->内网服务 22 | - 请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,nginx扮演的就是一个反向代理角色 23 | - 用户去访问淘宝,但返回给用户的内容的服务器,可能来自浙江,可能来自北京 24 | ## nginx负载均衡 25 | - 硬件负载均衡 26 | - 软件负载均衡 27 | > 与硬件主机实现一种消息队列分发机智 28 | 29 | - 负载均衡调度算法 30 | - weight轮询 31 | > 皇帝翻牌子比较形象了!可以设定一些权重,来增加获得宠幸的几率,被打入冷宫的out 出局。。。 32 | - ip_hash 33 | > 客户端ip的hash匹配,一个固定ip从会访问到同一个后端,一定程度解决了集群下,session共享问题 34 | - fair 35 | > 智能调整算法调度?动态的 根据后端服务器的请求处理处理的响应时间,进行均衡的分配,响应时间短的,分配到的几率高,长的,分配的少!需要安装upstream_fair 模块 36 | - url_hash 37 | > 根据url+hash 结果,每次请求的url都指定到后端固定服务器,nginx作为静态服务器下,提高缓存效率。需要安装hash 软件包 38 | ## 一段基于vue项目nginx 配置文件 39 | ```txt 40 | { 41 | worker_processes 1; 42 | events { 43 | worker_connections 1024; 44 | } 45 | http { 46 | include mime.types; 47 | default_type application/octet-stream; 48 | sendfile on; 49 | keepalive_timeout 65; 50 | server { 51 | listen 80; 52 | server_name localhost; 53 | 54 | location / { 55 | root F:\baidu\dist; 56 | try_files $uri $uri/ @router; 57 | index index.html; 58 | } 59 | 60 | location @router { 61 | rewrite ^.*$ /index.html last; 62 | } 63 | location ^~/api/{ 64 | proxy_pass http://www.baidu.com/; 65 | } 66 | } 67 | } 68 | } 69 | 70 | ``` 71 | ## 一段基于nuxt项目的nginx 配置文件 72 | -------------------------------------------------------------------------------- /docs/nginx/config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Nginx Config 5 | -------------------------------------------------------------------------------- /docs/nginx/proxy.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Nginx Proxy 5 | -------------------------------------------------------------------------------- /docs/node/README.md: -------------------------------------------------------------------------------- 1 | # Node.js 2 | - [如何正确的学习Node.js](https://cnodejs.org/topic/5ab3166be7b166bb7b9eccf7) 3 | - [v14.2.0](https://nodejs.org/dist/latest-v14.x/docs/api/) 4 | 5 | ::: tip 6 | 使用python脚本,或者js脚本来完成这项爬取+翻译工作 7 | ::: 8 | 9 | ## 目录(v14.2.0) 10 | 11 | - Assertion Testing 12 | - Async Hooks 13 | - [Buffer]() 14 | - C++ Addons 15 | - C/C++ Addons with N-API 16 | - C++ Embedder API 17 | - Child Processes 18 | - [Cluster]() 19 | - [Command Line Options]() 20 | - [Console]() 21 | - [Crypto]() 22 | - [Debugger]() 23 | - Deprecated APIs 24 | - [DNS]() 25 | - Domain 26 | - [ECMAScript Modules]() 27 | - Errors 28 | - [Events]() 29 | - File System 30 | - Globals 31 | - HTTP 32 | - HTTP/2 33 | - HTTPS 34 | - Inspector 35 | - Internationalization 36 | - [Modules]() 37 | - [Net]() 38 | - [OS]() 39 | - [Path]() 40 | - Performance Hooks 41 | - Policies 42 | - Process 43 | - Punycode 44 | - Query Strings 45 | - Readline 46 | - [REPL]() 47 | - Report 48 | - [Stream]() 49 | - String Decoder 50 | - Timers 51 | - [TLS/SSL]() 52 | - Trace Events 53 | - [TTY]() 54 | - UDP/Datagram 55 | - URL 56 | - Utilities 57 | - [V8]() 58 | - [VM]() 59 | - WASI 60 | - [Worker Threads]() 61 | - [Zlib]() 62 | -------------------------------------------------------------------------------- /docs/node/fs.md: -------------------------------------------------------------------------------- 1 | ## fs 2 | 3 | > 不建议在调用 fs.open()、fs.readFile() 或 fs.writeFile() 之前使用 fs.access() 检查文件的可访问性。 这样做会引入竞争条件,因为其他进程可能会在两个调用之间更改文件的状态。 相反,用户代码应该直接打开、读取或写入文件,并处理在文件无法访问时引发的错误。 4 | - `.unlink()` 删除文件 异步 5 | ```js 6 | const fs= require("fs"); 7 | fs.unlink('./tmp/hello.js',(err)=>{ 8 | if(err) throw err; 9 | console.log('删除成功') 10 | }) 11 | ``` 12 | - `.unlinkSync()` 删除文件 ,同步 13 | ```js 14 | const fs = require('fs'); 15 | try{ 16 | fs.unlinkSync('./tmp/hello.js'); 17 | console.log('删除成功') 18 | }catch(err){ 19 | console.log(err,'删除失败') 20 | } 21 | ``` 22 | - `.rename()` 23 | ```js 24 | fs.rename('./tmp/hello.js','./tmp/world.js',(err)=>{ 25 | if(err) throw err; 26 | console.log('rename done') 27 | }) 28 | ``` 29 | 30 | - `.open()` 完成操作后,需要关闭描述符,否则可能导致内存泄漏 31 | - `wx` flag 32 | - `r` 33 | 34 | 线程池 35 | > 除了fs.FSWatcher() 和 显式同步的方法之外,都使用了`libuv` 线程池,这对于某些应用程序可能会产生其他负面性能问题,详见 http://nodejs.cn/api/cli.html#cli_uv_threadpool_size_size 36 | - `fs.FSWatcher()` 37 | >成功调用一个fs.watch 方法都会返回一个新的fs.FSWatcher对象 38 | - `fs.access(path,[.mode],callback)` 39 | - `fs.Dirent`类 40 | - `.dirent.isBlockDevice()` boolean 41 | 42 | ```js 43 | const fs = require('fs'); 44 | fs.open('./tmp/hello.js','r',(err,fd)=>{ 45 | if(err) throw err; 46 | fs.fstat(fd,(err1,stat)=>{ 47 | if(err1) throw err1; 48 | //文件属性 49 | console.log(stat) ; 50 | 51 | //关闭文件描述符 52 | fs.close(fd,(errC)=>{ 53 | if(errC) throw errC; 54 | console.loh('关闭') 55 | }) 56 | }) 57 | }) 58 | ``` 59 | - `fs.ReadStream` 类 60 | - `fs.WriteSteam`类 61 | - `fs.Stats` 类 62 | - `fs.stat()` 63 | ```js 64 | fs.stat('./tmp/world.js',(err,stats)=>{ 65 | if(err) throw err; 66 | conosle.log(stats) 67 | }) 68 | ``` 69 | - `fs.lsate()` 70 | - `.fstat` 71 | ```js 72 | fs.fstat(fd,(err1,stat)=>{ 73 | if(err1) throw err1; 74 | //文件属性 75 | console.log(stat) ; 76 | //关闭文件描述符 77 | fs.close(fd,(errC)=>{ 78 | if(errC) throw errC; 79 | console.log('关闭') 80 | }) 81 | }) 82 | ``` 83 | - `fs.close()` 84 | - `fs.appendFile(path,data[,options],callback)` 85 | > 异步地将数据追加到文件中,如果文件不存在,则创建该文件,`data`可以使字符串或者`Buffer` 86 | ```js 87 | fs.appendFile('/tmp.append.txt','hello world append file for node.js fs.appendFile function'+new Date(),(err)=>{ 88 | if(err) throw err 89 | }) 90 | ``` 91 | 92 | > 异步方法,顺序无法保证 93 | 94 | ```js 95 | fs.rename('./tmp/hello.js','./tmp/world.js',(err)=>{ 96 | if(err) throw err; 97 | console.log('rename done') 98 | }); 99 | //stat可能在rename 之前, 100 | fs.stat('./tmp/world.js',(err,stats)=>{ 101 | if(err) throw err; 102 | conosle.log(stats) 103 | }) 104 | ``` 105 | > 方法时,在回调内部 106 | -------------------------------------------------------------------------------- /docs/nuxt/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Nuxt 5 | 6 | ## AsyncData() 7 | 8 | - 导致session id不一直 9 | - 刷新都没有了 10 | 11 | ## Nuxt.conf.js 12 | -------------------------------------------------------------------------------- /docs/performance/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # 性能提升 5 | 6 | 网页性能管理详解 ——阮一峰 http://www.ruanyifeng.com/blog/2015/09/web-page-performance-in-depth.html 7 | 8 | ## 前端常见的性能优化请求手段 9 | 10 | 加快资源的加载速度,减少白屏事件 11 | - CDN 内容分发 12 | - css Sprite 图片合并 13 | - Compress/Gzip 资源文件压缩 14 | - Async/Defer 异步加载 15 | - HTTP Cache HTTP 缓存 16 | .... 17 | ## html/css 重绘回流(Repaint、Reflow) 18 | 19 | - display:none 不会发生回流和重绘 20 | - 回流一定触发重绘,重绘不一定会触发回流 21 | - 复杂动画,使用 `position: abosution` 使其脱离文档流 22 | - css3 硬件加速(GPU加速) 23 | - css3 硬件加速下以下属性不会发生重绘回流: 24 | - transform 25 | - opacity 26 | - filters 27 | - 使用 fixed 和 absolute,如果修改 css 不会发生回流 28 | 29 | 30 | ### 重绘(repaint) 31 | 32 | 33 | ### 回流(reflow) 34 | 35 | 回流(reflow):布局引擎为frame(框架)计算图形的过程,一个frame回流会导致所有父节点以及后续元素都会回流。 36 | - 理论上发生回流的原因 37 | - 初始化(initial)。dom载入后第一次回流,遍历所有frame 38 | - 渐进(incremental)。一个frame发生渐进reflow时,前面没变,自己内部发生变化。 39 | - 改变大小。容器边界发生变化,内部没变,复用内部状态 40 | - 样式改变。整个frame都会遍历 41 | - dirty。(脏的)已缓存了多个子元素的渐进回流时。 42 | - 具体的操作原因: 43 | - 窗口大小变化 44 | - 更改文档默认字体 45 | - 样式表改变 46 | - 元素内容变化,尤其是输入控件 47 | - input textarea 48 | - dom操作 49 | - 渐进回流,会使浏览器将渐进队列冲洗,立即执行回流 50 | - offsetWidth、offsetHeight计算。 整个可视区域大小,包括border scrollBar在内 51 | - width、height计算。 52 | - clientWidth计算 内部可视区域大小。 53 | - scrollTop计算。元素内容向上滚动了多少像素。 54 | - scrollHeight计算。元素内容的高度,包括溢出的部分 55 | - 避免回流 56 | - 避免逐项更改style 57 | - 避免循环操作dom 58 | - 避免循环读取offsetLeft 等属性,并在循环之前存起来 59 | - 绝对定位具有复杂变化的动画元素。position:absolute 脱离文档流,否则会引起父元素以及后续元素的大量回流。css3 transition 性能不错 60 | ```js 61 | // 一次bad 的demo 62 | 63 | var dom = document.body.style; 64 | dom.padding="2px"; // 回流+重绘 65 | dom.border="1px solid"; // 回流+重绘 66 | dom.border="blue"; // 重绘 67 | dom.backgroundColor="#ccc"; // 重绘 68 | dom.fontSize="14px"; // 重绘+回流 69 | document.body(document.createTextNode('abcdev!')); 70 | ``` 71 | 解决办法 72 | 73 | 1. 写style 更改class 74 | 75 | ```js 76 | document.body.className="dom" 77 | ``` 78 | 79 | ```html 80 | .dom { 81 | padding:2px; 82 | border:1px solid; 83 | background-color:#ccc; 84 | font-size:14px 85 | } 86 | ``` 87 | 88 | 2. 一次添加全部的style操作 89 | 90 | ```js 91 | var dom = document.body.style; 92 | dom="padding:2px;border:1px solid;background-color:#ccc;font-size:14px"; 93 | ``` 94 | 重绘(repaint):发生在元素的可见性发生变化时产生重新渲染的现象,回流必然引起重绘: 95 | - background 96 | - color 97 | 98 | 99 | ## 常见的内存泄露的问题 100 | ### 闭包在IE9之前的版本会导致一些特殊的问题。 101 | 102 | ```js 103 | 104 | // 内存泄漏 105 | function click1(){ 106 | let element = document.querySelector('.test'); 107 | element.onclick=function(){ 108 | console.log(element.id) 109 | } 110 | } 111 | // fix 版本 112 | function click2(){ 113 | let element2 = document.querySelector('.test'); 114 | let id = element2.id;// 引用赋值,消除变量循环引用 115 | element2.onclick=function(){ 116 | console.log(id) 117 | }; 118 | // 设置为null,解除对DOM对象的引用,减少计数 119 | element2=null 120 | } 121 | 122 | ``` 123 | -------------------------------------------------------------------------------- /docs/project/rollup/README.md: -------------------------------------------------------------------------------- 1 | # Rollup 2 | 3 | - umd 4 | - iife 5 | - cjs 6 | > rollup src\app.ts --file build.js --format cjs 7 | 8 | ## cjs 9 | 10 | ```js 11 | import { createServer } from "http"; 12 | import { Server } from "socket.io"; 13 | 14 | const httpServer = createServer(); 15 | const io = new Server(httpServer, { cors: true }); 16 | 17 | io.on("connection", (socket) => { 18 | console.log(socket.id); 19 | }); 20 | 21 | httpServer.listen(8080, () => { 22 | console.log("listen 8080"); 23 | }); 24 | ``` 25 | 26 | ==> 27 | 28 | ```js 29 | "use strict"; 30 | 31 | var http = require("http"); 32 | var socket_io = require("socket.io"); 33 | 34 | const httpServer = http.createServer(); 35 | const io = new socket_io.Server(httpServer, { cors: true }); 36 | 37 | io.on("connection", (socket) => { 38 | console.log(socket.id); 39 | }); 40 | 41 | httpServer.listen(8080, () => { 42 | console.log("listen 8080"); 43 | }); 44 | ``` 45 | 46 | ## umd 47 | 48 | > 49 | 50 | ```js 51 | import { createServer } from "http"; 52 | import { Server } from "socket.io"; 53 | 54 | const httpServer = createServer(); 55 | const io = new Server(httpServer, { cors: true }); 56 | 57 | io.on("connection", (socket) => { 58 | console.log(socket.id); 59 | }); 60 | 61 | httpServer.listen(8080, () => { 62 | console.log("listen 8080"); 63 | }); 64 | 65 | ``` 66 | 67 | ===> 68 | 69 | ```js 70 | (function (global, factory) { 71 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('http'), require('socket.io')) : 72 | typeof define === 'function' && define.amd ? define(['http', 'socket.io'], factory) : 73 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.http, global.socket_io)); 74 | }(this, (function (http, socket_io) { 'use strict'; 75 | 76 | const httpServer = http.createServer(); 77 | const io = new socket_io.Server(httpServer, { cors: true }); 78 | 79 | io.on("connection", (socket) => { 80 | console.log(socket.id); 81 | }); 82 | 83 | httpServer.listen(8080, () => { 84 | console.log("listen 8080"); 85 | }); 86 | 87 | }))); 88 | 89 | ``` 90 | 91 | ## iife 92 | - 立即执行 93 | > rollup src\app.ts --file build.js --format iife 94 | 95 | ```js 96 | import { createServer } from "http"; 97 | import { Server } from "socket.io"; 98 | 99 | const httpServer = createServer(); 100 | const io = new Server(httpServer, { cors: true }); 101 | 102 | io.on("connection", (socket) => { 103 | console.log(socket.id); 104 | }); 105 | 106 | httpServer.listen(8080, () => { 107 | console.log("listen 8080"); 108 | }); 109 | 110 | ``` 111 | 112 | ```js 113 | (function (http, socket_io) { 114 | 'use strict'; 115 | 116 | const httpServer = http.createServer(); 117 | const io = new socket_io.Server(httpServer, { cors: true }); 118 | 119 | io.on("connection", (socket) => { 120 | console.log(socket.id); 121 | }); 122 | 123 | httpServer.listen(8080, () => { 124 | console.log("listen 8080"); 125 | }); 126 | 127 | }(http, socket_io)); 128 | 129 | ``` -------------------------------------------------------------------------------- /docs/pwa/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # PWA 6 | # Service worker 工作线程,子线程 7 | >2014年5月提出,前身是Application Cache`被移除` 8 | - Application Cache 指定缓存策略 app.appcache 9 | - 不能直接访问/操作 DOM 特定的API 10 | - `全局`Promise/Fetch API/Cache API 11 | - 生命周期内,需要时,直接唤醒,不需要则自动休眠,不随浏览器窗口关闭、站点的关闭而失效 12 | - 离线内容可控 13 | - 一旦安装,永远存活,除非手动卸载 14 | - 必须HTTPS,除非本地环境下 15 | - 广泛使用Promise 16 | - 生命周期 17 | Register - > Install -> activated 18 | - 组织结构 19 | - 注册sw 是一个脚本文件`延时注册` 20 | - 工作时候的sw 又是另外一个脚本文件 21 | -------------------------------------------------------------------------------- /docs/reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # 引用 5 | > 索引__关于本作知识引用来源sub标签 6 | 1. [搜狐 - 如何减少HTML页面回流与重绘(Reflow & Repaint)](http://www.sohu.com/a/111695367_466959) 7 | 2. [闭包的应用场景一林枫山博客](https://www.cnblogs.com/star-studio/archive/2011/06/22/2086493.html) 8 | 3. [IE内存泄漏问题总结](https://blog.csdn.net/rootes/article/details/8784240) 9 | 4. [绑定-this-的方法](https://wangdoc.com/javascript/oop/this.html#%E7%BB%91%E5%AE%9A-this-%E7%9A%84%E6%96%B9%E6%B3%95) 10 | 5. [es6-proxy](https://es6.ruanyifeng.com/#docs/proxy) 11 | 6. [尚未录入-web大前端面试——JavaScript](https://juejin.im/post/5e93deb46fb9a03c77620c13) 12 | -------------------------------------------------------------------------------- /docs/rust/README.md: -------------------------------------------------------------------------------- 1 | # Rust 该部分属于后端部分 -------------------------------------------------------------------------------- /docs/rust/tokio/README.md: -------------------------------------------------------------------------------- 1 | # Tokio 2 | 3 | 4 | ## Link 5 | 6 | - [Tokio中文](https://tokio-zh.github.io/) -------------------------------------------------------------------------------- /docs/security/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # web安全问题 6 | ## CSRFs 7 | ## XSS 8 | ## DDOS 9 | ## CSP (内容安全策略) 10 | https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP 11 | ## SQL注入 12 | ## https 13 | ## DNS劫持 14 | -------------------------------------------------------------------------------- /docs/security/cookie.md: -------------------------------------------------------------------------------- 1 | # Cookie 2 | 3 | 有关 Cookie 安全的问题 4 | 5 | 有关 [SameSite](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Set-Cookie/SameSite) 问题 6 | 7 | ## SameSite 8 | 9 | 三个属性: 10 | 11 | - `Strict` (严格) 12 | 13 | - `Lax` (松懈) 14 | 15 | - `None` (无) 16 | 17 | ### `Strict` 18 | 19 | 将完全禁止第三方 `Cookie`,跨站点时候,不会发送 `Cookie`,只有当前网页 URL 与请求目标一致时才会带上 `Cookie`。 20 | 21 | 也就是 **`同站检查`** 的意思。 22 | 23 | ``` 24 | Set-cookie:CookieName=CookieValue; SameSite=Strict 25 | ``` 26 | 27 | 这个 `Strict` 过于严格,导致很多子链接跳转都被不带 `cookie` 28 | 29 | ### `Lax` 30 | 31 | 大多数是否,不发送第三方 `Cookie`,除了导航到目标网站的 `Get` 请求。 32 | 33 | ``` 34 | Set-cookie: CName=CValue; SameSite=Lax 35 | ``` 36 | 37 | 导航到目标的 `Get` 请求,有三种情况,a 链接,预加载,get 表单。 38 | 39 | | 请求类型 | 实例 | 正常情况 | Lax | 40 | | ---------- | ------------------------------------------ | -------- | -------- | 41 | | a 标签连接 | `...` | 发送 | 发送 | 42 | | 预加载 | `/` | 发送 | 发送 | 43 | | GET 表单 | `from method="GET" actions="">...` | 发送 | 发送 | 44 | | POST 表单 | `from method="POST" actions="">...` | 发送 | 不发送 | 45 | | iframe | `` | 发送 | 不发送 | 46 | | AJAX | `$.get(...)` | 发送 | 不发送 | 47 | | Image | ` 15 | ``` 16 | 17 | 这时候访问这个图片,就会带上 cookie,facebook 知道你的 `ip` 等等数据 18 | 19 | ## 原理 20 | 21 | 大多数情况下,被第三方网站或者 JS 脚本获取到 `cookie`,所以防御的手段之一就是防止 `cookie` 被获取。 22 | 23 | ## 防御 24 | 25 | ### 敏感信息都是用 `POST` 26 | 27 | - 就算是 copy 参数也很多,步骤 比 get 还多 28 | - 如果网站存在 `xss` 漏洞,都很费劲 29 | 30 | 比如构造一个 `from` 表单 31 | 32 | ```html 33 | 34 | 35 | 36 | 39 | ``` 40 | 41 | 在 console 执行 script 部分代码,如果有 from, 会直接跳到百度(或许与 Chrome )设置默认引擎有关系。 42 | 43 | 尝试在 firefox 中打开阮老师 blog,会网页提示: `留言提交失败。原因:Invalid request` 44 | 45 | ### 将 Cookie 设置为 `HttpOnly` 46 | 47 | 对应 header 是: `Set-Cookie: hello=world;httponly` 48 | 49 | - JS 脚本将无法读取 `cookie` 信息 50 | 51 | ### 将 Cookie 设置为 `SameHttp` 52 | 53 | ### 增加 token 54 | 55 | 原理:增加攻击者所不能伪造的信息,且不中存在于 `cookie` 中,重点是 `token` 的保密性、随机性。 56 | 57 | - 比如放在 `Token-Csrf: abcdef` 58 | 59 | - token 服务端生成,有一定的有效期 60 | 61 | ::: info 62 | 但这种方式,实际上,也躲不过直接复制信息到 `postman` 63 | ::: 64 | 65 | ### 根据 `referer` 判断 66 | 67 | - 用于验证发起请求是否是合法的网站 68 | -------------------------------------------------------------------------------- /docs/security/xss.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/veaba/web-advanced/6cecbbf996536d0fd965ceb99db72af2dc879bbc/docs/security/xss.md -------------------------------------------------------------------------------- /docs/self/README.md: -------------------------------------------------------------------------------- 1 | # 自我驱动 2 | 3 | - this 真深入理解 4 | - js继承 5 | - react 6 | - 小程序/微信/百度/快应用/支付宝 7 | - 闭包 8 | - 深拷贝 9 | - 浅拷贝 10 | - class 11 | - proxy 12 | - vue 源码 13 | - webgl 14 | -------------------------------------------------------------------------------- /docs/skill/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 业务技巧相关 6 | ## RESTful 与 GraphQL 比较 7 | ## 跨域问题 8 | >@https://segmentfault.com/a/1190000011145364 9 | - JSONP 跨域 10 | - **缺点:只支持get、不支持post** 11 | - 传递函数名 12 | - document.domain 13 | > 引入iframe 时候,无法使用js交互操作 14 | - 使用document.domain 将主页面和子页面都设置为相同的域名就可以了 15 | - **缺点:设置成自身或更高一级的父级,且主域必须相同** 16 | - 原因: 17 | - postMessage 跨文档通信API,跨窗口通信 18 | - window.name 进行跨域 19 | - 跨资源共享(CORS) 20 | - > IE10 21 | - 依赖服务端改造 header 22 | - nginx 代理跨域 23 | - nodejs中间件代理跨域 24 | - websocket 协议跨域 25 | > 26 | ## 微信支付开发 27 | > 已申请了微信开发者账号 9-17,有空再去看看。 28 | ## 支付宝支付开发 29 | > 已申请了支付宝开发者账号 9-17,有空再去看看。 30 | ## github 授权登录 31 | -------------------------------------------------------------------------------- /docs/svg/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # SVG 6 | 7 | - 不依赖分辨率 8 | - 支持事件处理器 9 | - 适合大型渲染区域的应用程序(如:Google map) 10 | - 复杂度高,会减慢渲染速度,太依赖 DOM 11 | - 不适合游戏应用 -------------------------------------------------------------------------------- /docs/typescript/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # TypeScript 5 | 6 | 7 | - [泛型](generics) -------------------------------------------------------------------------------- /docs/v8/README.md: -------------------------------------------------------------------------------- 1 | # V8引擎 2 | 3 | ## 相关链接 4 | - [v8官网](https://v8.dev/docs/) 5 | - [Chromium](https://github.com/chromium/chromium) 6 | 7 | ## 文档 8 | 9 | V8是Google的开源高性能JavaScript和WebAssembly引擎,用C++编写。它用于Chrome和Node.js等。 10 | 11 | 此文档旨在针对那些希望在应用程序中使用`V8`的C++开发人员,以及对V8的设计和性能感兴趣的人。 12 | 本文档向您介绍了`V8`,而其余的文档则向您展示了如何在代码中使用`V8`,并描述了它的一些设计细节,还提供了一组用于测量`V8`性能的JavaScript基准。 13 | 14 | 15 | ## 目录 16 | 17 | - 从源码构建`V8` 18 | - [`V8`源码检出](/v8/source-code/) 19 | - [通过GN构建](/v8/build-gn/) 20 | - `ARM/Android`的交叉编译与调试 21 | - `iOS`交叉编译 22 | - `GUI`和`IDE`安装 23 | - 贡献 24 | - `V8`公共`API`及其稳定性 25 | - 成为`V8`的提交者 26 | - 提交者的责任 27 | - Blink web 测试(也称布局测试) 28 | - 评估代码覆盖率 29 | - 发布进程 30 | - 设计评审指南 31 | - 实现和发布`JavaScript/WebAssembly`语言特性 32 | - `WebAssembly`特性的暂存和装运清单 33 | - 二分查找算法 34 | - 端口处理 35 | - 合并&补丁 36 | - Node.js 整合构建 37 | - 报告安全性bug 38 | - 在本地运行基准测试 39 | - 测试 40 | - 分流issues 41 | - 调试 42 | - 用模拟器进行Arm调试 43 | - `ARM/Android`的交叉编译与调试 44 | - 用`GDB`调试内置代码 45 | - 通过`V8`检查器协议进行调试 46 | - `GDB JIT`编译接口集成 47 | - 调查内存泄漏 48 | - 堆栈跟踪API 49 | - 使用`D8` 50 | - 嵌入V8 51 | - 嵌入V8指南 52 | - 版本号 53 | - 内置函数 54 | - i18n 支持 55 | - 不受信任的代码缓解 ? 56 | - 高级选项 57 | - 点火开关? 58 | - 发动机? 59 | - 扭矩用户手册? 60 | - 内置写入扭矩 61 | - 编写CSA内置 62 | - 添加新的`WebAssembly`操作码 63 | - 编写可优化的JavaScript 64 | - 使用`V8`的基于样本的探查器 65 | - 在`V8`中剖析 Chromium 66 | - 在V8中使用Linux性能 67 | - 跟踪 V8 68 | - 使用运行时调用统计信息 69 | -------------------------------------------------------------------------------- /docs/v8/build-gn.md: -------------------------------------------------------------------------------- 1 | # V8 build-gn 2 | -------------------------------------------------------------------------------- /docs/v8/garbage.md: -------------------------------------------------------------------------------- 1 | # V8 垃圾回收机制 2 | 3 | ## keyword 4 | 5 | - `堆` 6 | - `栈` 7 | - `基本类型` 8 | - `引用类型` 9 | - `新生代` 10 | - `老生代` 11 | - `生存时间长` 12 | - `生存时间短` 13 | - `Scavenge` 14 | - `Mark sweep & Mark Compact` 15 | - `from-space` 16 | - `to-space` 17 | - `root set` 18 | - `对象可达性` 19 | - `标记阶段` 20 | - `清理阶段` 21 | - `内存碎片` 22 | - `全停顿` 23 | - `Stop The World` 24 | - `Orinoco` 25 | - `Incremental marking` 26 | - `增量标记` 27 | - `lazy sweeping` 28 | - `懒性清理` 29 | - `Concurrent` 30 | - `并发` 31 | - `并行` 32 | - `Parallel` 33 | - `副垃圾回收器` 34 | - `主垃圾回收器` 35 | - `` 36 | 37 | ## 引用 38 | 39 | - [深入理解Chrome V8垃圾回收机制](https://juejin.cn/post/6876638765025067015) 40 | 41 | 42 | ## 基本类型和引用类型在内存中 43 | 44 | ``` 45 | +------------+ +--------------+ 46 | | 栈 | ---- | 堆 | 47 | +------------+ +--------------+ 48 | ``` -------------------------------------------------------------------------------- /docs/v8/source-code.md: -------------------------------------------------------------------------------- 1 | # todo 检出V8源码 2 | 3 | - [原文](https://v8.dev/docs/source-code) 4 | 5 | 本文档说明如何在本地检出V8源代码。如果您只想在线浏览源代码,请使用以下链接: 6 | 7 | - [阅览](https://chromium.googlesource.com/v8/v8/) 8 | - [浏览 bleeding edge](https://chromium.googlesource.com/v8/v8/+/master) 9 | - [变更](https://chromium.googlesource.com/v8/v8/+log/master) 10 | 11 | ## 使用GIT 12 | 13 | 14 | ## 说明 15 | 16 | ## 保持更新 17 | 18 | ## 发送审核代码 19 | 20 | ## 提交 21 | 22 | ## 实验工作 23 | 24 | ### 从codereview创建实验工作 25 | 26 | ### 从本地分支创建实验工作 27 | 28 | ### 可用的arguments 29 | 30 | ### 查看try 服务器 31 | 32 | ## 源码分支 -------------------------------------------------------------------------------- /docs/v8/v8.md: -------------------------------------------------------------------------------- 1 | # V8 引擎 2 | -------------------------------------------------------------------------------- /docs/vue/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Vue 5 | -------------------------------------------------------------------------------- /docs/vue/parser-vue.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # 解析Vue.js文件 6 | 7 | ## config 8 | 9 | ### optionMergeStrategies 10 | `Object.create(null)` 11 | 12 | ### silent 13 | 是否警告 14 | 15 | ### productionTip 16 | 开发环境提示 17 | 18 | ### devtools 19 | 是否启动devtools工具 20 | 21 | ### performance 22 | 是否记录性能 23 | 24 | ### errorHandler 25 | 错误处理程序中的错误 26 | 27 | ### warnHandler 28 | 警告处理程序观察家警告说 29 | 30 | ### ignoreElements 31 | 忽略某些自定义元素 32 | 33 | ### keyCodes 34 | 用户自定有v-on的别名 35 | 36 | ### isReservedTag 37 | 检查是否是保留的tag,以便不能注册为组件,可能被覆盖 38 | 39 | ### isReservedAttr 40 | 可能被覆盖,检查一个属性是否保留,以便它不能作为一个组件 41 | 42 | ### isUnknownElement 43 | 未知的元素 44 | 45 | ### getTagNamespace 46 | 获取元素的命名空间 47 | 48 | ### parsePlatformTagName 49 | 解析为特定平台真正的标签名称。 50 | 51 | ### mustUseProp 52 | 检查是否必须值,与平台相关 53 | 54 | ### _lifecycleHooks 55 | 暴露原因遗留 56 | 57 | ## 大量的工具类函数 58 | 59 | -------------------------------------------------------------------------------- /docs/vue/vue3.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # vue.datav.ai 6 | - [vue.datav.ai](https://vue.datav.ai) 7 | -------------------------------------------------------------------------------- /docs/webgl/REAME.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # WebGL 5 | 6 | 摘自MDN:https://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API 7 | 8 | > WebGL 是一种JavaScript API。用于任何兼容Web浏览器中呈现交互式3D和2D。WebGL通过一个与Open ES 2.0相符的API,可以在Canvas 元素中使用。 9 | 10 | (意味着,做一些嵌入式支持的话,其他设备是可以支持) 11 | 12 | ## 浏览器支持 13 | 14 | - Firefox 4 + 15 | - Google Chrome 9+ 16 | - Opera 12+ 17 | - Safari 5.1 + 18 | - Internet Explore 11+ 19 | 20 | ## 标准接口 21 | 22 | ## 拓展 23 | 24 | ## 事件 25 | 26 | ## 常量和类型 27 | - WebGL 常量 28 | - WebGL 类型 29 | 30 | ## WebGL 2 31 | -------------------------------------------------------------------------------- /docs/webpack/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Webpack 5 | -------------------------------------------------------------------------------- /docs/webpack/webpack-dev-server.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | # Webpack-dev-server 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "dev": "vuepress dev docs", 4 | "build": "vuepress build docs", 5 | "test": "jest" 6 | }, 7 | "dependencies": { 8 | "vuepress-plugin-container": "^2.0.2" 9 | }, 10 | "devDependencies": { 11 | "jest": "^26.6.3", 12 | "node-sass": "^4.12.0", 13 | "sass-loader": "^7.1.0", 14 | "vuepress": "^1.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | # !/bin/bash 2 | # 基于Github Actions 前端部署脚本 3 | set -e 4 | # 检查Actions目录配置 5 | if [ -z "${PUBLISH_DIR}" ]; then 6 | echo "【致命错误】:workflows尚未设置 PUBLISH_DIR" 7 | exit 1 8 | fi 9 | 10 | # 检查设置的目录是否存在,不存在直接退出 11 | if [ -d "$(pwd)${PUBLISH_DIR}" ]; then 12 | echo "【致命错误】:PUBLISH_DIR 尚未生成" 13 | exit 1 14 | fi 15 | 16 | # 检查要发布的分支名称 17 | if [ -z "${PUBLISH_BRANCH}" ]; then 18 | print_error "【致命错误】:没有发现 PUBLISH_BRANCH" 19 | exit 1 20 | fi 21 | 22 | # 进入到build的目录 23 | cd "${PUBLISH_DIR}" # dist 24 | 25 | # 为gh-pages 生成CNAME,发现使用别人提供的脚本,生成的竟然是小写的CNAME文件,所以改为小写的,使用脚本写入 26 | 27 | # 设置CNAME 28 | if [ -n "${CNAME}" ]; then 29 | echo "${CNAME}">CNAME 30 | fi 31 | 32 | # 格式化的输出 33 | function print_error() { 34 | echo -e "\e[31mERROR: ${1}\e[m" 35 | } 36 | 37 | function print_info() { 38 | echo -e "\e[36mINFO: ${1}\e[m" 39 | } 40 | 41 | # 配置仓库地址 42 | if [ -n "${EXTERNAL_REPOSITORY}" ]; then 43 | PUBLISH_REPOSITORY=${EXTERNAL_REPOSITORY} 44 | else 45 | PUBLISH_REPOSITORY=${GITHUB_REPOSITORY} 46 | fi 47 | 48 | # 配置ssh 49 | if [ -n "${ACCESS_TOKEN_DEPLOY}" ]; then 50 | echo "设置 ACCESS_TOKEN_DEPLOY" 51 | SSH_DIR="${HOME}/.ssh" 52 | mkdir "${SSH_DIR}" 53 | ssh-keyscan -t rsa github.com >"${SSH_DIR}/known_hosts" 54 | echo "${ACCESS_TOKEN_DEPLOY}" >"${SSH_DIR}/id_rsa" 55 | chmod 400 "${SSH_DIR}/id_rsa" 56 | remote_repo="git@github.com:${PUBLISH_REPOSITORY}.git" 57 | fi 58 | 59 | # 跳过配置personal_token 和 github_token 60 | remote_branch="${PUBLISH_BRANCH}" 61 | 62 | # 配置git 63 | git init 64 | git checkout --orphan "${remote_branch}" # 积累无数次commit,不算分支 65 | 66 | git config user.name "${GITHUB_ACTOR}" 67 | git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" 68 | 69 | git remote rm origin || true 70 | git remote add origin "${remote_repo}" 71 | 72 | # 更改时间 73 | cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 74 | 75 | # git提交 76 | git add . 77 | push_time="$(date '+%Y-%m-%d %H:%M:%S')" 78 | git commit -m "【部署成功】:${push_time}" 79 | 80 | git push origin -f "${PUBLISH_BRANCH}" 81 | 82 | print_info "${GITHUB_SHA} 漂亮!部署成功: ${push_time}" 83 | --------------------------------------------------------------------------------