├── .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 | 
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 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/demos/html/box-model.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
24 |
25 |
26 |
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 |
39 | - 1
40 | - 2
41 | - 3
42 | - 4
43 | - 5
44 | - 6
45 | - 7
46 | - 8
47 | - 9
48 | - 10
49 |
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 | `"
42 | }
43 | ],
44 | [
45 | "container",
46 | {
47 | type: "warning",
48 | before: title =>
49 | `"
51 | }
52 | ],
53 | [
54 | "container",
55 | {
56 | type: "danger",
57 | before: title =>
58 | `"
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 |
2 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
34 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
26 |
27 |
31 |
36 |
{{ feature.title }}
37 |
{{ feature.details }}
38 |
39 |
40 |
41 |
42 |
43 |
50 |
51 |
52 |
53 |
75 |
76 |
166 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Keyword.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/NavLink.vue:
--------------------------------------------------------------------------------
1 |
2 | {{ item.text }}
8 |
15 | {{ item.text }}
16 |
17 |
18 |
19 |
20 |
50 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/NavLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
34 |
35 |
36 |
117 |
118 |
150 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Navbar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
15 | {{ $siteTitle }}
21 |
22 |
23 |
36 |
37 |
38 |
39 |
87 |
88 |
129 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/Sidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
22 |
23 |
60 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
28 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarLink.vue:
--------------------------------------------------------------------------------
1 |
95 |
96 |
126 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/components/SidebarLinks.vue:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
24 |
87 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/global-components/Badge.vue:
--------------------------------------------------------------------------------
1 |
25 |
26 |
45 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/global-components/Catalog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 | {{ parent.title }}
7 |
8 | -
9 | {{ child.title }}
10 |
11 |
12 |
13 |
14 |
15 |
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 |
2 |
3 |
4 |
404
5 |
{{ getMsg() }}
6 |
Take me home.
7 |
8 |
9 |
10 |
11 |
27 |
--------------------------------------------------------------------------------
/docs/.vuepress/theme/layouts/Layout.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
13 |
17 |
18 |
22 |
26 |
30 |
31 |
32 |
33 |
34 |
38 |
42 |
46 |
50 |
51 |
52 |
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 |
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 | 
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 |
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 | 
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 | 
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 |
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 | 
115 |
116 | - children
117 | - 总 width: parent width = 200
118 | - 总 height: parent height = 200
119 |
120 | 
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------