├── docs ├── .vuepress │ ├── styles │ │ ├── palette.styl │ │ └── index.styl │ ├── public │ │ ├── logo.jpg │ │ └── demo │ │ │ └── test.html │ ├── shims-vue.d.ts │ ├── store │ │ ├── index.js │ │ └── modules │ │ │ └── app.js │ ├── views │ │ └── index.vue │ ├── components │ │ ├── clipboardComponent.vue │ │ ├── btn-upload.vue │ │ └── mIframe.vue │ └── enhanceApp.js ├── assets │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.gif │ ├── 6.png │ ├── 732.png │ ├── rect.png │ ├── 节流防抖.gif │ ├── 343615.png │ ├── 3_long.jpg │ ├── 706e67.png │ ├── 1_two_sum.jpeg │ ├── 2812025490.png │ ├── 3_median.jpeg │ ├── s8958650.jpeg │ ├── dom_navigate.gif │ ├── 1641693599167.jpg │ ├── 1645321528510.jpg │ ├── 1645321836097.jpg │ ├── 1645322462186.jpg │ ├── 1645322768186.jpg │ ├── 1645323427752.jpg │ ├── 1645324060764.jpg │ ├── 1645324507138.jpg │ ├── 1645324924704.jpg │ ├── 1645326234075.jpg │ ├── 1645327565128.jpg │ ├── 1645327840554.jpg │ ├── 1645328759610.jpg │ ├── 1645329101801.jpg │ ├── 1645330134734.jpg │ ├── 1645330273553.jpg │ ├── 1645330507471.jpg │ ├── 1645330666412.jpg │ ├── 1645331212297.jpg │ ├── 1645336912144.jpg │ ├── 1645337395918.jpg │ ├── 1645337975075.jpg │ ├── 1645338981328.jpg │ ├── 1645345633430.jpg │ ├── 1645348106231.jpg │ ├── 20180714105005.jpg │ ├── 20220117110923.jpg │ ├── 20220117111226.jpg │ ├── 20220117111446.jpg │ ├── 20220119154209.png │ ├── 20220119160750.png │ ├── 6a76772e676966.gif │ ├── 79178-12f8c9590705a099.png │ ├── 79178-15ee23e259ba96a1.png │ ├── 79178-3b1a13f5c8b993ef.png │ ├── 79178-49fffb573bff36e3.png │ ├── 79178-76b7cc717286a34f.png │ ├── 79178-7f94accd5a09b830.png │ ├── 79178-abc86e6cf1e065e4.png │ ├── 79178-f0a78b1c458cf16e.png │ ├── 79178-f90cd59191f3cc96.png │ ├── object-available-members.png │ ├── 2f86beba9dfa163212ec030dabf1be9c.png │ └── MDN-Graphics-person-person-object-2.png ├── Node │ └── README.md ├── Browser-Extensions │ └── README.md ├── Java │ ├── 1-9工作空间的切换.md │ ├── 1-8项目的导入和导出.md │ ├── 1-10HelloWorld的说明.md │ ├── 1-6编辑器和控制台字体修改.md │ ├── 1-7工程名、包名和类名的重命名.md │ ├── 1-5HelloWorld的编写和包的使用.md │ ├── 1-4Java工程创建和目录结构.md │ ├── 1-3Eclipse的下载安装和启动.md │ ├── 1-1JDK的下载和安装.md │ ├── 1-2环境变量的配置.md │ ├── README.md │ ├── 1-11-34.md │ └── 3-第三部分.md ├── Performance │ └── README.md ├── Programming │ └── README.md ├── React │ └── README.md ├── safety │ └── README.md ├── regular-expression │ ├── images │ │ ├── ip.png │ │ ├── char1.png │ │ ├── char10.png │ │ ├── char11.png │ │ ├── char2.png │ │ ├── char3.png │ │ ├── char4.png │ │ ├── char5.png │ │ ├── char6.png │ │ ├── char7.png │ │ ├── char8.png │ │ ├── char9.png │ │ ├── email.png │ │ ├── email2.png │ │ ├── num1.png │ │ ├── num10.png │ │ ├── num2.png │ │ ├── num3.png │ │ ├── num4.png │ │ ├── num5.png │ │ ├── num6.png │ │ ├── num7.png │ │ ├── num8.png │ │ ├── num9.png │ │ ├── phone.png │ │ ├── phone2.png │ │ ├── regex.png │ │ ├── userid.png │ │ ├── chineses.png │ │ └── domain-name.png │ └── README.md ├── HTML │ ├── README.md │ └── HTML基础.md ├── HTTP │ ├── README.md │ └── MDN-HTTP.md ├── JavaScript-advanced-programming │ ├── 10章-函数.md │ ├── 12章-BOM.md │ ├── 13章-客户端检测.md │ ├── 17章-事件.md │ ├── 19章-表单脚本.md │ ├── 22章-处理XML.md │ ├── 23章-JSON.md │ ├── 25章-客户端存储.md │ ├── 26章-模块.md │ ├── 27章-工作者线程.md │ ├── 28章-最佳实践.md │ ├── 3章-语言基础.md │ ├── 5章-基本引用类型.md │ ├── 6章-集合引用类型.md │ ├── 9章-代理与反射.md │ ├── 11章-期约与异步函数.md │ ├── 21章-错误处理与调试.md │ ├── 24章-网络请求与远程资源.md │ ├── 4章-变量与作用域与内存.md │ ├── 7章-迭代器与生成器.md │ ├── 8章-对象与类与面向对象编程.md │ ├── 18章-动画与Canvas图形.md │ ├── 1章-什么是JavaScript.md │ ├── 20章-JavaScriptAPI.md │ ├── 2章-HTML中的JavaScript.md │ ├── 16章-DOM2和DOM3.md │ └── README.md ├── browser │ ├── README.md │ └── 浏览器解析渲染页面过程.md ├── CSS │ ├── README.md │ ├── CSS选择器.md │ └── 盒子模型.md ├── front-end-engineering │ ├── README.md │ └── 三分钟了解AST.md ├── coding │ ├── textarea实现禁止拉伸.md │ ├── 同一个ip下的多个端口下的cookie是共享的.md │ ├── README.md │ ├── 浏览器中实现剪切板复制内容的功能.md │ ├── 切片上传和断点续传.md │ └── 实现图片的懒加载.md ├── DataStructure │ ├── README.md │ ├── 链表.md │ ├── 时间复杂度与空间复杂度.md │ └── 栈-队列-堆.md ├── html-css-js-coding │ ├── README.md │ ├── 新年快乐-来一个CSS文字特效.md │ └── 实现水平垂直居中最便捷的方法.md ├── ALG │ ├── README.md │ ├── 4-寻找两个正序数组的中位数.md │ ├── 1-两数之和.md │ ├── 3-无重复字符的最长子串.md │ └── 2-两数相加.md ├── APIs │ └── README.md ├── Vue │ ├── README.md │ ├── 对于MVVM的理解.md │ ├── vue-ts项目中Prop的用法.md │ ├── vue-ts项目中Emit的用法.md │ ├── vue-ts项目中Model的用法.md │ ├── vue-ts项目中watch的用法.md │ └── vue-ts项目中PropSync的用法.md ├── README.md └── JavaScript │ ├── README.md │ ├── 防抖.md │ ├── 节流.md │ ├── 词法作用域和动态作用域.md │ ├── 创建您自己的函数.md │ ├── 数组.md │ ├── 作用域.md │ ├── 执行上下文栈.md │ ├── 执行上下文.md │ ├── 变量对象.md │ ├── 闭包.md │ ├── 浅谈instanceof和typeof的实现原理.md │ ├── 原型链.md │ ├── 继承.md │ ├── 函数-可复用代码块.md │ ├── 对象.md │ ├── bind的实现.md │ ├── 立即执行函数.md │ ├── 类型.md │ └── eval-undefined-null-主动分号插入-setTimeout和setInterval.md ├── .gitignore ├── 1646832308609.jpg ├── deploy.sh ├── README.md └── package.json /docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | $accentColor = #3178c6 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | docs/.vuepress/dist 3 | yarn-error.log 4 | yarn.lock -------------------------------------------------------------------------------- /1646832308609.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/1646832308609.jpg -------------------------------------------------------------------------------- /docs/assets/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1.png -------------------------------------------------------------------------------- /docs/assets/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/2.png -------------------------------------------------------------------------------- /docs/assets/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/3.png -------------------------------------------------------------------------------- /docs/assets/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/4.png -------------------------------------------------------------------------------- /docs/assets/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/5.png -------------------------------------------------------------------------------- /docs/assets/6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/6.gif -------------------------------------------------------------------------------- /docs/assets/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/6.png -------------------------------------------------------------------------------- /docs/assets/732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/732.png -------------------------------------------------------------------------------- /docs/assets/rect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/rect.png -------------------------------------------------------------------------------- /docs/assets/节流防抖.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/节流防抖.gif -------------------------------------------------------------------------------- /docs/Node/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | -------------------------------------------------------------------------------- /docs/assets/343615.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/343615.png -------------------------------------------------------------------------------- /docs/assets/3_long.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/3_long.jpg -------------------------------------------------------------------------------- /docs/assets/706e67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/706e67.png -------------------------------------------------------------------------------- /docs/Browser-Extensions/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 -------------------------------------------------------------------------------- /docs/Java/1-9工作空间的切换.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 🈚️ -------------------------------------------------------------------------------- /docs/assets/1_two_sum.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1_two_sum.jpeg -------------------------------------------------------------------------------- /docs/assets/2812025490.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/2812025490.png -------------------------------------------------------------------------------- /docs/assets/3_median.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/3_median.jpeg -------------------------------------------------------------------------------- /docs/assets/s8958650.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/s8958650.jpeg -------------------------------------------------------------------------------- /docs/Java/1-8项目的导入和导出.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 🈚️ -------------------------------------------------------------------------------- /docs/Performance/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/Programming/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/assets/dom_navigate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/dom_navigate.gif -------------------------------------------------------------------------------- /docs/.vuepress/public/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/.vuepress/public/logo.jpg -------------------------------------------------------------------------------- /docs/Java/1-10HelloWorld的说明.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 🈚️ -------------------------------------------------------------------------------- /docs/React/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/assets/1641693599167.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1641693599167.jpg -------------------------------------------------------------------------------- /docs/assets/1645321528510.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645321528510.jpg -------------------------------------------------------------------------------- /docs/assets/1645321836097.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645321836097.jpg -------------------------------------------------------------------------------- /docs/assets/1645322462186.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645322462186.jpg -------------------------------------------------------------------------------- /docs/assets/1645322768186.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645322768186.jpg -------------------------------------------------------------------------------- /docs/assets/1645323427752.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645323427752.jpg -------------------------------------------------------------------------------- /docs/assets/1645324060764.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645324060764.jpg -------------------------------------------------------------------------------- /docs/assets/1645324507138.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645324507138.jpg -------------------------------------------------------------------------------- /docs/assets/1645324924704.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645324924704.jpg -------------------------------------------------------------------------------- /docs/assets/1645326234075.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645326234075.jpg -------------------------------------------------------------------------------- /docs/assets/1645327565128.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645327565128.jpg -------------------------------------------------------------------------------- /docs/assets/1645327840554.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645327840554.jpg -------------------------------------------------------------------------------- /docs/assets/1645328759610.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645328759610.jpg -------------------------------------------------------------------------------- /docs/assets/1645329101801.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645329101801.jpg -------------------------------------------------------------------------------- /docs/assets/1645330134734.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645330134734.jpg -------------------------------------------------------------------------------- /docs/assets/1645330273553.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645330273553.jpg -------------------------------------------------------------------------------- /docs/assets/1645330507471.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645330507471.jpg -------------------------------------------------------------------------------- /docs/assets/1645330666412.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645330666412.jpg -------------------------------------------------------------------------------- /docs/assets/1645331212297.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645331212297.jpg -------------------------------------------------------------------------------- /docs/assets/1645336912144.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645336912144.jpg -------------------------------------------------------------------------------- /docs/assets/1645337395918.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645337395918.jpg -------------------------------------------------------------------------------- /docs/assets/1645337975075.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645337975075.jpg -------------------------------------------------------------------------------- /docs/assets/1645338981328.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645338981328.jpg -------------------------------------------------------------------------------- /docs/assets/1645345633430.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645345633430.jpg -------------------------------------------------------------------------------- /docs/assets/1645348106231.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/1645348106231.jpg -------------------------------------------------------------------------------- /docs/assets/20180714105005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20180714105005.jpg -------------------------------------------------------------------------------- /docs/assets/20220117110923.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20220117110923.jpg -------------------------------------------------------------------------------- /docs/assets/20220117111226.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20220117111226.jpg -------------------------------------------------------------------------------- /docs/assets/20220117111446.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20220117111446.jpg -------------------------------------------------------------------------------- /docs/assets/20220119154209.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20220119154209.png -------------------------------------------------------------------------------- /docs/assets/20220119160750.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/20220119160750.png -------------------------------------------------------------------------------- /docs/assets/6a76772e676966.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/6a76772e676966.gif -------------------------------------------------------------------------------- /docs/Java/1-6编辑器和控制台字体修改.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 🈚️ 4 | 5 | -------------------------------------------------------------------------------- /docs/Java/1-7工程名、包名和类名的重命名.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 🈚️ 4 | -------------------------------------------------------------------------------- /docs/safety/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/assets/79178-12f8c9590705a099.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-12f8c9590705a099.png -------------------------------------------------------------------------------- /docs/assets/79178-15ee23e259ba96a1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-15ee23e259ba96a1.png -------------------------------------------------------------------------------- /docs/assets/79178-3b1a13f5c8b993ef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-3b1a13f5c8b993ef.png -------------------------------------------------------------------------------- /docs/assets/79178-49fffb573bff36e3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-49fffb573bff36e3.png -------------------------------------------------------------------------------- /docs/assets/79178-76b7cc717286a34f.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-76b7cc717286a34f.png -------------------------------------------------------------------------------- /docs/assets/79178-7f94accd5a09b830.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-7f94accd5a09b830.png -------------------------------------------------------------------------------- /docs/assets/79178-abc86e6cf1e065e4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-abc86e6cf1e065e4.png -------------------------------------------------------------------------------- /docs/assets/79178-f0a78b1c458cf16e.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-f0a78b1c458cf16e.png -------------------------------------------------------------------------------- /docs/assets/79178-f90cd59191f3cc96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/79178-f90cd59191f3cc96.png -------------------------------------------------------------------------------- /docs/regular-expression/images/ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/ip.png -------------------------------------------------------------------------------- /docs/assets/object-available-members.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/object-available-members.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char1.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char10.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char11.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char2.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char3.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char4.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char5.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char6.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char7.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char8.png -------------------------------------------------------------------------------- /docs/regular-expression/images/char9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/char9.png -------------------------------------------------------------------------------- /docs/regular-expression/images/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/email.png -------------------------------------------------------------------------------- /docs/regular-expression/images/email2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/email2.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num1.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num10.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num2.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num3.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num4.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num5.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num6.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num7.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num8.png -------------------------------------------------------------------------------- /docs/regular-expression/images/num9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/num9.png -------------------------------------------------------------------------------- /docs/regular-expression/images/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/phone.png -------------------------------------------------------------------------------- /docs/regular-expression/images/phone2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/phone2.png -------------------------------------------------------------------------------- /docs/regular-expression/images/regex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/regex.png -------------------------------------------------------------------------------- /docs/regular-expression/images/userid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/userid.png -------------------------------------------------------------------------------- /docs/regular-expression/images/chineses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/chineses.png -------------------------------------------------------------------------------- /docs/.vuepress/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | // .vuepress/shims-vue.d.ts 2 | declare module '*.vue' { 3 | import Vue from 'vue' 4 | export default Vue 5 | } -------------------------------------------------------------------------------- /docs/regular-expression/images/domain-name.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/regular-expression/images/domain-name.png -------------------------------------------------------------------------------- /docs/HTML/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## HTML 4 | 5 | - [HTML基础](/HTML/HTML基础.md) 6 | -------------------------------------------------------------------------------- /docs/HTTP/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [MDN-HTTP](/HTTP/MDN-HTTP.md) 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/10章-函数.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/12章-BOM.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/13章-客户端检测.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/17章-事件.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/19章-表单脚本.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/22章-处理XML.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/23章-JSON.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/25章-客户端存储.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/26章-模块.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/27章-工作者线程.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/28章-最佳实践.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/3章-语言基础.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/5章-基本引用类型.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/6章-集合引用类型.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/9章-代理与反射.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/assets/2f86beba9dfa163212ec030dabf1be9c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/2f86beba9dfa163212ec030dabf1be9c.png -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/11章-期约与异步函数.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/21章-错误处理与调试.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/24章-网络请求与远程资源.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/4章-变量与作用域与内存.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/7章-迭代器与生成器.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/8章-对象与类与面向对象编程.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/assets/MDN-Graphics-person-person-object-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webVueBlog/learn-web/HEAD/docs/assets/MDN-Graphics-person-person-object-2.png -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/18章-动画与Canvas图形.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/1章-什么是JavaScript.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/20章-JavaScriptAPI.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/2章-HTML中的JavaScript.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | -------------------------------------------------------------------------------- /docs/browser/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [浏览器解析渲染页面过程](/browser/浏览器解析渲染页面过程.md) 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/CSS/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## CSS 4 | 5 | - [盒子模型](/CSS/盒子模型.md) 6 | - [CSS选择器](/CSS/CSS选择器.md) 7 | -------------------------------------------------------------------------------- /docs/regular-expression/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [正则表达式](/regular-expression/正则表达式.md) 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/front-end-engineering/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [三分钟了解AST](/front-end-engineering/三分钟了解AST.md) 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docs/coding/textarea实现禁止拉伸.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 使用 CSS 样式可以避免拉伸 4 | 5 | ```js 6 | textarea { 7 | resize: none; 8 | } 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/coding/同一个ip下的多个端口下的cookie是共享的.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 根据同源策略,cookie 是区分端口的,但是浏览器实现来说,“cookie 区分域,而不区分端口,也就是说,同一个 ip 下的多个端口下的 cookie 是共享的! 4 | 5 | -------------------------------------------------------------------------------- /docs/.vuepress/public/demo/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
hello
9 | hello world! 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/DataStructure/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 《数据结构与算法》 4 | 5 | - [栈-队列-堆](/DataStructure/栈-队列-堆.md) 6 | - [链表](/DataStructure/链表.md) 7 | - [时间复杂度与空间复杂度](/DataStructure/时间复杂度与空间复杂度.md) 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/Java/1-5HelloWorld的编写和包的使用.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ```js 4 | public class HelloWorld { 5 | public static void main(String[] args) { 6 | System.out.println("Hello World!"); 7 | } 8 | } 9 | ``` 10 | 11 | -------------------------------------------------------------------------------- /docs/.vuepress/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | // Modules 5 | import moduleA from './modules/app' 6 | 7 | const modules = { 8 | app: moduleA, 9 | } 10 | 11 | Vue.use(Vuex) 12 | 13 | export default new Vuex.Store({ 14 | modules 15 | }) 16 | -------------------------------------------------------------------------------- /docs/Java/1-4Java工程创建和目录结构.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - Eclipse中工程的创建和项目结构 4 | - Eclipse中helloworld类和包的编写 5 | - 设置编辑器行号、字体和控制台字体 6 | - Eclipse中修改工程名、包名和类名 7 | - Java项目的导入和导出 8 | - 工程直接导入导出 9 | - 导入导出为压缩文件 10 | - 工作空间的切换 11 | -------------------------------------------------------------------------------- /docs/Java/1-3Eclipse的下载安装和启动.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | # Eclipse的使用 4 | 5 | ## Eclipse是什么? 6 | 7 | - Eclipse是著名的跨平台的自由集成开发环境(ide) 8 | 9 | ## ide 10 | 11 | - 是用于提供程序开发环境的应用程序,一般包括代码编辑器,编译器,调试器和图形用户界面工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。 12 | -------------------------------------------------------------------------------- /docs/html-css-js-coding/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [新年快乐-来一个CSS文字特效](/html-css-js-coding/新年快乐-来一个CSS文字特效.md) 4 | - [实现水平垂直居中最便捷的方法](/html-css-js-coding/实现水平垂直居中最便捷的方法.md) 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | // 通过检查,查看元素样式声明 2 | .dark .content__default code { 3 | background-color: rgba(58,58,92,0.7); 4 | color: #fff; 5 | } 6 | 7 | .page .page-title { 8 | display: none; 9 | } 10 | 11 | .theme-default-content pre { 12 | background-color: rgba(27,31,35,0.05); 13 | } 14 | -------------------------------------------------------------------------------- /docs/Java/1-1JDK的下载和安装.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | # 什么是JDK 4 | 5 | - 是Java语言的sdk(软件开发工具包) 6 | - 包含了Java的运行环境(Java Runtime Enviroment),Java工具(如javac.ext)和Java基础的类库。 7 | - 下载地址: 百度去 8 | - 安装路径不要有中文,安装后的目录结构: 9 | - jdk1.8.0_91 10 | - jre1.8.0_91 11 | -------------------------------------------------------------------------------- /docs/ALG/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [「LeetCode」01-两数之和⚡️](/ALG/1-两数之和.md) 4 | - [「LeetCode」02-两数相加⚡](/ALG/2-两数相加.md) 5 | - [「LeetCode」03-无重复字符的最长子串⚡](/ALG/3-无重复字符的最长子串.md) 6 | - [「LeetCode」04-寻找两个正序数组的中位数⚡](/ALG/4-寻找两个正序数组的中位数.md) 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/APIs/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## Web API 接口参考 4 | 5 | 在使用 JavaScript 编写 Web 代码时,有许多 Web API 可供调用。下面是开发Web应用程序或网站时可能使用的所有API和接口(对象类型)的列表。 6 | 7 | Web API主要用于JavaScript,但也可能有例外。 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/Java/1-2环境变量的配置.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | # 环境变量的配置 4 | 5 | - JAVA_HOME 6 | - Path 7 | - CLASSPATH 8 | 9 | 用户配置 10 | 11 | 高级系统配置: 12 | 13 | JAVA_HOME:jdk的安装路径 14 | 15 | Path: %JAVA_HOME%\bin; 16 | 17 | CLASSPATH: .; 18 | 19 | 新启动cmd 20 | 21 | 命令 javac -version / java -version -------------------------------------------------------------------------------- /docs/.vuepress/views/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 23 | -------------------------------------------------------------------------------- /docs/.vuepress/store/modules/app.js: -------------------------------------------------------------------------------- 1 | const moduleA = { 2 | state: () => ({ 3 | count: 2 4 | }), 5 | mutations: { 6 | increment(state) { 7 | // 这里的 `state` 对象是模块的局部状态 8 | state.count++ 9 | } 10 | }, 11 | actions: { 12 | 13 | }, 14 | getters: { 15 | doubleCount(state) { 16 | return state.count * 2 17 | } 18 | } 19 | } 20 | 21 | export default moduleA -------------------------------------------------------------------------------- /docs/.vuepress/components/clipboardComponent.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | -------------------------------------------------------------------------------- /docs/coding/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [实现图片的懒加载](/coding/实现图片的懒加载.md) 4 | - [浏览器中实现剪切板复制内容的功能](/coding/浏览器中实现剪切板复制内容的功能.md) 5 | - [同一个ip下的多个端口下的cookie是共享的](/coding/同一个ip下的多个端口下的cookie是共享的.md) 6 | - [textarea实现禁止拉伸](/coding/textarea实现禁止拉伸.md) 7 | - [实现大文件上传和断点续传](/coding/实现大文件上传和断点续传.md) 8 | - [切片上传和断点续传](/coding/切片上传和断点续传.md) 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docs/Vue/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | - [vue-ts项目中PropSync的用法️](/Vue/vue-ts项目中PropSync的用法.md) 4 | - [vue-ts项目中Prop的用法](/Vue/vue-ts项目中Prop的用法.md) 5 | - [vue-ts项目中watch的用法](/Vue/vue-ts项目中watch的用法.md) 6 | - [vue-ts项目中Emit的用法](/Vue/vue-ts项目中Emit的用法.md) 7 | - [vue-ts项目中Model的用法](/Vue/vue-ts项目中Model的用法.md) 8 | - [对于MVVM的理解](/Vue/对于MVVM的理解.md) 9 | - [vue篇](/Vue/vue篇.md) 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/Vue/对于MVVM的理解.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | - MVVM 是 Model-View-ViewModel 的缩写 6 | - Model: 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑。我们可以把 Model 称为数据层,因为它仅仅关注数据本身,不关心任何行为 7 | - View: 用户操作界面。当 ViewModel 对 Model 进行更新的时候,会通过数据绑定更新到 View 8 | - ViewModel: 业务逻辑层,View 需要什么数据,ViewModel 要提供这个数据;View 有某些操作,ViewModel 就要响应这些操作,所以可以说它是 Model for View. 9 | 10 | 总结: 11 | 12 | - MVVM 模式简化了界面与业务的依赖,解决了数据频繁更新。 13 | - MVVM 在使用当中,利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel 变化时,View 也会自动变化。 14 | 15 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | # 确保脚本抛出遇到的错误 2 | set -e 3 | 4 | # 打包生成静态文件 5 | yarn docs:build 6 | printf "打包成功\n" 7 | 8 | # 进入打包好的文件夹 9 | cd docs/.vuepress/dist 10 | 11 | # 写入域名 EOF是结束符标识 12 | # cat > CNAME << EOF 13 | # 1024bibi.com 14 | # EOF 15 | 16 | # 静态页面上传 17 | # 创建git的本地仓库,提交修改 18 | git init 19 | # ?? 20 | git checkout -b dist 21 | git add -A 22 | git commit -m 'deploy' 23 | printf "本地提交成功\n" 24 | # 覆盖式地将本地仓库发布至github,因为发布不需要保留历史记录 25 | # 格式为:git push -f git@github.com:'用户名'/'仓库名'.git master 26 | git push -f git@github.com:webVueBlog/learn-web.git dist 27 | 28 | printf "dist目录上传成功\n" -------------------------------------------------------------------------------- /docs/html-css-js-coding/新年快乐-来一个CSS文字特效.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 效果如下: 4 | 5 | 10 | -------------------------------------------------------------------------------- /docs/.vuepress/components/btn-upload.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /docs/DataStructure/链表.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | - 链表逆序 6 | - 链表求交点 7 | - 链表求环 8 | - 链表划分 9 | - 复杂链表的复制 10 | - 2个排序链表归并 11 | - k个排序链表归并 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | import ElementUI from 'element-ui'; 2 | import 'element-ui/lib/theme-chalk/index.css'; 3 | import store from './store/index.js'; 4 | import User from './views/index'; 5 | 6 | export default ({ 7 | Vue, // the version of Vue being used in the VuePress app 8 | options, // the options for the root Vue instance 9 | router, // the router instance for the app 10 | siteData, // site metadata 11 | }) => { 12 | Vue.use(ElementUI); 13 | Vue.mixin({ 14 | store, 15 | }); 16 | 17 | router.addRoutes([{ 18 | path: '/views', 19 | name: 'user', 20 | component: User 21 | }]) 22 | // Vue.prototype.$EventBus = new Vue(); 23 | } -------------------------------------------------------------------------------- /docs/Java/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 1、JAVA基础部分内容有:JAVA开发环境搭建、Eclipse的使用、JAVA中的数据类型、输入输出、分支结构、循环结构、数组、方法的使用等。 4 | 5 | 2、面向对象部分,内容有:类和对象、构造方法、对象间关系、对象数组、封装、继承、重写、多态、抽象类、接口、static和final、this和super关键字等。 6 | 7 | 3、JAVA进阶,内容有:异常处理、常用工具类的使用、集合、IO流、JSON及其解析。 8 | 9 | 4、tomcat和Servlet,主要内容有:tomcat的下载和安装、tomcat的常用配置、tomcat的启动和停止、Eclipse中tomcat的集成、Dynamic web Project的创建、Servlet的编写和运行、Servlet3.0中注解的使用、Servlet中请求参数的接收、中文乱码问题、tomcat调用Servlet的原理。 10 | 11 | 5、数据库和JDBC,主要内容有:Mysql数据库的安装和配置、数据库的连接和退出、数据库的操作、数据表的操作、数据的增删改查的操作、JDBC连接数据库、JDBC完成数据库的增删改查、JDBC工具类和PropertiesUtil工具类的抽取等。 12 | 13 | 6、从0到1开发java服务端项目驾照题库系统,主要内容有:数据库的设计、利用爬虫完成数据库中数据的收集、服务端项目搭建、服务端接收并处理客户端请求、服务端响应数据给客户端、客户端进行服务端测试。 -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/16章-DOM2和DOM3.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## DOM2 和 DOM3 6 | 7 | 1. DOM2 到 DOM3 的变化 8 | 2. 操作样式的 DOM API 9 | 3. DOM 遍历与范围 10 | 11 | > DOM1(DOM Level 1)主要定义了 HTML 和 XML 文档的底层结构。 12 | > 13 | > DOM2(DOM Level 2)和 DOM3(DOM Level 3)在这些结构之上加入更多交互能力,提供了更高级的 XML 特性。 14 | 15 | - DOM Core:在 DOM1 核心部分的基础上,为节点增加方法和属性。 16 | - DOM Views:定义基于样式信息的不同视图。 17 | - DOM Events:定义通过事件实现 DOM 文档交互 18 | - DOM Style:定义以编程方式访问和修改 CSS 样式的接口。 19 | - DOM Traversal and Range:新增遍历 DOM 文档及选择文档内容的接口。 20 | - DOM HTML:在 DOM1 HTML 部分的基础上,增加属性、方法和新接口。 21 | - DOM Mutation Observers:定义基于 DOM 变化触发回调的接口。这个模块是 DOM4 级模块,用于取代 Mutation Events。 22 | 23 | # XML 命名空间 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | lang: zh-CN 4 | heroText: 哪吒的全栈官方文档 5 | heroImage: /logo.jpg 6 | actionText: 开始 -> 7 | actionLink: /HTML/ 8 | features: 9 | - title: 知识管理 10 | details: 包含三种典型的知识管理形态:结构化、碎片化、体系化的知识管理平台 11 | - title: 简介搞笑 12 | details: 带给你一种沉浸式阅读体验。配合多维索引快速定位每个知识点 13 | - title: 沉浸式阅读 14 | details: 如果你所学的东西 处于喜欢 才会有强大的动力支撑 15 | - title: 仅适合本人 16 | details: 记录日常所得,见证成长之路~ 17 | - title: 特此说明 18 | details: 感谢大佬的文章,你们的付出我有在看~ 19 | - title: 文档网站 20 | details: 愿你遇到那个心疼你付出的人~ 21 | footer: Copyright © Jekson-learn-web 22 | --- 23 | 24 | **支持一下** 25 | 26 | - 进行关注 27 | - [Github链接在此, 欢迎点个 Start](https://github.com/webVueBlog/learn-web) 28 | - 将好文章分享给您身边更多的小伙伴 29 | 30 | ### 参与贡献 31 | 32 | 1. 如果您对本项目有任何建议或发现文中内容有误的,欢迎提交 issues 进行指正。 33 | 2. 对于文中我没有涉及到知识点,欢迎提交 PR。 34 | 3. 如果您有文章推荐请以 markdown 格式到邮箱 `2397923107@qq.com`,[中文技术文档的写作规范指南](https://github.com/ruanyf/document-style-guide)。 35 | -------------------------------------------------------------------------------- /docs/DataStructure/时间复杂度与空间复杂度.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 6 | 7 | ## 反转链表 8 | 9 | ``` 10 | var reverseList = function(head) { 11 | let prev = null; 12 | let curr = head; 13 | let next = null; 14 | while (curr != null) { 15 | next = curr.next; 16 | curr.next = prev; 17 | prev = curr; 18 | curr = next; 19 | } 20 | return prev; 21 | } 22 | ``` 23 | 24 | ## Set和Map 25 | 26 | ```js 27 | const numberSet = new Set(); 28 | numberSet.add(1); 29 | console.log(numberSet); 30 | // Set(1) {1} 31 | // Set里面的值是不重复的 32 | numberSet.has(1) // true 33 | numberSet.size() 34 | // forEach 35 | ``` 36 | 37 | ```js 38 | const person = new Map() 39 | person.set("name", "jeskson") 40 | // for...of 41 | ``` 42 | 43 | ## let和const 44 | 45 | var 函数作用域, let const 块级作用域 46 | -------------------------------------------------------------------------------- /docs/.vuepress/components/mIframe.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learn-web文档 2 | 3 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 4 | 5 | 文档地址[learn-web](https://webvueblog.github.io/learn-web/) 6 | 7 | 8 | 9 | **支持一下** 10 | 11 | - 进行关注 12 | - [Github链接在此, 欢迎点个 Start](https://github.com/webVueBlog/learn-web) 13 | - 将好文章分享给您身边更多的小伙伴 14 | 15 | ### 参与贡献 16 | 17 | 1. 如果您对本项目有任何建议或发现文中内容有误的,欢迎提交 issues 进行指正。 18 | 2. 对于文中我没有涉及到知识点,欢迎提交 PR。 19 | 3. 如果您有文章推荐请以 markdown 格式到邮箱 `2397923107@qq.com`,[中文技术文档的写作规范指南](https://github.com/ruanyf/document-style-guide)。 20 | 21 | ## 学前必读 22 | 23 | 哪吒希望能为开发人员提供最大程度的愉悦开发体验。提供便捷的阅读文档,帮助前端开发小团体高效率的工作进度,并维护本站learn-web文档。 24 | 25 | ## 感谢指正 26 | 27 | 指正不胜感激,无以回报。 28 | 29 | ## 声明 30 | 31 | 学习文档,仅适合本人食用!!! 32 | 33 | ## 勘误及提问 34 | 35 | 如果有疑问或者发现错误,可以在相应的 issues 进行提问或勘误。 36 | 37 | 如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。 38 | 39 | ## License 40 | 41 | 所有文章采用[知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/)进行许可。 -------------------------------------------------------------------------------- /docs/coding/浏览器中实现剪切板复制内容的功能.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 它一般可以使用第三方库 clipboard-copy (打开新窗口)来实现,源码很简单,可以读一读 6 | 7 | 目前最为推荐的方式是使用 Clipboard API 进行实现 8 | 9 | ```js 10 | navigator.clipboard.writeText(text); 11 | ``` 12 | 13 | 而对于一些不支持 Clipboard API 的浏览器,使用以下 API 进行复制 14 | 15 | 1. 选中: Selection API 16 | 2. 复制: document.execCommand (已被废弃) 17 | 18 | ## 选中: Selection API/Range API 19 | 20 | 选中主要利用了 Selection API (打开新窗口)给定范围 API 21 | 22 | 选中的代码如下 23 | 24 | ```js 25 | const selection = window.getSelection(); 26 | const range = document.createRange(); 27 | 28 | // RangeAPI: 制造区域 29 | range.selectNodeContents(element); 30 | 31 | // Selection: 选中区域 32 | selection.addRange(range); 33 | 34 | selectedText = selection.toString(); 35 | ``` 36 | 37 | 取消选中的代码如下 38 | 39 | ```js 40 | window.getSelection().removeAllRanges(); 41 | ``` 42 | 43 | 它有现成的第三方库可以使用: select.js(打开新窗口) 44 | 45 | ## 复制: execCommand 46 | 47 | 复制就比较简单了,execCommand 48 | 49 | ```js 50 | document.execCommand("copy"); 51 | ``` 52 | 53 | -------------------------------------------------------------------------------- /docs/JavaScript/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## JavaScript 4 | 5 | - [对象](/JavaScript/对象.md) 6 | - [函数](/JavaScript/函数.md) 7 | - [数组](/JavaScript/数组.md) 8 | - [类型](/JavaScript/类型.md) 9 | - [eval-undefined-null-主动分号插入-setTimeout和setInterval](/JavaScript/eval-undefined-null-主动分号插入-setTimeout和setInterval.md) 10 | - [函数-可复用代码块](/JavaScript/函数-可复用代码块.md) 11 | - [创建您自己的函数](/JavaScript/创建您自己的函数.md) 12 | - [对象原型](/JavaScript/对象原型.md) 13 | - [原型链](/JavaScript/原型链.md) 14 | - [词法作用域和动态作用域](/JavaScript/词法作用域和动态作用域.md) 15 | - [45道Promise](/JavaScript/45道Promise.md) 16 | - [深浅拷贝](/JavaScript/深浅拷贝.md) 17 | - [继承](/JavaScript/继承.md) 18 | - [执行上下文栈](/JavaScript/执行上下文栈.md) 19 | - [变量对象](/JavaScript/变量对象.md) 20 | - [作用域](/JavaScript/作用域.md) 21 | - [防抖](/JavaScript/防抖.md) 22 | - [节流](/JavaScript/节流.md) 23 | - [40道this](/JavaScript/40道this.md) 24 | - [执行上下文](/JavaScript/执行上下文.md) 25 | - [闭包](/JavaScript/闭包.md) 26 | - [立即执行函数](/JavaScript/立即执行函数.md) 27 | - [浅谈instanceof和typeof的实现原理](/JavaScript/浅谈instanceof和typeof的实现原理.md) 28 | - [bind的实现](/JavaScript/bind的实现.md) 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /docs/html-css-js-coding/实现水平垂直居中最便捷的方法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 在 flex 格式化上下文中,设置了 margin: auto 的元素,在通过 justify-content 和 align-self 进行对齐之前,任何正处于空闲的空间都会分配到该方向的自动 margin 中去 4 | 5 | 这里,很重要的一点是,margin auto 的生效不仅是水平方向,垂直方向也会自动去分配这个剩余空间。 6 | 7 | HTML: 8 | 9 | ```js 10 |
11 |
12 |
13 | ``` 14 | 15 | SCSS: 16 | 17 | ```js 18 | .g-container { 19 | width: 100vw; 20 | height: 100vh; 21 | 22 | display: flex; 23 | // display: grid; 24 | // display: inline-flex; 25 | // display: inline-grid; 26 | 27 | } 28 | 29 | .g-box { 30 | width: 40vmin; 31 | height: 40vmin; 32 | background: #000; 33 | margin: auto; 34 | } 35 | ``` 36 | 37 | 效果如下: 38 | 39 | 44 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "@vue/babel-preset-jsx": "^1.0.0", 4 | "@vuepress/plugin-back-to-top": "^1.9.5", 5 | "@vuepress/plugin-nprogress": "^1.9.5", 6 | "node-sass": "^7.0.1", 7 | "sass-loader": "^12.4.0", 8 | "ts-loader": "^6.0.0", 9 | "typescript": "^4.5.4", 10 | "vue": "^2.6.11", 11 | "vue-router": "^3.5.3", 12 | "vuepress": "^1.9.5", 13 | "vuepress-plugin-code-copy": "^1.0.6", 14 | "vuepress-plugin-dynamic-title": "^1.0.0", 15 | "vuepress-plugin-medium-zoom": "^1.1.9", 16 | "vuepress-plugin-social-share": "^1.1.0", 17 | "vuepress-plugin-typescript": "^0.3.1", 18 | "vuepress-types": "^0.9.4", 19 | "vuex": "^3.6.2" 20 | }, 21 | "scripts": { 22 | "docs:dev": "vuepress dev docs", 23 | "docs:build": "vuepress build docs" 24 | }, 25 | "dependencies": { 26 | "async-validator": "1.11.5", 27 | "element-ui": "^2.15.6", 28 | "vue-property-decorator": "^9.1.2", 29 | "vuepress-plugin-last-reading": "^1.0.0", 30 | "vuepress-plugin-reading-progress": "^1.0.10", 31 | "vuex-module-decorators": "^2.0.0" 32 | }, 33 | "name": "learn-web", 34 | "version": "1.0.0", 35 | "repository": "git@github.com:webVueBlog/learn-web.git", 36 | "author": "webVueBlog <2979986590@qq.com>", 37 | "license": "MIT" 38 | } 39 | -------------------------------------------------------------------------------- /docs/JavaScript/防抖.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 原理 6 | 7 | 防抖(`debounce`):不管事件触发频率多高,一定在事件触发n秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。 8 | 9 | 10 | 11 | 应用场景 12 | 13 | ## 窗口大小变化,调整样式 14 | 15 | ```js 16 | window.addEventListener('resize', debounce(handleResize, 200)); 17 | ``` 18 | 19 | ## 搜索框,输入后1000毫秒搜索 20 | 21 | ```js 22 | debounce(fetchSelectData, 300); 23 | ``` 24 | 25 | ## 表单验证,输入1000毫秒后验证 26 | 27 | ```js 28 | debounce(validator, 1000); 29 | ``` 30 | 31 | ## 实现 32 | 33 | 注意考虑两个问题: 34 | 35 | 在debounce函数中返回一个闭包,这里用的普通function,里面的setTimeout则用的箭头函数,这样做的意义是让this的指向准确,this的真实指向并非debounce的调用者,而是返回闭包的调用者。 36 | 37 | 对传入闭包的参数进行透传。 38 | 39 | ```js 40 | function debounce(event, time) { 41 | let timer = null; 42 | return function (...args) { 43 | clearTimeout(timer); 44 | timer = setTimeout(() => { 45 | event.apply(this, args); 46 | }, time); 47 | }; 48 | } 49 | ``` 50 | 51 | 有时候我们需要让函数立即执行一次,再等后面事件触发后等待n秒执行,我们给debounce函数一个flag用于标示是否立即执行。 52 | 53 | 当定时器变量timer为空时,说明是第一次执行,我们立即执行它。 54 | 55 | ```js 56 | function debounce(event, time, flag) { 57 | let timer = null; 58 | return function (...args) { 59 | clearTimeout(timer); 60 | if (flag && !timer) { 61 | event.apply(this, args); 62 | } 63 | timer = setTimeout(() => { 64 | event.apply(this, args); 65 | }, time); 66 | }; 67 | } 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /docs/JavaScript/节流.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## 定义 4 | 5 | 节流(throttle):不管事件触发频率多高,只在单位时间内执行一次。 6 | 7 | 8 | 9 | ## 实现 10 | 11 | 有两种方式可以实现节流,使用时间戳和定时器。 12 | 13 | ## 时间戳实现 14 | 15 | 第一次事件肯定触发,最后一次不会触发 16 | 17 | ```js 18 | function throttle(event, time) { 19 | let pre = 0; 20 | return function (...args) { 21 | if (Date.now() - pre > time) { 22 | pre = Date.now(); 23 | event.apply(this, args); 24 | } 25 | } 26 | ``` 27 | 28 | ## 定时器实现 29 | 30 | 第一次事件不会触发,最后一次一定触发 31 | 32 | ```js 33 | function throttle(event, time) { 34 | let timer = null; 35 | return function (...args) { 36 | if (!timer) { 37 | timer = setTimeout(() => { 38 | timer = null; 39 | event.apply(this, args); 40 | }, time); 41 | } 42 | } 43 | } 44 | ``` 45 | 46 | ## 结合版 47 | 48 | 定时器和时间戳的结合版,也相当于节流和防抖的结合版,第一次和最后一次都会触发 49 | 50 | ```js 51 | function throttle(event, time) { 52 | let pre = 0; 53 | let timer = null; 54 | return function (...args) { 55 | if (Date.now() - pre > time) { 56 | clearTimeout(timer); 57 | timer = null; 58 | pre = Date.now(); 59 | event.apply(this, args); 60 | } else if (!timer) { 61 | timer = setTimeout(() => { 62 | event.apply(this, args); 63 | }, time); 64 | } 65 | } 66 | } 67 | ``` 68 | 69 | -------------------------------------------------------------------------------- /docs/Vue/vue-ts项目中Prop的用法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet 4 | 5 | 首先安装: 6 | 7 | ```js 8 | npm i -D vue-property-decorator 9 | ``` 10 | 11 | @Prop(options: (PropOptions | Constructor[] | Constructor) = {}) 12 | 13 | > @Prop装饰器接收一个参数,这个参数可以有三种写法: 14 | 15 | PropOptions ,包含以下选项:type(类型), required(必填), default(默认值), validator(验证函数) 16 | 17 | > Constructor[], 指定prop的可选类型; 18 | 19 | Constructor,如String,Number,Boolean,Array,Object,Date,Function,Symbol或自定义函数类型等,指定prop的类型 20 | 21 | 如下面例子: 22 | 23 | ```js 24 | import { Vue, Component, Prop } from 'vue-property-decorator' 25 | 26 | @Component 27 | export default class Component extends Vue { 28 | // number类型 29 | @Prop(Number) readonly propA: number | undefined 30 | // 默认值为'default value' 31 | @Prop({ default: 'default value' }) readonly propB!: string 32 | @Prop([String, Boolean]) readonly propC: string | boolean | undefined 33 | @Prop({ 34 | default: () => { 35 | return []; 36 | } 37 | }) 38 | readonly propD: {}[] 39 | } 40 | ``` 41 | 42 | 注:属性的类型后面需要加上`undefined` 类型;或者在属性名后面加上`!`,表示非`null` 和 非`undefined`的断言,否则编译器会给出错误提示; 43 | 44 | 以上代码等同于: 45 | 46 | ```js 47 | export default { 48 | props: { 49 | propA: { 50 | type: Number, 51 | }, 52 | propB: { 53 | default: 'default value', 54 | }, 55 | propC: { 56 | type: [String, Boolean], 57 | }, 58 | propD: { 59 | default () { 60 | return [] 61 | } 62 | } 63 | }, 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /docs/ALG/4-寻找两个正序数组的中位数.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 1. 题目描述(中等难度) 6 | 7 | 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 8 | 9 | 算法的时间复杂度应该为 O(log (m+n)) 。 10 | 11 | 12 | 13 | 已知两个有序数组,找到两个数组合并后的中位数。 14 | 15 | ## 2. 解法一 16 | 17 | 简单粗暴,先将两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数。 18 | 19 | ## 前置知识 20 | 21 | - 中位数 22 | - 分治法 23 | - 二分查找 24 | 25 | ## 暴力法 26 | 27 | 暴力解主要是要 merge 两个排序的数组(A,B)成一个排序的数组。 28 | 29 | 用两个`pointer(i,j)`,i 从数组A起始位置开始,即i=0开始,j 从数组B起始位置, 即j=0开始. 一一比较 `A[i]` 和 `B[j]`, 30 | 31 | - 如果`A[i] <= B[j]`, 则把`A[i]` 放入新的数组中,i 往后移一位,即 i+1. 32 | - 如果`A[i] > B[j]`, 则把`B[j]` 放入新的数组中,j 往后移一位,即 j+1. 33 | - 重复步骤#1 和 #2,直到i移到A最后,或者j移到B最后。 34 | - 如果j移动到B数组最后,那么直接把剩下的所有A依次放入新的数组中. 35 | - 如果i移动到A数组最后,那么直接把剩下的所有B依次放入新的数组中. 36 | 37 | ## 3. 代码 38 | 39 | ```js 40 | /** 41 | * @param {number[]} nums1 42 | * @param {number[]} nums2 43 | * @return {number} 44 | */ 45 | var findMedianSortedArrays = function (nums1, nums2) { 46 | // 归并排序 47 | const merged = []; 48 | let i = 0; 49 | let j = 0; 50 | while (i < nums1.length && j < nums2.length) { 51 | if (nums1[i] < nums2[j]) { 52 | merged.push(nums1[i++]); 53 | } else { 54 | merged.push(nums2[j++]); 55 | } 56 | } 57 | while (i < nums1.length) { 58 | merged.push(nums1[i++]); 59 | } 60 | while (j < nums2.length) { 61 | merged.push(nums2[j++]); 62 | } 63 | 64 | const { length } = merged; 65 | return length % 2 === 1 66 | ? merged[Math.floor(length / 2)] 67 | : (merged[length / 2] + merged[length / 2 - 1]) / 2; 68 | }; 69 | ``` 70 | 71 | ## 复杂度分析 72 | 73 | - 时间复杂度:$O(max(m, n))$ 74 | - 空间复杂度:$O(m + n)$ 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/ALG/1-两数之和.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 1. 题目描述 (简单难度) 6 | 7 | 8 | 9 | 给定一个数组和一个目标和,从数组中找两个数字相加等于目标和,输出这两个数字的下标。 10 | 11 | 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 12 | 13 | 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 14 | 15 | 你可以按任意顺序返回答案。 16 | 17 | 示例 1: 18 | 19 | ```js 20 | 输入:nums = [2,7,11,15], target = 9 21 | 输出:[0,1] 22 | 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 23 | 示例 2: 24 | 25 | 输入:nums = [3,2,4], target = 6 26 | 输出:[1,2] 27 | 示例 3: 28 | 29 | 输入:nums = [3,3], target = 6 30 | 输出:[0,1] 31 | ``` 32 | 33 | 提示: 34 | 35 | ```js 36 | 2 <= nums.length <= 104 37 | -109 <= nums[i] <= 109 38 | -109 <= target <= 109 39 | ``` 40 | 41 | 只会存在一个有效答案 42 | 43 | 进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗? 44 | 45 | ## 2. 解法一 46 | 47 | 简单粗暴些,两重循环,遍历所有情况看相加是否等于目标和,如果符合直接输出。 48 | 49 | ```js 50 | /** 51 | * @param {number[]} nums 52 | * @param {number} target 53 | * @return {number[]} 54 | */ 55 | var twoSum = function(nums, target) { 56 | 57 | var map = {}; 58 | for(var i = 0 ; i < nums.length ; i++){ 59 | var v = nums[i]; 60 | 61 | for(var j = i+1 ; j < nums.length ; j++ ){ 62 | if( nums[i] + nums[j] == target ){ 63 | return [i,j]; 64 | } 65 | } 66 | 67 | } 68 | }; 69 | ``` 70 | 71 | ## 进阶 72 | 73 | 上面双回圈的时间复杂度是O(n^2),效率明显不太好,用map就可以在一次走访中找到i,j的位置 74 | 75 | ```js 76 | var twoSum = function(nums, target) { 77 | 78 | var map = {}; 79 | for(var i = 0 ; i < nums.length ; i++){ 80 | var v = nums[i]; 81 | 82 | if(map[target-v] >= 0){ 83 | // 如果 target - v可以在map中找到值x,代表之前已經出現過值x, target = x + v 84 | // 因此回傳 x的位置與目前v的位置 85 | return [map[target-v],i] 86 | } else { 87 | // 使用map儲存目前的數字與其位置 88 | 89 | map[v] = i; 90 | } 91 | } 92 | }; 93 | ``` 94 | 95 | -------------------------------------------------------------------------------- /docs/browser/浏览器解析渲染页面过程.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 浏览器向服务器请求资源过程 6 | 7 | 1. 输入网址; 8 | 2. 浏览器查找域名的IP地址; 9 | 3. 浏览器给web服务器发送一个HTTP请求 ; 10 | 4. 网站服务的永久重定向响应 ; 11 | 5. 浏览器跟踪重定向地址知道了要访问的正确地址,所以它会发送另一个获取请求; 12 | 6. 服务器“处理”请求,服务器接收到获取请求,然后处理并返回一个响应; 13 | 7. 服务器发回一个HTML响应 ; 14 | 8. 浏览器开始渲染HTML,显示HTML 15 | 9. 浏览器发送请求,以获取嵌入在HTML中的对象,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签,这时,浏览器会发送一个获取请求来重新获得这些文件,这些文件就包括CSS/JS/图片等资源,这些资源的地址都要经历一个和HTML读取类似的过程,所以浏览器会在DNS中查找这些域名,发送请求,重定向等。 16 | 17 | ## 浏览器解析渲染流程 18 | 19 | 一、大致分为五步: 20 | 21 | 1. 解析HTML 22 | 2. 构建DOM树 23 | 3. DOM树与CSS样式进行附着构造呈现树 24 | 4. 布局 25 | 5. 绘制 26 | 27 | 二、解析渲染过程 28 | 29 | 1. DOM Tree:浏览器将HTML解析成树形的数据结构,构建一颗DOM树,同时进行第三步。 30 | 2. CSS Rule Tree:浏览器将CSS解析成树形的数据结构,构建CSSOM tree,生成页面的样式表。 31 | 3. Render Tree: 将DOM树和样式表,关联起来,构建一颗Render树(这一过程又称为Attachment)。每个DOM节点都有attach方法,接受样式信息,返回一个render对象(又名renderer)。这些render对象最终会被构建成一颗Render树。 32 | 4. layout: 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去计算出每个节点在屏幕中的位置。 33 | 5. painting: 按照算出来的规则,调用每个节点paint方法,把它们绘制出来。 34 | 6. reflow(回流or重排):当浏览器发现某个部分发生了点变化影响了布局,需要倒回去重新渲染,这个回退的过程叫 reflow。reflow 会从 `` 这个 root frame 开始递归往下,依次计算所有的结点几何尺寸和位置。reflow 几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠、展开(实质上是元素的显示与隐藏)等,都将引起浏览器的 reflow。鼠标滑过、点击……只要这些行为引起了页面上某些元素的占位面积、定位方式、边距等属性的变化,都会引起它内部、周围甚至整个页面的重新渲染。通常我们都无法预估浏览器到底会 reflow 哪一部分的代码,它们都彼此相互影响着。要从第四步重新开始,更加耗费性能。 35 | 7. repaint(重绘):改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸没有变,只需要重新走第五步。 36 | 37 | 38 | 39 | - 浏览器从服务端拿到html文件后,首先开始解析html文件,构建DOM tree,并且同时构建Render Tree; 40 | - 遇到js文件的话,阻塞DOM tree的构建;因为js可能会改变dom和css,因此浏览器会先解析script,避免浪费。 41 | - 遇到css文件的话,先加载css然后构建CSSOM Tree,与此同时构建DOM Tree, 但是将阻塞Render Tree的构建。 42 | - 如果将css文件放在底部,render tree在之前就已经构建完了,因此用户可能会看到无样式的页面,或者闪屏。 43 | - 重排意味着重新计算节点的位置大小等信息,重新在草稿本上画了草图,所以一定会重绘。重绘不一定会重排,比如背景颜色改变 44 | - 重排和重绘代价很高,所以浏览器并不会一有信息改变就去执行重排和重绘,而是会将多个可能的重排和重绘一次执行。 45 | - 有两个css属性,display: none和visibility: hidden,前者会导致重排和重绘,后者会导致重绘。这是后者的优点,但缺点是此节点一直保存在内存中,占用资源。 46 | 47 | -------------------------------------------------------------------------------- /docs/Vue/vue-ts项目中Emit的用法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet 4 | 5 | 首先安装: 6 | 7 | ```js 8 | npm i -D vue-property-decorator 9 | ``` 10 | 11 | > @Emit(event?: string) 12 | 13 | @Emit装饰器接收一个可选参数,作为事件名;如果没有提供这个参数,$emit会将回调函数的camelCase(驼峰式)转为kebab-case(短横线命名),并将其作为事件名; 14 | 15 | @Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象,$emit会将Promise对象状态为resolved之后触发; 16 | 17 | @Emit的回调函数的参数,会放在其返回值之后,一起被$emit当作参数使用; 18 | 19 | 看下面例子: 20 | 21 | ```js 22 | import { Vue, Component, Emit } from 'vue-property-decorator' 23 | 24 | @Component 25 | export default class YourComponent extends Vue { 26 | count = 0 27 | 28 | @Emit() 29 | addToCount(n: number) { 30 | this.count += n 31 | } 32 | 33 | @Emit('reset') 34 | resetCount() { 35 | this.count = 0 36 | } 37 | 38 | @Emit() 39 | returnValue() { 40 | return 10 41 | } 42 | 43 | @Emit() 44 | onInputChange(e) { 45 | return e.target.value 46 | } 47 | 48 | @Emit() 49 | promise() { 50 | return new Promise((resolve) => { 51 | setTimeout(() => { 52 | resolve(20) 53 | }, 0) 54 | }) 55 | } 56 | } 57 | ``` 58 | 59 | 以上代码等同于: 60 | 61 | ```js 62 | export default { 63 | data() { 64 | return { 65 | count: 0, 66 | } 67 | }, 68 | methods: { 69 | addToCount(n) { 70 | this.count += n 71 | // 将addToCount转成add-to-count 72 | this.$emit('add-to-count', n) 73 | }, 74 | resetCount() { 75 | this.count = 0 76 | this.$emit('reset') 77 | }, 78 | returnValue() { 79 | this.$emit('return-value', 10) 80 | }, 81 | onInputChange(e) { 82 | this.$emit('on-input-change', e.target.value, e) 83 | }, 84 | promise() { 85 | const promise = new Promise((resolve) => { 86 | setTimeout(() => { 87 | resolve(20) 88 | }, 0) 89 | }) 90 | 91 | promise.then((value) => { 92 | this.$emit('promise', value) 93 | }) 94 | }, 95 | }, 96 | } 97 | ``` 98 | -------------------------------------------------------------------------------- /docs/Vue/vue-ts项目中Model的用法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet 4 | 5 | 首先安装: 6 | 7 | ```js 8 | npm i -D vue-property-decorator 9 | ``` 10 | 11 | @Model(event?: string, options: (PropOptions | Constructor[] | Constructor) = {}) 12 | 13 | > @Model装饰器允许我们在一个组件上自定义v-model,接受两个参数: 14 | 15 | 1. event: string类型,表示事件名; 16 | 2. options: PropOptions | Constructor[] | Constructor与@Prop的第一个参数一致; 17 | 18 | 看下面例子: 19 | 20 | ```js 21 | import { Vue, Component, Model } from 'vue-property-decorator' 22 | 23 | @Component 24 | export default class YourComponent extends Vue { 25 | @Model('change', { type: Boolean }) readonly checked!: boolean 26 | } 27 | ``` 28 | 29 | 等同于以下代码: 30 | 31 | ```js 32 | export default { 33 | model: { 34 | prop: 'checked', 35 | event: 'change', 36 | }, 37 | props: { 38 | checked: { 39 | type: Boolean, 40 | }, 41 | }, 42 | } 43 | ``` 44 | 45 | 看下面父子组件例子: 46 | 47 | ```js 48 | // 父组件 49 | 55 | 64 | 65 | // 子组件 66 | 71 | 72 | 84 | ``` 85 | -------------------------------------------------------------------------------- /docs/Vue/vue-ts项目中watch的用法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet 4 | 5 | 首先安装: 6 | 7 | ```js 8 | npm i -D vue-property-decorator 9 | ``` 10 | 11 | @Watch(path: string, options: WatchOptions = {}) 12 | 13 | > @Watch装饰器接受两个参数: 14 | 15 | 1. path: string类型,表示需要被监听的属性名; 16 | 2. options?: WatchOptions = {} 包含两个属性: 17 | - immediate?: boolean 监听开始后是否立即调用该回调函数; 18 | - deep?: boolean 表示是否深度监听 19 | 20 | 使用Demo如下: 21 | 22 | ```js 23 | 29 | 30 | 51 | ``` 52 | 53 | 以上script中代码等同于: 54 | 55 | ```js 56 | export default { 57 | data() { 58 | return { 59 | child: '', 60 | person: { 61 | name: 'zxx' 62 | } 63 | } 64 | } 65 | watch: { 66 | child: [ 67 | { 68 | handler: 'onChildChanged', 69 | immediate: false, 70 | deep: false, 71 | }, 72 | ], 73 | person: [ 74 | { 75 | handler: 'onPersonChanged', 76 | immediate: true, 77 | deep: true, 78 | } 79 | ], 80 | }, 81 | methods: { 82 | onChildChanged(val, oldVal) { 83 | console.log(val ,oldVal); 84 | }, 85 | onPersonChanged(val, oldVal) { 86 | console.log(val ,oldVal); 87 | } 88 | }, 89 | } 90 | ``` 91 | 92 | -------------------------------------------------------------------------------- /docs/JavaScript/词法作用域和动态作用域.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 作用域 6 | 7 | 作用域是指程序源代码中定义变量的区域。 8 | 9 | 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。 10 | 11 | JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。 12 | 13 | 静态作用域与动态作用域 14 | 15 | 因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。 16 | 17 | 而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。 18 | 19 | 让我们认真看个例子就能明白之间的区别: 20 | 21 | ```js 22 | var value = 1; 23 | 24 | function foo() { 25 | console.log(value); 26 | } 27 | 28 | function bar() { 29 | var value = 2; 30 | foo(); 31 | } 32 | 33 | bar(); 34 | 35 | // 结果是 ??? 36 | ``` 37 | 38 | 假设JavaScript采用静态作用域,让我们分析下执行过程: 39 | 40 | 执行 foo 函数,先从 foo 函数内部查找是否有局部变量 value,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。 41 | 42 | 假设JavaScript采用动态作用域,让我们分析下执行过程: 43 | 44 | 执行 foo 函数,依然是从 foo 函数内部查找是否有局部变量 value。如果没有,就从调用函数的作用域,也就是 bar 函数内部查找 value 变量,所以结果会打印 2。 45 | 46 | 前面我们已经说了,JavaScript采用的是静态作用域,所以这个例子的结果是 1。 47 | 48 | ## 动态作用域 49 | 50 | 也许你会好奇什么语言是动态作用域? 51 | 52 | `bash` 就是动态作用域,不信的话,把下面的脚本存成例如 `scope.bash`,然后进入相应的目录,用命令行执行 `bash ./scope.bash`,看看打印的值是多少。 53 | 54 | ```js 55 | value=1 56 | function foo () { 57 | echo $value; 58 | } 59 | function bar () { 60 | local value=2; 61 | foo; 62 | } 63 | bar 64 | ``` 65 | 66 | ## 思考题 67 | 68 | ```js 69 | var scope = "global scope"; 70 | function checkscope(){ 71 | var scope = "local scope"; 72 | function f(){ 73 | return scope; 74 | } 75 | return f(); 76 | } 77 | checkscope(); 78 | ``` 79 | 80 | ```js 81 | var scope = "global scope"; 82 | function checkscope(){ 83 | var scope = "local scope"; 84 | function f(){ 85 | return scope; 86 | } 87 | return f; 88 | } 89 | checkscope()(); 90 | ``` 91 | 92 | 猜猜两段代码各自的执行结果是多少? 93 | 94 | 这里直接告诉大家结果,两段代码都会打印:local scope。 95 | 96 | 原因也很简单,因为JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。 97 | 98 | JavaScript 函数的执行用到了作用域链,这个作用域链是在函数定义的时候创建的。嵌套的函数 f() 定义在这个作用域链里,其中的变量 scope 一定是局部变量,不管何时何地执行函数 f(),这种绑定在执行 f() 时依然有效。 99 | 100 | 但是在这里真正想让大家思考的是: 101 | 102 | 虽然两段代码执行的结果一样,但是两段代码究竟有哪些不同呢? 103 | 104 | 如果要回答这个问题,就要牵涉到很多的内容,词法作用域只是其中的一小部分 105 | -------------------------------------------------------------------------------- /docs/HTTP/MDN-HTTP.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 超文本传输​​协议(HTTP)是一个用于传输超媒体文档(例如 HTML)的应用层协议。它是为 Web 浏览器与 Web 服务器之间的通信而设计的,但也可以用于其他目的。HTTP 遵循经典的客户端-服务端模型,客户端打开一个连接以发出请求,然后等待直到收到服务器端响应。HTTP 是无状态协议,这意味着服务器不会在两个请求之间保留任何数据(状态)。尽管通常基于 TCP/IP 层,但它可以在任何可靠的传输层上使用,也就是说,该协议不会像 UDP 那样静默的丢失消息。RUDP——作为 UDP 的可靠化升级版本——是一种合适的替代选择。 6 | 7 | ## HTTP 概述 8 | 9 | 介绍了客户端-服务器端协议的基本特征:它能够做什么以及它的设计意图。 10 | 11 | ## HTTP 缓存 12 | 13 | 缓存对高速 Web 站点来说是非常之重要的。这篇文章阐述了不同种类的缓存以及如何配置 HTTP Headers 来控制它们。 14 | 15 | ## HTTP Cookie 16 | 17 | RFC 6265 定义了 cookie 的工作方式。在处理 HTTP 请求时,服务器可以在 HTTP 响应头中通过HTTP Headers Set-Cookie 为客户端设置 cookie。然后,对于同一服务器发起的每一个请求,客户端都会在 HTTP 请求头中以字段 Cookie 的形式将 cookie 的值发送过去。也可以将 cookie 设置为在特定日期过期,或限制为特定的域和路径。 18 | 19 | ## 跨域资源共享(CORS) 20 | 21 | 跨站点 HTTP 请求就是从另一个域名,而不是资源所在的域名发起的 HTTP 请求。举例来说,在域名 A (http://domaina.example/) 的 HTML 页面上使用 img 元素 () 来请求域名 B (http://domainb.foo/) 上的图片资源。这在当今的 Web 页面上是很常见的 —— 加载跨站点资源,包括 CSS 样式表,图片,脚本和其他资源。CORS 允许 Web 开发人员控制其站点对跨站点请求的反应。 22 | 23 | ## HTTP 的演变 24 | 25 | 简单描述了从早期版本的 HTTP 到现代 HTTP/2,新兴的 HTTP/3 以及未来版本的 HTTP 这个过程中发生的变更。 26 | 27 | ## Mozilla Web 安全准则 28 | 29 | 一系列用于帮助运营团队创建安全的 Web 应用程序的技巧。 30 | 31 | ## HTTP 消息 32 | 33 | 描述了 HTTP/1.x 和 HTTP/2 中不同种类消息的类型和结构。 34 | 35 | ## 典型的 HTTP 会话 36 | 37 | 展现并解释了一个常见 HTTP 会话的流程。 38 | 39 | ## HTTP/1.x 中的连接管理 40 | 41 | 描述了在 HTTP/1.x 中的三种连接管理模型,以及它们的优点和缺点。 42 | 43 | ## HTTP 头 44 | 45 | HTTP 消息头用于描述资源或服务器或客户端的行为。可以使用 `X-` 前缀添加自定义专有头。其他的可以在 `IANA registry` 中找到,其原始定义在 `RFC 4229`。`IANA` 同时也维护着一份 `registry of proposed new HTTP message headers`。 46 | 47 | ## HTTP 请求方式 48 | 49 | 可以使用 `HTTP`: `GET`,`POST` 方式来完成不同操作,或是一些不太常见的请求方式,像是: `OPTIONS`,`DELETE` 和 `TRACE`。 50 | 51 | ## HTTP 状态码 52 | 53 | `HTTP` 状态码用来表示特定的 `HTTP` 请求是否已成功完成。响应分为五类:消息响应,成功响应,重定向,客户端错误和服务器错误。 54 | 55 | ## CSP 指令 56 | 57 | `Content-Security-Policy` 响应报头字段允许网站管理员控制页面上哪些资源能够被用户代理程序加载。除了少数例外,此策略主要涉及指定服务器来源和脚本终端。 58 | 59 | ## Firefox 开发者工具 60 | 61 | 网络监视器 62 | 63 | ## Mozilla Observatory 64 | 65 | 一个旨在帮助开发人员,系统管理员和安全专业人员安全地配置其站点的项目。 66 | 67 | ## RedBot 68 | 69 | 用于检查与缓存相关的 HTTP 头的工具。 70 | 71 | ## 浏览器的工作原理 72 | 73 | 一篇非常全面的关于浏览器内部实现与通过 HTTP 协议的请求流的文章。可以说是所有 Web 开发者的必读内容。 74 | 75 | - [HTTP](https://developer.mozilla.org/zh-CN/docs/Web/HTTP) -------------------------------------------------------------------------------- /docs/JavaScript/创建您自己的函数.md: -------------------------------------------------------------------------------- 1 | 2 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 3 | 4 | [[toc]] 5 | 6 | 让我们来组织一个基本的函数。 7 | 8 | :::tip 9 | 注:对于函数命名约定,应遵循与变量命名约定相同的规则。 这很好,尽你所能理解它们之间的区别 - 函数名称后带有括号,而变量则没有。 10 | ::: 11 | 12 | ```js 13 | const html = document.querySelector('html'); 14 | 15 | const panel = document.createElement('div'); 16 | panel.setAttribute('class', 'msgBox'); 17 | html.appendChild(panel); 18 | 19 | const msg = document.createElement('p'); 20 | msg.textContent = 'This is a message box'; 21 | panel.appendChild(msg); 22 | 23 | const closeBtn = document.createElement('button'); 24 | closeBtn.textContent = 'x'; 25 | panel.appendChild(closeBtn); 26 | 27 | closeBtn.onclick = function() { 28 | panel.parentNode.removeChild(panel); 29 | } 30 | ``` 31 | 32 | 第一行代码使用了一个DOM(文档对象模型)的内置方法 document.querySelector() 来选择`` 元素并且把它存放在一个叫 html的常量中, 这样方便我们接下来使用这个元素: 33 | 34 | ```js 35 | const html = document.querySelector('html'); 36 | ``` 37 | 38 | 一个名字叫做 Document.createElement() 的DOM方法,用来创建 `
` 元素并且把该新建元素的引用(实际上是新建对象的地址)放在一个叫做 panel的常量中。 这个元素将成为我们的消息框的外部容器。 39 | 40 | 一个叫做 Element.setAttribute() 的DOM方法给panel元素添加了一个值为msgBox 的class 类属性。 这样做方便我们来给这个元素添加样式 — 查看CSS代码你就知道我们使用.msgBox 类选择器来给消息框和消息内容设置样式。 41 | 42 | 使用了一个叫做 Node.appendChild() 的DOM方法,给 html 常量(我们之前定义好的)追加了我们设置好样式的panel元素 。 43 | 44 | ## 使用参数列表改进函数 45 | 46 | 就现在看来,我们的函数还不是特别有用 — 我们想要的不仅仅是每点击一次展示一个默认的消息。我们来改造下我们的函数,给它添加几个参数, 允许我们以不同的方式调用这个函数。 47 | 48 | 第一步,修改函数的第一行代码: 49 | 50 | ```js 51 | function displayMessage() { 52 | ``` 53 | 54 | 改成这样的: 55 | 56 | ```js 57 | function displayMessage(msgText, msgType) { 58 | ``` 59 | 60 | 当我们调用函数的时候,我们可以在括号里添加两个变量,来指定显示在消息框里面的消息,和消息的类型。 61 | 62 | 为了使用第一个参数, 把接下来的一行: 63 | 64 | ```js 65 | msg.textContent = 'This is a message box'; 66 | ``` 67 | 68 | 改成这样: 69 | 70 | ```js 71 | msg.textContent = msgText; 72 | ``` 73 | 74 | 最后但同样重要的一点, 我们来调用这个函数,并且使用了带参数的形式,修改下面这行: 75 | 76 | ```js 77 | btn.onclick = displayMessage; 78 | ``` 79 | 80 | 改成这样: 81 | 82 | ```js 83 | btn.onclick = function() { 84 | displayMessage('Woo, this is a different message!'); 85 | }; 86 | ``` 87 | 88 | 如果我们要在点击事件里面绑定这个新函数,我们不能直接使用`(btn.onclick = displayMessage('Woo, this is a different message!');)`前面已经讲过— 我们要把它放在一个匿名函数里面,不然函数会直接调用,而不是按钮点击之后才会调用,这不是我们想要的结果。 89 | 90 | 保存刷新, 就像你所期待的那样现在你可以随意的指定消息框里面显示的消息! 91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/JavaScript-advanced-programming/README.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | ## 内容简介 4 | 5 | 本书是JavaScript经典图书的新版。第4版全面、深入地介绍了JavaScript开发者必须掌握的前端开发技术,涉及JavaScript的基础特性和高级特性。书中详尽讨论了JavaScript的各个方面,从JavaScript的起源开始,逐步讲解到新出现的技术,其中重点介绍ECMAScript和DOM标准。在此基础上,接下来的各章揭示了JavaScript的基本概念,包括类、期约、迭代器、代理,等等。另外,书中深入探讨了客户端检测、事件、动画、表单、错误处理及JSON。本书同时也介绍了近几年来涌现的重要新规范,包括Fetch API、模块、工作者线程、服务线程以及大量新API。 6 | 7 | 建议看原书籍内容。 8 | 9 | ## 笔记 10 | 11 | - [1章-什么是JavaScript](/JavaScript-advanced-programming/1章-什么是JavaScript.md) 12 | - [2章-HTML中的JavaScript](/JavaScript-advanced-programming/2章-HTML中的JavaScript.md) 13 | - [3章-语言基础](/JavaScript-advanced-programming/3章-语言基础.md) 14 | - [4章-变量与作用域与内存](/JavaScript-advanced-programming/4章-变量与作用域与内存.md) 15 | - [5章-基本引用类型](/JavaScript-advanced-programming/5章-基本引用类型.md) 16 | - [6章-集合引用类型](/JavaScript-advanced-programming/6章-集合引用类型.md) 17 | - [7章-迭代器与生成器](/JavaScript-advanced-programming/7章-迭代器与生成器.md) 18 | - [8章-对象与类与面向对象编程](/JavaScript-advanced-programming/8章-对象与类与面向对象编程.md) 19 | - [9章-代理与反射](/JavaScript-advanced-programming/9章-代理与反射.md) 20 | - [10章-函数](/JavaScript-advanced-programming/10章-函数.md) 21 | - [11章-期约与异步函数](/JavaScript-advanced-programming/11章-期约与异步函数.md) 22 | - [12章-BOM](/JavaScript-advanced-programming/12章-BOM.md) 23 | - [13章-客户端检测](/JavaScript-advanced-programming/13章-客户端检测.md) 24 | - [14章-DOM](/JavaScript-advanced-programming/14章-DOM.md) 25 | - [15章-DOM扩展](/JavaScript-advanced-programming/15章-DOM扩展.md) 26 | - [16章-DOM2和DOM3](/JavaScript-advanced-programming/16章-DOM2和DOM3.md) 27 | - [17章-事件](/JavaScript-advanced-programming/17章-事件.md) 28 | - [18章-动画与Canvas图形](/JavaScript-advanced-programming/18章-动画与Canvas图形.md) 29 | - [19章-表单脚本](/JavaScript-advanced-programming/19章-表单脚本.md) 30 | - [20章-JavaScriptAPI](/JavaScript-advanced-programming/20章-JavaScriptAPI.md) 31 | - [21章-错误处理与调试](/JavaScript-advanced-programming/21章-错误处理与调试.md) 32 | - [22章-处理XML](/JavaScript-advanced-programming/22章-处理XML.md) 33 | - [23章-JSON](/JavaScript-advanced-programming/23章-JSON.md) 34 | - [24章-网络请求与远程资源](/JavaScript-advanced-programming/24章-网络请求与远程资源.md) 35 | - [25章-客户端存储](/JavaScript-advanced-programming/25章-客户端存储.md) 36 | - [26章-模块](/JavaScript-advanced-programming/26章-模块.md) 37 | - [27章-工作者线程](/JavaScript-advanced-programming/27章-工作者线程.md) 38 | - [28章-最佳实践](/JavaScript-advanced-programming/28章-最佳实践.md) 39 | -------------------------------------------------------------------------------- /docs/Vue/vue-ts项目中PropSync的用法.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | 要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet 4 | 5 | 首先安装: 6 | 7 | ```js 8 | npm i -D vue-property-decorator 9 | ``` 10 | 11 | @PropSync(propName: string, options: (PropOptions | Constructor[] | Constructor) = {}) 12 | 13 | > @PropSync和@Prop用法类似,二者区别在于: 14 | 15 | @PropSync装饰器接受两个参数: 16 | 17 | propName: string类型,表示父组件传递过来的属性名; 18 | 19 | ```js 20 | options: PropOptions | Constructor[] | Constructor 与@Prop中第一个参数一致; 21 | ``` 22 | 23 | @PropSync会生成一个新的计算属性 24 | 25 | 注意,使用@PropSync的时候是要在父组件配合`.sync`使用的 26 | 27 | ```js 28 | import { Vue, Component, PropSync } from 'vue-property-decorator' 29 | 30 | @Component 31 | export default class YourComponent extends Vue { 32 | @PropSync('name', { type: String }) syncedName!: string 33 | } 34 | ``` 35 | 36 | 以上代码等同于: 37 | 38 | ```js 39 | export default { 40 | props: { 41 | name: { 42 | type: String, 43 | }, 44 | }, 45 | computed: { 46 | syncedName: { 47 | get() { 48 | return this.name 49 | }, 50 | set(value) { 51 | this.$emit('update:name', value) 52 | }, 53 | }, 54 | }, 55 | } 56 | ``` 57 | 58 | 来看一个父子组件的例子: 59 | 60 | ```js 61 | // 父组件 62 | 69 | 70 | 79 | 80 | // 子组件 81 | 88 | 89 | 101 | ``` -------------------------------------------------------------------------------- /docs/coding/切片上传和断点续传.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 一、计算文件MD5 6 | 7 | 在计算文件MD5之前写过的判断文件类型:文件上传判断文件格式,计算文件的MD5就是为了传值给后端比较文件的准确性和完整性,可以使用spark-md5插件,但是我们需要考虑的是大文件上传,需要把文件切片后再进行MD5计算。 8 | 9 | 安装语法: 10 | 11 | `npm install --save spark-md5` 12 | 13 | ```js 14 | async calculateHashWorker() { 15 | return new Promise(resolve => { 16 | this.worker = new Worker('./hash.js'); 17 | this.worker.postMessage({chunks: this.chunks});//文件通过hash通过标识,用来区分唯一性 18 | this.worker.onMessage = e => { 19 | const {progress,hash} = e.data; 20 | this.hashProgress = Number(progress.toFixed(2));//展示计算hash进度条 21 | if(hash) { 22 | resolve(hash); 23 | } 24 | } 25 | }) 26 | }, 27 | async uploadFile() { 28 | this.chunks = this.createFileChunk(this.file);//拿到文件切片后的数组 29 | const hash = await this.calculateHashWorker();//计算md5 30 | } 31 | ``` 32 | 33 | ## 二、切片上传 34 | 35 | 前端把文件切片成很多块,成为文件切片数组,并且可以固定成每一块的大小,限制大小例如1M这样。等文件上传完成后再合并成一个文件,这样就实现了大文件切片上传功能,如果上传过程中出现网络中断或其他问题,下次继续上传时就可以使用下面的断点续传。 36 | 37 | ```js 38 | //把文件切片,生成文件块 39 | createFileChunk(file) { 40 | const chunks = []; 41 | let cur = 0; 42 | const CHUNK_SIZE = 1 * 1024 * 1024;//把文件分块指定成1M大小 43 | while(cur < file.size) { 44 | chunks.push({ 45 | index: cur, 46 | file: file.slice(cur,cur + CHUNK_SIZE) 47 | }); 48 | cur += size; 49 | } 50 | return chunks; 51 | } 52 | ``` 53 | 54 | 把文件分块上传,如果上传了一半网络断了或者用户进行浏览器刷新,就不会继续上传,这时候只有一半到了服务器,这时候可以进行断点续传,后面有网络了只传分片剩下了的部分,然后后端进行合并。这里需要考虑的是把每个切片保存唯一性标识,根据唯一性标识判断文件上传进度,直到文件全部上传完成为止。 55 | 56 | 上传到后端后需要进行文件合并,文件合并按什么顺序呢?这里是后端需要在服务器搭建一个单独临时的文件夹保存所有的切片,切片上传的时候给每个切片加一个索引,这样后端在合并的时候进行索引排序。 57 | 58 | ## 断点续传 59 | 60 | 查询服务器看哪些数据已经传成功标记一下,表示已经上传成功,只需要传剩下的部分。断点续传还需要实现文件覆盖功能,所以如果文件已经有了完整的大文件就要进行删除,上传完成后还要进行文件校验,比较上传前和上传成功后的文件大小。 61 | 62 | ```js 63 | async uploadChunks(uploadedList = []) { 64 | const list = this.chunks.filter(chunks => uploadedList.indexOf(chunk.hash) == -1).map(({chunk,hash,index},i) => { 65 | const form = new FormData(); 66 | form.append('chunk',chunk); 67 | form.append('hash',hash); 68 | form.append('filename',this.container.file.name); 69 | form.append('fileHash',this.container.hash); 70 | return {form,index,status: Status.wait} 71 | }).map(({form,index}) => { 72 | request({ 73 | url: '/upload', 74 | data: form, 75 | onProgress: this.createProgresshandler(this.chunks[index]), 76 | requestList: this.requestList 77 | }) 78 | }) 79 | await Promise.all(list); 80 | } 81 | ``` 82 | -------------------------------------------------------------------------------- /docs/Java/1-11-34.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | # 变量 📝 4 | 5 | ```js 6 | package 包名 7 | public class TestHelloWorld { // 类体 8 | // main 方法: main方法作为程序的入口 9 | public static void main(String[] args) { 10 | // 变量的使用:声明,初始化,使用 11 | // 声明:类型 变量名 12 | } 13 | } 14 | ``` 15 | 16 | # Scanner的使用 17 | 18 | ```js 19 | package ...; 20 | import java.util.Scanner; 21 | 22 | // Scanner: 扫描器 23 | public class TestScanner { 24 | public static void main(String[] args) { 25 | // 1.创建一个扫描器 26 | Scanner scan = new Scanner(System.in); 27 | // 2.接收用户输入的字符串内容 28 | String s = scan.next(); // 方法就是一个功能 29 | System.out.println("您输入的内容为" + s); 30 | } 31 | } 32 | ``` 33 | 34 | ```js 35 | public class TestDesc { 36 | public static void main(String[] args) { 37 | // 1.创建一个扫描器 38 | Scanner scan = new Scanner(System.in); 39 | System.out.println("请输入您的姓名"); 40 | String name = scan.next(); 41 | System.out.println("请输入您的年龄:"); 42 | int age = scan.nextInt(); 43 | ... 44 | } 45 | } 46 | ``` 47 | 48 | # for 循环使用 if 分支的使用 49 | 50 | # break 和 continue 51 | 52 | break: 结束for循环 53 | 54 | continue: 结束本次循环,进入下次循环 55 | 56 | # 模拟聊天室 Scanner 57 | 58 | # switch while 59 | 60 | # 数组 61 | 62 | 1. 默认的初始化 63 | 2. 动态初始化 64 | 3. 静态初始化 65 | 66 | ```js 67 | import java.util.Arrays; 68 | import java.util.Scanner; 69 | public class TestArray { 70 | public static void main(String[] args) { 71 | int num = 3; 72 | String[] nameArr = new String[num]; 73 | int[] scoreArr = new int[num]; 74 | Scanner scan = new Scanner(System.in); 75 | // 循环录入姓名和分数,完成两个数组元素的初始化 76 | for(int i=0; i 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 数组 6 | 7 | ## 数组遍历与属性 8 | 9 | 虽然在 JavaScript 中数组是对象,但是没有好的理由去使用 for in 循环 遍历数组。 相反,有一些好的理由不去使用 for in 遍历数组。 10 | 11 | 注意: JavaScript 中数组不是 关联数组。 JavaScript 中只有对象 来管理键值的对应关系。但是关联数组是保持顺序的,而对象不是。 12 | 13 | 由于 for in 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 hasOwnProperty 函数, 因此会比普通的 for 循环慢上好多倍。 14 | 15 | ## 遍历 16 | 17 | 为了达到遍历数组的最佳性能,推荐使用经典的 for 循环。 18 | 19 | ```js 20 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 21 | for(var i = 0, l = list.length; i < l; i++) { 22 | console.log(list[i]); 23 | } 24 | ``` 25 | 26 | 上面代码有一个处理,就是通过 l = list.length 来缓存数组的长度。 27 | 28 | ## 遍历 29 | 30 | 为了达到遍历数组的最佳性能,推荐使用经典的 for 循环。 31 | 32 | ```js 33 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 34 | for(var i = 0, l = list.length; i < l; i++) { 35 | console.log(list[i]); 36 | } 37 | ``` 38 | 39 | 上面代码有一个处理,就是通过 `l = list.length` 来缓存数组的长度。 40 | 41 | 虽然 `length` 是数组的一个属性,但是在每次循环中访问它还是有性能开销。 可能最新的 `JavaScript` 引擎在这点上做了优化,但是我们没法保证自己的代码是否运行在这些最近的引擎之上。 42 | 43 | 实际上,不使用缓存数组长度的方式比缓存版本要慢很多。 44 | 45 | ## length 属性 46 | 47 | length 属性的 getter 方式会简单的返回数组的长度,而 setter 方式会截断数组。 48 | 49 | ```js 50 | var foo = [1, 2, 3, 4, 5, 6]; 51 | foo.length = 3; 52 | foo; // [1, 2, 3] 53 | 54 | foo.length = 6; 55 | foo; // [1, 2, 3] 56 | ``` 57 | 58 | 在 Firebug 中查看此时 foo 的值是: [1, 2, 3, undefined, undefined, undefined] 但是这个结果并不准确,如果你在 Chrome 的控制台查看 foo 的结果,你会发现是这样的: [1, 2, 3] 因为在 JavaScript 中 undefined 是一个变量,注意是变量不是关键字,因此上面两个结果的意义是完全不相同的。 59 | 60 | ```js 61 | // 为了验证,我们来执行下面代码,看序号 5 是否存在于 foo 中。 62 | 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false 63 | foo[5] = undefined; 64 | 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true 65 | ``` 66 | 67 | 为 length 设置一个更小的值会截断数组,但是增大 length 属性值不会对数组产生影响。 68 | 69 | ## 结论 70 | 71 | 为了更好的性能,推荐使用普通的 for 循环并缓存数组的 length 属性。 使用 for in 遍历数组被认为是不好的代码习惯并倾向于产生错误和导致性能问题。 72 | 73 | ## Array 构造函数 74 | 75 | 由于 `Array` 的构造函数在如何处理参数时有点模棱两可,因此总是推荐使用数组的字面语法 - `[]` - 来创建数组。 76 | 77 | ```js 78 | [1, 2, 3]; // 结果: [1, 2, 3] 79 | new Array(1, 2, 3); // 结果: [1, 2, 3] 80 | 81 | [3]; // 结果: [3] 82 | new Array(3); // 结果: [] 83 | new Array('3') // 结果: ['3'] 84 | 85 | // 因此下面的代码将会使人很迷惑 86 | new Array(3, 4, 5); // 结果: [3, 4, 5] 87 | new Array(3) // 结果: [],此数组长度为 3 88 | ``` 89 | 90 | 这里的模棱两可指的是数组的两种构造函数语法 91 | 92 | 由于只有一个参数传递到构造函数中(指的是 new Array(3); 这种调用方式),并且这个参数是数字,构造函数会返回一个 length 属性被设置为此参数的空数组。 需要特别注意的是,此时只有 length 属性被设置,真正的数组并没有生成。 93 | 94 | 译者注:在 Firebug 中,你会看到 [undefined, undefined, undefined],这其实是不对的。在上一节有详细的分析。 95 | 96 | ```js 97 | var arr = new Array(3); 98 | arr[1]; // undefined 99 | 1 in arr; // false, 数组还没有生成 100 | ``` 101 | 102 | 这种优先于设置数组长度属性的做法只在少数几种情况下有用,比如需要循环字符串,可以避免 for 循环的麻烦。 103 | 104 | ```js 105 | new Array(count + 1).join(stringToRepeat); 106 | ``` 107 | 108 | 译者注: new Array(3).join('#') 将会返回 ## 109 | 110 | ## 结论 111 | 112 | 应该尽量避免使用数组构造函数创建新数组。推荐使用数组的字面语法。它们更加短小和简洁,因此增加了代码的可读性。 113 | -------------------------------------------------------------------------------- /docs/JavaScript/作用域.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 当JavaScript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。 6 | 7 | 对于每个执行上下文,都有三个重要属性: 8 | 9 | - 变量对象(Variable object,VO) 10 | - 作用域链(Scope chain) 11 | - this 12 | 13 | 今天重点讲讲作用域链。 14 | 15 | ## 作用域链 16 | 17 | 当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。 18 | 19 | 下面,让我们以一个函数的创建和激活两个时期来讲解作用域链是如何创建和变化的。 20 | 21 | ## 函数创建 22 | 23 | 函数的作用域在函数定义的时候就决定了。 24 | 25 | 这是因为函数有一个内部属性 `[[scope]]`,当函数创建的时候,就会保存所有父变量对象到其中,你可以理解 `[[scope]]` 就是所有父变量对象的层级链,但是注意:`[[scope]]` 并不代表完整的作用域链! 26 | 27 | 举个例子: 28 | 29 | ```js 30 | function foo() { 31 | function bar() { 32 | ... 33 | } 34 | } 35 | ``` 36 | 37 | 函数创建时,各自的`[[scope]]`为: 38 | 39 | ```js 40 | foo.[[scope]] = [ 41 | globalContext.VO 42 | ]; 43 | 44 | bar.[[scope]] = [ 45 | fooContext.AO, 46 | globalContext.VO 47 | ]; 48 | ``` 49 | 50 | ## 函数激活 51 | 52 | 当函数激活时,进入函数上下文,创建 VO/AO 后,就会将活动对象添加到作用链的前端。 53 | 54 | 这时候执行上下文的作用域链,我们命名为 Scope: 55 | 56 | ```js 57 | Scope = [AO].concat([[Scope]]); 58 | ``` 59 | 60 | 至此,作用域链创建完毕。 61 | 62 | ## 捋一捋 63 | 64 | 以下面的例子为例,结合着之前讲的变量对象和执行上下文栈,我们来总结一下函数执行上下文中作用域链和变量对象的创建过程: 65 | 66 | ```js 67 | var scope = "global scope"; 68 | function checkscope(){ 69 | var scope2 = 'local scope'; 70 | return scope2; 71 | } 72 | checkscope(); 73 | ``` 74 | 75 | 执行过程如下: 76 | 77 | 1.checkscope 函数被创建,保存作用域链到 内部属性`[[scope]]` 78 | 79 | ```js 80 | checkscope.[[scope]] = [ 81 | globalContext.VO 82 | ]; 83 | ``` 84 | 85 | 2.执行 `checkscope` 函数,创建 `checkscope` 函数执行上下文,`checkscope` 函数执行上下文被压入执行上下文栈 86 | 87 | ```js 88 | ECStack = [ 89 | checkscopeContext, 90 | globalContext 91 | ]; 92 | ``` 93 | 94 | 3.checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数`[[scope]]`属性创建作用域链 95 | 96 | ```js 97 | checkscopeContext = { 98 | Scope: checkscope.[[scope]], 99 | } 100 | ``` 101 | 102 | 4.第二步:用 `arguments` 创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明 103 | 104 | ```js 105 | checkscopeContext = { 106 | AO: { 107 | arguments: { 108 | length: 0 109 | }, 110 | scope2: undefined 111 | }, 112 | Scope: checkscope.[[scope]], 113 | } 114 | ``` 115 | 116 | 5.第三步:将活动对象压入 `checkscope` 作用域链顶端 117 | 118 | ```js 119 | checkscopeContext = { 120 | AO: { 121 | arguments: { 122 | length: 0 123 | }, 124 | scope2: undefined 125 | }, 126 | Scope: [AO, [[Scope]]] 127 | } 128 | ``` 129 | 130 | 6.准备工作做完,开始执行函数,随着函数的执行,修改 `AO` 的属性值 131 | 132 | ```js 133 | checkscopeContext = { 134 | AO: { 135 | arguments: { 136 | length: 0 137 | }, 138 | scope2: 'local scope' 139 | }, 140 | Scope: [AO, [[Scope]]] 141 | } 142 | ``` 143 | 144 | 7.查找到 `scope2` 的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出 145 | 146 | ```js 147 | ECStack = [ 148 | globalContext 149 | ]; 150 | ``` 151 | -------------------------------------------------------------------------------- /docs/CSS/CSS选择器.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 简介 6 | 7 | 选择器是 CSS 规则的一部分且位于 CSS 声明块前。 8 | 9 | 10 | 11 | 选择器可以被分为以下类别: 12 | 13 | - 简单选择器(Simple selectors):通过元素类型、class 或 id 匹配一个或多个元素。 14 | - 属性选择器(Attribute selectors):通过 属性 / 属性值 匹配一个或多个元素。 15 | - 伪类(Pseudo-classes):匹配处于确定状态的一个或多个元素,比如被鼠标指针悬停的元素,或当前被选中或未选中的复选框,或元素是 DOM 树中一父节点的第一个子节点。 16 | - 伪元素(Pseudo-elements):匹配处于相关的确定位置的一个或多个元素,例如每个段落的第一个字,或者某个元素之前生成的内容。 17 | - 组合器(Combinators):这里不仅仅是选择器本身,还有以有效的方式组合两个或更多的选择器用于非常特定的选择的方法。例如,你可以只选择 divs 的直系子节点的段落,或者直接跟在 headings 后面的段落。 18 | - 多用选择器(Multiple selectors):这些也不是单独的选择器;这个思路是将以逗号分隔开的多个选择器放在一个 CSS 规则下面, 以将一组声明应用于由这些选择器选择的所有元素。 19 | 20 | ## 简单选择器 21 | 22 | ### 类型选择器(又名:元素选择器) 23 | 24 | 此选择器只是一个选择器名和指定的HTML元素名的不区分大小写的匹配。这是选择所有指定类型的最简单方式。 25 | 26 | ### 类选择器(Class selectors) 27 | 28 | 类选择器由一个点“.”以及类后面的类名组成。类名是在HTML class文档元素属性中没有空格的任何值。由你自己选择一个名字。同样值得一提的是,文档中的多个元素可以具有相同的类名,而单个元素可以有多个类名(以空格分开多个类名的形式书写)。 29 | 30 | ### ID 选择器 31 | 32 | ID选择器由哈希/磅符号 (#)组成,后面是给定元素的ID名称。 任何元素都可以使用id属性设置唯一的ID名称。 由你自己选择的ID是什么。 这是选择单个元素的最有效的方式。 33 | 34 | :::tip 35 | 重要提示:一个ID名称必须在文件中是唯一的。关于重复ID的行为是不可预测的,比如在一些浏览器只是第一个实例计算,其余的将被忽略。 36 | ::: 37 | 38 | ### 通用选择器(Universal selector) 39 | 40 | 通用选择(`*`)是最终的王牌。它允许选择在一个页面中的所有元素。由于给每个元素应用同样的规则几乎没有什么实际价值,更常见的做法是与其他选择器结合使用。 41 | 42 | :::tip 43 | 重要提示:使用通用选择时小心。因为它适用于所有的元素,在大型网页利用它可以对性能有明显的影响:网页可以显示比预期要慢。不会有太多的情况下,您想使用此选择。 44 | ::: 45 | 46 | ### 组合器(Combinators) 47 | 48 | 在CSS中,组合器允许您将多个选择器组合在一起,这允许您在其他元素中选择元素,或者与其他元素相邻。四种可用的类型是: 49 | 50 | - 后代选择器——(空格键)——允许您选择嵌套在另一个元素中的某个元素(不一定是直接的后代;例如,它可以是一个孙子)。 51 | - 子选择器—— > ——允许您选择一个元素,该元素是另一个元素的直接子元素。 52 | - 相邻兄弟选择器—— + ——允许您选择一个元素,它是另一个元素的直接兄弟元素(也就是说,在它的旁边,在层次结构的同一层)。 53 | - 通用兄弟选择器—— ~ — —允许您选择其他元素的兄弟元素(例如,在层次结构中的相同级别,但不一定就在它的旁边)。 54 | 55 | ```js 56 | Combinators Select 57 | A,B 匹配满足A(和/或)B的任意元素. 58 | A B 匹配任意元素,满足条件:B是A的后代结点(B是A的子节点,或者A的子节点的子节点) 59 | A > B 匹配任意元素,满足条件:B是A的直接子节点 60 | A + B 匹配任意元素,满足条件:B是A的下一个兄弟节点(AB有相同的父结点,并且B紧跟在A的后面) 61 | A ~ B 匹配任意元素,满足条件:B是A之后的兄弟节点中的任意一个(AB有相同的父节点,B在A之后,但不一定是紧挨着A) 62 | ``` 63 | 64 | ## 伪类和伪元素 65 | 66 | ### 伪类(Pseudo-class) 67 | 68 | 一个 CSS 伪类(pseudo-class) 是一个以冒号`(:)`作为前缀的关键字,当你希望样式在特定状态下才被呈现到指定的元素时,你可以往元素的选择器后面加上对应的伪类(pseudo-class)。你可能希望某个元素在处于某种状态下呈现另一种样式,例如当鼠标悬停在元素上面时,或者当一个 `checkbox` 被禁用或被勾选时,又或者当一个元素是它在 DOM 树中父元素的第一个孩子元素时。 69 | 70 | ```js 71 | :active 72 | :any 73 | :checked 74 | :default 75 | :dir() 76 | :disabled 77 | :empty 78 | :enabled 79 | :first 80 | :first-child 81 | :first-of-type 82 | :fullscreen 83 | :focus 84 | :hover 85 | :indeterminate 86 | :in-range 87 | :invalid 88 | :lang() 89 | :last-child 90 | :last-of-type 91 | :left 92 | :link 93 | :not() 94 | :nth-child() 95 | :nth-last-child() 96 | :nth-last-of-type() 97 | :nth-of-type() 98 | :only-child 99 | :only-of-type 100 | :optional 101 | :out-of-range 102 | :read-only 103 | :read-write 104 | :required 105 | :right 106 | :root 107 | :scope 108 | :target 109 | :valid 110 | :visited 111 | ``` 112 | 113 | ### 伪元素 114 | 115 | 伪元素(`Pseudo-element`)跟伪类很像,但它们又有不同的地方。它们都是关键字 —— 但这次伪元素前缀是两个冒号 `(::)` —— 同样是添加到选择器后面达到指定某个元素的某个部分。 116 | 117 | ```js 118 | ::after 119 | ::before 120 | ::first-letter 121 | ::first-line 122 | ::selection 123 | ::backdrop 124 | ``` 125 | 126 | - [CSS选择器](https://segmentfault.com/a/1190000013424772) -------------------------------------------------------------------------------- /docs/JavaScript/执行上下文栈.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 顺序执行? 6 | 7 | 如果要问到 JavaScript 代码执行顺序的话,想必写过 JavaScript 的开发者都会有个直观的印象,那就是顺序执行,毕竟: 8 | 9 | ```js 10 | var foo = function () { 11 | 12 | console.log('foo1'); 13 | 14 | } 15 | 16 | foo(); // foo1 17 | 18 | var foo = function () { 19 | 20 | console.log('foo2'); 21 | 22 | } 23 | 24 | foo(); // foo2 25 | ``` 26 | 27 | 然而去看这段代码: 28 | 29 | ```js 30 | function foo() { 31 | 32 | console.log('foo1'); 33 | 34 | } 35 | 36 | foo(); // foo2 37 | 38 | function foo() { 39 | 40 | console.log('foo2'); 41 | 42 | } 43 | 44 | foo(); // foo2 45 | ``` 46 | 47 | 打印的结果却是两个 foo2。 48 | 49 | JavaScript 引擎并非一行一行地分析和执行程序,而是一段一段地分析执行。当执行一段代码的时候,会进行一个“准备工作”,比如第一个例子中的变量提升,和第二个例子中的函数提升。 50 | 51 | 但是本文真正想让大家思考的是:这个“一段一段”中的“段”究竟是怎么划分的呢? 52 | 53 | 到底JavaScript引擎遇到一段怎样的代码时才会做“准备工作”呢? 54 | 55 | ## 可执行代码 56 | 57 | 这就要说到 JavaScript 的可执行代码(executable code)的类型有哪些了? 58 | 59 | 其实很简单,就三种,全局代码、函数代码、eval代码。 60 | 61 | 举个例子,当执行到一个函数的时候,就会进行准备工作,这里的“准备工作”,让我们用个更专业一点的说法,就叫做"执行上下文(execution context)"。 62 | 63 | ## 执行上下文栈 64 | 65 | 接下来问题来了,我们写的函数多了去了,如何管理创建的那么多执行上下文呢? 66 | 67 | 所以 JavaScript 引擎创建了执行上下文栈(Execution context stack,ECS)来管理执行上下文 68 | 69 | 为了模拟执行上下文栈的行为,让我们定义执行上下文栈是一个数组: 70 | 71 | ```js 72 | ECStack = []; 73 | ``` 74 | 75 | 试想当 JavaScript 开始要解释执行代码的时候,最先遇到的就是全局代码,所以初始化的时候首先就会向执行上下文栈压入一个全局执行上下文,我们用 globalContext 表示它,并且只有当整个应用程序结束的时候,ECStack 才会被清空,所以程序结束之前, ECStack 最底部永远有个 globalContext: 76 | 77 | ```js 78 | ECStack = [ 79 | globalContext 80 | ]; 81 | ``` 82 | 83 | 现在 JavaScript 遇到下面的这段代码了: 84 | 85 | ```js 86 | function fun3() { 87 | console.log('fun3') 88 | } 89 | 90 | function fun2() { 91 | fun3(); 92 | } 93 | 94 | function fun1() { 95 | fun2(); 96 | } 97 | 98 | fun1(); 99 | ``` 100 | 101 | 当执行一个函数的时候,就会创建一个执行上下文,并且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。知道了这样的工作原理,让我们来看看如何处理上面这段代码: 102 | 103 | ```js 104 | // 伪代码 105 | 106 | // fun1() 107 | ECStack.push( functionContext); 108 | 109 | // fun1中竟然调用了fun2,还要创建fun2的执行上下文 110 | ECStack.push( functionContext); 111 | 112 | // 擦,fun2还调用了fun3! 113 | ECStack.push( functionContext); 114 | 115 | // fun3执行完毕 116 | ECStack.pop(); 117 | 118 | // fun2执行完毕 119 | ECStack.pop(); 120 | 121 | // fun1执行完毕 122 | ECStack.pop(); 123 | 124 | // javascript接着执行下面的代码,但是ECStack底层永远有个globalContext 125 | ``` 126 | 127 | ## 解答思考题 128 | 129 | 好啦,现在我们已经了解了执行上下文栈是如何处理执行上下文的 130 | 131 | ```js 132 | var scope = "global scope"; 133 | function checkscope(){ 134 | var scope = "local scope"; 135 | function f(){ 136 | return scope; 137 | } 138 | return f(); 139 | } 140 | checkscope(); 141 | var scope = "global scope"; 142 | function checkscope(){ 143 | var scope = "local scope"; 144 | function f(){ 145 | return scope; 146 | } 147 | return f; 148 | } 149 | checkscope()(); 150 | ``` 151 | 152 | 两段代码执行的结果一样,但是两段代码究竟有哪些不同呢? 153 | 154 | 答案就是执行上下文栈的变化不一样。 155 | 156 | 让我们模拟第一段代码: 157 | 158 | ```js 159 | ECStack.push( functionContext); 160 | ECStack.push( functionContext); 161 | ECStack.pop(); 162 | ECStack.pop(); 163 | ``` 164 | 165 | 让我们模拟第二段代码: 166 | 167 | ```js 168 | ECStack.push( functionContext); 169 | ECStack.pop(); 170 | ECStack.push( functionContext); 171 | ECStack.pop(); 172 | ``` 173 | 174 | 是不是有些不同呢? 175 | 176 | 当然了,这样概括的回答执行上下文栈的变化不同 177 | -------------------------------------------------------------------------------- /docs/Java/3-第三部分.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | java进阶:常用类;异常处理;集合;json及其解析;io流 6 | 7 | ## String类常用方法 8 | 9 | length; substring; compareTo; indexOf; lastIndexOf; split; charAt; matches 10 | 11 | ## jdk api 文档 12 | 13 | ## 正则表达式 14 | 15 | 类 Pattern 16 | 17 | ```js 18 | public final class Pattern 19 | extends Object 20 | implements Serializable 21 | ``` 22 | 23 | ```js 24 | . 任何字符 25 | \d 数字:[0-9] 26 | \D 非数字:[^0-9] 27 | \s 空白字符:[\t\n\x0B\f\r] 28 | \S 非空白字符:[^\s] 29 | \w 单词字符:[a-zA-Z_0-9] 30 | \W 非单词字符:[^\w] 31 | ``` 32 | 33 | ```js 34 | public class Test { 35 | public static void main(String[] args) { 36 | String str1 = "ab23lsl345mol"; 37 | String[] strArr = str1.split("\\d{2,3}"); 38 | System.out.println(Arrays.toString(strArr)); 39 | 40 | String name = '2343lsdf'; 41 | if(name.matches("[a-zA-Z0-9_]")) {} 42 | } 43 | } 44 | ``` 45 | 46 | ## Integer 47 | 48 | Java中的数据类型: 49 | 50 | 1. 基本数据类型: 51 | 52 | byte, short, int, long, float, double, char, boolean 53 | 54 | 2. 基本数据类型对应的包装类: 55 | 56 | Byte, Short, Integer, Long, Float, Double, Character, Boolean 57 | 58 | 3. 引用数据类型:类,接口,数组,枚举等都是引用数据类型 59 | 60 | Integer: 常用: 61 | 62 | 1. 获取int类型的最大最小值 63 | 2. 获取十进制整数对应的二进制,八进制,十六进制的字符串形式 64 | 3. 将字符串转为int类型 65 | 66 | ## 异常简介 67 | 68 | 不正常的情况: 69 | 70 | 1. 运行时异常 71 | 2. 非运行异常 72 | 73 | ## try-catch基础用法 74 | 75 | ```js 76 | String s1 = null; 77 | try { 78 | char ch = s1.charAt(0); 79 | System.out.println(ch); 80 | } catch(Exception e) { 81 | e.printStackTrace(); 82 | } 83 | ``` 84 | 85 | ```js 86 | package ...; 87 | 88 | public class Test { 89 | public static void main(String[] args) { 90 | String s1 = null; 91 | try { 92 | // 放可能会发生异常的代码 93 | char ch = s1.charAt(0); // 向上抛出一个NullPointerException的对象 94 | System.out.println(ch); 95 | } catch (Exception e) { 96 | // 当try中抛出异常时,并处理。Exception e = new NullPointerException(); 97 | e.printStackTrace(); // 打印异常的堆栈信息 98 | } 99 | System.out.println("其他的代码") 100 | } 101 | } 102 | ``` 103 | 104 | ## try-catch-finally完整用法 105 | 106 | ```js 107 | // 检测时异常(非运行时异常)必须进行异常的处理 108 | public class TestNullPointerException { 109 | public static void main(String[] args) { 110 | try { 111 | FileInputStream is = new FileInputStream(new File("E:/a.txt")); 112 | } catch (FIleNotFoundException e) { 113 | e.printStackTrace(); 114 | } 115 | } 116 | } 117 | ``` 118 | 119 | ```js 120 | public class Test() { 121 | public static void main(String[] args) { 122 | FileInputStream is = null; 123 | try { 124 | is = new FileInputStream(new File("E:/a.txt")) 125 | } catch (FileNotFoundException e) { 126 | e.printStackTrace(); 127 | } finally { 128 | // 指肯定会执行的代码 129 | try { 130 | is.close(); 131 | } catch (IOException e) { 132 | e.printStackTrace(); 133 | } 134 | } 135 | } 136 | } 137 | ``` 138 | 139 | ## throws 140 | 141 | ```js 142 | throws 向上抛异常 143 | ``` 144 | 145 | ## catch 和 finally 补充说明 146 | 147 | ## 异常总结 148 | 149 | ## 集合概述 150 | 151 | 集合,是存储数据的容器,存储类型不同,个数不同 152 | 153 | ## ArrayList的添加修改和删除 154 | 155 | ```js 156 | public class Test { 157 | public static void main(String[] args) { 158 | // 1.定义ArrayList 159 | ArrayList list = new ArrayList(); 160 | } 161 | } 162 | ``` 163 | 164 | ## ArrayList根据元素的equals方法来删除元素 165 | 166 | ## ArrayList中的查询和泛型 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /docs/front-end-engineering/三分钟了解AST.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | AST 是 Abstract Syntax Tree 的简称,是前端工程化绕不过的一个名词。它涉及到工程化诸多环节的应用,比如: 6 | 7 | 1. 如何将 Typescript 转化为 Javascript (typescript) 8 | 2. 如何将 SASS/LESS 转化为 CSS (sass/less) 9 | 3. 如何将 ES6+ 转化为 ES5 (babel) 10 | 4. 如何将 Javascript 代码进行格式化 (eslint/prettier) 11 | 5. 如何识别 React 项目中的 JSX (babel) 12 | 6. GraphQL、MDX、Vue SFC 等等 13 | 14 | 而在语言转换的过程中,实质上就是对其 AST 的操作,核心步骤就是 AST 三步走 15 | 16 | 1. Code -> AST (Parse) 17 | 2. AST -> AST (Transform) 18 | 3. AST -> Code (Generate) 19 | 20 | 21 | 22 | 以下是一段代码,及其对应的 AST 23 | 24 | ```js 25 | // Code 26 | const a = 4 27 | 28 | // AST 29 | { 30 | "type": "Program", 31 | "start": 0, 32 | "end": 11, 33 | "body": [ 34 | { 35 | "type": "VariableDeclaration", 36 | "start": 0, 37 | "end": 11, 38 | "declarations": [ 39 | { 40 | "type": "VariableDeclarator", 41 | "start": 6, 42 | "end": 11, 43 | "id": { 44 | "type": "Identifier", 45 | "start": 6, 46 | "end": 7, 47 | "name": "a" 48 | }, 49 | "init": { 50 | "type": "Literal", 51 | "start": 10, 52 | "end": 11, 53 | "value": 4, 54 | "raw": "4" 55 | } 56 | } 57 | ], 58 | "kind": "const" 59 | } 60 | ], 61 | "sourceType": "module" 62 | } 63 | ``` 64 | 65 | 不同的语言拥有不同的解析器,比如 Javascript 的解析器和 CSS 的解析器就完全不同。 66 | 67 | 对相同的语言,也存在诸多的解析器,也就会生成多种 AST,如 babel 与 espree。 68 | 69 | 在 AST Explorer 中,列举了诸多语言的解析器(Parser),及转化器(Transformer)。 70 | 71 | 72 | 73 | ## AST 的生成 74 | 75 | AST 的生成这一步骤被称为「解析(Parser)」,而该步骤也有两个阶段: 词法分析(Lexical Analysis)和语法分析(Syntactic Analysis) 76 | 77 | ## 词法分析 (Lexical Analysis) 78 | 79 | 词法分析用以将代码转化为 Token 流,维护一个关于 Token 的数组 80 | 81 | 82 | 83 | ```js 84 | // Code 85 | a = 3 86 | 87 | // Token 88 | [ 89 | { type: { ... }, value: "a", start: 0, end: 1, loc: { ... } }, 90 | { type: { ... }, value: "=", start: 2, end: 3, loc: { ... } }, 91 | { type: { ... }, value: "3", start: 4, end: 5, loc: { ... } }, 92 | ... 93 | ] 94 | ``` 95 | 96 | 词法分析后的 Token 流也有诸多应用,如: 97 | 98 | 1. 代码检查,如 eslint 判断是否以分号结尾,判断是否含有分号的 token 99 | 2. 语法高亮,如 highlight/prism 使之代码高亮 100 | 3. 模板语法,如 ejs 等模板也离不开 101 | 102 | ## 语法分析 (Syntactic Analysis) 103 | 104 | 语法分析将 Token 流转化为结构化的 AST,方便操作 105 | 106 | ```js 107 | { 108 | "type": "Program", 109 | "start": 0, 110 | "end": 5, 111 | "body": [ 112 | { 113 | "type": "ExpressionStatement", 114 | "start": 0, 115 | "end": 5, 116 | "expression": { 117 | "type": "AssignmentExpression", 118 | "start": 0, 119 | "end": 5, 120 | "operator": "=", 121 | "left": { 122 | "type": "Identifier", 123 | "start": 0, 124 | "end": 1, 125 | "name": "a" 126 | }, 127 | "right": { 128 | "type": "Literal", 129 | "start": 4, 130 | "end": 5, 131 | "value": 3, 132 | "raw": "3" 133 | } 134 | } 135 | } 136 | ], 137 | "sourceType": "module" 138 | } 139 | ``` 140 | 141 | ## 实践 142 | 143 | 可通过自己写一个解析器,将语言 (DSL) 解析为 AST 进行练手,以下两个示例是不错的选择 144 | 145 | 1. 解析简单的 HTML 为 AST 146 | 2. 解析 Marktodwn List 为 AST -------------------------------------------------------------------------------- /docs/DataStructure/栈-队列-堆.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 1. 使用队列实现栈 (栈,队列) 6 | 2. 使用栈实现队列 (栈,队列) 7 | 3. 包含min函数的栈 8 | 4. 合法的出栈序列 9 | 5. 简单的计算器 10 | 6. 寻找中位数 11 | 12 | 栈,先进后出的线性表。 13 | 14 | - 1,2,3 按顺序压入栈中(push操作) 栈 15 | - 按照栈顶栈低3,2,1的顺序出栈(pop操作) 16 | 17 | 队列,先进先出的线性表。 18 | 19 | - 1,2,3按照顺序压入队列中(push操作) 20 | - 按照队列头部到尾部1,2,3的顺序出队列(pop操作) 21 | 22 | 23 | 24 | ## 栈 25 | 26 | ```js 27 | s.top(): 取出栈顶 28 | s.empty(): 判断栈是否为空 29 | s.push(x): 将x添加至栈 30 | s.pop(): 弹出栈顶 31 | s.size(): 栈的存储元素个数 32 | ``` 33 | 34 | 35 | 36 | ```js 37 | int main() { 38 | std::stack S; 39 | if () { 40 | print() 41 | } 42 | S.push(5); 43 | ... 44 | } 45 | ``` 46 | 47 | ## 队列 48 | 49 | 50 | 51 | ```js 52 | q.empty(): 判断队列是否为空 53 | q.front(): 返回队列头部元素 54 | q.back(): 返回队列尾部元素 55 | q.pop(): 弹出队列头部元素 56 | q.push(x): 将x添加至队列 57 | q.size(): 返回队列的存储元素的个数 58 | ``` 59 | 60 | ## 使用队列实现栈 61 | 62 | 设计一个栈,支持基本的栈操作,这个栈的内部存储数据的结构为队列,队列的方法只能包含push,peek(front),pop,size,empty等标准的队列方法 63 | 64 | 1. push(x): 将元素x压入栈中 65 | 2. pop(): 弹出(移除)栈顶元素 66 | 3. top(): 返回栈顶元素 67 | 4. empty(): 判断栈是否是空 68 | 69 | ```js 70 | class MyStack { 71 | public: 72 | MyStack() { 73 | } 74 | void push(int x) { 75 | } 76 | int pop() {} 77 | int top() {} 78 | bool empty() {} 79 | j} 80 | ``` 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | ## 包含min函数的栈 97 | 98 | 设计一个栈,支持如下操作,这些操作的算法复杂度需要是常数级: 99 | 100 | 1. push(x): 将元素x压入栈中 101 | 2. pop(): 弹出(移除)栈顶元素 102 | 3. top(): 返回栈顶元素 103 | 4. getMin(): 返回栈内最小元素 104 | 105 | ```js 106 | class MinStack { 107 | public: 108 | MinStack() { 109 | // 构造函数 110 | } 111 | void push(int x) {} 112 | void pop() {} 113 | int top() {} 114 | int getMin() {} 115 | } 116 | ``` 117 | 118 | 119 | 120 | ## 用另一个栈,存储各个状态最小值 121 | 122 | 123 | 124 | ## 合法的出栈序列 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /docs/JavaScript/执行上下文.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 当 JavaScript 代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。 6 | 7 | 对于每个执行上下文,都有三个重要属性: 8 | 9 | - 变量对象(Variable object,VO) 10 | - 作用域链(Scope chain) 11 | - this 12 | 13 | ## 思考题 14 | 15 | ```js 16 | var scope = "global scope"; 17 | function checkscope(){ 18 | var scope = "local scope"; 19 | function f(){ 20 | return scope; 21 | } 22 | return f(); 23 | } 24 | checkscope(); 25 | ``` 26 | 27 | ```js 28 | var scope = "global scope"; 29 | function checkscope(){ 30 | var scope = "local scope"; 31 | function f(){ 32 | return scope; 33 | } 34 | return f; 35 | } 36 | checkscope()(); 37 | ``` 38 | 39 | 两段代码都会打印'local scope'。虽然两段代码执行的结果一样,但是两段代码究竟有哪些不同呢? 40 | 41 | ## 具体执行分析 42 | 43 | 我们分析第一段代码: 44 | 45 | ```js 46 | var scope = "global scope"; 47 | function checkscope(){ 48 | var scope = "local scope"; 49 | function f(){ 50 | return scope; 51 | } 52 | return f(); 53 | } 54 | checkscope(); 55 | ``` 56 | 57 | 执行过程如下: 58 | 59 | 1.执行全局代码,创建全局执行上下文,全局上下文被压入执行上下文栈 60 | 61 | ```js 62 | ECStack = [ 63 | globalContext 64 | ]; 65 | ``` 66 | 67 | 2.全局上下文初始化 68 | 69 | ```js 70 | globalContext = { 71 | VO: [global], 72 | Scope: [globalContext.VO], 73 | this: globalContext.VO 74 | } 75 | ``` 76 | 77 | 2.初始化的同时,checkscope 函数被创建,保存作用域链到函数的内部属性[[scope]] 78 | 79 | ```js 80 | checkscope.[[scope]] = [ 81 | globalContext.VO 82 | ]; 83 | ``` 84 | 85 | 3.执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 函数执行上下文被压入执行上下文栈 86 | 87 | ```js 88 | ECStack = [ 89 | checkscopeContext, 90 | globalContext 91 | ]; 92 | ``` 93 | 94 | 4.checkscope 函数执行上下文初始化: 95 | 96 | 1. 复制函数 [[scope]] 属性创建作用域链, 97 | 2. 用 arguments 创建活动对象, 98 | 3. 初始化活动对象,即加入形参、函数声明、变量声明, 99 | 4. 将活动对象压入 checkscope 作用域链顶端。 100 | 101 | 同时 f 函数被创建,保存作用域链到 f 函数的内部属性[[scope]] 102 | 103 | ```js 104 | checkscopeContext = { 105 | AO: { 106 | arguments: { 107 | length: 0 108 | }, 109 | scope: undefined, 110 | f: reference to function f(){} 111 | }, 112 | Scope: [AO, globalContext.VO], 113 | this: undefined 114 | } 115 | ``` 116 | 117 | 5.执行 f 函数,创建 f 函数执行上下文,f 函数执行上下文被压入执行上下文栈 118 | 119 | ```js 120 | ECStack = [ 121 | fContext, 122 | checkscopeContext, 123 | globalContext 124 | ]; 125 | ``` 126 | 127 | 6.f 函数执行上下文初始化, 以下跟第 4 步相同: 128 | 129 | 1. 复制函数 [[scope]] 属性创建作用域链 130 | 2. 用 arguments 创建活动对象 131 | 3. 初始化活动对象,即加入形参、函数声明、变量声明 132 | 4. 将活动对象压入 f 作用域链顶端 133 | 134 | ```js 135 | fContext = { 136 | AO: { 137 | arguments: { 138 | length: 0 139 | } 140 | }, 141 | Scope: [AO, checkscopeContext.AO, globalContext.VO], 142 | this: undefined 143 | } 144 | ``` 145 | 146 | 7.f 函数执行,沿着作用域链查找 scope 值,返回 scope 值 147 | 148 | 8.f 函数执行完毕,f 函数上下文从执行上下文栈中弹出 149 | 150 | ```js 151 | ECStack = [ 152 | checkscopeContext, 153 | globalContext 154 | ]; 155 | ``` 156 | 157 | 9.checkscope 函数执行完毕,checkscope 执行上下文从执行上下文栈中弹出 158 | 159 | ```js 160 | ECStack = [ 161 | globalContext 162 | ]; 163 | ``` 164 | 165 | 第二段代码就留给大家去尝试模拟它的执行过程。 166 | 167 | ```js 168 | var scope = "global scope"; 169 | function checkscope(){ 170 | var scope = "local scope"; 171 | function f(){ 172 | return scope; 173 | } 174 | return f; 175 | } 176 | checkscope()(); 177 | ``` 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /docs/ALG/3-无重复字符的最长子串.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 1. 题目描述(中等难度) 6 | 7 | 8 | 9 | 给定一个字符串,找到没有重复字符的最长子串,返回它的长度。 10 | 11 | ```js 12 | 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 13 | 14 | 示例 1: 15 | 16 | 输入: "abcabcbb" 17 | 输出: 3 18 | 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 19 | 示例 2: 20 | 21 | 输入: "bbbbb" 22 | 输出: 1 23 | 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 24 | 示例 3: 25 | 26 | 输入: "pwwkew" 27 | 输出: 3 28 | 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 29 |   请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 30 | ``` 31 | 32 | 对原数组进行判断,是否在arr里 如果在就将arr字符串之前的全部去除,不在就直接push,最后判断长度 33 | 34 | ```js 35 | var lengthOfLongestSubstring = function(s) { 36 | let arr = []; 37 | let length = 0; 38 | for(let item of s) { 39 | if(arr.includes(item)) { 40 | let index = arr.indexOf(item); 41 | arr.splice(0, index+1); 42 | } 43 | arr.push(item); 44 | length = length > arr.length ? length : arr.length; 45 | } 46 | return length; 47 | }; 48 | ``` 49 | 50 | ## 复杂度分析 51 | 52 | - 时间复杂度:$O(N)$ 53 | - 空间复杂度:$O(N)$ 54 | 55 | 56 | 57 | ```js 58 | /** 59 | * @param {string} s 60 | * @return {number} 61 | */ 62 | var lengthOfLongestSubstring = function(s) { 63 | var str="" //存放无重复子串 64 | var size=0 //当前最长无重复子串的长度 65 | for(var i=0,len=s.length;i 98 | 99 | 代码实现: 100 | 101 | ```js 102 | var lengthOfLongestSubstring = function(s) { 103 | let arr = [], max = 0 104 | for(let i = 0; i < s.length; i++) { 105 | let index = arr.indexOf(s[i]) 106 | if(index !== -1) { 107 | arr.splice(0, index+1); 108 | } 109 | arr.push(s.charAt(i)) 110 | max = Math.max(arr.length, max) 111 | } 112 | return max 113 | }; 114 | ``` 115 | 116 | ## 维护下标 117 | 118 | 解题思路: 使用下标来维护滑动窗口 119 | 120 | 代码实现: 121 | 122 | ```js 123 | var lengthOfLongestSubstring = function(s) { 124 | let index = 0, max = 0 125 | for(let i = 0, j = 0; j < s.length; j++) { 126 | index = s.substring(i, j).indexOf(s[j]) 127 | if(index !== -1) { 128 | i = i + index + 1 129 | } 130 | max = Math.max(max, j - i + 1) 131 | } 132 | return max 133 | }; 134 | ``` 135 | 136 | ## 优化的Map 137 | 138 | 解题思路: 139 | 140 | 使用 map 来存储当前已经遍历过的字符,key 为字符,value 为下标 141 | 142 | 使用 i 来标记无重复子串开始下标,j 为当前遍历字符下标 143 | 144 | 遍历字符串,判断当前字符是否已经在 map 中存在,存在则更新无重复子串开始下标 i 为相同字符的下一位置,此时从 i 到 j 为最新的无重复子串,更新 max ,将当前字符与下标放入 map 中 145 | 146 | 最后,返回 max 即可 147 | 148 | 代码实现: 149 | 150 | ```js 151 | var lengthOfLongestSubstring = function(s) { 152 | let map = new Map(), max = 0 153 | for(let i = 0, j = 0; j < s.length; j++) { 154 | if(map.has(s[j])) { 155 | i = Math.max(map.get(s[j]) + 1, i) 156 | } 157 | max = Math.max(max, j - i + 1) 158 | map.set(s[j], j) 159 | } 160 | return max 161 | }; 162 | ``` 163 | 164 | 时间复杂度:O(n) 165 | 166 | 空间复杂度:O(n) 167 | 168 | -------------------------------------------------------------------------------- /docs/JavaScript/变量对象.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 当 JavaScript 代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。 6 | 7 | 对于每个执行上下文,都有三个重要属性: 8 | 9 | - 变量对象(Variable object,VO) 10 | - 作用域链(Scope chain) 11 | - this 12 | 13 | 今天重点讲讲创建变量对象的过程。 14 | 15 | ## 变量对象 16 | 17 | 变量对象是与执行上下文相关的数据作用域,存储了在上下文中定义的变量和函数声明。 18 | 19 | 因为不同执行上下文下的变量对象稍有不同,所以我们来聊聊全局上下文下的变量对象和函数上下文下的变量对象。 20 | 21 | ## 全局上下文 22 | 23 | 我们先了解一个概念,叫全局对象。在 W3School 中也有介绍: 24 | 25 | 全局对象是预定义的对象,作为 JavaScript 的全局函数和全局属性的占位符。通过使用全局对象,可以访问所有其他所有预定义的对象、函数和属性。 26 | 27 | 在顶层 JavaScript 代码中,可以用关键字 this 引用全局对象。因为全局对象是作用域链的头,这意味着所有非限定性的变量和函数名都会作为该对象的属性来查询。 28 | 29 | 例如,当JavaScript 代码引用 parseInt() 函数时,它引用的是全局对象的 parseInt 属性。全局对象是作用域链的头,还意味着在顶层 JavaScript 代码中声明的所有变量都将成为全局对象的属性。 30 | 31 | 如果看的不是很懂的话,容我再来介绍下全局对象: 32 | 33 | 1.可以通过 this 引用,在客户端 JavaScript 中,全局对象就是 Window 对象。 34 | 35 | ```js 36 | console.log(this); 37 | ``` 38 | 39 | 2.全局对象是由 Object 构造函数实例化的一个对象。 40 | 41 | ```js 42 | console.log(this instanceof Object); 43 | ``` 44 | 45 | 3.预定义了一堆,嗯,一大堆函数和属性。 46 | 47 | ```js 48 | // 都能生效 49 | console.log(Math.random()); 50 | console.log(this.Math.random()); 51 | ``` 52 | 53 | 4.作为全局变量的宿主。 54 | 55 | ```js 56 | var a = 1; 57 | console.log(this.a); 58 | ``` 59 | 60 | 5.客户端 JavaScript 中,全局对象有 window 属性指向自身。 61 | 62 | ```js 63 | var a = 1; 64 | console.log(window.a); 65 | 66 | this.window.b = 2; 67 | console.log(this.b); 68 | ``` 69 | 70 | 花了一个大篇幅介绍全局对象,其实就想说: 71 | 72 | 全局上下文中的变量对象就是全局对象呐! 73 | 74 | ## 函数上下文 75 | 76 | 在函数上下文中,我们用活动对象(activation object, AO)来表示变量对象。 77 | 78 | 活动对象和变量对象其实是一个东西,只是变量对象是规范上的或者说是引擎实现上的,不可在 JavaScript 环境中访问,只有到当进入一个执行上下文中,这个执行上下文的变量对象才会被激活,所以才叫 activation object 呐,而只有被激活的变量对象,也就是活动对象上的各种属性才能被访问。 79 | 80 | 活动对象是在进入函数上下文时刻被创建的,它通过函数的 arguments 属性初始化。arguments 属性值是 Arguments 对象。 81 | 82 | ## 执行过程 83 | 84 | 执行上下文的代码会分成两个阶段进行处理:分析和执行,我们也可以叫做: 85 | 86 | 1. 进入执行上下文 87 | 2. 代码执行 88 | 89 | ## 进入执行上下文 90 | 91 | 当进入执行上下文时,这时候还没有执行代码, 92 | 93 | 变量对象会包括: 94 | 95 | 1. 函数的所有形参 (如果是函数上下文) 96 | - 由名称和对应值组成的一个变量对象的属性被创建 97 | - 没有实参,属性值设为 undefined 98 | 99 | 2. 函数声明 100 | - 由名称和对应值(函数对象(function-object))组成一个变量对象的属性被创建 101 | - 如果变量对象已经存在相同名称的属性,则完全替换这个属性 102 | 103 | 3. 变量声明 104 | - 由名称和对应值(undefined)组成一个变量对象的属性被创建; 105 | - 如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性 106 | 107 | 举个例子: 108 | 109 | ```js 110 | function foo(a) { 111 | var b = 2; 112 | function c() {} 113 | var d = function() {}; 114 | 115 | b = 3; 116 | 117 | } 118 | 119 | foo(1); 120 | ``` 121 | 122 | 在进入执行上下文后,这时候的 AO 是: 123 | 124 | ```js 125 | AO = { 126 | arguments: { 127 | 0: 1, 128 | length: 1 129 | }, 130 | a: 1, 131 | b: undefined, 132 | c: reference to function c(){}, 133 | d: undefined 134 | } 135 | ``` 136 | 137 | ## 代码执行 138 | 139 | 在代码执行阶段,会顺序执行代码,根据代码,修改变量对象的值 140 | 141 | 还是上面的例子,当代码执行完后,这时候的 AO 是: 142 | 143 | ```js 144 | AO = { 145 | arguments: { 146 | 0: 1, 147 | length: 1 148 | }, 149 | a: 1, 150 | b: 3, 151 | c: reference to function c(){}, 152 | d: reference to FunctionExpression "d" 153 | } 154 | ``` 155 | 156 | 到这里变量对象的创建过程就介绍完了,让我们简洁的总结我们上述所说: 157 | 158 | 全局上下文的变量对象初始化是全局对象 159 | 160 | 函数上下文的变量对象初始化只包括 Arguments 对象 161 | 162 | 在进入执行上下文时会给变量对象添加形参、函数声明、变量声明等初始的属性值 163 | 164 | 在代码执行阶段,会再次修改变量对象的属性值 165 | 166 | ## 思考题 167 | 168 | 最后让我们看几个例子: 169 | 170 | 1.第一题 171 | 172 | ```js 173 | function foo() { 174 | console.log(a); 175 | a = 1; 176 | } 177 | 178 | foo(); // ??? 179 | 180 | function bar() { 181 | a = 1; 182 | console.log(a); 183 | } 184 | bar(); // ??? 185 | ``` 186 | 187 | 第一段会报错:`Uncaught ReferenceError: a is not defined。` 188 | 189 | 第二段会打印:1。 190 | 191 | 这是因为函数中的 "a" 并没有通过 var 关键字声明,所有不会被存放在 AO 中。 192 | 193 | 第一段执行 console 的时候, AO 的值是: 194 | 195 | ```js 196 | AO = { 197 | arguments: { 198 | length: 0 199 | } 200 | } 201 | ``` 202 | 203 | 没有 a 的值,然后就会到全局去找,全局也没有,所以会报错。 204 | 205 | 当第二段执行 console 的时候,全局对象已经被赋予了 a 属性,这时候就可以从全局找到 a 的值,所以会打印 1。 206 | 207 | 2.第二题 208 | 209 | ```js 210 | console.log(foo); 211 | 212 | function foo(){ 213 | console.log("foo"); 214 | } 215 | 216 | var foo = 1; 217 | ``` 218 | 219 | 会打印函数,而不是 undefined 。 220 | 221 | 这是因为在进入执行上下文时,首先会处理函数声明,其次会处理变量声明,如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。 222 | -------------------------------------------------------------------------------- /docs/JavaScript/闭包.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 定义 6 | 7 | MDN 对闭包的定义为: 8 | 9 | 闭包是指那些能够访问自由变量的函数。 10 | 11 | 那什么是自由变量呢? 12 | 13 | 自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。 14 | 15 | 由此,我们可以看出闭包共有两部分组成: 16 | 17 | 闭包 = 函数 + 函数能够访问的自由变量 18 | 19 | 举个例子: 20 | 21 | ```js 22 | var a = 1; 23 | 24 | function foo() { 25 | console.log(a); 26 | } 27 | 28 | foo(); 29 | ``` 30 | 31 | foo 函数可以访问变量 a,但是 a 既不是 foo 函数的局部变量,也不是 foo 函数的参数,所以 a 就是自由变量。 32 | 33 | 那么,函数 foo + foo 函数访问的自由变量 a 不就是构成了一个闭包嘛…… 34 | 35 | 还真是这样的! 36 | 37 | 所以在《JavaScript权威指南》中就讲到:从技术的角度讲,所有的JavaScript函数都是闭包。 38 | 39 | 咦,这怎么跟我们平时看到的讲到的闭包不一样呢!? 40 | 41 | 别着急,这是理论上的闭包,其实还有一个实践角度上的闭包 42 | 43 | ECMAScript中,闭包指的是: 44 | 45 | - 从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。 46 | - 从实践角度:以下函数才算是闭包: 47 | - 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回) 48 | - 在代码中引用了自由变量 49 | 50 | ## 分析 51 | 52 | ```js 53 | var scope = "global scope"; 54 | function checkscope(){ 55 | var scope = "local scope"; 56 | function f(){ 57 | return scope; 58 | } 59 | return f; 60 | } 61 | 62 | var foo = checkscope(); 63 | foo(); 64 | ``` 65 | 66 | 首先我们要分析一下这段代码中执行上下文栈和执行上下文的变化情况。 67 | 68 | 这里直接给出简要的执行过程: 69 | 70 | - 进入全局代码,创建全局执行上下文,全局执行上下文压入执行上下文栈 71 | - 全局执行上下文初始化 72 | - 执行 checkscope 函数,创建 checkscope 函数执行上下文,checkscope 执行上下文被压入执行上下文栈 73 | - checkscope 执行上下文初始化,创建变量对象、作用域链、this等 74 | - checkscope 函数执行完毕,checkscope 执行上下文从执行上下文栈中弹出 75 | - 执行 f 函数,创建 f 函数执行上下文,f 执行上下文被压入执行上下文栈 76 | - f 执行上下文初始化,创建变量对象、作用域链、this等 77 | - f 函数执行完毕,f 函数上下文从执行上下文栈中弹出 78 | 79 | 了解到这个过程,我们应该思考一个问题,那就是: 80 | 81 | 当 f 函数执行的时候,checkscope 函数上下文已经被销毁了啊(即从执行上下文栈中被弹出),怎么还会读取到 checkscope 作用域下的 scope 值呢? 82 | 83 | 当我们了解了具体的执行过程后,我们知道 f 执行上下文维护了一个作用域链: 84 | 85 | ```js 86 | fContext = { 87 | Scope: [AO, checkscopeContext.AO, globalContext.VO], 88 | } 89 | ``` 90 | 91 | 对的,就是因为这个作用域链,f 函数依然可以读取到 checkscopeContext.AO 的值,说明当 f 函数引用了 checkscopeContext.AO 中的值的时候,即使 checkscopeContext 被销毁了,但是 JavaScript 依然会让 checkscopeContext.AO 活在内存中,f 函数依然可以通过 f 函数的作用域链找到它,正是因为 JavaScript 做到了这一点,从而实现了闭包这个概念。 92 | 93 | 所以,让我们再看一遍实践角度上闭包的定义: 94 | 95 | - 即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回) 96 | - 在代码中引用了自由变量 97 | 98 | 在这里再补充一个《JavaScript权威指南》英文原版对闭包的定义: 99 | 100 | :::tip 101 | This combination of a function object and a scope (a set of variable bindings) in which the function’s variables are resolved is called a closure in the computer science literature. 102 | ::: 103 | 104 | ## 必刷题 105 | 106 | 接下来,看这道刷题必刷,面试必考的闭包题: 107 | 108 | ```js 109 | var data = []; 110 | 111 | for (var i = 0; i < 3; i++) { 112 | data[i] = function () { 113 | console.log(i); 114 | }; 115 | } 116 | 117 | data[0](); 118 | data[1](); 119 | data[2](); 120 | ``` 121 | 122 | 答案是都是 3,让我们分析一下原因: 123 | 124 | 当执行到 data[0] 函数之前,此时全局上下文的 VO 为: 125 | 126 | ```js 127 | globalContext = { 128 | VO: { 129 | data: [...], 130 | i: 3 131 | } 132 | } 133 | ``` 134 | 135 | 当执行 data[0] 函数的时候,data[0] 函数的作用域链为: 136 | 137 | ```js 138 | data[0]Context = { 139 | Scope: [AO, globalContext.VO] 140 | } 141 | ``` 142 | 143 | data[0]Context 的 AO 并没有 i 值,所以会从 globalContext.VO 中查找,i 为 3,所以打印的结果就是 3。 144 | 145 | data[1] 和 data[2] 是一样的道理。 146 | 147 | 所以让我们改成闭包看看: 148 | 149 | ```js 150 | var data = []; 151 | 152 | for (var i = 0; i < 3; i++) { 153 | data[i] = (function (i) { 154 | return function(){ 155 | console.log(i); 156 | } 157 | })(i); 158 | } 159 | 160 | data[0](); 161 | data[1](); 162 | data[2](); 163 | ``` 164 | 165 | 当执行到 data[0] 函数之前,此时全局上下文的 VO 为: 166 | 167 | ```js 168 | globalContext = { 169 | VO: { 170 | data: [...], 171 | i: 3 172 | } 173 | } 174 | ``` 175 | 176 | 跟没改之前一模一样。 177 | 178 | 当执行 data[0] 函数的时候,data[0] 函数的作用域链发生了改变: 179 | 180 | ```js 181 | data[0]Context = { 182 | Scope: [AO, 匿名函数Context.AO globalContext.VO] 183 | } 184 | ``` 185 | 186 | 匿名函数执行上下文的AO为: 187 | 188 | ```js 189 | 匿名函数Context = { 190 | AO: { 191 | arguments: { 192 | 0: 0, 193 | length: 1 194 | }, 195 | i: 0 196 | } 197 | } 198 | ``` 199 | 200 | data[0]Context 的 AO 并没有 i 值,所以会沿着作用域链从匿名函数 Context.AO 中查找,这时候就会找 i 为 0,找到了就不会往 globalContext.VO 中查找了,即使 globalContext.VO 也有 i 的值(值为3),所以打印的结果就是0。 201 | 202 | data[1] 和 data[2] 是一样的道理。 203 | 204 | 205 | -------------------------------------------------------------------------------- /docs/JavaScript/浅谈instanceof和typeof的实现原理.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## typeof 实现原理 6 | 7 | typeof 一般被用于判断一个变量的类型,我们可以利用 typeof 来判断number, string, object, boolean, function, undefined, symbol 这七种类型,这种判断能帮助我们搞定一些问题,比如在判断不是 object 类型的数据的时候,typeof能比较清楚的告诉我们具体是哪一类的类型。但是,很遗憾的一点是,typeof 在判断一个 object的数据的时候只能告诉我们这个数据是 object, 而不能细致的具体到是哪一种 object, 比如👉 8 | 9 | ```js 10 | let s = new String('abc'); 11 | typeof s === 'object'// true 12 | s instanceof String // true 13 | ``` 14 | 15 | 要想判断一个数据具体是哪一种 object 的时候,我们需要利用 instanceof 这个操作符来判断,这个我们后面会说到。 16 | 17 | 来谈谈关于 typeof 的原理吧,我们可以先想一个很有意思的问题,js 在底层是怎么存储数据的类型信息呢?或者说,一个 js 的变量,在它的底层实现中,它的类型信息是怎么实现的呢? 18 | 19 | 其实,js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息 20 | 21 | - 000:对象 22 | - 010:浮点数 23 | - 100:字符串 24 | - 110:布尔 25 | - 1:整数 26 | 27 | but, 对于 undefined 和 null 来说,这两个值的信息存储是有点特殊的。 28 | 29 | null:所有机器码均为0 30 | 31 | undefined:用 −2^30 整数来表示 32 | 33 | 所以,typeof 在判断 null 的时候就出现问题了,由于 null 的所有机器码均为0,因此直接被当做了对象来看待。 34 | 35 | 然而用 instanceof 来判断的话 36 | 37 | ```js 38 | null instanceof null // TypeError: Right-hand side of 'instanceof' is not an object 39 | ``` 40 | 41 | null 直接被判断为不是 object,这也是 JavaScript 的历史遗留bug 42 | 43 | 因此在用 typeof 来判断变量类型的时候,我们需要注意,最好是用 typeof 来判断基本数据类型(包括symbol),避免对 null 的判断。 44 | 45 | 还有一个不错的判断类型的方法,就是Object.prototype.toString,我们可以利用这个方法来对一个变量的类型来进行比较准确的判断 46 | 47 | ```js 48 | Object.prototype.toString.call(1) // "[object Number]" 49 | 50 | Object.prototype.toString.call('hi') // "[object String]" 51 | 52 | Object.prototype.toString.call({a:'hi'}) // "[object Object]" 53 | 54 | Object.prototype.toString.call([1,'a']) // "[object Array]" 55 | 56 | Object.prototype.toString.call(true) // "[object Boolean]" 57 | 58 | Object.prototype.toString.call(() => {}) // "[object Function]" 59 | 60 | Object.prototype.toString.call(null) // "[object Null]" 61 | 62 | Object.prototype.toString.call(undefined) // "[object Undefined]" 63 | 64 | Object.prototype.toString.call(Symbol(1)) // "[object Symbol]" 65 | ``` 66 | 67 | ## instanceof 操作符的实现原理 68 | 69 | 之前我们提到了 instanceof 来判断对象的具体类型,其实 instanceof 主要的作用就是判断一个实例是否属于某种类型 70 | 71 | ```js 72 | let person = function () { 73 | } 74 | let nicole = new person() 75 | nicole instanceof person // true 76 | ``` 77 | 78 | 当然,instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。 79 | 80 | ```js 81 | let person = function () { 82 | } 83 | let programmer = function () { 84 | } 85 | programmer.prototype = new person() 86 | let nicole = new programmer() 87 | nicole instanceof person // true 88 | nicole instanceof programmer // true 89 | ``` 90 | 91 | 是 instanceof 的用法,但是 instanceof 的原理是什么呢?根据 ECMAScript 语言规范,我梳理了一下大概的思路,然后整理了一段代码如下 92 | 93 | ```js 94 | function new_instance_of(leftVaule, rightVaule) { 95 | let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值 96 | leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值 97 | while (true) { 98 | if (leftVaule === null) { 99 | return false; 100 | } 101 | if (leftVaule === rightProto) { 102 | return true; 103 | } 104 | leftVaule = leftVaule.__proto__ 105 | } 106 | } 107 | ``` 108 | 109 | 其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。 110 | 111 | 看几个很有趣的例子 112 | 113 | ```js 114 | function Foo() { 115 | } 116 | 117 | Object instanceof Object // true 118 | Function instanceof Function // true 119 | Function instanceof Object // true 120 | Foo instanceof Foo // false 121 | Foo instanceof Object // true 122 | Foo instanceof Function // true 123 | ``` 124 | 125 | 我们知道每个 JavaScript 对象均有一个隐式的 `__proto__` 原型属性,而显式的原型属性是 prototype,只有 `Object.prototype.__proto__` 属性在未修改的情况下为 null 值。根据图上的原理,我们来梳理上面提到的几个有趣的 instanceof 使用的例子。 126 | 127 | Object instanceof Object 128 | 129 | 由图可知,Object 的 prototype 属性是 Object.prototype, 而由于 Object 本身是一个函数,由 Function 所创建,所以 `Object.__proto__ `的值是 Function.prototype,而 Function.prototype 的 `__proto__` 属性是 Object.prototype,所以我们可以判断出,Object instanceof Object 的结果是 true 。用代码简单的表示一下 130 | 131 | Function instanceof Function 和 Function instanceof Object 的运行过程与 Object instanceof Object 类似 132 | 133 | Foo instanceof Foo 134 | 135 | Foo 函数的 prototype 属性是 Foo.prototype,而 Foo 的 `__proto__` 属性是 Function.prototype,由图可知,Foo 的原型链上并没有 Foo.prototype ,因此 Foo instanceof Foo 也就返回 false 。 136 | 137 | 总结 138 | 139 | 简单来说,我们使用 typeof 来判断基本数据类型是 ok 的,不过需要注意当用 typeof 来判断 null 类型时的问题,如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组,他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。 140 | 141 | -------------------------------------------------------------------------------- /docs/CSS/盒子模型.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 盒模型的认识 6 | 7 | 1. 基本概念:标准模型+IE模型。包括 margin, border, padding, content 8 | 2. 标准模型和IE模型的区别 9 | 3. css如何设置获取这两种模型的宽和高 10 | 4. js如何设置获取盒模型对应的宽和高 11 | 5. 根据盒模型解释边距重叠 12 | 6. BFC(边距重叠解决方案,还有IFC) 解决边距重叠 13 | 14 | ## 一、基本概念:标准模型+IE模型 15 | 16 | 什么是盒模型:盒模型 又称 框模型(Box Model), 包含了 元素内容(content)、内边距(padding)、边距(border)、外边距(margin) 几个要素。如图: 17 | 18 | 19 | 20 | 由于IE盒模型的怪异模式,IE模型和标准模型的内容计算方式不同。 21 | 22 | ## 二、标准模型和IE模型的区别 23 | 24 | IE模型和标准模型唯一的区别是内容计算方式的不同,如下图所示: 25 | 26 | 27 | 28 | IE模型元素宽度width=content+padding+border,高度计算相同 29 | 30 | 31 | 32 | 标准模型元素宽度width=content,高度计算相同 33 | 34 | ## 三、css如何设置获取这两种模型的宽和高 35 | 36 | 通过css3新增的属性 `box-sizing: content-box` | `border-box`分别设置盒模型为标准模型(`content-box`)和IE模型(`border-box`)。 37 | 38 | ```js 39 | .content-box { 40 | box-sizing:content-box; 41 | width: 100px; 42 | height: 50px; 43 | padding: 10px; 44 | border: 5px solid red; 45 | margin: 15px; 46 | } 47 | ``` 48 | 49 | 50 | 51 | .content-box设置为标准模型,它的元素宽度width=100px。 52 | 53 | ```js 54 | .border-box { 55 | box-sizing: border-box; 56 | width: 100px; 57 | height: 50px; 58 | padding: 10px; 59 | border: 5px solid red; 60 | margin: 15px; 61 | } 62 | ``` 63 | 64 | 65 | 66 | .border-box设置为IE模型,它的元素宽度width=content + 2 padding + 2 border = 70px + 2 10px + 2 5px = 100px。 67 | 68 | ## 四、javascript如何设置获取盒模型对应的宽和高 69 | 70 | 1. `dom.style.width/height` 只能取到行内样式的宽和高,style标签中和link外链的样式取不到。 71 | 2. `dom.currentStyle.width/height` 取到的是最终渲染后的宽和高,只有IE支持此属性。 72 | 3. `window.getComputedStyle(dom).width/height` 同(2)但是多浏览器支持,IE9以上支持。 73 | 4. `dom.getBoundingClientRect().width/height` 也是得到渲染后的宽和高,大多浏览器支持。IE9以上支持,除此外还可以取到相对于视窗的上下左右的距离 74 | 75 | ## 五、外边距重叠 76 | 77 | 当两个垂直外边距相遇时,他们将形成一个外边距,合并后的外边距高度等于两个发生合并的外边距的高度中的较大者。注意:只有普通文档流中块框的垂直外边距才会发生外边距合并,行内框、浮动框或绝对定位之间的外边距不会合并。 78 | 79 | 80 | 81 | 这里父元素section的高度是多少呢,100px,但是我们给section设置overflow:hidden后高度就变成110px,这是为什么呢,其实这里我们给父元素创建了BFC。,什么是BFC,请看下面的介绍。 82 | 83 | ## 六 、BFC 84 | 85 | BFC(Block Formatting Context):块级格式化上下文。 86 | 87 | BFC决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。当设计到可视化布局的时候,BFC提供了一个环境,HTML元素在这个环境中按照一定的规则进行布局。一个环境中的元素不会影响到其他环境中的布局。 88 | 89 | ### BFC的原理(渲染规则) 90 | 91 | 1. BFC元素垂直方向的边距会发生重叠。属于不同BFC外边距不会发生重叠 92 | 2. BFC的区域不会与浮动元素的布局重叠。 93 | 3. BFC元素是一个独立的容器,外面的元素不会影响里面的元素。里面的元素也不会影响外面的元素。 94 | 4. 计算BFC高度的时候,浮动元素也会参与计算(清除浮动) 95 | 96 | #### 如何创建BFC 97 | 98 | 1. overflow不为visible; 99 | 2. float的值不为none; 100 | 3. position的值不为static或relative; 101 | 4. display属性为inline-blocks,table,table-cell,table-caption,flex,inline-flex; 102 | 103 | 说了这么多规则,放几个实类出来看看。 104 | 105 | ```js 106 |
107 | 121 |

1

122 |
123 |

2

124 |
125 |

3

126 |

4

127 |
128 | ``` 129 | 130 | 请看这里的第二个p元素`

2

`他被一个父元素包裹,并且父元素有 overflow:hidden 样式,前面的如何创建BFC的第一条就说了 overflow:hidden 可以创建一个BFC。结果如下图所示。 131 | 132 | 133 | 134 | 我们看这里的2,它的上下外边距都没有与1和3发生重叠,但3与4外边距发生了重叠。这就解释了BFC创建了一个独立的环境,这个环境中的元素不会影响到其他环境中的布局,所以BFC内的外边距不与外部的外边距发生重叠。 135 | 136 | 再看看下面的列子: 137 | 138 | ```js 139 |
140 | 155 |
156 |
157 |
158 | ``` 159 | 160 | 效果如下: 161 | 162 | 163 | 164 | 写过前端页面的我们肯定遇到过这种情况,这里其实是浮动元素叠在 .right 元素的上面,如果我们想让.right元素不会延伸到 float元素怎么办,其实我们在.right元素上加 overflow:hidden (用其他的方式创建BFC也可以)创建BFC就可以解决。因为BFC不会与浮动元素发生重叠。 165 | 166 | 167 | 168 | 还有一种情况很常见,就是由于子元素浮动,导致父元素的高度不会把浮动元素算在内,那么我们在父元素创建BFC就可以让可以让浮动元素也参与高度计算。 169 | 170 | IFC这里就不介绍,大家可以自行搜索。 171 | -------------------------------------------------------------------------------- /docs/JavaScript/原型链.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 构造函数创建对象 6 | 7 | 我们先使用构造函数创建一个对象: 8 | 9 | ```js 10 | function Person() { 11 | 12 | } 13 | var person = new Person(); 14 | person.name = '哪吒'; 15 | console.log(person.name) // 哪吒 16 | ``` 17 | 18 | 在这个例子中,Person 就是一个构造函数,我们使用 new 创建了一个实例对象 person。 19 | 20 | ## prototype 21 | 22 | 每个函数都有一个 `prototype` 属性,就是我们经常在各种例子中看到的那个 `prototype` ,比如: 23 | 24 | ```js 25 | function Person() { 26 | 27 | } 28 | // 虽然写在注释里,但是你要注意: 29 | // prototype是函数才会有的属性 30 | Person.prototype.name = '哪吒'; 31 | var person1 = new Person(); 32 | var person2 = new Person(); 33 | console.log(person1.name) // 哪吒 34 | console.log(person2.name) // 哪吒 35 | ``` 36 | 37 | 那这个函数的 prototype 属性到底指向的是什么呢?是这个函数的原型吗? 38 | 39 | 其实,函数的 prototype 属性指向了一个对象,这个对象正是调用该构造函数而创建的实例的原型,也就是这个例子中的 person1 和 person2 的原型。 40 | 41 | 那什么是原型呢?你可以这样理解:每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。 42 | 43 | 让我们用一张图表示构造函数和实例原型之间的关系: 44 | 45 | 46 | 47 | 在这张图中我们用 Object.prototype 表示实例原型。 48 | 49 | 那么我们该怎么表示实例与实例原型,也就是 person 和 Person.prototype 之间的关系呢,这时候我们就要讲到第二个属性: 50 | 51 | ## `__proto__` 52 | 53 | 这是每一个JavaScript对象(除了 null )都具有的一个属性,叫`__proto__`,这个属性会指向该对象的原型。 54 | 55 | 为了证明这一点,我们可以在火狐或者谷歌中输入: 56 | 57 | ```js 58 | function Person() { 59 | 60 | } 61 | var person = new Person(); 62 | console.log(person.__proto__ === Person.prototype); // true 63 | ``` 64 | 65 | 于是我们更新下关系图: 66 | 67 | 68 | 69 | 既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢? 70 | 71 | ## constructor 72 | 73 | 指向实例倒是没有,因为一个构造函数可以生成多个实例,但是原型指向构造函数倒是有的,这就要讲到第三个属性:`constructor`,每个原型都有一个 `constructor` 属性指向关联的构造函数。 74 | 75 | 为了验证这一点,我们可以尝试: 76 | 77 | ```js 78 | function Person() { 79 | 80 | } 81 | console.log(Person === Person.prototype.constructor); // true 82 | ``` 83 | 84 | 所以再更新下关系图: 85 | 86 | 87 | 88 | 综上我们已经得出: 89 | 90 | ```js 91 | function Person() { 92 | 93 | } 94 | 95 | var person = new Person(); 96 | 97 | console.log(person.__proto__ == Person.prototype) // true 98 | console.log(Person.prototype.constructor == Person) // true 99 | // 顺便学习一个ES5的方法,可以获得对象的原型 100 | console.log(Object.getPrototypeOf(person) === Person.prototype) // true 101 | ``` 102 | 103 | 了解了构造函数、实例原型、和实例之间的关系,接下来我们讲讲实例和原型的关系: 104 | 105 | ## 实例与原型 106 | 107 | 当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。 108 | 109 | 举个例子: 110 | 111 | ```js 112 | function Person() { 113 | 114 | } 115 | 116 | Person.prototype.name = 'Kevin'; 117 | 118 | var person = new Person(); 119 | 120 | person.name = 'Daisy'; 121 | console.log(person.name) // Daisy 122 | 123 | delete person.name; 124 | console.log(person.name) // Kevin 125 | ``` 126 | 127 | 在这个例子中,我们给实例对象 `person` 添加了 `name` 属性,当我们打印 `person.name` 的时候,结果自然为 `Daisy。` 128 | 129 | 但是当我们删除了 `person` 的 `name` 属性时,读取 `person.name`,从 `person` 对象中找不到 name 属性就会从 person 的原型也就是 `person.__proto__`,也就是 `Person.prototype`中查找,幸运的是我们找到了 `name` 属性,结果为 `Kevin。` 130 | 131 | 但是万一还没有找到呢?原型的原型又是什么呢? 132 | 133 | ## 原型的原型 134 | 135 | 在前面,我们已经讲了原型也是一个对象,既然是对象,我们就可以用最原始的方式创建它,那就是: 136 | 137 | ```js 138 | var obj = new Object(); 139 | obj.name = 'Kevin' 140 | console.log(obj.name) // Kevin 141 | ``` 142 | 143 | 其实原型对象就是通过 `Object` 构造函数生成的,结合之前所讲,实例的 `__proto__` 指向构造函数的 `prototype` ,所以我们再更新下关系图: 144 | 145 | 146 | 147 | ## 原型链 148 | 149 | 那 `Object.prototype` 的原型呢? 150 | 151 | `null`,我们可以打印: 152 | 153 | ```js 154 | console.log(Object.prototype.__proto__ === null) // true 155 | ``` 156 | 157 | 然而 `null` 究竟代表了什么呢? 158 | 159 | 引用阮一峰老师的 《`undefined与null的区别`》 就是: 160 | 161 | :::tip 162 | `null` 表示“没有对象”,即该处不应该有值。 163 | ::: 164 | 165 | 所以 `Object.prototype.__proto__` 的值为 `null` 跟 `Object.prototype` 没有原型,其实表达了一个意思。 166 | 167 | 所以查找属性的时候查到 `Object.prototype` 就可以停止查找了。 168 | 169 | 最后一张关系图也可以更新为: 170 | 171 | 172 | 173 | 顺便还要说一下,图中由相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线。 174 | 175 | ## 补充 176 | 177 | ### constructor 178 | 179 | 首先是 `constructor` 属性,我们看个例子: 180 | 181 | ```js 182 | function Person() { 183 | 184 | } 185 | var person = new Person(); 186 | console.log(person.constructor === Person); // true 187 | ``` 188 | 189 | 当获取 `person.constructor` 时,其实 `person` 中并没有 `constructor` 属性,当不能读取到`constructor` 属性时,会从 `person` 的原型也就是 `Person`.`prototype` 中读取,正好原型中有该属性,所以: 190 | 191 | ```js 192 | person.constructor === Person.prototype.constructor 193 | ``` 194 | 195 | ## `__proto__` 196 | 197 | 其次是 `__proto__` ,绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 `Person.prototype` 中,实际上,它是来自于 `Object.prototype` ,与其说是一个属性,不如说是一个 `getter/setter`,当使用 `obj.__proto__` 时,可以理解成返回了 `Object.getPrototypeOf(obj)。` 198 | 199 | ## 真的是继承吗? 200 | 201 | 最后是关于继承,前面我们讲到“每一个对象都会从原型‘继承’属性”,实际上,继承是一个十分具有迷惑性的说法,引用《你不知道的JavaScript》中的话,就是: 202 | 203 | 继承意味着复制操作,然而 JavaScript 默认并不会复制对象的属性,相反,JavaScript 只是在两个对象之间创建一个关联,这样,一个对象就可以通过委托访问另一个对象的属性和函数,所以与其叫继承,委托的说法反而更准确些。 204 | 205 | `Function`作为一个内置对象,是运行前就已经存在的东西,所以根本就不会根据自己生成自己,所以就没有什么鸡生蛋蛋生鸡,就是鸡生蛋。至于为什么`Function.__proto__ === Function.prototype`,我认为有两种可能:一是为了保持与其他函数一致,二是就是表明一种关系而已。 206 | 207 | 简单的说,我认为:就是先有的`Function`,然后实现上把原型指向了`Function.prototype`,但是我们不能倒过来推测因为`Function.__proto__ === Function.prototype`,所以`Function`调用了自己生成了自己。 208 | 209 | 函数的`prototype`属性指向原型,说`prototype`是原型略显不严谨,原型链通过`__proto__`链接起来,这个是可以的。 210 | -------------------------------------------------------------------------------- /docs/HTML/HTML基础.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## div 6 | 7 | div标签用于组合其他HTML元素,本身无实在意义。常用于页面的布局,比如一个展开式的广告页面框架大致如下: 8 | 9 | ```html 10 | 11 |
12 |
13 |
14 |
15 | 16 | ``` 17 | 18 | ## h1~h6, p, span, strong, em... 19 | 20 | 此类标签用于设置文本,常见的使用方式是填充段落,比如弹出的legal框文字HTML结构如下: 21 | 22 | ```html 23 | 28 | ``` 29 | 30 | ## ul, li, ol, dl, dt, dd 31 | 32 | 此类标签用于设置带有列表内容的,比如导航栏的下拉菜单,多视频的缩略图等: 33 | 34 | ``` 35 | 61 | ``` 62 | 63 | ## 基本 HTML 64 | 65 | ```js 66 | Tag Description 67 | Defines the document type 68 | Defines an HTML document 69 | Contains metadata/information for the document 70 | Defines a title for the document 71 | <body> Defines the document's body 72 | <h1> to <h6> Defines HTML headings 73 | <p> Defines a paragraph 74 | <br> Inserts a single line break 75 | <hr> Defines a thematic change in the content 76 | <!--...--> Defines a comment 77 | ``` 78 | 79 | ## HTML语义化 80 | 81 | 语义化的含义就是用正确的标签做正确的事情,html语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;在没有样式CCS情况下也以一种文档格式显示,并且是容易阅读的。搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于 SEO。使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。 82 | 83 | ## DOCTYPE和浏览器渲染模式 84 | 85 | 文档类型,一个文档类型标记是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档。Doctype还会对浏览器的渲染模式产生影响,不同的渲染模式会影响到浏览器对于 CSS 代码甚至 JavaScript 脚本的解析,所以Doctype是非常关键的,尤其是在 IE 系列浏览器中,由DOCTYPE 所决定的 HTML 页面的渲染模式至关重要。 86 | 87 | ## 浏览器解析HTML方式 88 | 89 | 有三种解析方式: 90 | 91 | - 非怪异(标准)模式 92 | - 怪异模式 93 | - 部分怪异(近乎标准)模式 94 | 95 | 在“标准模式”`(standards mode) `页面按照 `HTML` 与 `CSS` 的定义渲染,而在“怪异模式(`quirks mode`) 模式”中则尝试模拟更旧的浏览器的行为。 一些浏览器(例如,那些基于 `Mozilla` 的 `Gecko` 渲染引擎的,或者 `Internet Explorer 8` 在 `strict mode` 下)也使用一种尝试于这两者之间妥协的“近乎标准”(`almost standards`) 模式,实施了一种表单元格尺寸的怪异行为,除此之外符合标准定义。 96 | 97 | 一个不含任何 `DOCTYPE` 的网页将会以 怪异(`quirks`) 模式渲染。 98 | 99 | `HTML5`提供的`<DOCTYPE html>`是标准模式,向后兼容的, 等同于开启了标准模式,那么浏览器就得老老实实的按照W3C的 标准解析渲染页面,这样一来,你的页面在所有的浏览器里显示的就都是一个样子了。 100 | 101 | ## 理解DOM结构 102 | 103 | DOM: Document Object Module, 文档对象模型。我们通过JavaScript操作页面的元素,进行添加、移动、改变或移除的方法和属性, 都是DOM提供的。 104 | 105 | ## W3C DOM 标准 106 | 107 | 被分为 3 个不同的部分: 108 | 109 | - 核心 DOM - 针对任何结构化文档的标准模型 110 | - XML DOM - 针对 XML 文档的标准模型 111 | - HTML DOM - 针对 HTML 文档的标准模型 112 | 113 | ## DOM节点 114 | 115 | 根据 W3C 的 HTML DOM 标准,HTML 文档中的所有内容都是节点: 116 | 117 | - 整个文档是一个文档节点 118 | - 每个 HTML 元素是元素节点 119 | - HTML 元素内的文本是文本节点 120 | - 每个 HTML 属性是属性节点 121 | - 注释是注释节点 122 | 123 | ## HTML DOM 节点树 124 | 125 | HTML文本会被解析为DOM树, 树中的所有节点均可通过 JavaScript 进行访问。所有 HTML 元素(节点)均可被修改,也可以创建或删除节点。 126 | 127 | ## 节点的关系 128 | 129 | 父(parent)、子(child)和同胞(sibling)等术语用于描述这些关系。父节点拥有子节点。同级的子节点被称为同胞(兄弟或姐妹): 130 | 131 | - 在节点树中,顶端节点被称为根(root) 132 | - 每个节点都有父节点、除了根(它没有父节点) 133 | - 一个节点可拥有任意数量的子节点 134 | - 同胞是拥有相同父节点的节点 135 | 136 | <img src="../assets/dom_navigate.gif" style="display: flex; margin: auto; width: 50%;"/> 137 | 138 | ## HTML5新增内容 139 | 140 | HTML5 是对 HTML 标准的第五次修订。其主要的目标是将互联网语义化,以便更好地被人类和机器阅读,并同时提供更好地支持各种媒体的嵌入。HTML5 的语法是向后兼容的。现在国内普遍说的 H5 是包括了 CSS3,JavaScript 的说法(严格意义上说,这么叫并不合适,但是已经这么叫开了,就将错就错了)。 141 | 142 | ## 与HTML 4的不同之处 143 | 144 | - 文件类型声明`(<!DOCTYPE>)`仅有一型:`<!DOCTYPE HTML>`。 145 | - 新的解析顺序:不再基于SGML。 146 | - 新的元素:section, video, progress, nav, meter, time, aside, canvas, command, datalist, details, embed, figcaption, figure, footer, header, hgroup, keygen, mark, output, rp, rt, ruby, source, summary, wbr。 147 | - input元素的新类型:date, email, url等等。 148 | - 新的属性:ping(用于a与area), charset(用于meta), async(用于script)。 149 | - 全域属性:id, tabindex, repeat。 150 | - 新的全域属性:contenteditable, contextmenu, draggable, dropzone, hidden, spellcheck。 151 | - 移除元素:acronym, applet, basefont, big, center, dir, font, frame, frameset, isindex, noframes, strike, tt。 152 | 153 | ## 新增标签 154 | 155 | HTML 5提供了一些新的元素和属性,反映典型的现代用法网站。其中有些是技术上类似`<div>`和`<span>`标签,但有一定含义,例如`<nav>`(网站导航块)和`<footer> <audio>`和`<video>`标记。 156 | 157 | ## 移除的标签 158 | 159 | 一些过时的HTML 4标记将取消,其中包括纯粹用作显示效果的标记,如`<font>`和`<center>`,因为它们已经被CSS取代。还有一些通过DOM的网络行为。 160 | 161 | ## 修改的标签 162 | 163 | 尽管和SGML在标记上的相似性,HTML5的句法并不再基于它了,而是被设计成向后兼容对老版本的HTML的解析。它有一个新的开始列看起来就像SGML的文档类型声明,`<!DOCTYPE HTML>`,这会触发和标准兼容的渲染模式。在2009年1月5号,HTML5添加了Web Form 2.0的内容,html5开始发展起来。 164 | -------------------------------------------------------------------------------- /docs/ALG/2-两数相加.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 1. 题目描述(中等难度) 6 | 7 | <img src="../assets/20180714105005.jpg" style="display: flex; margin: auto; width: 100%;"/> 8 | 9 | 就是两个链表表示的数相加,这样就可以实现两个很大的数相加了,无需考虑数值 int ,float 的限制了。 10 | 11 | 由于自己实现的很乱,直接按答案的讲解了。 12 | 13 | 给你两个链表,代表两个非负数。这些数字以相反的顺序存储, 14 | 它们的每个节点都包含一个数字。将两个数字相加并将其作为链表返回。 15 | 16 | ```js 17 | 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8 18 | ``` 19 | 20 | ## 翻译 21 | 22 | 有两个连结阵列分别代表两个非负整数,他们的位数是反向储存(越前面的节点位数越低),毎一个节点代表一个位数,将这两个连结阵列加总后以连结阵列形式回传。 23 | 24 | ```js 25 | 范例: 26 | Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 27 | Output: 个位数为2与5,相加为7 ; 十位数为4+6 = 10,需要进位; 百位数为3 + 4 + 1(进位) = 8,结果为7->0->8 28 | ``` 29 | 30 | ## 思路 31 | 32 | - 就只是用一个新的linked list来储存相加后的结果 33 | - 要注意的就是list1跟list2长度可能不一样 34 | - 另外就是相加后可能比9还大,需要考虑进位的情况 35 | 36 | ## 解题 37 | 38 | ```js 39 | /** 40 | * Definition for singly-linked list. 41 | * function ListNode(val) { 42 | * this.val = val; 43 | * this.next = null; 44 | * } 45 | */ 46 | /** 47 | * @param {ListNode} l1 48 | * @param {ListNode} l2 49 | * @return {ListNode} 50 | */ 51 | var addTwoNumbers = function(l1, l2) { 52 | var list = new ListNode(0); //儲存輸出的結果,因為list的指針要不斷往後移,因此用一個假節點方便操作 53 | var result = list; // 使用一個ListNode來儲存相加的結果 54 | 55 | var sum,carry = 0; // carry用來處理進位 56 | 57 | //當 list1, list2 都沒有值,而且carry也為0的時候才結束迴圈 58 | while(l1 || l2 || carry > 0){ 59 | sum = 0; 60 | 61 | // list1與list2長度可能不同,分開處理 62 | if(l1!== null){ 63 | sum += l1.val; 64 | l1 = l1.next; 65 | } 66 | 67 | if(l2!==null){ 68 | sum += l2.val; 69 | l2 = l2.next; 70 | } 71 | 72 | // 如果之前有進位,carry = 1;沒有的話carry = 0 73 | sum += carry; 74 | list.next = new ListNode(sum%10); //相加如果超過9,只能留下個位數放入結果list,十位數的地方進位 75 | carry = parseInt(sum/10); 76 | 77 | // list指標向後 78 | list = list.next; 79 | } 80 | // 因為第一個節點為假節點,跳過 81 | return result.next; 82 | } 83 | ``` 84 | 85 | ## 用递回解 86 | 87 | ```js 88 | var addTwoNumbers = function(l1, l2) { 89 | 90 | var list = new ListNode(0); 91 | var result = list; // 使用一個ListNode來儲存相加的結果 92 | 93 | add(l1,l2,0); 94 | return result.next; 95 | 96 | function add(l1,l2,gap){ 97 | var sum = 0; 98 | if(l1 === null && l2 === null && gap === 0){ 99 | return 0; 100 | } 101 | 102 | if(l1 !== null){ 103 | sum += l1.val; 104 | l1 = l1.next; 105 | } 106 | 107 | if(l2 !== null){ 108 | sum += l2.val; 109 | l2 = l2.next; 110 | } 111 | sum += gap; 112 | list.next = new ListNode(sum%10); 113 | gap = parseInt(sum/10); 114 | list = list.next; 115 | add(l1,l2,gap); 116 | } 117 | }; 118 | ``` 119 | 120 | <img src="../assets/2f86beba9dfa163212ec030dabf1be9c.png" style="display: flex; margin: auto; width: 100%;"/> 121 | 122 | 可以用两种做法:循环 + 递归。 123 | ​ 124 | 在实现中需要注意的有: 125 | 126 | 1. 不可以把链表先转化成 int 型数字再求和,因为可能溢出; 127 | 2. 两个「加数」的字符串长度可能不同; 128 | 3. 在最后,如果进位 carry 不为 0,那么最后需要计算进位; 129 | 130 | 代码中的巧妙之处: 131 | 132 | - while (i >= 0 || j >= 0 || carry != 0)含义: 133 | 134 | 链表 a 和 b 只要有一个没遍历完,那么就继续遍历; 135 | 如果链表 a 和 b 都遍历完了,但是最后留下的进位 carry != 0,那么需要把进位也保留到结果中。 136 | 137 | - 取 a 和 b 当前位置数字 的时候,如果链表 a 或 b 已经遍历完了(即 i < = 0 i <= 0i<=0 或者 j < = 0 j <= 0j<=0),则认为 a 和 b 的对应位置是 0 00 。 138 | 139 | 给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。 140 | 141 | 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 142 | 143 | 示例: 144 | 145 | ```js 146 | 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 147 | 输出:7 -> 0 -> 8 148 | 原因:342 + 465 = 807 149 | ``` 150 | 151 | <img src="../assets/732.png" style="display: flex; margin: auto; width: 100%;"/> 152 | 153 | 既然是求和,那不难知道,取出两个链表中的每一个节点,然后进行求和(sum),如果大于10则记一个进位1,然后拿sum对10进行求余,得的到结果就是目标链表的第一个有效节点,具体过程如图: 154 | 155 | <img src="../assets/2812025490.png" style="display: flex; margin: auto; width: 100%;"/> 156 | 157 | 实现过程: 158 | 159 | 1、核心方法就是对两个链表进行遍历,然后逐个节点求和 160 | 161 | - 因为不知道这两个要求和的链表的节点个数(也就是不知道循环次数),所以选择while循环。只要任何一个链表的节点不为null,都需要继续进行循环 162 | - 但是因为有进位的情况,所以,当进位不是0时,也不能停止循环(比如9999+1) 163 | 164 | 2、生成新的链表存储求和的结果 165 | 166 | - 对于链表的问题,通常都会创建一个标志节点,它不存具体的值,它的next负责指向第一个有效节点(始终指向第一个,不移动),主要是为了方便我们返回得到的目标链表 167 | - 同时需要创建一个current节点,他负责生成每一个节点,它是移动的,每生成一个节点,它都需要向后移动一个节点,从而实现构建新的链表 168 | 169 | ## 复杂度分析 170 | 171 | - 时间复杂度:O(min(m,n)),其中 m 和 n 分别为两个链表的长度。当其中一个或两个链表为空时,递归终止。 172 | - 空间复杂度:O(min(m,n))。 173 | 174 | <img src="../assets/6.gif" style="display: flex; margin: auto; width: 100%;"/> 175 | 176 | ```js 177 | /** 178 | * Definition for singly-linked list. 179 | * function ListNode(val) { 180 | * this.val = val; 181 | * this.next = null; 182 | * } 183 | */ 184 | /** 185 | * @param {ListNode} l1 186 | * @param {ListNode} l2 187 | * @return {ListNode} 188 | */ 189 | var addTwoNumbers = function (l1, l2) { 190 | if (l1 === null || l2 === null) return null; 191 | 192 | // 使用dummyHead可以简化对链表的处理,dummyHead.next指向新链表 193 | let dummyHead = new ListNode(0); 194 | let cur1 = l1; 195 | let cur2 = l2; 196 | let cur = dummyHead; // cur用于计算新链表 197 | let carry = 0; // 进位标志 198 | 199 | while (cur1 !== null || cur2 !== null) { 200 | let val1 = cur1 !== null ? cur1.val : 0; 201 | let val2 = cur2 !== null ? cur2.val : 0; 202 | let sum = val1 + val2 + carry; 203 | let newNode = new ListNode(sum % 10); // sum%10取模结果范围为0~9,即为当前节点的值 204 | carry = sum >= 10 ? 1 : 0; // sum>=10,carry=1,表示有进位 205 | cur.next = newNode; 206 | cur = cur.next; 207 | 208 | if (cur1 !== null) { 209 | cur1 = cur1.next; 210 | } 211 | 212 | if (cur2 !== null) { 213 | cur2 = cur2.next; 214 | } 215 | } 216 | 217 | if (carry > 0) { 218 | // 如果最后还有进位,新加一个节点 219 | cur.next = new ListNode(carry); 220 | } 221 | 222 | return dummyHead.next; 223 | }; 224 | ``` 225 | 226 | -------------------------------------------------------------------------------- /docs/coding/实现图片的懒加载.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | 懒加载,顾名思义,在当前网页,滑动页面到能看到图片的时候再加载图片 6 | 7 | 故问题拆分成两个: 8 | 9 | 1. 如何判断图片出现在了当前视口 (即如何判断我们能够看到图片) 10 | 2. 如何控制图片的加载 11 | 12 | ## 方案一: 位置计算 + 滚动事件 (Scroll) + DataSet API 13 | 14 | ### 如何判断图片出现在了当前视口 15 | 16 | clientTop,offsetTop,clientHeight 以及 scrollTop 各种关于图片的高度作比对 17 | 18 | 仅仅知道它静态的高度还不够,我们还需要知道动态的 19 | 20 | 如何动态?监听 window.scroll 事件 21 | 22 | ## 如何控制图片的加载 23 | 24 | ```js 25 | <img data-src="xxx.jpg" /> 26 | ``` 27 | 28 | 首先设置一个临时 Data 属性 data-src,控制加载时使用 src 代替 data-src,可利用 DataSet API 实现 29 | 30 | ```js 31 | img.src = img.dataset.src 32 | ``` 33 | 34 | ## 方案二: getBoundingClientRect API + Scroll with Throttle + DataSet API 35 | 36 | 引入一个新的 API, Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。 37 | 38 | <img src="../assets/rect.png" style="display: flex; margin: auto; width: 100%;"/> 39 | 40 | 那如何判断图片出现在了当前视口呢,根据示例图示意,代码如下 41 | 42 | ```js 43 | // clientHeight 代表当前视口的高度 44 | img.getBoundingClientRect().top < document.documentElement.clientHeight; 45 | ``` 46 | 47 | 监听 window.scroll 事件也优化一下 48 | 49 | 加个节流器,提高性能。工作中一般使用 lodash.throttle 就可以了,万能的 lodash 啊! 50 | 51 | ```js 52 | _.throttle(func, [(wait = 0)], [(options = {})]); 53 | ``` 54 | 55 | - 防抖:防止抖动,单位时间内事件触发会被重置,避免事件被误伤触发多次。代码实现重在清零 clearTimeout。防抖可以比作等电梯,只要有一个人进来,就需要再等一会儿。业务场景有避免登录按钮多次点击的重复提交。 56 | - 节流:控制流量,单位时间内事件只能触发一次,与服务器端的限流 (Rate Limit) 类似。代码实现重在开锁关锁 timer=timeout; timer=null。节流可以比作过红绿灯,每等一个红灯时间就可以过一批。 57 | 58 | ## 防抖 (debounce) 59 | 60 | 防抖,顾名思义,防止抖动,以免把一次事件误认为多次,敲键盘就是一个每天都会接触到的防抖操作。 61 | 62 | 想要了解一个概念,必先了解概念所应用的场景。在 JS 这个世界中,有哪些防抖的场景呢 63 | 64 | 1. 登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要防抖 65 | 2. 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖 66 | 3. 文本编辑器实时保存,当无任何更改操作一秒后进行保存 67 | 68 | 代码如下,可以看出来防抖重在清零 clearTimeout(timer) 69 | 70 | ```js 71 | function debounce (f, wait) { 72 | let timer 73 | return (...args) => { 74 | clearTimeout(timer) 75 | timer = setTimeout(() => { 76 | f(...args) 77 | }, wait) 78 | } 79 | } 80 | ``` 81 | 82 | ## 节流 (throttle) 83 | 84 | 节流,顾名思义,控制水的流量。控制事件发生的频率,如控制为1s发生一次,甚至1分钟发生一次。与服务端(server)及网关(gateway)控制的限流 (Rate Limit) 类似。 85 | 86 | 1. scroll 事件,每隔一秒计算一次位置信息等 87 | 2. 浏览器播放事件,每个一秒计算一次进度信息等 88 | 3. input 框实时搜索并发送请求展示下拉列表,每隔一秒发送一次请求 (也可做防抖) 89 | 90 | 代码如下,可以看出来节流重在加锁 timer=timeout 91 | 92 | ```js 93 | function throttle (f, wait) { 94 | let timer 95 | return (...args) => { 96 | if (timer) { return } 97 | timer = setTimeout(() => { 98 | f(...args) 99 | timer = null 100 | }, wait) 101 | } 102 | } 103 | ``` 104 | 105 | ## 方案三: IntersectionObserver API + DataSet API 106 | 107 | 如何判断图片出现在了当前视口 108 | 109 | 方案二使用的方法是: window.scroll 监听 Element.getBoundingClientRect() 并使用 _.throttle 节流 110 | 111 | 一系列组合动作太复杂了,于是浏览器出了一个三合一事件: IntersectionObserver API,一个能够监听元素是否到了当前视口的事件,一步到位! 112 | 113 | 事件回调的参数是 IntersectionObserverEntry (打开新窗口)的集合,代表关于是否在可见视口的一系列值 114 | 115 | 其中,entry.isIntersecting 代表目标元素可见 116 | 117 | ```js 118 | const observer = new IntersectionObserver((changes) => { 119 | // changes: 目标元素集合 120 | changes.forEach((change) => { 121 | // intersectionRatio 122 | if (change.isIntersecting) { 123 | const img = change.target; 124 | img.src = img.dataset.src; 125 | observer.unobserve(img); 126 | } 127 | }); 128 | }); 129 | 130 | observer.observe(img); 131 | ``` 132 | 133 | 当然,IntersectionObserver 除了给图片做懒加载外,还可以对单页应用资源做预加载。 134 | 135 | 如在 next.js v9 中,会对视口内的资源做预加载,可以参考 next 9 production optimizations(打开新窗口) 136 | 137 | ```js 138 | <Link href="/about"> 139 | <a>xxx</a> 140 | </Link> 141 | ``` 142 | 143 | ## 方案四: LazyLoading 属性 144 | 145 | 浏览器觉得懒加载这事可以交给自己做,你们开发者加个属性就好了。实在是...! 146 | 147 | ```js 148 | <img src="shanyue.jpg" loading="lazy" /> 149 | ``` 150 | 151 | 不过目前浏览器兼容性不太好,关于 loading 属性的文章也可以查看 Native image lazy-loading for the web! 152 | 153 | ```js 154 | <!DOCTYPE html> 155 | <html lang="en"> 156 | <head> 157 | <meta charset="UTF-8" /> 158 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 159 | <title>图片懒加载 160 | 166 | 167 | 168 | 1 172 | 2 176 | 3 180 | 4 184 | 5 188 | 6 192 | 7 196 | 197 | 214 | 215 | 216 | ``` -------------------------------------------------------------------------------- /docs/JavaScript/继承.md: -------------------------------------------------------------------------------- 1 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 2 | 3 | [[toc]] 4 | 5 | ## 1.原型链继承 6 | 7 | ```js 8 | function Parent() { 9 | this.name = 'x'; 10 | } 11 | 12 | Parent.prototype.getName = function () { 13 | console.log(this.name); 14 | } 15 | 16 | function Child() { 17 | 18 | } 19 | 20 | Child.prototype = new Parent(); 21 | 22 | var child1 = new Child(); 23 | console.log(child1.getName()) // x 24 | ``` 25 | 26 | 问题: 27 | 28 | 1.引用类型的属性被所有实例共享,举个例子: 29 | 30 | ```js 31 | function Parent () { 32 | this.names = ['a', 'f']; 33 | } 34 | 35 | function Child () { 36 | 37 | } 38 | 39 | Child.prototype = new Parent(); 40 | 41 | var child1 = new Child(); 42 | 43 | child1.names.push('xx'); 44 | 45 | console.log(child1.names); // ["a", "f", "xx"] 46 | 47 | var child2 = new Child(); 48 | 49 | console.log(child2.names); // ["a", "f", "xx"] 50 | ``` 51 | 52 | 2.在创建 Child 的实例时,不能向Parent传参 53 | 54 | ## 2.借用构造函数(经典继承) 55 | 56 | ```js 57 | function Parent () { 58 | this.names = ['a', 'f']; 59 | } 60 | 61 | function Child () { 62 | Parent.call(this); 63 | } 64 | 65 | var child1 = new Child(); 66 | 67 | child1.names.push('s'); 68 | 69 | console.log(child1.names); // ["a", "f", "s"] 70 | 71 | var child2 = new Child(); 72 | 73 | console.log(child2.names); // ["a", "f"] 74 | ``` 75 | 76 | 优点: 77 | 78 | 1.避免了引用类型的属性被所有实例共享 79 | 80 | 2.可以在 Child 中向 Parent 传参 81 | 82 | 举个例子: 83 | 84 | ```js 85 | function Parent (name) { 86 | this.name = name; 87 | } 88 | 89 | function Child (name) { 90 | Parent.call(this, name); 91 | } 92 | 93 | var child1 = new Child('a'); 94 | 95 | console.log(child1.name); // a 96 | 97 | var child2 = new Child('s'); 98 | 99 | console.log(child2.name); // s 100 | ``` 101 | 102 | 缺点: 103 | 104 | 方法都在构造函数中定义,每次创建实例都会创建一遍方法。 105 | 106 | ## 3.组合继承 107 | 108 | 原型链继承和经典继承双剑合璧。 109 | 110 | ```js 111 | function Parent (name) { 112 | this.name = name; 113 | this.colors = ['red', 'blue', 'green']; 114 | } 115 | 116 | Parent.prototype.getName = function () { 117 | console.log(this.name) 118 | } 119 | 120 | function Child (name, age) { 121 | 122 | Parent.call(this, name); 123 | 124 | this.age = age; 125 | 126 | } 127 | 128 | Child.prototype = new Parent(); 129 | Child.prototype.constructor = Child; 130 | 131 | var child1 = new Child('kevin', '18'); 132 | 133 | child1.colors.push('black'); 134 | 135 | console.log(child1.name); // kevin 136 | console.log(child1.age); // 18 137 | console.log(child1.colors); // ["red", "blue", "green", "black"] 138 | 139 | var child2 = new Child('daisy', '20'); 140 | 141 | console.log(child2.name); // daisy 142 | console.log(child2.age); // 20 143 | console.log(child2.colors); // ["red", "blue", "green"] 144 | ``` 145 | 146 | 优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。 147 | 148 | ## 4.原型式继承 149 | 150 | ```js 151 | function createObj(o) { 152 | function F(){} 153 | F.prototype = o; 154 | return new F(); 155 | } 156 | ``` 157 | 158 | 就是 `ES5 Object.create` 的模拟实现,将传入的对象作为创建的对象的原型。 159 | 160 | 缺点: 161 | 162 | 包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。 163 | 164 | ```js 165 | var person = { 166 | name: 'kevin', 167 | friends: ['daisy', 'kelly'] 168 | } 169 | 170 | var person1 = createObj(person); 171 | var person2 = createObj(person); 172 | 173 | person1.name = 'person1'; 174 | console.log(person2.name); // kevin 175 | 176 | person1.friends.push('taylor'); 177 | console.log(person2.friends); // ["daisy", "kelly", "taylor"] 178 | ``` 179 | 180 | 注意:修改person1.name的值,person2.name的值并未发生改变,并不是因为person1和person2有独立的 name 值,而是因为person1.name = 'person1',给person1添加了 name 值,并非修改了原型上的 name 值。 181 | 182 | ## 5. 寄生式继承 183 | 184 | 创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。 185 | 186 | ```js 187 | function createObj (o) { 188 | var clone = Object.create(o); 189 | clone.sayName = function () { 190 | console.log('hi'); 191 | } 192 | return clone; 193 | } 194 | ``` 195 | 196 | 缺点:跟借用构造函数模式一样,每次创建对象都会创建一遍方法。 197 | 198 | ## 6. 寄生组合式继承 199 | 200 | 为了方便大家阅读,在这里重复一下组合继承的代码: 201 | 202 | ```js 203 | function Parent (name) { 204 | this.name = name; 205 | this.colors = ['red', 'blue', 'green']; 206 | } 207 | 208 | Parent.prototype.getName = function () { 209 | console.log(this.name) 210 | } 211 | 212 | function Child (name, age) { 213 | Parent.call(this, name); 214 | this.age = age; 215 | } 216 | 217 | Child.prototype = new Parent(); 218 | 219 | var child1 = new Child('kevin', '18'); 220 | 221 | console.log(child1) 222 | ``` 223 | 224 | 组合继承最大的缺点是会调用两次父构造函数。 225 | 226 | 一次是设置子类型实例的原型的时候: 227 | 228 | ```js 229 | Child.prototype = new Parent(); 230 | ``` 231 | 232 | 一次在创建子类型实例的时候: 233 | 234 | ```js 235 | var child1 = new Child('kevin', '18'); 236 | ``` 237 | 238 | 回想下 new 的模拟实现,其实在这句中,我们会执行: 239 | 240 | ```js 241 | Parent.call(this, name); 242 | ``` 243 | 244 | 在这里,我们又会调用了一次 Parent 构造函数。 245 | 246 | 所以,在这个例子中,如果我们打印 child1 对象,我们会发现 Child.prototype 和 child1 都有一个属性为colors,属性值为['red', 'blue', 'green']。 247 | 248 | 那么我们该如何精益求精,避免这一次重复调用呢? 249 | 250 | 如果我们不使用 Child.prototype = new Parent() ,而是间接的让 Child.prototype 访问到 Parent.prototype 呢? 251 | 252 | 看看如何实现: 253 | 254 | ```js 255 | function Parent (name) { 256 | this.name = name; 257 | this.colors = ['red', 'blue', 'green']; 258 | } 259 | 260 | Parent.prototype.getName = function () { 261 | console.log(this.name) 262 | } 263 | 264 | function Child (name, age) { 265 | Parent.call(this, name); 266 | this.age = age; 267 | } 268 | 269 | // 关键的三步 270 | var F = function () {}; 271 | 272 | F.prototype = Parent.prototype; 273 | 274 | Child.prototype = new F(); 275 | 276 | 277 | var child1 = new Child('kevin', '18'); 278 | 279 | console.log(child1); 280 | ``` 281 | 282 | 最后我们封装一下这个继承方法: 283 | 284 | ```js 285 | function object(o) { 286 | function F() {} 287 | F.prototype = o; 288 | return new F(); 289 | } 290 | 291 | function prototype(child, parent) { 292 | var prototype = object(parent.prototype); 293 | prototype.constructor = child; 294 | child.prototype = prototype; 295 | } 296 | 297 | // 当我们使用的时候: 298 | prototype(Child, Parent); 299 | ``` 300 | 301 | 引用《JavaScript高级程序设计》中对寄生组合式继承的夸赞就是: 302 | 303 | 这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。 304 | 305 | -------------------------------------------------------------------------------- /docs/JavaScript/函数-可复用代码块.md: -------------------------------------------------------------------------------- 1 | 2 | > 点击勘误[issues](https://github.com/webVueBlog/learn-web/issues),哪吒感谢大家的阅读 3 | 4 | [[toc]] 5 | 6 | 在JavaScript中另一个基本概念是函数, 它允许你在一个代码块中存储一段用于处理单任务的代码,然后在任何你需要的时候用一个简短的命令来调用,而不是把相同的代码写很多次。 7 | 在本文中,我们将探索函数的基本概念,如基本语法、如何定义和调用、范围和参数。 8 | 9 | ## 我能在哪找到函数? 10 | 11 | 在 JavaScript中, 你将发现函数无处不在 。事实上, 到目前为止,我们一直在使用函数,只是我们还没很好的讨论它们。然而现在是时候了,让我们开始聊聊函数,并探索它们的语法。 12 | 13 | 几乎任何时候,只要你使用一个带有一对圆括号()的JavaScript结构,并且你不是在使用一个常见的比如for for循环,while或do…while循环,或者if语句这样的内置语言结构时,那么您就正在使用函数。 14 | 15 | ## 浏览器内置函数 16 | 17 | 当我们操作一个字符串的时候,例如: 18 | 19 | ```js 20 | var myText = 'I am a string'; 21 | var newString = myText.replace('string', 'sausage'); 22 | console.log(newString); 23 | // the replace() string function takes a string, 24 | // replaces one substring with another, and returns 25 | // a new string with the replacement made 26 | ``` 27 | 28 | 或者当我们操作一个数组的时候: 29 | 30 | ```js 31 | var myArray = ['I', 'love', 'chocolate', 'frogs']; 32 | var madeAString = myArray.join(' '); 33 | console.log(madeAString); 34 | // the join() function takes an array, joins 35 | // all the array items together into a single 36 | // string, and returns this new string 37 | ``` 38 | 39 | 或者当我们生成一个随机数时: 40 | 41 | ```js 42 | var myNumber = Math.random() 43 | // the random() function generates a random 44 | // number between 0 and 1, and returns that 45 | // number 46 | ``` 47 | 48 | JavaScript有许多内置的函数,可以让您做很多有用的事情,而无需自己编写所有的代码。事实上, 许多你调用(运行或者执行的专业词语)浏览器内置函数时调用的代码并不是使用JavaScript来编写——大多数调用浏览器后台的函数的代码,是使用像C++这样更低级的系统语言编写的,而不是像JavaScript这样的web编程语言。 49 | 50 | 请记住,这些内置浏览器函数不是核心JavaScript语言的一部分——被定义为浏览器API的一部分,它建立在默认语言之上,以提供更多的功能(请参阅本课程的早期部分以获得更多的描述)。我们将在以后的模块中更详细地使用浏览器API。 51 | 52 | ## 函数与方法 53 | 54 | 程序员把函数称为对象方法(method)的一部分。你还不必了解JavaScript中已建构的对象在更深层次上是如何运作的——你可以等到下一小节,我们会教给你有关对象运作方式的一切。在我们继续前进之前,我们需要澄清一些有关方法和函数概念之间可能存在的误会——当你在网络上浏览相关信息的时候,你很可能会碰上这两个术语。 55 | 56 | 到目前为止我们所使用的内置代码同属于这两种形式:函数和方法。你可以在这里查看内置函数,内置对象以及其相关方法的完整列表。 57 | 58 | 严格说来,内置浏览器函数并不是函数——它们是方法。这听起来有点可怕和令人困惑,但不要担心 ——函数和方法在很大程度上是可互换的,至少在我们的学习阶段是这样的。 59 | 60 | 二者区别在于方法是在对象内定义的函数。浏览器内置函数(方法)和变量(称为属性)存储在结构化对象内,以使代码更加高效,易于处理。 61 | 62 | ## 自定义函数 63 | 64 | 您在过去的课程中还看到很多定制功能 - 在代码中定义的功能,而不是在浏览器中。每当您看到一个自定义名称后面都带有括号,那么您使用的是自定义函数. 65 | 66 | 自定义函数:draw() 67 | 68 | ```js 69 | function draw() { 70 | ctx.clearRect(0,0,WIDTH,HEIGHT); 71 | for (var i = 0; i < 100; i++) { 72 | ctx.beginPath(); 73 | ctx.fillStyle = 'rgba(255,0,0,0.5)'; 74 | ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); 75 | ctx.fill(); 76 | } 77 | } 78 | ``` 79 | 80 | 该函数在``元素中绘制100个随机圆。每次我们想要这样做,我们可以使用这个函数来调用这个功能 81 | 82 | ```js 83 | draw(); 84 | ``` 85 | 86 | 而不是每次我们想重复一遍,都要写出所有的代码。函数可以包含任何您喜欢的代码 - 甚至可以从内部函数调用其他函数。以上函数例如调用random()函数三次,由以下代码定义: 87 | 88 | ```js 89 | function random(number) { 90 | return Math.floor(Math.random()*number); 91 | } 92 | ``` 93 | 94 | 我们需要这个函数,因为浏览器的内置`Math.random()`函数只生成一个0到1之间的随机十进制数。我们想要一个0到一个指定数字之间的随机整数。 95 | 96 | ## 调用函数 97 | 98 | 现在你可能很清楚这一点,但仅仅为了防止……,要在函数定义之后,实际使用它,你必须运行或调用它。这是通过将函数名包含在代码的某个地方,后跟圆括号来完成的。 99 | 100 | ```js 101 | function myFunction() { 102 | alert('hello'); 103 | } 104 | 105 | myFunction() 106 | // calls the function once 107 | ``` 108 | 109 | ## 匿名函数 110 | 111 | 到目前为止,我们刚刚创建了如下函数: 112 | 113 | ```js 114 | function myFunction() { 115 | alert('hello'); 116 | } 117 | ``` 118 | 119 | 但是您也可以创建一个没有名称的函数: 120 | 121 | ```js 122 | function() { 123 | alert('hello'); 124 | } 125 | ``` 126 | 127 | 这个函数叫做匿名函数 — 它没有函数名`!` 它也不会自己做任何事情。 128 | 你通常将匿名函数与事件处理程序一起使用, 例如,如果单击相关按钮,以下操作将在函数内运行代码: 129 | 130 | ```js 131 | var myButton = document.querySelector('button'); 132 | 133 | myButton.onclick = function() { 134 | alert('hello'); 135 | } 136 | ``` 137 | 138 | 上述示例将要求`