├── 04-JavaScript基础 ├── 22-闭包.md ├── 常见代码解读.md ├── 20-作用域链.md ├── 00-编程语言.md ├── 12-基本数据类型vs引用数据类型.md ├── 29-包装类.md ├── 19-预编译及变量提升详解.md ├── 50-定时器.md ├── 28-内置对象:Math.md ├── 47-事件委托.md ├── 18-作用域.md ├── 21-this.md ├── 44-client(可视区)相关属性.md └── 原型链.md ├── 08-移动web开发 └── 02-Bootstrap使用.md ├── .gitattributes ├── 15-面试题积累 ├── 05-BAT爱考的JS面试题.md ├── 函数.md ├── 清单.md ├── 异步.md ├── 03-http.md ├── 面经链接推荐.md └── 01-我的面试经历 by smyhvae.md ├── 14-前端面试 ├── z-其他.md ├── z-计算机网络.md ├── z-web安全.md ├── 11-02.ES6.md ├── 15-虚拟DOM.md ├── 11-00.JavaScript高级面试:前言.md ├── 23-面试技巧 by smyhvae.md ├── 22-网友面经.md ├── z-推荐文章.md ├── 11-01.ES6:模块化的使用和编译环境.md ├── 16-01.MVVM.md ├── 08-算法问题.md ├── 21-面试题整理 by smyhvae.md ├── 10-02.前端错误监控.md ├── 05-02.面向对象:类的定义和继承的几种方式.md ├── 09-01.浏览器渲染机制.md ├── 04-HTTP协议.md ├── 05-01.创建对象和原型链.md ├── 07-安全问题:CSRF和XSS.md └── 09-02.js运行机制:异步和单线程.md ├── 12-Vue基础 ├── Vue-router路由.md ├── Vue.js在开发中的常见写法积累.md ├── Vue开发积累.md ├── 07-Vue-router路由.md └── 02-Vue实例的生命周期函数.md ├── 00-前端工具 ├── iTerm2 + OhMyZsh + agnoster 搭建.md ├── iconMoon.md ├── 05-GitHub的使用.md ├── 06-chrome浏览器.md ├── whistle网络抓包.md ├── 07-Emmet in VS Code.md ├── 05-Atom在前端的使用.md ├── 04-Sublime Text在前端中的使用.md ├── 04-WebStorm的使用.md └── 02-Git的使用.md ├── 09-Ajax ├── 1.php ├── 05-模板引擎.md ├── 04-同源和跨域.md └── 03-函数封装:Ajax发送http请求(get&post).md ├── 16-前端进阶 ├── 01-前端常见专有名词.md ├── 04-前端监控技术.md ├── 09-lazyload&防抖动和节流阀.md ├── Vue开发积累.md ├── 02-数组的常见操作.md └── 前端的几道题目.md ├── 17-前端综合 ├── json相关.md ├── CSS开发总结.md ├── 前端博客推荐.md ├── 网友对本项目提的建议.md ├── ajax相关.md ├── html相关.md ├── 前端开发积累.md ├── json字符串的解析和遍历.md └── 01-2019年Web前端入门自学路线.md ├── 05-JavaScript进阶 ├── 浅拷贝和深拷贝.md ├── JavaScript开发积累.md ├── call、apply、bind的区别.md ├── this.md └── 创建对象和继承.md ├── 02-CSS基础 ├── 16-浏览器的兼容性问题.md └── others.md ├── 18-推荐链接 ├── 2019-推荐文章.md ├── 03-网站推荐.md ├── 深圳有哪些IT互联网大厂.md └── 02-GitHub项目推荐.md ├── README.md ├── 03-CSS进阶 ├── 01-CSS中的非布局样式.md ├── 00-准备.md ├── CSS开发积累.md ├── CSS的一些小知识.md ├── CSS面试题.md └── 02-CSS布局.md ├── 13-React基础 ├── 10-React Navive初识.md ├── 03-React组件(一):生命周期.md ├── 08-Ant Design的基本使用.md └── 06-React的单向数据绑定.md ├── LICENSE ├── 11-Node.js和模块化 ├── Node.js代码举例.md ├── WebSocket.md ├── CommonJS.md ├── ES6.md ├── 00-事件驱动和非阻塞机制.md ├── 02-JavaScript模块化02:AMD.md └── 02-JavaScript模块化03:CMD.md ├── 10-ES6 ├── 01-ES5中的严格模式.md ├── 03-ES6的介绍和环境配置.md └── 09-ES6:字符串、数组、对象的扩展.md ├── 06-前端基本功:CSS和DOM练习 └── 05-DOM操作练习:访问关系的封装.md └── 01-html └── 07-HTML基础回顾.md /04-JavaScript基础/22-闭包.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /08-移动web开发/02-Bootstrap使用.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.php linguist-language=JavaScript -------------------------------------------------------------------------------- /15-面试题积累/05-BAT爱考的JS面试题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## this 在各个场景下的指向 5 | 6 | -------------------------------------------------------------------------------- /14-前端面试/z-其他.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前端基础 4 | 5 | ### 闭包和作用域,面试喜欢问。 6 | 7 | -------------------------------------------------------------------------------- /12-Vue基础/Vue-router路由.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 路由:就是SPA(单页应用)的**路径管理器**。 6 | 7 | -------------------------------------------------------------------------------- /14-前端面试/z-计算机网络.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [HTTP最强资料大全](https://github.com/semlinker/awesome-http) 4 | 5 | -------------------------------------------------------------------------------- /14-前端面试/z-web安全.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## 前言 6 | 7 | 攻击的原理也许你能讲出来,主要是想知道如何发现这个网站的漏洞,毕竟大部分的网站都已经把用户输入的内容各种花式过滤了 -------------------------------------------------------------------------------- /00-前端工具/iTerm2 + OhMyZsh + agnoster 搭建.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 推荐链接: 4 | 5 | - 6 | 7 | 8 | -------------------------------------------------------------------------------- /09-Ajax/1.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /16-前端进阶/01-前端常见专有名词.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 性能相关 5 | 6 | - 防抖和节流 7 | 8 | - 滚动穿透 9 | 10 | 11 | ## 样式相关 12 | 13 | - 多行文字截断 14 | 15 | -------------------------------------------------------------------------------- /17-前端综合/json相关.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## json中根据键获取值 4 | 5 | 参考链接: 6 | 7 | - 8 | 9 | - 10 | 11 | -------------------------------------------------------------------------------- /17-前端综合/CSS开发总结.md: -------------------------------------------------------------------------------- 1 | 2 | ### p标签里的文字溢出怎么办 3 | 4 | 加一个属性即可: 5 | 6 | ```css 7 | word-break: break-all; 8 | 9 | ``` 10 | 11 | ### inline-block 相关 12 | 13 | 图片默认是 inline-block 布局,会存在经典的底部 3px 的问题。 14 | -------------------------------------------------------------------------------- /15-面试题积累/函数.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ``` 4 | var arr = [1, 2, 3]; 5 | 6 | fun(arr); 7 | console.log(arr); 8 | 9 | function fun(a) { 10 | a = []; 11 | 12 | } 13 | ``` 14 | 15 | 上方代码的打印结果是:[1,2,3] 16 | 17 | -------------------------------------------------------------------------------- /15-面试题积累/清单.md: -------------------------------------------------------------------------------- 1 | 01.md 2 | 3 | 4 | 5 | ### CommonJS、RequireJS(AMD) SeaJS(CMD)区别 6 | 7 | 8 | 9 | 10 | ### Webpack 打包 11 | 12 | 13 | ### WebSocket 14 | 15 | 16 | ### ES6 17 | 18 | 会 ES6 是应该的部分,不算加分项。 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /00-前端工具/iconMoon.md: -------------------------------------------------------------------------------- 1 | iconMoon.md 2 | 3 | 4 | 5 | - 6 | 7 | - 8 | 9 | - 10 | 11 | -------------------------------------------------------------------------------- /17-前端综合/前端博客推荐.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前端博客推荐 3 | 4 | - 冴羽的博客: 5 | 6 | 冴羽写博客的地方,预计写四个系列:JavaScript深入系列、JavaScript专题系列、ES6系列、React系列。 7 | 8 | - 颜乐乐: 9 | 10 | 在头条做前端,博客内容很全,尤其是“单元测试”系列。 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /00-前端工具/05-GitHub的使用.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## GitHub的使用 4 | 5 | 6 | ### GitHub添加wiki 7 | 8 | 参考链接: 9 | 10 | 11 | - 12 | 13 | ### GitHub项目添加 licence 14 | 15 | 参考链接: 16 | 17 | - 18 | 19 | -------------------------------------------------------------------------------- /16-前端进阶/04-前端监控技术.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 要监控的内容: 6 | 7 | - 业务数据 8 | 9 | - 稳定性 10 | 11 | - 性能 12 | 13 | - 错误 14 | 15 | - 用户操作路径 16 | 17 | 18 | 怎么监控: 19 | 20 | - PV/UV、业务操作上报 21 | 22 | - 根据上报寻找异常 23 | 24 | - 将页面性能数据上报 25 | 26 | - 将页面产生错误上报 27 | 28 | - 跟踪用户操作路径 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /17-前端综合/网友对本项目提的建议.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - 图片的宽度,最好不要超过800px,否则在github上显示不完整,甚至无法显示。 5 | 6 | - 建议把图片压缩后再上传。图片大小最好控制在100kb左右。比如说,[javascript-tutorial-cn](https://github.com/iliakan/javascript-tutorial-cn)这个项目,在这方面就做得很好。 7 | 8 | 比如`20180223_2201.gif`这张图,原本是500kb,我压缩后重新上传,是200kb。 9 | 10 | 再比如`20180611_2130.png`这张图,原本是400kb,我压缩后重新上传,是200kb。 -------------------------------------------------------------------------------- /00-前端工具/06-chrome浏览器.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 控制台的使用 5 | 6 | ### 控制台查看源码 7 | 8 | 控制台的`Sources`标签可以查看源码。按住快捷键「cmd + P」,可以根据文件名查找源码文件。 9 | 10 | 11 | 12 | ## 其他 13 | 14 | ### show user agent shadow DOM 15 | 16 | ![](http://img.smyhvae.com/20180206_1610.png) 17 | 18 | 19 | ![](http://img.smyhvae.com/20180206_1616.png) 20 | 21 | 把上图中的红框部分打钩。 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /14-前端面试/11-02.ES6.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Class和普通构造函数有何区别 4 | 5 | > 我们经常会用ES6中的Class来代替JS中的构造函数做开发。 6 | 7 | 8 | - Class 在语法上更加贴合面向对象的写法 9 | 10 | - Class 实现继承更加易读、易理解 11 | 12 | 13 | 14 | - 更易于写 java 等后端语言的使用 15 | 16 | 17 | - 本质还是语法糖,使用 prototype 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /05-JavaScript进阶/浅拷贝和深拷贝.md: -------------------------------------------------------------------------------- 1 | 2 | ## 浅拷贝 3 | 4 | 对于对象或数组类型,当我们将a赋值给b,然后更改b中的属性,a也会随着变化。 5 | 6 | 也就是说,a和b指向了同一块堆内存,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝。 7 | 8 | ## 深拷贝 9 | 10 | 那么相应的,如果给b放到新的内存中,将a的各个属性都复制到新内存里,就是深拷贝。 11 | 12 | 也就是说,当b中的属性有变化的时候,a内的属性不会发生变化。 13 | 14 | 15 | 16 | 17 | 18 | 参考链接: 19 | 20 | - [深拷贝与浅拷贝的实现(一)](http://www.alloyteam.com/2017/08/12978/) 21 | 22 | - [javaScript中浅拷贝和深拷贝的实现](https://github.com/wengjq/Blog/issues/3) 23 | 24 | 25 | -------------------------------------------------------------------------------- /17-前端综合/ajax相关.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### jsonp ajax 4 | 5 | ajax跨域访问是一个老问题了,解决方法很多,比较常用的是JSONP方法,JSONP方法是一种非官方方法,而且这种方法只支持GET方式,不如POST方式安全。 6 | 7 | 意思是说,如果后台返回的数据类型是jsonp,那么前端的请求方式只能是get,不能是post。 8 | 9 | 如果跨域使用POST方式,可以使用创建一个隐藏的iframe来实现,与ajax上传图片原理一样,但这样会比较麻烦。 10 | 11 | 因此,在**前端使用post方法,数据类型是json**的情况下,如果想跨域的话,可以通过设置Access-Control-Allow-Origin来实现跨域访问比较简单。 12 | 13 | 14 | 15 | 参考链接: 16 | 17 | - [ajax 设置Access-Control-Allow-Origin实现跨域访问](https://blog.csdn.net/fdipzone/article/details/46390573/) 18 | 19 | 20 | -------------------------------------------------------------------------------- /16-前端进阶/09-lazyload&防抖动和节流阀.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## lazyload 5 | 6 | 用的最多的场景是: 7 | 8 | - 图片lazyload 9 | 10 | - 组件lazyload 11 | 12 | 现在一般都单独做css的lazyload或者js的lazyload,因为这种方式,其实还是要加载图片和组件。 13 | 14 | 15 | 16 | ### 图片lazyload 17 | 18 | 图片一般是页面最大的资源,所以**非首屏**延迟加载很重要(让首屏尽快显示)。 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ## 防抖动(Debouncing)和节流阀(Throtting) 31 | 32 | 33 | 34 | 35 | 参考链接: 36 | 37 | - [实例解析防抖动(Debouncing)和节流阀(Throttling)](http://www.css88.com/archives/7010) 38 | 39 | 40 | -------------------------------------------------------------------------------- /02-CSS基础/16-浏览器的兼容性问题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 我们在div里放一个img,发现: 4 | 5 | 在html和html5中,div的长宽是不同的,后者的高度要超过几个像素。 6 | 7 | 比如说,下面这个是html的。 8 | 9 | ```html 10 | 11 | 12 | 13 | 14 | Document 15 | 21 | 22 | 23 |
24 | 25 | 26 |
27 | 28 | 29 | ``` 30 | -------------------------------------------------------------------------------- /04-JavaScript基础/常见代码解读.md: -------------------------------------------------------------------------------- 1 | 2 | ### `callback && callback()`的含义 3 | 4 | ```javascript 5 | callback && callback() 6 | ``` 7 | 8 | 9 | 含义是:如果callback存在,则执行callback()函数。 10 | 11 | 这个 callback 通常作为函数的参数使用。举例: 12 | 13 | 14 | ```javascript 15 | function foo(callback) { 16 | { 17 | // do something 18 | } 19 | callback && callback() // 不传 callback 参数,则不会执行 callback() 函数 20 | } 21 | 22 | foo(); // 只执行do something中的代码 23 | foo(callback);//callback是另一个函数,将此函数传入 foo,将会执行callback() 24 | ``` 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /16-前端进阶/Vue开发积累.md: -------------------------------------------------------------------------------- 1 | 2 | ## Vue 开发积累 3 | 4 | 5 | ### 001:scoped 关键字的作用 6 | 7 | 在 `xx.vue` 组件中,我们可能会遇到带 `scoped` 关键字的样式。比如: 8 | 9 | ```html 10 | 11 | 27 | ``` 28 | 29 | 30 | 上方的`scoped`表示的是**作用域化**,样式只对当前子组件生效。 31 | 32 | -------------------------------------------------------------------------------- /18-推荐链接/2019-推荐文章.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 记录平时遇到的优质技术文章,按时间先后排序。 6 | 7 | ## 内容 8 | 9 | ### 2019-05-11 10 | 11 | - 《[博客园美化教程大集合----极致个性化你的专属博客(超详细,看这篇就够了)](https://www.cnblogs.com/shwee/p/9060226.html#dingzhi12)》 12 | 13 | 网上写图文教程的人,还真是贴心。 14 | 15 | 16 | ### 2019-09-06 17 | 18 | - [https://www.yuque.com/sxc/front/kvokg4](https://www.yuque.com/sxc/front/kvokg4) 19 | 20 | 作者在语雀上的系列文章,都值得一看。 21 | 22 | ### 2019-10-05 23 | 24 | - [前端学习网站和资源推荐](https://www.twblogs.net/a/5d400329bd9eee51fbf962b2) 25 | 26 | 作者整理的一些基础性的学习资源,还可以。 27 | 28 | -------------------------------------------------------------------------------- /18-推荐链接/03-网站推荐.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ### 2018-10-26 6 | 7 | - 前端面试图谱: 8 | 9 | 这个项目已经很全面了,是从面试的角度出发的。我自己的项目是,是从基础入门的角度出发的。可以起到互补的作用。 10 | 11 | 12 | 13 | ### 2018-12-07 14 | 15 | - css的各种效果实现: 16 | 17 | css的各种效果实现(尤其是动画效果),关键时刻能救命。作者内化后输出,并贡献出来。这种也是颇为难得了。很有极客精神。 18 | 19 | 比如,我在这里面找到了「抖动效果」,很有帮助。 20 | 21 | 22 | ### 2018-12-17 23 | 24 | - github排行: 25 | 26 | ### 2019-10-05 27 | 28 | - 现代 JavaScript 教程: 29 | 30 | 31 | -------------------------------------------------------------------------------- /14-前端面试/15-虚拟DOM.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | 7 | vdom 是 vue 和 React 的**核心**,先讲哪个都绕不开它。 8 | 9 | vdom 比较独立,使用也比较简单。 10 | 11 | 如果面试问到 vue 和 React 和实现,免不了问 vdom: 12 | 13 | - vdom 是什么?为何会存在 vdom? 14 | 15 | - vdom 的如何应用,核心 API 是什么 16 | 17 | - 介绍一下 diff 算法 18 | 19 | 20 | ## 什么是 vdom 21 | 22 | 23 | ### 什么是 vdom 24 | 25 | DOM操作是昂贵的。 26 | 27 | 步骤一:用JS对象模拟DOM树 28 | 29 | 步骤二:比较两棵虚拟DOM树的差异 30 | 31 | 步骤三:把差异应用到真正的DOM树上 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /15-面试题积累/异步.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 面试题 4 | 5 | ### 20180321面试题 6 | 7 | ```javascript 8 | console.log(1); 9 | 10 | setTimeout(function () { 11 | console.log(2); 12 | }, 1000); 13 | 14 | setTimeout(function () { 15 | console.log(3); 16 | }, 0); 17 | 18 | console.log(4); 19 | ``` 20 | 21 | 22 | 23 | ### 20180321面试题 24 | 25 | ```javascript 26 | var arr = [1, 2, 3]; 27 | for (var i = 0; i < arr.length; i++) { 28 | setTimeout(function () { 29 | console.log(i); 30 | }, 0); 31 | } 32 | ``` 33 | 34 | 打印结果:3,3,3 35 | 36 | -------------------------------------------------------------------------------- /12-Vue基础/Vue.js在开发中的常见写法积累.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### 001、对象的赋值 4 | 5 | (1)在 store 中定义一个对象: 6 | 7 | ```javascript 8 | userInfo: { 9 | pin: '', 10 | nickName: '', 11 | avatarUrl: DEFAULT_AVATAR, 12 | definePin: '', 13 | isbind: true 14 | }, 15 | ``` 16 | 17 | (2)从接口拿到数据后,给这个对象赋值: 18 | 19 | ```javascript 20 | this.userInfo = { 21 | ...this.userInfo, 22 | pin: res.base.curPin, 23 | nickName: res.base.nickname, 24 | avatarUrl: res.base.headImageUrl ? res.base.headImageUrl : DEFAULT_AVATAR, 25 | definePin: res.definePin 26 | } 27 | ``` -------------------------------------------------------------------------------- /04-JavaScript基础/20-作用域链.md: -------------------------------------------------------------------------------- 1 | 2 | ## 一些概念 3 | 4 | ### 作用域和作用域链 5 | 6 | **作用域**: 7 | 8 | 每个 JS 函数都是一个对象,对象中有些属性我们可以访问,有些属性我们不可以访问。无法访问的这些属性仅供 JS 引擎存取,[[scope]] 属性就是其中之一。 9 | 10 | [[scope]]就是我们所说的作用域,其中存储了执行期上下文的集合。 11 | 12 | 13 | 14 | **作用域链**: 15 | 16 | [[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。 17 | 18 | 19 | ### 执行期上下文 20 | 21 | 当**函数执行**时(准确来说,是在函数发生预编译的前一刻),会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境。 22 | 23 | 每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立且独一无二的。当函数执行完毕,它所产生的执行期上下文会被销毁。 24 | 25 | ## 最后一段 26 | 27 | 备注:本文的内容还有待完善。 28 | 29 | 30 | 31 | ## 参考链接 32 | 33 | - 34 | 35 | 36 | -------------------------------------------------------------------------------- /14-前端面试/11-00.JavaScript高级面试:前言.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | 一、基础知识: 7 | 8 | - ES 6常用语法:class 、module、Promise等 9 | 10 | - 原型高级应用:结合 jQuery 和 zepto 源码 11 | 12 | - 异步全面讲解:从原理到 jQuery 再到 Promise 13 | 14 | 二、框架原理: 15 | 16 | - 虚拟DOM:存在价值、如何使用、diff算法 17 | 18 | - MVVM vue:MVVM、vue响应式、模板解析、渲染 19 | 20 | - 组件化 React:组件化、JSX、vdom、setState 21 | 22 | 三、混合开发: 23 | 24 | - hybrid 25 | 26 | - H5 27 | 28 | - 前端客户端通讯 29 | 30 | 31 | 内容优势 32 | 33 | - 面试官爱问“源码”、“实现”。 34 | 35 | - 介绍常用框架实现原理 36 | 37 | - 介绍hybrid原理和应用 38 | 39 | 40 | 41 | 42 | ## ES6 43 | 44 | 45 | - 模块化的使用和编译环境 46 | 47 | - Class与JS构造函数的区别 48 | 49 | - Promise的用法 50 | 51 | - ES6其他常用功能 52 | 53 | ## 异步 54 | 55 | 56 | - 什么是单线程,和异步有什么关系 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /17-前端综合/html相关.md: -------------------------------------------------------------------------------- 1 | 2 | ## SSI:服务器端嵌入 3 | 4 | SSI:Server Side Include,服务器端嵌入。 5 | 6 | 通俗点讲,就是在本地的html页面中,插入服务器上的文件。即:静态页面中,插入动态的代码。 7 | 8 | 比如: 9 | 10 | ```html 11 | 12 | 13 | 14 | 15 | Document 16 | 19 | 20 | 21 | 22 | 23 | ``` 24 | 25 | 上面的代码中,注释里的代码,就是SSI部分,它加载的是服务器端的html页面。 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /16-前端进阶/02-数组的常见操作.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前言 3 | 4 | 数组在实战开发中,使用得相当频繁。前端同学通过接口拿到json数据后,往往需要把数据进行各种形式的变换和展示。这个时候,数组的常见操作,就发挥了很大的作用。 5 | 6 | 如果你对数组的基础知识不太熟悉,建议回去看看`03-JavaScript`的基础知识。 7 | 8 | 掌握了基础知识之后,我们再来看看,实战开发中,数组都有哪些常见操作。 9 | 10 | ## 数组的常见操作 11 | 12 | ### 从对象数组中,将属性的值提取为数组 13 | 14 | 一般人可能会想着通过 for 循环进行遍历,但这种做法不够简洁。 15 | 16 | 最佳答案: 17 | 18 | ```javascript 19 | const arr1 = [ 20 | { skuId: "123", name: "商品1" }, 21 | { skuId: "456", name: "商品2" }, 22 | { skuId: "789", name: "商品3" } 23 | ]; 24 | 25 | const skuIdArr = arr1.map(item => item.skuId); // 将数组 arr1 中的 skuId字段提取为一个新的数组 26 | console.log(JSON.stringify(skuIdArr)); 27 | ``` 28 | 29 | 30 | 打印结果: 31 | 32 | ```json 33 | ["123","456","789"] 34 | ``` 35 | 36 | 37 | - 参考链接: -------------------------------------------------------------------------------- /14-前端面试/23-面试技巧 by smyhvae.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 写简历的注意事项 5 | 6 | - 最多可以写“深入了解”,但不要写“精通”。 7 | 8 | 9 | ## 遇到不知道的问题,该怎么回答 10 | 11 | - 这块儿我没了解过,准备回去看一下。 12 | 13 | - 这块儿我没研究过,您有没有好的资料,我可以补充一下细节。 14 | 15 | - 写不出详细的代码,但是知道思路。 16 | 17 | 18 | 19 | ## 项目经历 20 | 21 | 22 | - 面试要体现项目的设计思路、方案设计等 23 | 24 | 25 | 26 | ## 模块化思维 27 | 28 | 29 | 30 | 31 | (1)模块化设计的关键词:**封装、继承**;把**通用**的模块**先抽象,后具体**,达到**复用**。【面试记住】 32 | 33 | 比如,**panel、按钮、轮播图**、列表等等,都可以提取为**抽象**的组件,复用。 34 | 35 | (2)页面有哪几个模块 36 | 37 | (3)每个模块分成不同的文件,然后在index页面中import。 38 | 39 | 40 | 41 | 42 | 43 | ## ES6新特性 44 | 45 | - let、const 46 | 47 | - 函数扩展:参数默认值、箭头函数、扩展运算符`...` 48 | 49 | - for ... of 循环 50 | 51 | - map 52 | 53 | - 模块化 54 | 55 | 56 | 57 | ## 薪资 58 | 59 | 面试官;"你要求多少薪资?" 60 | 61 | 我:“能给个范围吗?” 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /04-JavaScript基础/00-编程语言.md: -------------------------------------------------------------------------------- 1 | 2 | ## 编程语言 3 | 4 | ### 编程 5 | 6 | **编程**:让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程。 7 | 8 | **计算机程序**:就是计算机所执行的一系列的**指令集合**,而程序全部都是用我们所掌握的语言来编写的,所以人们如果要控制计算机,则需要通过计算机语言向计算机发出命令。 9 | 10 | ### 计算机语言 11 | 12 | **计算机语言**:人与计算机之间通讯的语言。它是人与计算机之间传递信息的媒介,是用来控制计算机的一系列指令。 13 | 14 | 计算机语言的种类非常的多,总的来说可以分成三大类:机器语言、汇编语言和高级语言。 15 | 16 | 计算机最终所执行的都是机器语言,它是由“0”和“1”组成的二进制数,二进制是计算机语言的基础。 17 | 18 | ### 编程语言 19 | 20 | 通过类似于人类语言的 ”语言”来控制计算机,让计算机为我们做事情,这样的语言就叫做编程语言。不同的编程语言,有不同的语法,必须遵守。 21 | 22 | 如今通用的编程语言有两种形式:汇编语言和高级语言。 23 | 24 | - **汇编语言**:与机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。 25 | 26 | - **高级语言**:主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,比如:C语言、C++、Java、C#、PHP、JavaScript、Python、Objective-C、Swift、Go语言等。 27 | 28 | ### 编译器 29 | 30 | 高级语言所编写的程序不能直接被计算机识别,必须经过转换才能被执行,为此,我们需要一个编译器。 31 | 32 | 编译器可以将我们所编写的源代码转换(翻译)为机器语言,这也被称为二进制化。 33 | 34 | 35 | -------------------------------------------------------------------------------- /14-前端面试/22-网友面经.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ### 2018-03-08 5 | 6 | - [jawil | 一年经验初探阿里巴巴前端社招](https://github.com/jawil/blog/issues/22) 7 | 8 | 9 | 此博主的博客签名: 10 | 11 | 20180308_1703.png 12 | 13 | 14 | - [2017我遇到的前端面试题](https://blog.dunizb.com//2017/09/08/interview-questions-2017/) 15 | 16 | 作者整理的这些题目,很多是来自面试跳槽的视频。非常推荐。 17 | 18 | 作者说,性能优化和ES6,是必问的。 19 | 20 | 21 | 22 | - [2018年web前端经典面试题及答案](https://www.cnblogs.com/wdlhao/p/8290436.html) 23 | 24 | 写得很长啊。 25 | 26 | 27 | ### 2018-03-11 28 | 29 | - [2017年BAT面试题大全集](http://www.bijishequ.com/detail/421600?p=) 30 | 31 | - [bat前端面试内容记录](https://www.jianshu.com/p/d94d5290328c) 32 | 33 | 34 | 35 | ### 2018-03-18 36 | 37 | - [笔记:阿里、网易、滴滴共十次前端面试碰到的问题](https://zhoukekestar.github.io/notes/2017/06/07/interview-answers.html) 38 | 39 | - [笔记补充:阿里、网易、滴滴共十次前端面试碰到的问题](https://zhoukekestar.github.io/notes/2017/07/06/interview-answers.html) 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /14-前端面试/z-推荐文章.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 征服JavaScript面试系列 | 众城翻译 4 | 5 | 6 | - [征服 JavaScript 面试:什么是闭包?](http://www.zcfy.cc/article/master-the-javascript-interview-what-is-a-closure) 7 | 8 | - [征服 JavaScript 面试:什么是函数组合](http://www.zcfy.cc/article/master-the-javascript-interview-what-is-function-composition) 9 | 10 | - [征服JavaScript面试系列:类继承和原型继承的区别](http://www.zcfy.cc/article/master-the-javascript-interview-what-s-the-difference-between-class-amp-prototypal-inheritance-2185.html) 11 | 12 | - [征服 JavaScript 面试:什么是纯函数](http://www.zcfy.cc/article/master-the-javascript-interview-what-is-a-pure-function-2186.html) 13 | 14 | - [征服 JavaScript 面试: 什么是函数式编程?](http://www.zcfy.cc/article/master-the-javascript-interview-what-is-functional-programming-2221.html) 15 | 16 | - [征服 JavaScript 面试: 什么是 Promise?](http://www.zcfy.cc/article/master-the-javascript-interview-what-is-a-promise) 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /18-推荐链接/深圳有哪些IT互联网大厂.md: -------------------------------------------------------------------------------- 1 | 2 | ## 深圳IT互联网大厂有哪些(2019年版) 3 | 4 | ### 一线大厂 5 | 6 | - 腾讯 7 | 8 | - 华为 9 | 10 | - 阿里(深圳) 11 | 12 | - 百度(深圳) 13 | 14 | - 京东(深圳) 15 | 16 | - 头条(深圳) 17 | 18 | ### 二线大厂 19 | 20 | - 大疆 21 | 22 | - oppo(深圳) 23 | 24 | - 顺丰 25 | 26 | - 微众银行 27 | 28 | - 平安系列(平安科技、平安寿险、平安产险、平安金融等,各自独立,可分开投简历) 29 | 30 | ### 独角兽公司 31 | 32 | - 商汤科技(人工智能领域的独角兽) 33 | 34 | - 超级猩猩(运动健身领域的独角兽) 35 | 36 | ### 三线大厂 37 | 38 | - Shopee(中文名“虾皮”,东南亚最大的电商平台) 39 | 40 | - 有赞(深圳) 41 | 42 | - 中兴 43 | 44 | - 海能达(专网通信领域全国第一、全球第二,仅次于摩托罗拉) 45 | 46 | - 金蝶、随手记(随手记属于金蝶旗下,但可以分开投简历) 47 | 48 | - vivo 49 | 50 | - 迅雷 51 | 52 | - 卷皮网 53 | 54 | ### 互联网金融 55 | 56 | - 乐信 57 | 58 | - 广发 59 | 60 | - 中信 61 | 62 | - 招商 63 | 64 | ### 其他 65 | 66 | - 珍爱网(福利好,但招人少) 67 | 68 | - shein(跨境时尚电商) 69 | 70 | ### 传统行业(不仅限于IT领域) 71 | 72 | - 三大电信运营商:中国移动、中国电信、中国联通 73 | 74 | - 恒大、万科 75 | 76 | - 万师傅(行业领先家居服务平台) 77 | 78 | -------------------------------------------------------------------------------- /12-Vue基础/Vue开发积累.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ### 动态添加对象的属性 5 | 6 | - Vue中,动态新增对象的属性时,不能直接添加。正确的做法是:Vue.set(obj,key,value)。参考链接:[#](https://blog.csdn.net/tian361zyc/article/details/72909187) 7 | 8 | 9 | 10 | 11 | ### 判断一个checkbox是否被选中 12 | 13 | ```html 14 | 15 | 16 | 17 | 18 | {{isSelected}} 19 | 20 | 21 | 22 | haha 23 | 24 | ``` 25 | 26 | 27 | 28 | ### 多个checkbox的全选和反选 29 | 30 | 现在有多个checkbox的item在一个数组中,另外还有一个“全选”的checkbox按钮。 31 | 32 | **点击全选按钮,让子item全部选中**: 33 | 34 | 采用 watch 监听全选按钮,然后改变子item。 35 | 36 | **当子item全部被选中时,触发全选按钮**: 37 | 38 | 采用 computed 计算子item 的状态,存放到变量 allChecked 中,然后用 watch 监听 allChecked 的值。 39 | 40 | 参考链接: 41 | 42 | - [问Vue.js 如何在 data 里含数组的情况下,监听数组内指定属性的变化?](https://segmentfault.com/q/1010000014514160/a-1020000014514452) 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 项目介绍 3 | 4 | 项目地址: 5 | 6 | 前端入门和进阶学习笔记。从零开始学前端,做一名精致的前端工程师。持续更新中。本项目的主要作用有: 7 | 8 | 9 | - 网上的大部分入门教程,都不太适合初学者,本项目争取照顾到每一位入门者的同理心。 10 | 11 | - 帮助前端同学提供一个精品学习路线和资源,提高学习效率,少走很多弯路。 12 | 13 | - 可以当做前端字典,随时翻阅,查漏补缺。 14 | 15 | 16 | 维护这个项目的初衷,可以看这篇文章:[《裸辞两个月,海投一个月,从Android转战Web前端的求职之路》](https://www.cnblogs.com/qianguyihao/p/8732781.html) 17 | 18 | 前端入门路线和推荐学习资源,可以看这篇文章:[《2019年Web前端入门的自学路线》](https://www.cnblogs.com/qianguyihao/p/8776837.html) 19 | 20 | ## 项目指引 21 | 22 | 如果你发现文中的部分图片加载不出来,不妨[看这里](https://github.com/qianguyihao/Web/issues/20#issue-390074432)。当然,您也可以直接「下载项目到本地」,通过 markdown 软件(比如 typora)打开项目文件,以便正常展示图片。 23 | 24 | 如果你发现本项目有内容上的错误,欢迎提交 issues 进行指正。 25 | 26 | ## 学习交流 27 | 28 | 我建了一个“前端学习”的微信交流群,目前来看,学习氛围很不错。在下方公众号里回复「前端学习」,拉你进群: 29 | 30 | - 进群暗号:前端学习。 31 | 32 | - 进群要求:少提问、少闲聊、多分享(长期潜水的,就不必了)。 33 | 34 | 关注微信公众号「**千古壹号**」,学习代码之外的技能。扫一扫,你将发现一个全新的世界,而这将是一场美丽的意外: 35 | 36 | ![](http://img.smyhvae.com/20190101.png) 37 | 38 | 39 | -------------------------------------------------------------------------------- /03-CSS进阶/01-CSS中的非布局样式.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前言 3 | 4 | CSS中,有很多**非布局样式**,这些样式(属性)和与布局无关,包括: 5 | 6 | - 字体、字重、颜色、大小、行高 7 | - 背景、边框 8 | - 滚动、换行 9 | - 装饰性属性(粗体、斜体、下划线)等。 10 | 11 | 这篇文章,我们来对上面的部分样式做一个回顾。 12 | 13 | ## 边框 14 | 15 | 如何用边框画一个三角形?详见《02-CSS基础/06-CSS盒模型详解》中的最后一段。 16 | 17 | ## 文字换行 18 | 19 | - ovferflow-wrap:通用的属性。用来说明当一个不能被分开的字符串(单词)太长而不能填充其包裹盒时,为防止其溢出,浏览器是否允许这样的单词**中断换行**。 20 | 21 | - word-break:指定了怎样在单词内断行。这里涉及到CJK(中文/日文/韩文)的文字换行。 22 | 23 | - white-space:空白处是否换行。 24 | 25 | 上面这三个 css 属性进行组合,可以设置各种不同的属性。 26 | 27 | 当然,如果想让一段很长的文本不换行,可以直接设置`white-space: nowrap` 这一个属性即可。 28 | 29 | ## CSS Hack 30 | 31 | - CSS Hack 的方式:不合法但可以生效的写法。 32 | 33 | - 可以用来解决一些浏览器的兼容性问题。 34 | 35 | - 缺点:难理解、难维护、易失效(比如浏览器升级后,hack可能会失效)。 36 | 37 | - 替代方案:特性检测。 38 | 39 | - 替代方案:针对性加 class 40 | 41 | 42 | ## CSS 效果 43 | 44 | 我们可以利用 CSS 实现各种效果,常见的效果属性有: 45 | 46 | - box-shadow:盒子的阴影 47 | 48 | - text-shadow:文本的阴影 49 | 50 | - border-radius 51 | 52 | - background 53 | 54 | - clip-path 55 | 56 | 57 | -------------------------------------------------------------------------------- /13-React基础/10-React Navive初识.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 搭建开发环境 4 | 5 | 官方文档: 6 | 7 | ### 安装Node、homebrew、Watchman 8 | 9 | 安装 homebrew: 10 | 11 | ``` 12 | 13 | ``` 14 | 15 | 安装 watchman: 16 | 17 | ``` 18 | brew install watchman 19 | ``` 20 | 21 | 22 | Watchman则是由 Facebook 提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager 可以快速捕捉文件的变化从而实现实时刷新)。 23 | 24 | 25 | 26 | ### 安装 React Native 的命令行工具(react-native-cli) 27 | 28 | 安装 react-native-cli: 29 | 30 | ``` 31 | npm install -g react-native-cli 32 | ``` 33 | 34 | 35 | React Native 的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务。 36 | 37 | ### 创建新项目 38 | 39 | ``` 40 | react-native init MyApp --version 0.44.3 41 | ``` 42 | 43 | ### 编译并运行 React Native 应用 44 | 45 | 在 ios 模拟器上运行: 46 | 47 | ``` 48 | react-native run-ios 49 | ``` 50 | 51 | ## 调试 52 | 53 | 官网文档: 54 | 55 | 56 | ### 访问 App 内的开发菜单 57 | 58 | 如果是在 iOS 模拟器中运行,还可以按下`Command + D`快捷键,Android 模拟器对应的则是Command⌘ + M(windows 上可能是 F1 或者 F2),或是直接在命令行中运行adb shell input keyevent 82来发送菜单键命令。 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /12-Vue基础/07-Vue-router路由.md: -------------------------------------------------------------------------------- 1 | 2 | ## 什么是路由 3 | 4 | 5 | ### 后端路由 6 | 7 | 对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源。 8 | 9 | 当前端输入url请求资源时,服务器会监听到是什么url地址,那后端会返回什么样的资源呢?后端这个处理的过程就是通过**路由**来**分发**的。 10 | 11 | **总结**:后端路由,就是把所有url地址都对应到服务器的资源,这个**对应关系**就是路由。 12 | 13 | ### 前端路由 14 | 15 | 对于单页面应用程序来说,主要通过URL中的`hash`(url地址中的#号)来实现不同页面之间的切换。 16 | 17 | 同时,hash有一个特点:HTTP请求中不会包含hash相关的内容。所以,单页面程序中的页面跳转主要用hash实现。 18 | 19 | **总结**:在**单页应用**程序中,这种通过`hash`改变来**切换页面**的方式,称作前端路由(区别于后端路由)。 20 | 21 | ## 安装Vue-router的两种方式 22 | 23 | - 官方文档: 24 | 25 | 26 | **方式一**:直接下载文件 27 | 28 | 下载网址: 29 | 30 | 31 | 下载之后,放进项目工程,然后我们在引入`vue.js`之后,再引入`vue-router.js`即可: 32 | 33 | ```html 34 | 35 | 36 | ``` 37 | 38 | 39 | 然后,我们就可以在 window全局对象中使用 VueRouter这个对象。具体解释可以看接下来的代码中的注释。 40 | 41 | 注意,只要我们导入了`vue-router.js`这个包,在浏览器中打开网页时,url后面就会显示`#`这个符号。 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /17-前端综合/前端开发积累.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### SPU 和 SKU 4 | 5 | 6 | SKU(stock keeping unit):库存量单位。 SKU是物理上不可分割的最小库存单元。通俗来讲,你可以把 sku 理解成是「**最小单元**」。 7 | 8 | SPU(Standard Product Unit):标准化产品单元。是商品信息聚合的最小单位。通俗来讲,你可以把 spu 理解成是「**某一类的单元**」。 9 | 10 | 比如说,针对 Kindle paperwhite4 这款阅读器,颜色分白色、黑色两种。那么,白色和黑色的sku是不一样的。因此,Kindle paperwhite4 这款阅读器有「**两个sku、一个spu**」。 11 | 12 | 再比如说,针对 iPhone 8 这款手机,颜色有银色、红色、金色三种,存储空间有分64G、256G两种。那么,64G和256G的sku是不一样的;不同的颜色,也代表着不同的sku。因此,iPhone 8 这款手机有「**六个sku、一个spu**」。 13 | 14 | 单品:对一种商品而言,当其品牌、型号、配置、等级、花色、包装容量、单位、生产日期、保质期、用途、价格、产地等属性中任一属性与其他商品存在不同时,可称为一个单品。 15 | 16 | ### 移动端WebApp前端真机调试:iPhone/iOS借助Safari进行真机调试 17 | 18 | (1)手机端:设置 → Safari → 高级 → Web 检查器 → 开。 19 | 20 | (2)mac端:Safari → 偏好设置 → 高级 → 在菜单栏中显示“开发”菜单。 21 | 22 | (3)在 OS X 中启动 Safari 之后,以 USB 电缆正常接入 iOS 设备,并在此移动设备上启动 Safari。此时点击计算机上的 Safari 菜单中的“开发”,可以看到有 iOS 设备的名称显示,其子菜单项即为移动设备上 Safari 的所有标签页,点击任意一个开始调试。如下: 23 | 24 | ![](http://img.smyhvae.com/20180621_1900.png) 25 | 26 | 参考链接: 27 | 28 | - [移动端前端开发真机调试攻略](https://juejin.im/entry/563ab66400b0bf37d79aa17d) 29 | 30 | - [iOS、Android 之类的如何调试 Web APP](https://segmentfault.com/q/1010000000124121) 31 | 32 | -------------------------------------------------------------------------------- /03-CSS进阶/00-准备.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前言 3 | 4 | css 进阶的主要内容如下。 5 | 6 | ### 1、css 非布局样式 7 | 8 | - html 元素的分类和特性 9 | 10 | - css 选择器 11 | 12 | - css 常见属性(非布局样式) 13 | 14 | ### 2、css 布局相关 15 | 16 | - css 布局属性和组合解析 17 | 18 | - 常见布局方案 19 | 20 | - 三栏布局案例 21 | 22 | ### 3、动画和效果 23 | 24 | > 属于 css 中最出彩的内容。 25 | 26 | - 多背景多投影特效 27 | 28 | - 3D特效编写实践 29 | 30 | - 过渡动画和关键帧动画实践 31 | 32 | - 动画细节和原理深入解析 33 | 34 | ### 4、框架集成和 css 工程化 35 | 36 | - 预处理器作用和原理 37 | 38 | - less/sass 代码实践 39 | 40 | - Bootstrap 原理和用法 41 | 42 | - css 工程化的的实践方式 43 | 44 | - js 框架中的 css 集成实践 45 | 46 | ## 常见问题 47 | 48 | > 不会 css 的前端称之为伪前端。 49 | 50 | ### Vue 中模拟Scoped CSS的方式 51 | 52 | 方案一:随机选择器。css modules。 53 | 54 | 方案二:**随机属性**。`
`、`div[adcd]{}` 55 | 56 | ### 其他问题 57 | 58 | - html 元素的嵌套关系是怎么确定的?哪些嵌套不可以发生? 59 | 60 | - 比如说,为什么 div 可以放在 a 标签里面? 61 | 62 | - css 选择器的权重是如何计算的?写代码时要注意什么? 63 | 64 | - 浮动布局是怎么回事?有什么优缺点?国内用的多吗? 65 | 66 | - css 可否做逐帧动画吗?性能如何? 67 | 68 | - Bootstrap 怎么做响应式布局? 69 | 70 | - 如何解决 css 模块化过程中的选择器互相干扰的问题? 71 | 72 | ## 总结 73 | 74 | 单独看 css 属性并不难,难的是需要把这些思路和思想,想到它的应用场景。 75 | 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 千古壹号 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /00-前端工具/whistle网络抓包.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 手机设置代理 4 | 5 | 连接好指定的wifi后,点击那个wifi里的设置,将「代理」那一项,设置为手动,然后输入ip(电脑上的ip)、端口号(8899)。然后就可以通过电脑上的whistle工具,查看手机的网页请求。 6 | 7 | 注意,要保证手机和电脑在同一个网络下。 8 | 9 | 10 | 11 | ## 捕获和拦截https请求 12 | 13 | 14 | whistle安装证书后,可以拦截 https 请求。但是,我现在又不想拦截https请求了,该怎么卸载证书呢? 15 | 16 | 我发现,证书无法卸载,正确的操作是: 17 | 18 | ![](http://img.smyhvae.com/20180426_1621.png) 19 | 20 | 上图中,把红框部分,去掉勾选,就不捕获https了。谢谢azh童鞋。 21 | 22 | 23 | 24 | 参考链接: 25 | 26 | - [Android 手机如何设置http代理?](https://www.zhihu.com/question/21474174) 27 | 28 | - [使用 Whistle 对 iOS HTTPS 进行抓包](http://zhuscat.com/2017/09/20/https-proxy-on-ios/) 29 | 30 | 31 | 32 | ## 移动端调试神器:eruda 33 | 34 | 35 | > 手机连接代理时,如何看console.log的日志信息? 36 | 37 | > 现在,代码里有console.log,如果是在电脑浏览器上看,可以直接在控制台查看console.log的内容。但是,如果手机连接代理,在手机上打开网页的话,要怎么查看console.log的内容呢?具体做法如下: 38 | 39 | (1)在 whistle中,新建一个名叫`Eruda H5`的代理,代理中的内容是: 40 | 41 | ``` 42 | http://xxx.com htmlAppend://{eruda.html} 43 | ``` 44 | 45 | 46 | (2)新建一个values,里面的内容是: 47 | 48 | ```html 49 | 50 | 53 | ``` 54 | 55 | 56 | 然后就OK了。 57 | 58 | -------------------------------------------------------------------------------- /03-CSS进阶/CSS开发积累.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### 让文字只显示一行,超出显示省略号 4 | 5 | ``` 6 | overflow: hidden; 7 | white-space: nowrap; 8 | text-overflow: ellipsis; 9 | 10 | ``` 11 | 12 | 13 | ### 让文字最多只显示两行,超出后显示省略号 14 | 15 | ``` 16 | overflow:hidden; 17 | text-overflow:ellipsis; 18 | display:-webkit-box; 19 | -webkit-box-orient:vertical; 20 | -webkit-line-clamp:2; 21 | ``` 22 | 23 | ### 问题描述:文本内容里自带了换行,但是在前端没有展示出来 24 | 25 | 解决办法:增加如下属性即可。 26 | 27 | ``` 28 | white-space:pre-wrap; 29 | ``` 30 | 31 | 32 | ### 2019-11-12-CSS的逗号和空格 33 | 34 | CSS的逗号一般写在()里。**不同属性值之间,用的是空格**,不是逗号。比如: 35 | 36 | ```css 37 | transform: translate(-50%, -50%); /* 这种写逗号 */ 38 | transform: translate(-50%, -50%) scale(0.5); /* 不同属性值之间,用的是空格 */ 39 | 40 | background-size: 100% 100%; /* 这里是空格,不是逗号 */ 41 | ``` 42 | 43 | 44 | ### 2019-11-01 45 | 46 | 价格中的羊角符号,有半角和全角之分: 47 | 48 | - ¥半角 49 | 50 | - ¥全角 51 | 52 | 可以看出,半角的宽度更小。考虑到容器的空间一般比较紧张,所以推荐使用**半角**。 53 | 54 | 55 | ### 2019-11-19-鼠标悬停时,弹出提示文字 56 | 57 | 参考链接:[css实现鼠标悬浮后的提示效果](https://www.cnblogs.com/zhaojian-08/p/10074660.html) 58 | 59 | 60 | ### 2019-11-27-图片的宽度固定,高度自适应 61 | 62 | 这个场景下,别用background。直接放img元素就好了,将图片的高度设置为`auto`。 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /15-面试题积累/03-http.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## HTTP 状态码知道哪些? 4 | 5 | 301 和 302 的区别: 6 | 7 | - 301 永久重定向,浏览器会记住(有缓存) 8 | 9 | - 302 临时重定向(无缓存) 10 | 11 | 12 | ## HTTP 缓存怎么做? 13 | 14 | 强缓存: 15 | 16 | - **`Expires`**或**`Cache-Control`** 17 | 18 | 协商缓存: 19 | 20 | - 第一对:`Last-Modified`、`If-Modified-Since` 21 | 22 | - 第二对:`ETag`、`If-None-Match` 23 | 24 | 25 | ## Cookie 是什么?Session 是什么? 26 | 27 | ### Cookie 28 | 29 | - HTTP响应通过 Set-Cookie 设置 Cookie 30 | 31 | - 浏览器访问指定域名是必须带上 Cookie 作为 Request Header 32 | 33 | - Cookie 一般用来记录用户信息 34 | 35 | ### Session 36 | 37 | - Session 是服务器端的内存(数据) 38 | 39 | - session 一般通过在 Cookie 里记录 SessionID 实现 40 | 41 | - SessionID 一般是随机数 42 | 43 | 44 | ## LocalStorage 和 Cookie 的区别是什么? 45 | 46 | - Cookie 会随请求被发到服务器上,而 LocalStorage 不会 47 | 48 | - Cookie 大小一般4k以下,LocalStorage 一般5Mb 左右 49 | 50 | ## GET 和 POST 的区别是什么? 51 | 52 | GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。 53 | 54 | 55 | 需要注意的是,web 中的 get/post 只是 http 中的 get/post 的子集。http 中的 get 与 post 只是单纯的名字上的区别,get 请求的数据也可以放在 request body 中,只是浏览器没有实现它,但是 get 并不只是在 web 中使用 56 | 57 | 58 | 参考链接: 59 | 60 | - 61 | 62 | - 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /15-面试题积累/面经链接推荐.md: -------------------------------------------------------------------------------- 1 | 2 | ### 2018-01-25 3 | 4 | 5 | 6 | - [有时在面试时,我都替候选人着急——候选人完全可以在面试前准备](https://www.cnblogs.com/JavaArchitect/p/8353578.html) 7 | 8 | ### 2018-01-26 9 | 10 | - [转眼人到中年:前端老程序员无法忘怀的一次百度电话面试](https://www.cnblogs.com/chyingp/p/a-telephone-interview-long-age.html) 11 | 12 | 八年前的面经,咋记得这么清楚? 13 | 14 | 15 | ### 2018-01-27 16 | 17 | - [16年毕业的前端er在杭州求职ing](https://www.cnblogs.com/qianduantuanzhang/archive/2018/01/27/8365670.html) 18 | 19 | 20 | ### 2018-02-04 21 | 22 | - [2018秋招前端总结](https://www.cnblogs.com/Mr-stockings/archive/2018/02/02/8407295.html) 23 | 24 | 25 | 26 | 27 | ### 2018-02-25 28 | 29 | - [前端开发面试题(CSS)](http://www.bijishequ.com/detail/379621) 30 | 31 | - [超过20家的前端面试题](https://www.jianshu.com/p/8b68f4df749e) 32 | 33 | 34 | - [来聊聊前端工程师的面试套路](https://baijiahao.baidu.com/s?id=1570338146494165&wfr=spider&for=pc) 35 | 36 | - [我的前端进阶之路(面试题)](https://www.cnblogs.com/libin-1/p/6864344.html) 37 | 38 | 这几个链接里讲到了 less。听说面试爱问 less 和 Sass的区别。 39 | 40 | 41 | 42 | 43 | 44 | ### 2018-03-02 45 | 46 | - [记录前端的面试日常(持续更新)](https://www.cnblogs.com/fangdongdemao/p/8492563.html) 47 | 48 | 49 | 50 | ### 2018-03-06 51 | 52 | - [我遇到的前端面试题2017](https://segmentfault.com/a/1190000011091907) 53 | 54 | 55 | 里面有很多面试跳槽里的内容。 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /14-前端面试/11-01.ES6:模块化的使用和编译环境.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | ### ES6的主要内容 7 | 8 | - 模块化的使用和编译环境 9 | 10 | - Class与JS构造函数的区别 11 | 12 | - Promise的用法 13 | 14 | - ES6其他常用功能 15 | 16 | 本文来讲“模块化的使用和编译环境”。 17 | 18 | ### 面试常见问题 19 | 20 | - ES6 模块化如何使用,开发环境如何打包 21 | 22 | - Class 和普通构造函数有何区别 23 | 24 | - Promise 的基本使用和原理 25 | 26 | - 总结一下 ES6 其他常用功能 27 | 28 | 29 | ### ES6的现状 30 | 31 | - 开发环境已经普及使用 32 | 33 | - 浏览器环境却支持不好(需要开发环境编译) 34 | 35 | - 内容很多,重点了解常用语法 36 | 37 | - 面试:开发环境的使用 + 重点语法的掌握 38 | 39 | 40 | ## 模块化的基本语法 41 | 42 | 43 | (1)util1.js: 44 | 45 | ```javascript 46 | export default var a = 100; 47 | 48 | export function foo { 49 | console.log('util1-foo'); 50 | } 51 | ``` 52 | 53 | `export default`命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出。 54 | 55 | 有了默认输出之后,其他模块加载该模块时,import命令可以为该匿名变量/函数,起**任意的名字**。 56 | 57 | 上面的代码中,默认输出是一个变量。当然,我们也可以换成**默认输出一个匿名函数**: 58 | 59 | ```javascript 60 | export default function() { 61 | console.log('util1-function'); 62 | } 63 | ``` 64 | 65 | 66 | (2)util2.js: 67 | 68 | ```javascript 69 | 70 | export var myUtil2 = 'this is util2'; 71 | 72 | export function fn1() { 73 | console.log('util2-fn1'); 74 | } 75 | 76 | export function fn2() { 77 | console.log('util2-fn2'); 78 | } 79 | ``` 80 | 81 | 82 | 上方代码中,我把一个变量和两个函数作为了导出。 83 | 84 | 85 | (3)index.js: 86 | 87 | -------------------------------------------------------------------------------- /14-前端面试/16-01.MVVM.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | MVVM的常见问题: 6 | 7 | - 如何理解MVVM 8 | 9 | - 如何实现MVVM 10 | 11 | - 是否解读过Vue的源码 12 | 13 | 14 | 题目: 15 | 16 | - 说一下使用 jQuery 和使用框架的区别 17 | 18 | 19 | - 说一下对 MVVM 的理解 20 | 21 | 22 | - vue 中如何实现响应式 23 | 24 | 25 | - vue 中如何解析模板 26 | 27 | - vue 的整个实现流程 28 | 29 | 30 | 31 | ## 说一下使用 jQuery 和使用框架的区别 32 | 33 | 34 | 35 | 36 | ## MVVM / Vue 37 | 38 | 39 | ## MVVM模式 40 | 41 | - Model:负责数据存储 42 | 43 | - View:负责页面展示 44 | 45 | - View Model:负责业务逻辑处理(比如Ajax请求等),对数据进行加工后交给视图展示 46 | 47 | 数据驱动视图,只关心数据变化,DOM操作被封装。 48 | 49 | ### MVVM / Vue的三要素 50 | 51 | - **响应式**:vue 如何监听到 data 的每个属性变化? 52 | 53 | - **模板引擎**:vue 的模板如何被解析,指令如何处理? 54 | 55 | 56 | - **渲染**:vue 的模板如何被渲染成 html ?以及渲染过程 57 | 58 | 59 | 60 | ### 什么是虚拟 DOM 61 | 62 | 传统的web开发,是利用 jQuery操作DOM,这是非常耗资源的。 63 | 64 | 我们可以在 JS 的内存里构建类似于DOM的对象,去拼装数据,拼装完整后,把数据整体解析,一次性插入到html里去。这就形成了虚拟 DOM。 65 | 66 | 67 | Vue1.0没有虚拟DOM,Vue2.0改成了基于虚拟DOM。 68 | 69 | 70 | ### 如何理解MVC 71 | 72 | C指的是Controller。控制器能够控制视图的变化,也能控制数据的变化。 73 | 74 | 单项通信。一般情况下是:view 发出命令给控制器,控制器处理业务逻辑后控制 Model,Model再去改 view。 75 | 76 | 77 | ## hybrid 78 | 79 | ### 使用场景 80 | 81 | 不是所有的场景都适合用 hybrid: 82 | 83 | - 使用原生应用:体验要求极致,变化不频繁(如头条的首页) 84 | 85 | - 使用 hybrid:体验要求高,变化频繁(如新闻详情页) 86 | 87 | - 使用H5:体验无要求、不常用(比举报、反馈等) 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /00-前端工具/07-Emmet in VS Code.md: -------------------------------------------------------------------------------- 1 | ## 前言 2 | 3 | `Emmet`可以极大的提高 html 和 css 的编写效率,它提供了一种非常简练的语法规则。 4 | 5 | 举个例子,我们在编辑器中输入缩写代码:`ul>li*6` ,然后按下 Tab 键,即可得到如下代码片段: 6 | 7 | ```html 8 |
    9 |
  • 10 |
  • 11 |
  • 12 |
  • 13 |
  • 14 |
  • 15 |
16 | ``` 17 | 18 | 19 | ## 如何在某个语言中打开 Emmet 支持 20 | 21 | 默认情况下,你可以直接在 html、haml、jade、slim、jsx、xml、xsl、css、scss、sass、less、stylus、handlebars、php 和 javascriptreact 中使用 Emmet 。 22 | 23 | 但对于其他语言,你也可以通过如下设置将其打开: 24 | 25 | ```json 26 | "emmet.includeLanguages": { 27 | "javascript": "javascriptreact", 28 | "vue-html": "html", 29 | "razor": "html", 30 | "plaintext": "jade" 31 | } 32 | 33 | ``` 34 | 35 | 上方代码的意思是,将某个 Emmet 默认不支持的语言,映射到某个 Emmet 支持的语言上。比如上面的设置里,我们把 vue-html 映射成了 html,那么当你在 vue-html 使用 Emmet 时,Emmet 就会把它当作 html 来处理了。 36 | 37 | 38 | ## Emmet 语法规则 39 | 40 | 语法规则: 41 | 42 | ``` 43 | ul>li*6 44 | ``` 45 | 46 | 47 | 最终效果: 48 | 49 | ```html 50 |
    51 |
  • 52 |
  • 53 |
  • 54 |
  • 55 |
  • 56 |
  • 57 |
58 | ``` 59 | 60 | 61 | --- 62 | 63 | 语法规则: 64 | 65 | ``` 66 | p5 67 | 68 | ``` 69 | 70 | 71 | 72 | 最终效果: 73 | 74 | ``` 75 | padding: 5px; 76 | ``` 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /11-Node.js和模块化/Node.js代码举例.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 在 Node.js 上建一个 http 服务器 5 | 6 | 7 | (1)新建一个文件 `server01.js`,然后在里面输入如下代码: 8 | 9 | ```javascript 10 | 11 | const http = require('http'); //引入 node.js里面的一个http包。因为引入之后,我们不会去修改它,所以用常量来表示 12 | 13 | 14 | // 创建一台服务器 15 | var server = http.createServer(function (){ //当有人来访问这台服务器时,就会执行 function 回调函数 16 | console.log('有人来访问我了'); 17 | }); 18 | 19 | server.listen(8080); //要让服务器设置为监听状态,端口设置为8080 20 | 21 | ``` 22 | 23 | 注意看注释。 24 | 25 | 我们把上面这个 js 文件跑起来,然后在浏览器端输入`http://localhost:8080/`,每请求一次,服务器的控制台就会打印 `有人来访问我了`。 26 | 27 | 28 | (2)write()函数和 end()函数: 29 | 30 | 将上面的代码修改如下: 31 | 32 | server02.js: 33 | 34 | ```javascript 35 | const http = require('http'); 36 | 37 | 38 | // 创建一台服务器 39 | var server = http.createServer(function (request, response) { //当有人来访问这个服务器时,就会执行function 这个回调函数 40 | console.log('有人来访问我了'); 41 | 42 | response.write('smyhvae'); //向浏览器输出内容 43 | response.end(); //结束了,浏览器你走吧。 44 | 45 | }); 46 | 47 | server.listen(8080); 48 | 49 | 50 | ``` 51 | 52 | function 回调函数里可以设置两个参数:request 和 response。`response.write()`表示向浏览器输出一些内容。 53 | 54 | 将上面的 js 代码跑起来,产生的问题是,无论我们在浏览器端输入`http://localhost:8080/1.html`,还是输入`http://localhost:8080/2.jpg`,浏览器上显示的都是`smyhvae`。 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /18-推荐链接/02-GitHub项目推荐.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## CSS 4 | 5 | - CSS Inspiration,在这里找到写 CSS 的灵感: 6 | 7 | - CSS 常用样式: 8 | 9 | ## JavaScript 10 | 11 | - 优秀的JS代码规范: 12 | 13 | - 据说这个项目,是宝藏: 14 | 15 | ## TS 16 | 17 | - TypeScript 教程: 18 | 19 | ## 算法类 20 | 21 | - 数据结构和算法: 22 | 23 | - leetcode解题之路: 24 | 25 | - 五分钟学算法: 26 | 27 | - LeetCode 攻略 - 2019 年 8 月上半月汇总(109 题攻略): 28 | 29 | - 极客时间 App 的《数据结构与算法之美》 30 | 31 | ## 前端教程类 32 | 33 | ## 其他 34 | 35 | - 单元测试: 36 | 37 | ## 面试 38 | 39 | - 反向面试(反问面试官的问题): 40 | 41 | - 掘金前端面试题合集: 42 | 43 | ## 博客 44 | 45 | - 收集优质的中文前端博客: 46 | 47 | - 前端博客: 48 | 49 | 讲得比较详细。比如说这篇:[CSS布局说——可能是最全的](https://github.com/laizimo/zimo-article/issues/36) 50 | 51 | ## 文档类 52 | 53 | - 中文博客排版指南: 54 | 55 | - 中国程序员容易发音错误的单词: 56 | 57 | ## 学会提问 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /04-JavaScript基础/12-基本数据类型vs引用数据类型.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | 在之前的**javascript基础**文章中,我们介绍过,变量有以下数据类型: 7 | 8 | - **基本数据类型(值类型)**:String 字符串、Number 数值、Boolean 布尔值、Null 空值、Undefined 未定义。 9 | 10 | - **引用数据类型(引用类型)**:Object 对象。 11 | 12 | 本文,我们针对这两种类型,做个详细介绍。我们先来看个例子。 13 | 14 | 15 | **基本数据类型举例**: 16 | 17 | ```javascript 18 | var a = 23; 19 | var b = a; 20 | 21 | a++; 22 | 23 | console.log(a); // 打印结果:24 24 | console.log(b); // 打印结果:23 25 | ``` 26 | 27 | 上面的代码中:a 和 b 都是基本数据类型,让 b 等于 a,然后**改变 a 的值之后,发现 b 的值并没有被改变**。 28 | 29 | 但是在引用数据类型中,就不同了,我们来看一看。 30 | 31 | **引用数据类型举例**: 32 | 33 | ```javascript 34 | var obj1 = new Object(); 35 | obj1.name = 'smyh'; 36 | 37 | // 让 obj2 等于 obj1 38 | var obj2 = obj1; 39 | 40 | // 修改 obj1 的 name 属性 41 | obj1.name = 'vae'; 42 | 43 | console.log(obj1.name); // 打印结果:vae 44 | console.log(obj2.name); // 打印结果:vae 45 | ``` 46 | 47 | 48 | 上面的代码中:obj1 和 obj2 都是引用数据类型,让 obj2 等于 obj1,然后**修改 obj1.name 的值之后,发现 obj2.name 的值也发生了改变**。 49 | 50 | 51 | 从上面的例子中,可以反映出,基本数据类型和引用数据类型是有区别的。 52 | 53 | 54 | 55 | ## 栈内存和堆内存 56 | 57 | 我们首先记住一句话:JS中,所有的**变量**都是保存在**栈内存**中的。 58 | 59 | 然后来看看下面的区别。 60 | 61 | **基本数据类型**: 62 | 63 | 基本数据类型的值,直接保存在栈内存中。值与值之间是独立存在,修改一个变量不会影响其他的变量。 64 | 65 | **引用数据类型**: 66 | 67 | 68 | 对象是保存到**堆内存**中的。每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而**变量保存了对象的内存地址**(对象的引用)。如果两个变量保存了同一个对象的引用,当一个通过一个变量修改属性时,另一个也会受到影响。 69 | 70 | 71 | 72 | 73 | ## 我的公众号 74 | 75 | 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 76 | 77 | 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: 78 | 79 | ![](http://img.smyhvae.com/2016040102.jpg) 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /04-JavaScript基础/29-包装类.md: -------------------------------------------------------------------------------- 1 | 2 | ## 包装类 3 | 4 | ### 包装类的介绍 5 | 6 | 我们都知道,js中的数据类型包括以下几种。 7 | 8 | - 基本数据类型:String、Number、Boolean、Null、Undefined 9 | 10 | - 引用数据类型:Object 11 | 12 | JS为我们提供了**三个包装类**: 13 | 14 | - String():将基本数据类型字符串,转换为String对象。 15 | 16 | - Number():将基本数据类型的数字,转换为Number对象。 17 | 18 | - Boolean():将基本数据类型的布尔值,转换为Boolean对象。 19 | 20 | 通过上面这这三个包装类,我们可以**将基本数据类型的数据转换为对象**。 21 | 22 | 23 | 代码举例: 24 | 25 | ```javascript 26 | var num = new Number(3); 27 | 28 | var str = new String("hello"); 29 | 30 | var bool = new Boolean(true); 31 | 32 | console.log(typeof num); // 打印结果:object 33 | ``` 34 | 35 | 36 | **需要注意的是**:我们在实际应用中不会使用基本数据类型的对象。如果使用基本数据类型的对象,在做一些比较时可能会带来一些**不可预期**的结果。 37 | 38 | 比如说: 39 | 40 | ```javascript 41 | var boo1 = new Boolean(true); 42 | var boo2 = new Boolean(true); 43 | 44 | console.log(boo1 === boo2); // 打印结果竟然是:false 45 | ``` 46 | 47 | 48 | 再比如说: 49 | 50 | ```javascript 51 | var boo3 = new Boolean(false); 52 | 53 | if (boo3) { 54 | console.log('qianguyihao'); // 这行代码竟然执行了 55 | } 56 | ``` 57 | 58 | 59 | ### 基本数据类型不能添加属性和方法 60 | 61 | 方法和属性只能添加给对象,不能添加给基本数据类型。 62 | 63 | **注意**:当我们对一些基本数据类型的值去调用属性和方法时,浏览器会**临时使用包装类将其转换为对象**,然后在调用对象的属性和方法;调用完以后,在将其转换为基本数据类型。 64 | 65 | 代码举例: 66 | 67 | ```javascript 68 | var str = 123; 69 | 70 | str = str.toString(); // 将 number 类型转换为 string 类型 71 | str.hello = "千古壹号"; // 添加属性 72 | 73 | console.log(typeof str); // 打印结果:string 74 | console.log(str.hello); // 打印结果:undefined 75 | ``` 76 | 77 | 再比如,String 对象的很多内置方法,也可以直接给字符串用。此时,也是临时将字符串转换为 String 对象,然后再调用内置方法。 78 | 79 | 80 | 81 | ## 我的公众号 82 | 83 | 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 84 | 85 | 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: 86 | 87 | ![](http://img.smyhvae.com/20190101.png) 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /11-Node.js和模块化/WebSocket.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## WebSocket 的引入 5 | 6 | ### 背景分析 7 | 8 | HTTP协议是无状态的,服务器只会响应来自客户端的请求,但是它与客户端之间不具备持续连接。 9 | 10 | 11 | 当用户在浏览器上进行操作时,可以请求服务器上的api;但是反过来却不可能:服务器端发生了一个事件,无法将这个事件的信息**实时主动**地通知客户端。只有在客户端查询服务器当前状态时,所发生事件的信息才会从服务器传递到客户端。 12 | 13 | 14 | 那怎么去实时地知道服务器的状态呢?方法有两个: 15 | 16 | (1)**轮询**:客户端每隔很短的时间,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的印象。这种做法是无奈之举,实际上对服务器、客户端双方都造成了大量的性能浪费。 17 | 18 | 19 | (2)**长连接**:客户端只请求一次,但是服务器会将连接保持,不会返回结果。当服务器有了新数据时,实时地发给客户端,而一直保持挂起状态。这种做法的也造成了大量的性能浪费。 20 | 21 | ### WebSocket 协议 22 | 23 | 最新的 HTML5协议,制定了 WebSocket 协议标准,允许客户端和服务器端以**全双工**的方式进行通信。 24 | 25 | WebSocket 的原理非常简单:利用HTTP请求产生握手,HTTP头部含有 WebSocket 协议的请求,**握手之后,二者转用TCP协议进行交流*(QQ的协议)。 26 | 27 | WebSocket协议需要浏览器和服务器都支持才可以使用: 28 | 29 | 30 | - 支持WebSocket协议的浏览器有:Chrome 4、火狐4、IE10、Safari5 31 | 32 | - 支持WebSocket协议的服务器有:Node 0、Apach7.0.2、Nginx1.3 33 | 34 | 35 | ### http 长连接和 websocket 的长连接区别 36 | 37 | HTTP1.1通过使用Connection:keep-alive进行长连接,HTTP 1.1默认进行持久连接。在一次 TCP 连接中可以完成多个 HTTP 请求,但是对每个请求仍然要单独发 header,Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。 38 | 39 | websocket是一个真正的全双工。长连接第一次tcp链路建立之后,后续数据可以双方都进行发送,**不需要发送请求头**。 40 | 41 | keep-alive双方并没有建立正真的连接会话,服务端可以在任何一次请求完成后关闭。WebSocket 它本身就规定了是正真的、双工的长连接,两边都必须要维持住连接的状态。 42 | 43 | ### Socket.IO 的引入 44 | 45 | Node.js上需要写一些程序,来处理TCP请求。 46 | 47 | Node.js从诞生之日起,就支持 WebSocket 协议。不过,从底层一步一步搭建一个Socket服务器很费劲(想象一下Node写一个静态文件服务都那么费劲)。所以,有大神帮我们写了一个库 Socket.IO。 48 | 49 | Socket.IO 是业界良心,新手福音。它屏蔽了所有底层细节,让顶层调用非常简单。并且还为不支持 WebSocket 协议的浏览器,提供了长轮询的透明模拟机制。 50 | 51 | Node的单线程、非阻塞I/O、事件驱动机制,使它非常适合Socket服务器。 52 | 53 | ### Socket.IO 的安装 54 | 55 | Socket.IO 的官网是: 56 | 57 | 安装方式: 58 | 59 | ``` 60 | npm install socket.io 61 | ``` 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /11-Node.js和模块化/CommonJS.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 全局对象 5 | 6 | ### global 7 | 8 | 类似于客户端 JavaScript 运行环境中的 window。 9 | 10 | 11 | ## process 12 | 13 | 用于获取当前的 Node 进程信息,一般用于获取环境变量之类的信息。 14 | 15 | ### console 16 | 17 | Node 中内置的 console 模块,提供操作控制台的输入输出功能,常见使用方式与客户端类似。 18 | 19 | ## 全局函数 20 | 21 | - setInterval(callback, millisecond) 22 | 23 | - clearInterval(timer) 24 | 25 | - setTimeout(callback, millisecond) 26 | 27 | - clearTimeout(timer) 28 | 29 | - Buffer:Class 30 | - 用于操作二进制数据 31 | - 以后介绍 32 | 33 | 34 | ## Node 调试 35 | 36 | ### 最简单的调试 37 | 38 | 最方便也是最简单的调试:console.log() 39 | 40 | 41 | ### Node 原生的调试 42 | 43 | 网址: 44 | 45 | ### 第三方模块提供的调试工具 46 | 47 | ``` 48 | $ npm install node-inspector –g //方式一 49 | 50 | 51 | $ npm install devtool -g //方式二 52 | ``` 53 | 54 | ### 开发工具的调试 55 | 56 | - Visual Studio Code 57 | 58 | - WebStorm 59 | 60 | ## 模块化结构 61 | 62 | Node 实现 CommonJS 规范,所以可以使用模块化的方式组织代码结构。 63 | 64 | - Node 采用的模块化结构是按照 CommonJS 规范。 65 | 66 | - 模块与文件是一一对应关系,即加载一个模块,实际上就是加载对应的一个模块文件。 67 | 68 | ### CommonJS 规范 69 | 70 | CommonJS 就是一套约定标准,不是技术。用于约定我们的代码应该是怎样的一种结构。 71 | 72 | 参考链接: 73 | 74 | - 75 | 76 | ### 常用内置模块 77 | 78 | - `path`:处理文件路径。 79 | 80 | - `fs`:操作(CRUD)文件系统。 81 | 82 | - `child_process`:新建子进程。 83 | 84 | - `util`:提供一系列实用小工具。 85 | 86 | - `http`:提供 HTTP 服务器功能。 87 | 88 | - `url`:用于解析 URL。 89 | 90 | - `querystring`:解析 URL 中的查询字符串。 91 | 92 | - `crypto`:提供加密和解密功能。 93 | 94 | 95 | 总结:更多内容可以参考 api文档: 96 | 97 | 98 | ## 文件系统操作 99 | 100 | ### 相关模块 101 | 102 | - fs:基础的文件操作 API 103 | 104 | - path:提供和路径相关的操作 API 105 | 106 | - readline:用于读取大文本文件,一行一行读 107 | 108 | - fs-extra(第三方): 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /03-CSS进阶/CSS的一些小知识.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 隐藏盒子的几种方式 5 | 6 | 隐藏盒子,有以下几种方式: 7 | 8 | (1)方式一: 9 | 10 | ``` 11 | overflow:hidden; //隐藏盒子超出的部分 12 | ``` 13 | 14 | 15 | (2)**方式二**: 16 | 17 | ``` 18 | display: none; 隐藏盒子,而且不占位置(用的最多) 19 | ``` 20 | 21 | 比如,点击`X`,关闭京东首页上方的广告栏。 22 | 23 | (3)方式三: 24 | 25 | ``` 26 | visibility: hidden; //隐藏盒子,占位置。 27 | visibility: visible; //让盒子重新显示 28 | 29 | ``` 30 | 31 | (4)方式四: 32 | 33 | ``` 34 | pacity: 0; //设置盒子的透明度(不建议,因为内容也会半透明),占位置 35 | ``` 36 | 37 | 38 | (4)方式五: 39 | 40 | ``` 41 | Position/top/left/...-999px //把盒子移得远远的,占位置。 42 | ``` 43 | 44 | (5)方式六: 45 | 46 | ``` 47 | margin-left: 1000px; 48 | ``` 49 | 50 | 51 | 52 | ### 设置盒子的半透明 53 | 54 | 方式一:`pacity: 0.4`。优点是方便。缺点是:里面的内容也会半透明 55 | 56 | 57 | 方式二:css3的技术来解决半透明。如下: 58 | 59 | - background: rgba(0,0,0,0.3); 60 | 61 | - background: rgba(0,0,0,.3); 62 | 63 | 备注:`a`指的是alpha透明度。 64 | 65 | 66 | ### 给标签的形状设置为圆角矩形 67 | 68 | ``` 69 | border-radius: 50%; 70 | border-radius: 10px 0 0 10px; 71 | ``` 72 | 73 | 74 | ### 行高的问题:儿子把父亲撑开 75 | 76 | 比如对于下面这样的标签: 77 | 78 | ``` 79 |
80 | 81 |
82 | 83 | ``` 84 | 85 | 86 | 前置条件:如果我们给父亲div的行高设为31px,然后给儿子a的行高也设置为31 87 | 88 | 结果:当我们给儿子a设置了字体属性之后,会发现,父亲被撑高为32px了。因为font字体自身会比较大,多撑出了一个像素。 89 | 90 | 解决办法:**行内元素尽量不要设置font属性**。对于行内元素而言,如果它和父亲都设置了行高,就不要去给自己设置font属性了。要么就,不要同时设置行高。 91 | 92 | 93 | ### 背景图不能撑开盒子 94 | 95 | 高和行高都可以城开盒子,但背景图不能撑开盒子。 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | ## JS 104 | 105 | ### 超链接``的href跳转 106 | 107 | 一个空白的超链接如下: 108 | 109 | ``` 110 | 111 | ``` 112 | 113 | 当点击超链接时,由于 href 的属性值的不同,可以产生很多种情况: 114 | 115 | ```bash 116 | href="" //刷新页面 117 | 118 | href="#" //跳转到当前页面的顶部(不会刷新) 119 | 120 | href="javascript:void(0)" // 什么都不做 121 | 122 | href="javascript:;" // 什么都不做 123 | 124 | ``` 125 | 126 | -------------------------------------------------------------------------------- /14-前端面试/08-算法问题.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | 算法主要包括: 7 | 8 | - 1、排序 9 | 10 | 排序一定要准备。 11 | 12 | - 2、堆栈、队列、链表 13 | 14 | 队列和链表可以不准备,但是堆栈一定要准备。 15 | 16 | 一个小技巧:JS的数组本身就具备堆栈和队列的特性。比如:top、push、shift、unshift这四个api,本身就帮我们实现了堆栈和队列。 17 | 18 | 堆栈:先进后出。 19 | 20 | - 3、递归 21 | 22 | 递归是一定不能偷懒的。算法比较难的时候,一般要用到递归。 23 | 24 | - 4、波兰式和逆波兰式 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 | 50 | 51 | 52 | ## 堆栈、队列、链表 53 | 54 | 参考链接: 55 | 56 | - 57 | 58 | 上面这个链接是转载的。原创博主的系列文章是: 59 | 60 | - [数组、队列、链表](http://huang303513.github.io/2016/12/08/Javascript%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95(%E4%B8%80).html) 61 | 62 | 63 | 64 | - [排序](http://huang303513.github.io/2016/12/19/Javascript%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95(%E5%9B%9B).html) 65 | 66 | 67 | 68 | 69 | 70 | ## 递归 71 | 72 | 参考链接: 73 | 74 | - [JavaScript中的递归](https://segmentfault.com/a/1190000009857470) 75 | 76 | 递归理解起来不难,但是用的时候很难,因为你没抓住他的本质。递归的终止条件是什么?参数是怎么传递的?一定要搞清楚。 77 | 78 | 很多人说:“我知道这道题是考递归,但是我就是不知道该怎么写”。这个面试官很无奈。 79 | 80 | 81 | 82 | ## 波兰式和逆波兰式 83 | 84 | > 如果复习时间很紧张,这部分也不用准备了。也不是所有的公司都会问。 85 | 86 | 推荐链接: 87 | 88 | - 理论: 89 | 90 | - 源码: 91 | 92 | 93 | ## 总结 94 | 95 | 如果实在答不来,就说,这个算法我不是很会,只知道一些基本概念。 96 | 97 | 如果第一面就碰到算法题,这个公司不用去了。说明这个公司是招算法的,不是招前端的。 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /00-前端工具/05-Atom在前端的使用.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 常用插件 4 | 5 | 6 | - `Emmet`:快速生成HTML片段,比如输入ul>li*3可以快速生成: 7 | 8 | ```html 9 |
    10 |
  • 11 |
  • 12 |
  • 13 |
14 | ``` 15 | 16 | [详细地址](https://atom.io/packages/emmet),[Emmet教程](https://docs.emmet.io/cheat-sheet/) 17 | 18 | - `Snippets`:快速生成 js 代码片段(用来处理代码片段的模板输出),[详细地址](https://atom.io/packages/snippets) 19 | 20 | - `Tree View`:文件浏览器,[详细地址](https://atom.io/packages/tree-view) 21 | 22 | - `file icons`:文件识别图标,使用这个插件会让你的编辑器显示对应的图标,[详细地址](https://atom.io/packages/file-icons) 23 | 24 | - `language-javascript-jsx`:jsx语法高亮 ,[详细地址](https://atom.io/packages/language-javascript-jsx) 25 | 26 | - `language-vue`:vue语法高亮,[详细地址](https://atom.io/packages/language-vue) 27 | 28 | - `linter-eslint`:eslint插件,[详细地址](https://atom.io/packages/linter-eslint) 29 | 30 | - `vue-snippets`:vue代码片段,[详细地址](https://atom.io/packages/vue-snippets) 31 | 32 | - `pigments`:颜色显示器,[详细地址](https://atom.io/packages/pigments) 33 | 34 | - `linter-eslint`:语法检查 35 | 36 | - `Atom-Beautify`:代码格式化 37 | 38 | 参考链接: 39 | 40 | ## 插件无法安装的问题 41 | 42 | ### 方法一:设置代理 43 | 44 | `C:\Users\smyhvae\.atom\.apm`目录下的.apmrc配置文件(没有就新建一个),然后添加代理信息: 45 | 46 | ``` 47 | strict-ssl=false 48 | https-proxy=http://127.0.0.1:1080/ 49 | http-proxy =http://127.0.0.1:1080/ 50 | ``` 51 | 52 | 这里的 http://127.0.0.1:1080,是我自己的 Shadowsocks 代理,你需要设置成自己的可用代理。 53 | 然后再执行: 54 | 55 | ``` 56 | apm install --check 57 | ``` 58 | 59 | 应该可以测试成功,祝好运~~ 60 | 61 | 参考链接: 62 | 63 | - 64 | 65 | - 66 | 67 | 68 | ## Markdown相关 69 | 70 | ### 在编辑器中预览 71 | 72 | 2018-06-JD日记.md 73 | 74 | Packages -> Markdown Preview -> Toggle Preview 75 | 76 | 快捷键:Shift + Ctrl + M 77 | 78 | 79 | 80 | ### 参考链接: 81 | 82 | - [使用Atom打造无懈可击的Markdown编辑器](http://www.cnblogs.com/fanzhidongyzby/p/6637084.html) 83 | 84 | 85 | 86 | 87 | 88 | ## 相关设置 89 | 90 | ### 显示缩进线 91 | 92 | settings -->Editor --> Show Indent Guide 93 | 94 | -------------------------------------------------------------------------------- /05-JavaScript进阶/JavaScript开发积累.md: -------------------------------------------------------------------------------- 1 | 2 | ### 方法的注释 3 | 4 | 方法写完之后(注意,一定要先写完整),我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。 5 | 6 | 比如: 7 | 8 | 9 | ```javascript 10 | /** 11 | * 功能:给定元素查找他的第一个元素子节点,并返回 12 | * @param ele 13 | * @returns {Element|*|Node} 14 | */ 15 | function getFirstNode(ele){ 16 | var node = ele.firstElementChild || ele.firstChild; 17 | return node; 18 | } 19 | ``` 20 | 21 | ### 断点调试 22 | 23 | (1)先让程序运行一遍。 24 | 25 | (2)f12,弹出代码调试工具 26 | 27 | (3)打断点: 28 | 29 | ![](http://img.smyhvae.com/20180124_2035.png) 30 | 31 | 然后刷新页面。 32 | 33 | (4)一步步调试,每点击一次,执行一步: 34 | 35 | ![](http://img.smyhvae.com/20180124_2036.png) 36 | 37 | (5)监视变量: 38 | 39 | 当然,也可以添加变量或者表达式到监视窗口。操作如下: 40 | 41 | ![](http://img.smyhvae.com/20180124_2037.png) 42 | 43 | 上图中,选择变量或表达式,然后右键add to watch. 44 | 45 | 然后监视窗口: 46 | 47 | ![](http://img.smyhvae.com/20180124_2038.png) 48 | 49 | 50 | ### 2019-05-20-给数组、对象赋值 51 | 52 | **数组赋值的正确写法**: 53 | 54 | ```javascript 55 | this.todayList.splice(0, 0, ...dataList); 56 | ``` 57 | 58 | **对象赋值的正确写法**: 59 | 60 | ```javascript 61 | Object.assign(this.dataObj, dataObj); 62 | ``` 63 | 64 | 上方代码中,是将`dataObj` 的值追加到`this.dataObj`中。如果对象里属性名相同,会被覆盖。 65 | 66 | 67 | ### 2019-11-25-在新的窗口中打开url 68 | 69 | 在原来的窗体中跳转到新页面: 70 | 71 | ```javascript 72 | window.location.href="要跳转的新页面"; 73 | ``` 74 | 75 | 在新窗体中打开新页面: 76 | 77 | ```javascript 78 | window.open('你所要跳转的新页面'); 79 | ``` 80 | 81 | 82 | ### 2019-12-10-JavaScript 新特性:Optional Chaining(可选链式调用)语法 83 | 84 | 以往写代码,我们一般都这么写: 85 | 86 | ```javascript 87 | if (result && result.user && result.user.name && result.user.name.length) { 88 | console.log('qianguyihao'); 89 | } 90 | ``` 91 | 92 | 有了 Optinal Chain 语法之后,就简洁很多了,可以这么写: 93 | 94 | 95 | ```javascript 96 | if (result?.user?.name?.length) { 97 | console.log('qianguyihao'); 98 | } 99 | ``` 100 | 101 | 102 | 103 | 参考链接: 104 | 105 | - 了解 JavaScript 新特性:Optional Chaining: 106 | 107 | - 原文链接: https://v8.dev/features/optional-chaining 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /05-JavaScript进阶/call、apply、bind的区别.md: -------------------------------------------------------------------------------- 1 | 2 | ## call()和apply() 3 | 4 | ### 介绍 5 | 6 | 这两个方法都是函数对象的方法,需要通过函数对象来调用。 7 | 8 | 当函数调用call()和apply()时,函数都会立即**执行**。 9 | 10 | - 都可以用来改变函数的this对象的指向。 11 | 12 | - 第一个参数都是this要指向的对象(函数执行时,this将指向这个对象),后续参数用来传实参。 13 | 14 | ### 显式绑定this 15 | 16 | JS提供的绝大多数函数以及我们自己创建的所有函数,都可以使用call 和apply方法。 17 | 18 | 它们的第一个参数是一个对象。因为你可以直接指定 this 绑定的对象,因此我们称之为显式绑定。 19 | 20 | 例1: 21 | 22 | ```javascript 23 | function foo() { 24 | console.log(this.a); 25 | } 26 | 27 | var obj = { 28 | a: 2 29 | }; 30 | 31 | // 将 this 指向 obj 32 | foo.apply(obj); //打印结果:2 33 | ``` 34 | 35 | ### 第一个参数的传递 36 | 37 | 1、thisObj不传或者为null、undefined时,函数中的this会指向window对象(非严格模式)。 38 | 39 | 2、传递一个别的函数名时,函数中的this将指向这个**函数的引用**。 40 | 41 | 3、传递的值为数字、布尔值、字符串时,this会指向这些基本类型的包装对象Number、Boolean、String。 42 | 43 | 4、传递一个对象时,函数中的this则指向传递的这个对象。 44 | 45 | 46 | ### call()和apply()的区别 47 | 48 | call()和apply()方法都可以将实参在对象之后依次传递,但是apply()方法需要将实参封装到一个**数组**中统一传递(即使只有实参只有一个,也要放到数组中)。 49 | 50 | 比如针对下面这样的代码: 51 | 52 | ```javascript 53 | var persion1 = { 54 | name: "小王", 55 | gender: "男", 56 | age: 24, 57 | say: function (school, grade) { 58 | alert(this.name + " , " + this.gender + " ,今年" + this.age + " ,在" + school + "上" + grade); 59 | } 60 | } 61 | var person2 = { 62 | name: "小红", 63 | gender: "女", 64 | age: 18 65 | } 66 | ``` 67 | 68 | 如果是通过call的参数进行传参,是这样的: 69 | 70 | ```javascript 71 | persion1.say.call(persion2, "实验小学", "六年级"); 72 | ``` 73 | 74 | 如果是通过apply的参数进行传参,是这样的: 75 | 76 | ```javascript 77 | persion1.say.apply(persion2, ["实验小学", "六年级"]); 78 | ``` 79 | 80 | 看到区别了吗,call后面的实参与say方法中是一一对应的,而apply传实参时,要封装成一个数组,数组中的元素是和say方法中一一对应的,这就是两者最大的区别。 81 | 82 | ### call()和apply()的作用 83 | 84 | - 改变this的指向 85 | 86 | - 实现继承。Father.call(this) 87 | 88 | ## bind() 89 | 90 | - 都能改变this的指向 91 | 92 | - call()/apply()是**立即调用函数** 93 | 94 | - bind()是将函数返回,因此后面还需要加`()`才能调用。 95 | 96 | bind()传参的方式与call()相同。 97 | 98 | 参考链接: 99 | 100 | - 101 | 102 | - 103 | 104 | - 105 | 106 | - [JS中改变this指向的方法](http://www.xiaoxiaohan.com/js/38.html) 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /09-Ajax/05-模板引擎.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 模版引擎 4 | 5 | ### 引入 6 | 7 | 我们在使用ajax请求数据时,返回的如果是一个 JSON 格式的字符串,我们需要将其包装到对应的HTML代码中,再添加到页面上,才能看到效果。那么这个包装得过程有没有简单的方法呢? 8 | 9 | 10 | 假设在 js 中有如下数据: 11 | 12 | 13 | 14 | ```javascript 15 | var obj = { 16 | name:"fox", 17 | age:18, 18 | skill:"卖萌" 19 | }; 20 | ``` 21 | 22 | 希望包装为: 23 | 24 | ```html 25 |
    26 |
  • 姓名:fox
  • 27 |
  • 年龄:18
  • 28 |
  • 爱好:卖萌
  • 29 |
30 | ``` 31 | 32 | 33 | 我们可以通过模板插件来实现。 34 | 35 | ### 模版插件的原理 36 | 37 | 我们定义一段文本作为模板,读取文本,使用特殊的符号<%= 属性名 %>,通过正则表达式找到这些特殊的符号进行替换,是不是就实现了这样的效果呢? 38 | 39 | ### 常见的模板引擎 40 | 41 | - BaiduTemplate(百度开发) 42 | 43 | - ArtTemplate(腾讯开发):[GitHub地址](https://github.com/aui/art-template)、[文档地址](https://aui.github.io/art-template/zh-cn/docs/)。 44 | 45 | - velocity.js(淘宝开发) 46 | 47 | - Handlebars 48 | 49 | 50 | ## ArtTemplate 51 | 52 | 53 | 标准语法: 54 | 55 | 56 | 57 | 58 | ```html 59 | {{if user}} 60 |

{{user.name}}

61 | {{/if}} 62 | ``` 63 | 64 | 65 | 66 | 67 | 渲染模板: 68 | 69 | 70 | ```javascript 71 | var data = { 72 | title: `标签`, 73 | list: [`文艺`, `博客`, `摄影`] 74 | }; 75 | var html = template(`test`, data); 76 | document.getElementById(`content`).innerHTML = html; 77 | ``` 78 | 79 | 80 | 举例: 81 | 82 | 83 | 84 | ```html 85 | 86 | 87 | 88 | 89 | Title 90 | 91 | 92 | 93 | 102 | 103 | 114 | 115 | 116 | 117 |
118 | 119 |
120 | 121 | 122 | ``` 123 | 124 | 125 | 效果: 126 | 127 | ![](http://img.smyhvae.com/20180301_1223.png) 128 | 129 | -------------------------------------------------------------------------------- /11-Node.js和模块化/ES6.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | ECMAScript 是 JS 的语言标准。而 ES6 是新的 JS 语法标准。 6 | 7 | 8 | ### 发展历史 9 | 10 | 20180303_1633.png 11 | 12 | - 2015年6月,ES6正式发布。 13 | 14 | 15 | ### ES6 的其他优势 16 | 17 | - 使用 babel 语法转换器,支持低端浏览器 18 | 19 | - 流行的库基本都是基于 ES6 构建。 React 默认使用 ES6 新源发开发。 20 | 21 | 22 | ## ES6 的常用语法 23 | 24 | ### ES6语法概览 25 | 26 | - 块级作用域、字符串 27 | 28 | - 对象扩展、解构 29 | 30 | - 类、模块化等。 31 | 32 | 33 | ### 作用域:let 和 const 34 | 35 | - 用 `let`定义变量 ,替代 var 36 | 37 | - 用const 定义常量(定义后,不可修改) 38 | 39 | - 作用域和 {} 40 | 41 | 42 | 举例: 43 | 44 | ```javascript 45 | let a1 = 'haha'; 46 | 47 | const name = `smyhvae`; 48 | ``` 49 | 50 | 51 | ### 模板字符串 52 | 53 | 我们以前让字符串进行拼接的时候,是这样做的:(传统写法的字符串拼接) 54 | 55 | ```javascript 56 | var name = 'smyhvae'; 57 | var age = '26'; 58 | console.log('name:'+name+',age:'+age); //传统写法 59 | ``` 60 | 61 | 62 | 这种写法,比较繁琐,而且容易出错。 63 | 64 | 现在有了 ES6 语法,字符串拼接可以这样写: 65 | 66 | ```javascript 67 | var name = 'smyhvae'; 68 | var age = '26'; 69 | 70 | console.log('name:'+name+',age:'+age); //传统写法 71 | 72 | console.log(`name:${name},age:${age}`); //ES6 写法 73 | 74 | ``` 75 | 76 | 注意,上方代码中,倒数第二行用的是单引号,最后一行用的是反引号(在tab键的上方)。 77 | 78 | 79 | ### 函数扩展 80 | 81 | ES6 中函数的用法: 82 | 83 | - 参数默认值 84 | 85 | - 箭头函数 86 | 87 | - 展开运算符 88 | 89 | 90 | 91 | 定义和调用函数:(传统写法) 92 | 93 | ```javascript 94 | function fn1(name) { 95 | console.log(name); 96 | } 97 | 98 | fn1('smyhvae'); 99 | ``` 100 | 101 | 102 | 定义和调用函数:(ES6写法) 103 | 104 | ```javascript 105 | var fn2 = (name)=>{ 106 | console.log(name); 107 | } 108 | 109 | fn2('smyhvae'); 110 | ``` 111 | 112 | 113 | 上面两端代码,执行的结果是一样的。 114 | 115 | 当然,也可以给上面这个函数的参数加一个默认值: 116 | 117 | ```javascript 118 | var fn2 = (name='enen')=>{ 119 | console.log(name); 120 | } 121 | 122 | fn2(); //参数用默认值 enen 123 | fn2('smyhvae'); 124 | ``` 125 | 126 | 127 | 128 | 比如说,1秒后执行一段代码,可以用箭头函数: 129 | 130 | ```javascript 131 | setTimeout(()=>{ 132 | console.log('something'); 133 | },1000); 134 | ``` 135 | 136 | 如果函数体只有一条 return 语句,那么大括号可以省略: 137 | 138 | ```javascript 139 | const myDouble = x=>x*2; 140 | console.log(myDouble(5)); //打印结果为10 141 | 142 | ``` 143 | 144 | 145 | 箭头函数的好处: 146 | 147 | - 简写代码 148 | 149 | - 保持 this 的作用域 150 | 151 | 152 | 153 | ## -------------------------------------------------------------------------------- /03-CSS进阶/CSS面试题.md: -------------------------------------------------------------------------------- 1 | 2 | ## 常见问题 3 | 4 | ### 你是如何理解 HTML 语义化的? 5 | 6 | **语义化**:指对文本内容的结构化(内容语义化),选择合乎语义的标签(代码语义化)。 7 | 8 | **举例**:段落用 p,边栏用 aside,主要内容用 main 标签。 9 | 10 | **好处:** 11 | 12 | - 便于开发者阅读和维护 13 | 14 | - 有利于SEO:让浏览器的爬虫和辅助技术更好的解析, 15 | 16 | **语义化标签介绍**: 17 | 18 | 在HTML5出来之前,我们习惯于用div来表示页面的章节或者不同模块,但是`div`本身是没有语义的。但是现在,HTML5中加入了一些语义化标签,来更清晰的表达文档结构。 19 | 20 | 20180322_1120.jpg 21 | 22 | 参考链接: 23 | 24 | - [初探 · HTML5语义化](https://zhuanlan.zhihu.com/p/32570423) 25 | 26 | ### meta viewport 是做什么用的,怎么写? 27 | 28 | ```html 29 | 30 | ``` 31 | 32 | 控制页面在移动端不要缩小显示。 33 | 34 | ### canvas 元素是干什么的? 35 | 36 | 看 MDN 的 [canvas 入门手册](https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API)。 37 | 38 | ### 说一下CSS盒模型 39 | 40 | 可以参考本人的另外一篇文章:《02-CSS基础/06-CSS盒模型详解》。 41 | 42 | ### css reset 和 Normalize.css 有什么区别 43 | 44 | > 此题考英文。 45 | 46 | 二者都是用来**统一**浏览器的默认样式: 47 | 48 | - reset:重置。相对「暴力」,不管你有没有用,统统重置成一样的效果,且影响的范围很大,讲求跨浏览器的一致性。(一刀切) 49 | 50 | - `Normalize.css` :标准化。相对「平和」,注重通用的方案,重置掉该重置的样式,保留有用的 user agent 样式,同时进行一些 bug 的修复,这点是 reset 所缺乏的。(去伪存真) 51 | 52 | 参考链接: 53 | 54 | - [Normalize.css 与传统的 CSS Reset 有哪些区别?](https://p.baidu.com/question/ab496162636234613761335c00) 55 | 56 | - [CSS3初始化代码Normalize.css中文版](http://www.bbsxiaomi.com/html_css/html5_css3/177.html) 57 | 58 | - [谈谈一些有趣的 CSS 话题](https://github.com/chokcoco/iCSS) 59 | 60 | - [前端面试之CSS总结(上)](https://segmentfault.com/a/1190000006890725) 61 | 62 | 63 | ### 选择器的优先级如何确定 64 | 65 | - 选择器越具体,优先级越高。 #xxx 大于 .yyy 66 | 67 | - 同样优先级,写在后面的覆盖前面的。 68 | 69 | - color: red !important; 优先级最高。 70 | 71 | 72 | ### BFC 是什么 73 | 74 | 75 | overflow:hidden :取消父子 margin 合并。 (另一种推荐做法:`padding-top: 0.1px;`) 76 | 77 | 78 | ### 如何清除浮动 79 | 80 | (1)overflow: hidden 81 | 82 | (2).clearfix 清除浮动写在爸爸身上 83 | 84 | ```css 85 | .clearfix::after { 86 | content: ''; 87 | display: block; 88 | clear: both; 89 | } 90 | 91 | /* 兼容 IE */ 92 | .clearfix { 93 | zoom: 1; 94 | } 95 | ``` 96 | 97 | ### 伪类和伪元素的区别是什么? 98 | 99 | 概念上的区别: 100 | 101 | - 伪类表示一种状态 102 | 103 | - 伪元素是真的有元素。比如 ::after 是真的有元素,可以在页面上显示内容。 104 | 105 | 使用上的区别: 106 | 107 | - 伪类:使用单冒号 108 | 109 | - 伪元素:使用双冒号 110 | 111 | ## 参考链接 112 | 113 | - [互联网公司招聘启事的正确阅读方式](https://zhuanlan.zhihu.com/p/33998813) 114 | 115 | 116 | -------------------------------------------------------------------------------- /11-Node.js和模块化/00-事件驱动和非阻塞机制.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 异步编程 4 | 5 | ### 异步操作 6 | 7 | - Node 采用 Chrome V8 引擎处理 JavaScript 脚本。V8 最大特点就是**单线程运行**,一次只能运行一个任务。 8 | 9 | - Node 大量采用异步操作(asynchronous operation),即任务不是马上执行,而是插在任务队列的尾部,等到前面的任务运行完后再执行。 10 | 11 | - 提高代码的响应能力。 12 | 13 | 14 | 异步IO也叫非阻塞IO。例如读文件,传统的语言,基本都是读取完毕才能进行下一步操作。非阻塞就是Node的callback,不会影响下一步操作,等到文件读取完毕,回调函数自动被执行,而不是在等待。 15 | 16 | ### 异步操作回调 17 | 18 | 由于系统永远不知道用户什么时候会输入内容,所以代码不能永远停在一个地方。 19 | 20 | Node 中的操作方式就是以异步回调的方式解决无状态的问题。 21 | 22 | 23 | ### 回调函数的设计:错误优先 24 | 25 | 异步操作中,无法通过 try catch 捕获异常。 26 | 27 | 这是因为回调函数主要用于异步操作,当回调函数运行时,前期的操作早结束了,错误的执行栈早就不存在了,传统的错误捕捉机制try…catch对于异步操作行不通,所以只能把错误交给回调函数处理。 28 | 29 | **统一约定:** 30 | 31 | 回调函数的第一个参数默认接收错误信息,第二个参数才是真正的回调数据(便于外界获取调用的错误情况): 32 | 33 | ``` 34 | foo1('赵小黑', 19, function(error, data) { 35 | if(error) throw error; 36 | console.log(data); 37 | }); 38 | ``` 39 | 40 | 41 | ### 异步回调的问题 42 | 43 | 相比较于传统的代码: 44 | 45 | - 异步事件驱动的代码 46 | 47 | - 不容易阅读 48 | 49 | - 不容易调试 50 | 51 | - 不容易维护 52 | 53 | 另外还有个问题是**回调黑洞:**(回调黑洞) 54 | 55 | ```javascript 56 | do1(function() { 57 | do2(function() { 58 | do3(function() { 59 | do4(function() { 60 | do5(function() { 61 | do6() 62 | }); 63 | }); 64 | }); 65 | }); 66 | }); 67 | 68 | ``` 69 | 70 | 71 | ## 进程和线程 72 | 73 | ### 进程(进行中的程序) 74 | 75 | - 每一个 **正在运行** 的应用程序都称之为进程。 76 | 77 | - 每一个应用程序运行都至少有一个进程。 78 | 79 | - 进程是用来给应用程序提供一个运行的环境。 80 | 81 | - 进程是操作系统为应用程序分配资源的一个单位。 82 | 83 | 84 | ### 线程 85 | 86 | - 用来执行应用程序中的代码 87 | 88 | - 在一个进程内部,可以有很多的线程 89 | 90 | - 在一个线程内部,同时只可以干一件事 91 | 92 | - 传统的开发方式大部分都是 I/O 阻塞的,所以需要多线程来更好的利用硬件资源。 93 | 94 | 线程并不是越多越好。 95 | 96 | ### 多线程的弊端 97 | 98 | 缺点一: 99 | 100 | - 创建线程耗费。 101 | - 线程数量有限。 102 | - CPU 在不同线程之间转换,有个上下文转换,这个转换非常耗时。 103 | 104 | 所谓的多线程其实都是假的,对于单核CPU而言,它们无非是在抢占 CPU 资源。线程和线程之间需要**切换和调度**,这是很耗费资源的。 105 | 106 | 缺点二: 107 | 108 | - 线程之间共享某些数据,同步某个状态都很麻烦。 109 | 110 | 就算 CPU 是多核的,现在的问题是,线程与线程之间如果要共享数据,该怎么办?比如 A 线程要访问 B 线程的变量。 111 | 112 | 113 | 114 | ## 事件驱动和非阻塞机制 115 | 116 | 117 | 参考链接: 118 | 119 | 120 | 总结: 121 | 122 | - Node 中将所有的阻塞操作交给了内部线程池实现。 123 | 124 | - Node 主线程本身,主要就是不断的**往返调度**。 125 | 126 | 127 | ### 平台实现差异 128 | 129 | 130 | 由于 Windows 和 *nix 平台(其他平台)的差异,Node 提供了 libuv 作为抽象封装层,保证上层的 Node 与下层的自定义线程池及 IOCP 之间各自独立。 131 | 132 | 如下图所示: 133 | 134 | ![](http://img.smyhvae.com/20180301_2252.png) 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /10-ES6/01-ES5中的严格模式.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## ES的几个重要版本 5 | 6 | - ES5 : 09年发布。 7 | 8 | - ES6(ES2015) : 2015年发布,也称为ECMA2015。 9 | 10 | - ES7(ES2016) : 2016年发布,也称为ECMA2016 (变化不大)。 11 | 12 | 13 | ## 严格模式的理解 14 | 15 | ### 概念 16 | 17 | 18 | **理解**:除了正常运行模式(混杂模式),ES5添加了第二种运行模式:"严格模式"(strict mode)。 19 | 20 | 顾名思义,这种模式使得Javascript在更严格的语法条件下运行。 21 | 22 | **目的**: 23 | 24 | - 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为 25 | 26 | - 消除代码运行的一些不安全之处,为代码的安全运行保驾护航 27 | 28 | - 为未来新版本的Javascript做好铺垫 29 | 30 | ### 使用 31 | 32 | - 针对整个脚本文件:将`use strict`放在脚本文件的第一行,则整个脚本文件将以严格模式运行。 33 | 34 | - 针对单个函数:将`use strict`放在函数体的第一行,则整个函数以严格模式运行。 35 | 36 | PS:如果浏览器不支持,则这句话只解析为一条简单的语句, 没有任何副作用。 37 | 38 | 脚本文件的变通写法:因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中。 39 | 40 | ### 语法和行为改变 41 | 42 | - 必须用var声明变量 43 | 44 | - 禁止自定义的函数中的this指向window 45 | 46 | - 创建eval作用域 47 | 48 | - 对象不能有重名的属性 49 | 50 | 51 | ## 严格模式和普通模式的区别 52 | 53 | > 下面列举几条严格模式的内容。 54 | 55 | ### 全局变量显式声明 56 | 57 | 在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。 58 | 59 | 60 | ### 禁止this关键字指向全局对象: 61 | 62 | ```javascript 63 | var foo = function () { 64 | console.log(this); 65 | } 66 | 67 | foo(); 68 | ``` 69 | 上方代码中,普通模式打印的是window。严格模式下打印的是undefined。 70 | 71 | ### 创设eval作用域 72 | 73 | 74 | 75 | ### 禁止使用with语句 76 | 77 | 因为with语句无法在编译时就确定,属性到底归属哪个对象。 78 | 79 | 80 | ### 构造函数必须通过new实例化对象 81 | 82 | 构造函数必须通过new实例化对象,否则报错。因为this为undefined,此时无法设置属性。 83 | 84 | 比如说: 85 | 86 | 87 | ``` 88 | var Cat = function (name) { 89 | this.name = name; 90 | } 91 | 92 | Cat('haha'); 93 | ``` 94 | 95 | 上方代码中,如果在严格模式下,则会报错。 96 | 97 | 98 | ### 为了让代码更安全,禁止函数内部遍历调用栈 99 | 100 | ### 严格模式下无法删除变量 101 | 102 | 103 | ### 属性相关 104 | 105 | 普通模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。 106 | 107 | 严格模式下,对禁止扩展的对象添加新属性,会报错。 108 | 109 | 普通模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。 110 | 111 | 112 | 普通模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,多个重名的参数属于语法错误。 113 | 114 | 115 | 比如下面这样的代码: 116 | 117 | ```javascript 118 | var obj = { 119 | username: 'smyh'; 120 | username: 'vae' 121 | } 122 | ``` 123 | 124 | 上面的代码,在严格模式下属于语法错误,因为有重名的属性。 125 | 126 | ### 函数必须声明在顶层 127 | 128 | 129 | 将来Javascript的新版本会引入"块级作用域"。为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。 130 | 131 | ### 新增关键字 132 | 133 | 为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield。 134 | 135 | 136 | ## 总结 137 | 138 | 至少要能答出四五条。 139 | 140 | 141 | 参考链接: 142 | 143 | - [阮一峰 | Javascript 严格模式详解](http://www.ruanyifeng.com/blog/2013/01/javascript_strict_mode.html) 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /05-JavaScript进阶/this.md: -------------------------------------------------------------------------------- 1 | 2 | ## this 3 | 4 | ### this的作用 5 | 6 | - this可以帮我们简化很多代码。比如`xiaoming.name`、`xiaoming.age`可以直接写成`this.name`、`this.age`。 7 | 8 | - 特别是当我们不知道一个对象是什么,或者这个对象没有名字但又很想调用它的时候,就会使用到this对象。 9 | 10 | **举例:** 11 | 12 | - 遍历DOM对象,绑定click事件,调用当前点击的对象的id,而不是所有对象的id。 13 | 14 | 代码: 15 | 16 | ```html 17 | 18 | 19 | 20 | 21 | Document 23 | 32 | 33 | 34 | 47 |
48 |
div0
49 |
div1
50 |
div2
51 |
div3
52 |
div4
53 |
54 | 55 | 56 | 57 | 58 | 59 | ``` 60 | 61 | 62 | 点击其中的任何一个元素后,`i`的打印结果是5。你可能会觉得很惊讶。我们来解释一下: 63 | 64 | 当代码执行完毕后,i已经等于5了。因为一旦运行程序,for循环已经执行完了,此时i等于5。 65 | 66 | 现在,我们尝试在 myDiv[i].onclick事件中写代码,如果打印: 67 | 68 | ``` 69 | console.log(i); //打印结果为5 70 | ``` 71 | 72 | 73 | 如果打印: 74 | 75 | ``` 76 | console.log(myDiv[i].id); 77 | ``` 78 | 79 | 上方这行代码,打印会报错,因为i=5;如果想打印每个div的id,应该这样写: 80 | 81 | ``` 82 | console.log(this.id); 83 | ``` 84 | 85 | 你看,this的作用,就体现出来了。 86 | 87 | PS:顺便提醒一下,上面的代码中,如果把`var i`改成`let i`,效果又完全不同了。参考链接:[let和var在for循环中的表现](http://blog.csdn.net/stopllL/article/details/64130664) 88 | 89 | ### 全局作用域中的this 90 | 91 | 当一段代码在浏览器中执行时,所有的全局变量和对象都是在window对象上定义的。换而言之,所有的全局变量和对象都属于window对象。 92 | 93 | 94 | ## this的定律 95 | 96 | this关键字永远指向函数(方法)运行时的**所有者**。 97 | 98 | ### 函数赋值给变量时,this指向window 99 | 100 | 101 | 比如: 102 | 103 | ``` 104 | var foo1 = args.getInfo; 105 | foo1(); 106 | 107 | var foo2 = function(){}; 108 | foo2(); 109 | ``` 110 | 111 | 112 | this都是指向window。 113 | 114 | ### 以函数形式调用时,this永远都是window 115 | 116 | 117 | ### 以方法的形式调用时,this是调用方法的对象 118 | 119 | 120 | ## 解决闭包中的this指向问题 121 | 122 | 123 | 内部函数是可以访问到外部函数的变量的。 124 | 125 | 方式一:直接通过父函数的名字访问 126 | 127 | 方式二:如果不知道父函数的名字,在父函数里加一句`_this = this`,此时`_this`相当于父函数的名字。 128 | 129 | ### 当this遇到一些特殊的函数时 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /04-JavaScript基础/19-预编译及变量提升详解.md: -------------------------------------------------------------------------------- 1 | 2 | > 我们在上一篇文章《作用域》中简单讲过“变量提升”,今天来讲一下预编译,这对我们深入理解变量提升会有帮助。 3 | 4 | ## JavaScript 运行三部曲 5 | 6 | - 语法分析 7 | 8 | - 预编译 9 | 10 | - 解释执行 11 | 12 | ## 预编译前奏 13 | 14 | > 在讲预编译前,我们先来普及下面两个规律。 15 | 16 | ### 两个规律 17 | 18 | **规律1:任何变量,如果未经声明就赋值,此变量是属于 window 的属性**,而且不会做变量提升。(注意,无论在哪个作用域内赋值) 19 | 20 | 比如说,如果我们直接在代码里写 `console.log(a)`,这肯定会报错的,提示找不到 `a`。但如果我直接写 `a = 100`,这就不会报错,此时,这个 `a` 就是 `window.a`。 21 | 22 | **规律2:一切声明的全局变量,全是window的属性**。(注意,我说的是在全局作用域内声明的全局变量,不是说局部变量) 23 | 24 | 比如说,当我定义 `var a = 200` 时,这此时这个 `a` 就是 `window.a`。 25 | 26 | 由此,我们可以看出:**window 代表了全局作用域**(是说「代表」,没说「等于」)。 27 | 28 | ### 举例 29 | 30 | 掌握了上面两句话之后,我们再来看看下面的例子。 31 | 32 | ```javascript 33 | function foo() { 34 | var a = b = 100; // 连续赋值 35 | } 36 | 37 | foo(); 38 | 39 | console.log(window.b); // 在全局范围内访问 b 40 | console.log(b); // 在全局范围内访问 b,但是前面没有加 window 这个关键字 41 | 42 | console.log(window.a); // 在全局范围内访问 a 43 | console.log(a); // 在全局范围内访问 a,但是前面没有加 window 这个关键字 44 | 45 | ``` 46 | 47 | 上方代码的打印结果: 48 | 49 | ``` 50 | 100 51 | 52 | 100 53 | 54 | undefined 55 | 56 | (会报错,提示 Uncaught ReferenceError: a is not defined) 57 | 58 | ``` 59 | 60 | **解释**: 61 | 62 | 当执行了`foo()`函数之后, `var a = b = 100` 这行**连续赋值**的代码等价于 `var a = (b = 100)`,其执行顺序是: 63 | 64 | (1)先把 100 赋值给 b; 65 | 66 | (2)再声明变量 a; 67 | 68 | (3)再把 b 的值赋值给 a。 69 | 70 | 我们可以看到,b 是未经声明的变量就被赋值了,此时,根据规律1,这个 b 是属于 `window.b`;而 a 的作用域仅限于 foo() 函数内部,不属于 window。所以也就有了这样的打印结果。 71 | 72 | ## 预编译 73 | 74 | ### 函数预编译的步骤 75 | 76 | > 函数预编译,发生在函数执行的前一刻。 77 | 78 | (1)创建AO对象。AO即 Activation Object 活跃对象,其实就是「执行期上下文」。 79 | 80 | (2)找形参和变量声明,将形参名和变量作为 AO 的属性名,值为undefined。 81 | 82 | (3)将实参值和形参统一,实参的值赋给形参。 83 | 84 | (4)查找函数声明,函数名作为 AO 对象的属性名,值为整个函数体。 85 | 86 | 这个地方比较难理解。但只有了解了函数的预编译,才能理解明白函数的执行顺序。 87 | 88 | 代码举例: 89 | 90 | ```javascript 91 | function fn(a) { 92 | console.log(a); 93 | 94 | var a = 666; 95 | 96 | console.log(a); 97 | 98 | function a() {} 99 | 100 | console.log(a); 101 | 102 | var b = function() {}; 103 | 104 | console.log(b); 105 | 106 | function c() {} 107 | } 108 | 109 | fn(1); 110 | ``` 111 | 112 | 打印结果: 113 | 114 | ``` 115 | ƒ a() {} 116 | 666 117 | 666 118 | ƒ () {} 119 | ``` 120 | 121 | 122 | 123 | ## 参考链接 124 | 125 | - JavaScript预编译原理分析: 126 | 127 | - 128 | 129 | - 预编译及变量提升: 130 | 131 | - 132 | 133 | - 134 | 135 | - 宏任务&微任务相关: 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /04-JavaScript基础/50-定时器.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 定时器的常见方法 4 | 5 | - setInterval():循环调用。将一段代码,**每隔一段时间**执行一次。(循环执行) 6 | 7 | - setTimeout():延时调用。将一段代码,等待一段时间之后**再执行**。(只执行一次) 8 | 9 | 备注:在实际开发中,二者是可以根据需要,互相替代的。 10 | 11 | ## setInterval() 的使用 12 | 13 | `setInterval()`:循环调用。将一段代码,**每隔一段时间**执行一次。(循环执行) 14 | 15 | **参数**: 16 | 17 | - 参数1:回调函数,该函数会每隔一段时间被调用一次。 18 | 19 | - 参数2:每次调用的间隔时间,单位是毫秒。 20 | 21 | **返回值**:返回一个Number类型的数据。这个数字用来作为定时器的**唯一标识**,方便用来清除定时器。 22 | 23 | ### 定义定时器 24 | 25 | **方式一:**匿名函数 26 | 27 | 每间隔一秒,将 数字 加1: 28 | 29 | ```javascript 30 | let num = 1; 31 | setInterval(function () { 32 | num ++; 33 | console.log(num); 34 | }, 1000); 35 | ``` 36 | 37 | **方式二:** 38 | 39 | 每间隔一秒,将 数字 加1: 40 | 41 | ```javascript 42 | setInterval(fn,1000); 43 | 44 | num ++; 45 | console.log(num); 46 | } 47 | 48 | ``` 49 | 50 | ### 清除定时器 51 | 52 | 定时器的返回值是作为这个定时器的**唯一标识**,可以用来清除定时器。具体方法是:假设定时器setInterval()的返回值是`参数1`,那么`clearInterval(参数1)`就可以清除定时器。 53 | 54 | setTimeout()的道理是一样的。 55 | 56 | 代码举例: 57 | 58 | ```html 59 | 71 | 72 | ``` 73 | 74 | ## setTimeout() 的使用 75 | 76 | `setTimeout()`:延时调用。将一段代码,等待一段时间之后**再执行**。(只执行一次) 77 | 78 | **参数**: 79 | 80 | - 参数1:回调函数,该函数会每隔一段时间被调用一次。 81 | 82 | - 参数2:每次调用的间隔时间,单位是毫秒。 83 | 84 | **返回值**:返回一个Number类型的数据。这个数字用来作为定时器的**唯一标识**,方便用来清除定时器。 85 | 86 | ### 定义和清除定时器 87 | 88 | 代码举例: 89 | 90 | ```javascript 91 | const timer = setTimeout(function() { 92 | console.log(1); // 3秒之后,再执行这段代码。 93 | }, 3000); 94 | 95 | clearTimeout(timer); 96 | 97 | ``` 98 | 99 | 代码举例:(箭头函数写法) 100 | 101 | ```javascript 102 | setTimeout(() => { 103 | console.log(1); // 3秒之后,再执行这段代码。 104 | }, 3000); 105 | ``` 106 | 107 | 108 | ### setTimeout() 举例:5秒后关闭网页两侧的广告栏 109 | 110 | 假设网页两侧的广告栏为两个img标签,它们的样式为: 111 | 112 | 113 | ```html 114 | 119 | 120 | ``` 121 | 122 | 5秒后关闭广告栏的js代码为: 123 | 124 | ```html 125 | 137 | ``` 138 | 139 | 140 | -------------------------------------------------------------------------------- /13-React基础/03-React组件(一):生命周期.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 组件的生命周期 5 | 6 | 在组件创建、到加载到页面上运行、以及组件被销毁的过程中,总是伴随着各种各样的事件,这些在组件特定时期,触发的事件统称为组件的生命周期。 7 | 8 | ## 生命周期的阶段 9 | 10 | 组件生命周期分为三个阶段,下面分别来讲解。 11 | 12 | ### 1、组件创建阶段 13 | 14 | > 组件创建阶段的生命周期函数,有一个显著的特点:创建阶段的生命周期函数,在组件的一辈子中,只执行一次。 15 | 16 | 17 | - getDefaultProps 18 | 19 | 初始化 props 属性默认值。 20 | 21 | - getInitialState 22 | 23 | 初始化组件的私有数据。因为 state 是定义在组件的 constructor 构造器当中的,只要new 了 class类,必然会调用 constructor构造器。 24 | 25 | - componentWillMount() 26 | 27 | 组件将要被挂载。此时还没有开始渲染虚拟DOM。 28 | 29 | 在这个阶段,不能去操作DOM元素,但可以操作属性、状态、function。相当于 Vue 中的Create()函数。 30 | 31 | - render() 32 | 33 | 第一次开始渲染真正的虚拟DOM。当render执行完,内存中就有了完整的虚拟DOM了。 34 | 35 | 意思是,此时,虚拟DOM在内存中创建好了,但是还没有挂在到页面上。 36 | 37 | 在这个函数内部,不能去操作DOM元素,**因为还没return之前,虚拟DOM还没有创建**;当return执行完毕后,虚拟DOM就创建好了,但是还没有挂在到页面上。 38 | 39 | - **componentDidMount()** 40 | 41 | **当组件(虚拟DOM)挂载到页面之后,会进入这个生命周期函数**。 42 | 43 | 只要进入到这个生命周期函数,则必然说明,页面上已经有可见的DOM元素了。此时,组件已经显示到了页面上,state上的数据、内存中的虚拟DOM、以及浏览器中的页面,已经完全保持一致了。 44 | 45 | 当这个方法执行完,组件就进入都了 运行中 的状态。所以说,componentDidMount 是创建阶段的最后一个函数。 46 | 47 | 在这个函数中,我们可以放心的去 操作 页面上你需要使用的 DOM 元素了。如果我们想操作DOM元素,最早只能在 componentDidMount 中进行。相当于 Vue 中的 mounted() 函数 48 | 49 | ### 2、组件运行阶段 50 | 51 | >有一个显著的特点,根据组件的state和props的改变,有选择性的触发0次或多次。 52 | 53 | - componentWillReceiveProps() 54 | 55 | 组件将要接收新属性。只有当父组件中,通过某些事件,重新修改了 传递给 子组件的 props 数据之后,才会触发这个钩子函数。 56 | 57 | - shouldComponentUpdate() 58 | 59 | 判断组件是否需要被更新。此时,组件尚未被更新,但是,state 和 props 肯定是最新的。 60 | 61 | - componentWillUpdate() 62 | 63 | 组件将要被更新。此时,组件还没有被更新,在进入到这个生命周期函数的时候,内存中的虚拟DOM还是旧的,页面上的 DOM 元素也是旧的。(也就是说,此时操作的是旧的 DOM元素) 64 | 65 | - render 66 | 67 | 此时,又要根据最新的 state 和 props,重新渲染一棵内存中的 虚拟DOM树。当 render 调用完毕,内存中的旧DOM树,已经被新DOM树替换了!此时,虚拟DOM树已经和组件的 state 保持一致了,都是最新的;但是页面还是旧的。 68 | 69 | - componentDidUpdate 70 | 71 | 此时,组件完成更新,页面被重新渲染。此时,state、虚拟DOM 和 页面已经完全保持同步。 72 | 73 | ### 3、组件销毁阶段 74 | 75 | 一辈子只执行一次。 76 | 77 | - componentWillUnmount: 组件将要被卸载。此时组件还可以正常使用。 78 | 79 | React 生命周期的截图如下: 80 | 81 | 20190212_1745.jpg 82 | 83 | 生命周期对比: 84 | 85 | - [vue中的生命周期图](https://cn.vuejs.org/v2/guide/instance.html#生命周期图示) 86 | 87 | - [React Native 中组件的生命周期](http://www.race604.com/react-native-component-lifecycle/) 88 | 89 | ## 组件生命周期的执行顺序 90 | 91 | **1、Mounting**: 92 | 93 | - constructor() 94 | 95 | - componentWillMount() 96 | 97 | - render() 98 | 99 | - componentDidMount() 100 | 101 | **2、Updating**: 102 | 103 | - componentWillReceiveProps(nextProps):接收父组件传递过来的属性 104 | 105 | - shouldComponentUpdate(nextProps, nextState):一旦调用 setState,就会触发这个方法。方法默认 return true;如果 return false,后续的方法就不会走了。 106 | 107 | - componentWillUpdate(nextProps, nextState) 108 | 109 | - render() 110 | 111 | - componentDidUpdate(prevProps, prevState) 112 | 113 | **3、Unmounting**: 114 | 115 | - componentWillUnmount() 116 | 117 | 118 | -------------------------------------------------------------------------------- /14-前端面试/21-面试题整理 by smyhvae.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ## JavaScript 8 | 9 | ### 存储相关:请描述以下cookie、localStorage、sessionStorage的区别 10 | 11 | 12 | > 在H5之前,cookie一直都是本地存储的一个重要的方法。直到后面的两个出现了, 就开始用后面的两个做本地存储。 13 | 14 | 15 | **1、cookie**: 16 | 17 | - 本身用于客户端和服务器端的通信。 18 | 19 | - 但是它有本地存储的功能,于是就被“借用”。 20 | 21 | 我们可以通过`document.cookie`获取和修改cookie,获取到的其实就是一个字符串。 22 | 23 | 24 | cookie用于存储时的缺点: 25 | 26 | - 存储量太小,只有4kb 27 | 28 | - 所有http请求都带着,会影响获取资源的效率 29 | 30 | - api简单,需要封装才能用。`document.cookie = ...` 31 | 32 | 33 | 34 | ## HTML5 35 | 36 | ### HTML5新增了哪些内容或API?使用过哪些? 37 | 38 | 新元素: 39 | 40 | - `
`、`
106 | ``` 107 | 108 | 109 | 110 | 111 | 112 | 113 | ## sublime text 快捷键 114 | 115 | | Win快捷键 | Mac快捷键 |作用 | 备注 | 116 | |:-------------|:-------------|:-----|:-----| 117 | |html:5+tab||html结构代码|| 118 | |tab||补全标签代码|| 119 | |tab|补全标签代码| |比如,在html文件中输入`div`,然后 按住tab键后,会自动生成`
`。|| 120 | | **Ctrl + Shift + D** | Cmd + Shift + D|复制当前行到下一行 | | 121 | | Ctrl+Shift+K || 快速删除整行 | | 122 | |Ctrl+鼠标左键单击||集体输入|| 123 | |Ctrl+H|Option+Cmd+F|查找替换||| 124 | | Ctrl+/ || 注释单行 | | 125 | | Ctrl+Shift+/ || 注释多行 | | 126 | |Ctrl+L| | 快速选中整行,继续操作则继续选择下一行,效果和 `Shift + ↓` 效果一样| | 127 | |**Ctrl+Shift+L**| | 先选中多行,再按下快捷键,会在每行行尾插入光标,即可同时编辑这些行| 经常与上一个快捷键结合起来使用 | 128 | |**Ctrl + Shift +【↑/↓**| Ctrl + Cmd +↑/↓ | 移动当前行 | | 129 | |F11||全屏|| 130 | 131 | 132 | 133 | 134 | ## 推荐阅读 135 | 136 | 137 | - [Sublime Text使用技巧](https://github.com/smyhvae/tools/blob/master/01-%E4%B8%AA%E4%BA%BA%E6%95%B4%E7%90%86/Sublime%20Text%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7.md) 138 | 139 | 我自己整理的。 140 | 141 | 142 | ## 参考链接 143 | 144 | - [像 Sublime Text 一样使用 Chrome DevTools](https://chinagdg.org/2015/12/%E5%83%8F-sublime-text-%E4%B8%80%E6%A0%B7%E4%BD%BF%E7%94%A8-chrome-devtools/) 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /04-JavaScript基础/18-作用域.md: -------------------------------------------------------------------------------- 1 | 2 | > 作用域、变量提升的知识点,面试时会经常遇到。 3 | 4 | ## 作用域(Scope)的概念 5 | 6 | 通俗来讲,作用域是一个变量或函数的作用范围。作用域在**函数定义**时,就已经确定了。 7 | 8 | 9 | ### 作用域的分类 10 | 11 | 在js中,一共有两种作用域: 12 | 13 | - 全局作用域 14 | 15 | - 函数作用域 16 | 17 | ### js 是函数级别作用域 18 | 19 | 20 | js 是函数级别作用域:在内部作用域中可以访问到外部作用域的变量,在外部作用域中无法访问到内部作用域的变量。 21 | 22 | 代码举例: 23 | 24 | ```javascript 25 | var a = 'aaa'; 26 | function foo() { 27 | var b = 'bbb'; 28 | console.log(a); // 打印结果:aaa。说明 内层作用域 可以访问 外层作用域 里的变量 29 | } 30 | 31 | foo(); 32 | console.log(b); // 报错:Uncaught ReferenceError: b is not defined。说明 外层作用域 无法访问 内层作用域 里的变量 33 | ``` 34 | 35 | 定义在全局作用域的变量,叫「全局变量」。 36 | 37 | 定义在函数作用域的变量,叫「局部变量」。 38 | 39 | ### 作用域的上下级关系 40 | 41 | 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错 ReferenceError。 42 | 43 | 在函数中要访问全局变量可以使用window对象。(比如说,全局作用域和函数作用域都定义了变量a,如果想访问全局变量,可以使用`window.a`) 44 | 45 | ## 全局作用域 46 | 47 | 直接编写在script标签中的JS代码,都在全局作用域。 48 | 49 | - 全局作用域在页面打开时创建,在页面关闭时销毁。 50 | 51 | - 在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器创建,我们可以直接使用。 52 | 53 | 在全局作用域中: 54 | 55 | - 创建的**变量**都会作为window对象的属性保存。比如在全局作用域内写 `var a = 100`,这里的 `a` 等价于 `window.a`。 56 | 57 | - 创建的**函数**都会作为window对象的方法保存。 58 | 59 | 全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到。 60 | 61 | ### 变量的声明提前(变量提升) 62 | 63 | 使用var关键字声明的变量( 比如 `var a = 1`),**会在所有的代码执行之前被声明**(但是不会赋值),但是如果声明变量时不是用var关键字(比如直接写`a = 1`),则变量不会被声明提前。 64 | 65 | 举例1: 66 | 67 | ```javascript 68 | console.log(a); 69 | var a = 123; 70 | ``` 71 | 72 | 73 | 打印结果:undefined。注意,打印结果并没有报错,而是 undefined,说明变量 a 被提前声明了,只是尚未被赋值。 74 | 75 | 76 | 举例2: 77 | 78 | ```javascript 79 | console.log(a); 80 | a = 123; //此时a相当于window.a 81 | ``` 82 | 83 | 程序会报错: 84 | 85 | ![](http://img.smyhvae.com/20180314_2136.png) 86 | 87 | 88 | 举例3: 89 | 90 | ```javascript 91 | foo(); 92 | 93 | function foo() { 94 | if (false) { 95 | var i = 123; 96 | } 97 | console.log(i); 98 | } 99 | ``` 100 | 101 | 打印结果:undefined。注意,打印结果并没有报错,而是 undefined。这个例子,再次说明了:变量 i 在函数执行前,就被提前声明了,只是尚未被赋值。 102 | 打印结果: 103 | 104 | 105 | ### 函数的声明提前 106 | 107 | **函数声明**: 108 | 109 | 使用`函数声明`的形式创建的函数`function foo(){}`,**会被声明提前**。 110 | 111 | 也就是说,整个函数会在所有的代码执行之前就被**创建完成**。所以,在代码顺序里,我们可以先调用函数,再定义函数。 112 | 113 | 代码举例: 114 | 115 | ```javascript 116 | fn1(); // 虽然 函数 fn1 的定义是在后面,但是因为被提前声明了, 所以此处可以调用函数 117 | 118 | function fn1() { 119 | console.log('我是函数 fn1'); 120 | } 121 | 122 | ``` 123 | 124 | **函数表达式**: 125 | 126 | 使用`函数表达式`创建的函数`var foo = function(){}`,**不会被声明提前**,所以不能在声明前调用。 127 | 128 | 很好理解,因为此时foo被声明了(这里是变量声明),且为undefined,并没有把 `function(){}` 赋值给 foo。 129 | 130 | 所以说,下面的例子,会报错: 131 | 132 | ![](http://img.smyhvae.com/20180314_2145.png) 133 | 134 | ## 函数作用域 135 | 136 | **提醒1**:在函数作用域中,也有声明提前的特性: 137 | 138 | - 函数中,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明 139 | 140 | - 函数中,没有var声明的变量都是**全局变量**,而且并不会提前声明。 141 | 142 | 举例1: 143 | 144 | ```javascript 145 | var a = 1; 146 | 147 | function foo() { 148 | console.log(a); 149 | a = 2; // 此处的a相当于window.a 150 | } 151 | 152 | foo(); 153 | console.log(a); //打印结果是2 154 | 155 | ``` 156 | 157 | 上方代码中,执行foo()后,打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined` 158 | 159 | **提醒2**:定义形参就相当于在函数作用域中声明了变量。 160 | 161 | ```javascript 162 | function fun6(e) { // 这个函数中,因为有了形参 e,此时就相当于在函数内部的第一行代码里,写了 var e; 163 | console.log(e); 164 | } 165 | 166 | fun6(); //打印结果为 undefined 167 | fun6(123);//打印结果为123 168 | ``` 169 | 170 | ## 我的公众号 171 | 172 | 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 173 | 174 | 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: 175 | 176 | ![](http://img.smyhvae.com/2016040102.jpg) 177 | 178 | -------------------------------------------------------------------------------- /14-前端面试/10-02.前端错误监控.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 错误监控包含的内容是: 6 | 7 | - 前端错误的分类 8 | 9 | - 每种错误的捕获方式 10 | 11 | - 上报错误的基本原理 12 | 13 | 14 | 面试时,可能有两种问法: 15 | 16 | - 如何监测 js 错误?(开门见山的方式) 17 | 18 | - 如何保证**产品质量**?(其实问的也是错误监控) 19 | 20 | 21 | ## 前端错误的分类 22 | 23 | 包括两种: 24 | 25 | - 即时运行错误(代码错误) 26 | 27 | - 资源加载错误 28 | 29 | 30 | ## 每种错误的捕获方式 31 | 32 | 33 | ### 即时运行错误的捕获方式 34 | 35 | **方式1**:try ... catch。 36 | 37 | 这种方式要部署在代码中。 38 | 39 | **方式2:**`window.onerror`函数。这个函数是全局的。 40 | 41 | ``` 42 | window.onerror = function(msg, url, row, col, error) { ... } 43 | ``` 44 | 45 | 参数解释: 46 | 47 | - msg为异常基本信息 48 | 49 | - source为发生异常Javascript文件的url 50 | 51 | - row为发生错误的行号 52 | 53 | 方式二中的`window.onerror`是属于DOM0的写法,我们也可以用DOM2的写法:`window.addEventListener("error", fn);`也可以。 54 | 55 | **问题延伸1:** 56 | 57 | `window.onerror`默认无法捕获**跨域**的js运行错误。捕获出来的信息如下:(基本属于无效信息) 58 | 59 | 60 | 比如说,我们的代码想引入B网站的`b.js`文件,怎么捕获它的异常呢? 61 | 62 | **解决办法**:在方法二的基础之上,做如下操作: 63 | 64 | 65 | (1)在`b.js`文件里,加入如下 response header,表示允许跨域:(或者世界给静态资源`b.js`加这个 response header) 66 | 67 | ``` 68 | Access-Control-Allow-Origin: * 69 | ``` 70 | 71 | (2)引入第三方的文件`b.js`时,在` 164 | 165 | 166 | 167 | ``` 168 | 169 | 170 | 打开浏览器,效果如下: 171 | 172 | ![](http://img.smyhvae.com/20180311_2055.png) 173 | 174 | 上图中,红色那一栏表明,我的请求已经发出去了。点进去看看: 175 | 176 | ![](http://img.smyhvae.com/20180311_2057.png) 177 | 178 | 这种方式,不需要借助第三方的库,一行代码即可搞定。 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /14-前端面试/05-02.面向对象:类的定义和继承的几种方式.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | 6 | 类与实例: 7 | 8 | - 类的声明 9 | 10 | - 生成实例 11 | 12 | 类与继承: 13 | 14 | - 如何实现继承:继承的本质就是原型链 15 | 16 | - 继承的几种方式 17 | 18 | 19 | 20 | ## 类的定义、实例化 21 | 22 | ### 类的定义/类的声明 23 | 24 | **方式一**:用构造函数模拟类(传统写法) 25 | 26 | ```javascript 27 | function Animal1() { 28 | this.name = 'smyhvae'; //通过this,表明这是一个构造函数 29 | } 30 | ``` 31 | 32 | **方式二**:用 class 声明(ES6的写法) 33 | 34 | ```javascript 35 | class Animal2 { 36 | constructor() { //可以在构造函数里写属性 37 | this.name = name; 38 | } 39 | } 40 | ``` 41 | 42 | 控制台的效果: 43 | 44 | ![](http://img.smyhvae.com/20180307_0957.png) 45 | 46 | ### 实例化 47 | 48 | 类的实例化很简单,直接 new 出来即可。 49 | 50 | ```javascript 51 | console.log(new Animal1(),new Animal2()); //实例化。如果括号里没有参数,则括号可以省略 52 | ``` 53 | 54 | ![](http://img.smyhvae.com/20180307_1000.png) 55 | 56 | ## 继承的几种方式 57 | 58 | 继承的本质就是原型链。 59 | 60 | **继承的方式有几种?每种形式的优缺点是**?这些问题必问的。其实就是考察你对原型链的掌握程度。 61 | 62 | ### 方式一:借助构造函数 63 | 64 | 65 | ```javascript 66 | function Parent1() { 67 | this.name = 'parent1 的属性'; 68 | } 69 | 70 | function Child1() { 71 | Parent1.call(this); //【重要】此处用 call 或 apply 都行:改变 this 的指向 72 | this.type = 'child1 的属性'; 73 | } 74 | 75 | console.log(new Child1); 76 | ``` 77 | 78 | 【重要】上方代码中,最重要的那行代码:在子类的构造函数里写了`Parent1.call(this);`,意思是:**让Parent的构造函数在child的构造函数中执行**。发生的变化是:**改变this的指向**,parent的实例 --> 改为指向child的实例。导致 parent的实例的属性挂在到了child的实例上,这就实现了继承。 79 | 80 | 打印结果: 81 | 82 | ![](http://img.smyhvae.com/20180307_1015.png) 83 | 84 | 上方结果表明:child先有了 parent 实例的属性(继承得以实现),再有了child 实例的属性。 85 | 86 | **分析**: 87 | 88 | 这种方式,虽然改变了 this 的指向,但是,**Child1 无法继承 Parent1 的原型**。也就是说,如果我给 Parent1 的原型增加一个方法: 89 | 90 | ```javascript 91 | Parent1.prototype.say = function () { 92 | }; 93 | ``` 94 | 95 | 上面这个方法是无法被 Child1 继承的。如下: 96 | 97 | ![](http://img.smyhvae.com/20180307_1030.png) 98 | 99 | ### 方法二:通过原型链实现继承 100 | 101 | ```javascript 102 | /* 103 | 通过原型链实现继承 104 | */ 105 | function Parent() { 106 | this.name = 'Parent 的属性'; 107 | } 108 | 109 | function Child() { 110 | this.type = 'Child 的属性'; 111 | } 112 | 113 | Child.prototype = new Parent(); //【重要】 114 | 115 | console.log(new Child()); 116 | ``` 117 | 118 | 打印结果: 119 | 120 | ![](http://img.smyhvae.com/20180307_1109.png) 121 | 122 | 123 | 【重要】上方代码中,最重要的那行:每个函数都有`prototype`属性,于是,构造函数也有这个属性,这个属性是一个对象。现在,**我们把`Parent`的实例赋值给了`Child`的`prototye`**,从而实现**继承**。此时,`Child`构造函数、`Parent`的实例、`Child`的实例构成一个三角关系。于是: 124 | 125 | - `new Child.__proto__ === new Parent()`的结果为true 126 | 127 | **分析:** 128 | 129 | 这种继承方式,**Child 可以继承 Parent 的原型**,但有个缺点: 130 | 131 | 缺点是:**如果修改 child1实例的name属性,child2实例中的name属性也会跟着改变**。 132 | 133 | 如下: 134 | 135 | ![](http://img.smyhvae.com/20180307_1123.png) 136 | 137 | 上面的代码中, child1修改了arr属性,却发现,child2的arr属性也跟着改变了。这显然不太好,在业务中,两个子模块应该隔离才对。如果改了一个对象,另一个对象却发生了改变,就不太好。 138 | 139 | 造成这种缺点的原因是:child1和child2共用原型。即:`chi1d1.__proto__ === child2__proto__`是严格相同。而 arr方法是在 Parent 的实例上(即 Child实例的原型)的。 140 | 141 | 142 | ## 方式三:组合的方式:构造函数 + 原型链 143 | 144 | 就是把上面的两种方式组合起来: 145 | 146 | 147 | ```javascript 148 | /* 149 | 组合方式实现继承:构造函数、原型链 150 | */ 151 | function Parent3() { 152 | this.name = 'Parent 的属性'; 153 | this.arr = [1, 2, 3]; 154 | } 155 | 156 | function Child3() { 157 | Parent3.call(this); //【重要1】执行 parent方法 158 | this.type = 'Child 的属性'; 159 | } 160 | Child3.prototype = new Parent3(); //【重要2】第二次执行parent方法 161 | 162 | var child = new Child3(); 163 | ``` 164 | 165 | 这种方式,能解决之前两种方式的问题:既可以继承父类原型的内容,也不会造成原型里属性的修改。 166 | 167 | 这种方式的缺点是:让父亲Parent的构造方法执行了两次。 168 | 169 | 170 | 171 | ```javascript 172 | 173 | ``` 174 | 175 | 176 | ES6中的继承方式,一带而过即可,重点是要掌握ES5中的继承。 177 | 178 | -------------------------------------------------------------------------------- /14-前端面试/09-01.浏览器渲染机制.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 前言 5 | 6 | > 接下来的几篇文章,讲一下二面的内容。 7 | 8 | **二面的内容:** 9 | 10 | 11 | - 渲染机制 12 | 13 | - JS 运行机制 14 | 15 | - 页面性能 16 | 17 | - 错误监控 18 | 19 | 本文接下来讲渲染机制。 20 | 21 | 22 | **渲染机制**包括的内容: 23 | 24 | - 什么是DOCTYPE及作用 25 | 26 | - 浏览器渲染过程 27 | 28 | 面试经常会问:在浏览器中输入url,发生了哪些事情。其中有一部就是浏览器的渲染过程。 29 | 30 | - Reflow:重排 31 | 32 | 面试官问完了渲染机制,一般会紧接着问重排Reflow,你可千万别说你没听过。 33 | 34 | - Repaint:重绘 35 | 36 | - Layout:布局 37 | 38 | 这里的Layout指的是浏览器的Layout。 39 | 40 | ## 什么是DOCTYPE及作用 41 | 42 | ### 定义 43 | 44 | **DTD**(Document Type Definition):文档类型定义。 45 | 46 | 是一系列的语法规则,用来定义XML或者(X)HTML文件类型。**浏览器会使用DTD来判断文本类型**,决定使用何种协议来解析,以及切换浏览器模式。(说白了就是:DTD就是告诉浏览器,我是什么文档类型,你要用什么协议来解析我) 47 | 48 | **DOCTYPE**:用来声明DTD规范。 49 | 50 | 一个主要的用途便是文件的合法性验证。如果文件代码不合法,那么浏览器解析时便会出现一些差错。(说白了,DOCTYPE就是用来声明DTD的) 51 | 52 | 53 | ### 常见的DOCTYPE声明有几种 54 | 55 | > 面试官紧接着会问,常见的 DOCTYPE 有哪些,以及 HTML5 的 DOCTYPE 怎么写。 56 | 57 | 1、**HTML 4.01 Strict**:(严格的) 58 | 59 | ```html 60 | 61 | ``` 62 | 63 | PS:该DTD包含所有的HTML元素和属性,但不包括展示性的和弃用的元素(比如 font、u下划线等,这些是被废弃了的)。 64 | 65 | 2、**HTML 4.01 Transitional**:(传统的) 66 | 67 | ```html 68 | 69 | 70 | ``` 71 | 72 | PS:该DTD包含所有的HTML元素和属性,但包括展示性的和弃用的元素(比如 font、u下划线等)。 73 | 74 | 75 | 3、HTML 5: 76 | 77 | ```html 78 | 79 | ``` 80 | 81 | 82 | **总结:** 83 | 84 | 面试时,不会让你写出 HTML 4.01的写法,因为大家都记不住。但是要记住 HTML 5 的写法,别看它简单,知道的人还真不多。 85 | 86 | 面试时,可以这样回答: HTML 4.01 中有两种写法,一种是严格的,一种是传统的;并且答出二者的区别。 HTML 5的写法是``。 87 | 88 | 89 | ## 浏览器的渲染过程 90 | 91 | 92 | 浏览器的渲染过程非常复杂,但是面试只用说几句话就行了,不然太耗时间。如何快速简洁地描述清楚,是关键。 93 | 94 | 95 | ![](http://img.smyhvae.com/20180310_1257.png) 96 | 97 | 这里先解释一下几个概念,方便大家理解: 98 | 99 | - DOM Tree:浏览器将HTML解析成树形的数据结构(DOM 树)。 100 | 101 | - CSS Rule Tree:浏览器将CSS解析成树形的数据结构。 102 | 103 | - Render Tree: DOM和CSSOM合并后生成Render Tree。(虽然有了Render Tree,但并不知道节点的位置,需要依靠接下来的layout) 104 | 105 | - layout: 有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系,从而去**计算出每个节点在屏幕中的位置**(宽高、颜色等)。 106 | 107 | - painting:按照算出来的规则,通过显卡,把内容画到屏幕上。 108 | 109 | - display:打击看到的最终效果。 110 | 111 | 参考链接: 112 | 113 | - [浏览器渲染原理及流程[荐]](http://www.cnblogs.com/slly/p/6640761.html) 114 | 115 | 116 | ## Reflow:重排 117 | 118 | ### 定义 119 | 120 | **重排 Reflow**:DOM结果中的各个元素都有自己的盒子(模型),这些都需要浏览器**根据各种样式来计算,并根据计算结果将元素放在它该出现的位置**,这个过程称之为Reflow。 121 | 122 | 123 | ### 什么时候触发 Reflow 124 | 125 | - 增加、删除、修改DOM节点时,会导致 Reflow 或 Repaint。 126 | 127 | - 移动DOM的位置,或是加个动画的时候 128 | 129 | - 修改CSS样式时(宽高、display 为none等,都是通过css样式来修改的) 130 | 131 | - 当用户Resize窗口时(移动端没有这个问题),或是滚动的时候,**有可能**会触发(具体要看浏览器的规则)。 132 | 133 | - 修改网页的默认字体时(这个影响非常严重)。 134 | 135 | **面试总结:** 136 | 137 | 首先要答出 Reflow 定义;其次,什么时候触发,至少要答出两条。更进一步,面试官可能还会问你**怎么避免reflow**,这个自己去查查吧。 138 | 139 | 140 | ## Repaint:重绘 141 | 142 | ### 定义 143 | 144 | **Repaint重绘制:**当各种盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器便把这些元素都按照各自的特性绘制一遍,于是页面的内容出现了,这个过程称之为 Repaint。 145 | 146 | 说白了,页面要呈现的内容,统统画在屏幕上,这就叫 Repaint。 147 | 148 | 149 | ### 什么时候触发 Repaint 150 | 151 | - DOM改动 152 | 153 | - CSS改动 154 | 155 | 其实,就是判断当前呈现的内容是否发生变化(无论这个变化是通过DOM改动还是CSS改动)。只要页面显示的内容不一样了,肯定要 Repaint。 156 | 157 | **面试总结:** 158 | 159 | 面试官经常会问:“如何**尽量减少**Repaint的频率?” 160 | 161 | 注意, reflow是问“怎么避免”,repaint是问“怎么减少”。Repaint是无法避免的,否则就成了静态页面了。 162 | 163 | **答案**: 164 | 165 | (1)如果需要创建多个DOM节点,可以使用**DocumentFragment**创建完,然后一次性地加入document。(加一个节点,就repaint一次,不太好) 166 | 167 | (2)将元素的display设置为”none”,完成修改后再把display修改为原来的值。 168 | 169 | 参考链接:[如何减少浏览器repaint和reflow ?](http://blog.csdn.net/liaozhongping/article/details/47057889) 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /14-前端面试/04-HTTP协议.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 一面中,如果有笔试,考HTTP协议的可能性较大。 4 | 5 | ## 前言 6 | 7 | 一面要讲的内容: 8 | 9 | - HTTP协议的主要特点 10 | 11 | - HTTP报文的组成部分 12 | 13 | - HTTP方法 14 | 15 | - get 和 post的区别 16 | 17 | - HTTP状态码 18 | 19 | - 什么是持久连接 20 | 21 | - 什么是管线化 22 | 23 | 24 | 二面要讲的内容; 25 | 26 | - 缓存 27 | 28 | - CSRF攻击 29 | 30 | 31 | ## HTTP协议的主要特点 32 | 33 | - 简单快速 34 | 35 | - 灵活 36 | 37 | - **无连接** 38 | 39 | - **无状态** 40 | 41 | 42 | 通常我们要答出以上四个内容。如果实在记不住,一定要记得后面的两个:**无连接、无状态**。 43 | 44 | 45 | 我们分别来解释一下。 46 | 47 | 48 | ### 简单快速 49 | 50 | **简单**:每个资源(比如图片、页面)都通过 url 来定位。这都是固定的,在http协议中,处理起来也比较简单,想访问什么资源,直接输入url即可。 51 | 52 | 53 | ### 灵活 54 | 55 | http协议的头部有一个`数据类型`,通过http协议,就可以完成不同数据类型的传输。 56 | 57 | ### 无连接 58 | 59 | 连接一次,就会断开,不会继续保持连接。 60 | 61 | ### 无状态 62 | 63 | 客户端和服务器端是两种身份。第一次请求结束后,就断开了,第二次请求时,**服务器端并没有记住之前的状态**,也就是说,服务器端无法区分客户端是否为同一个人、同一个身份。 64 | 65 | 有的时候,我们访问网站时,网站能记住我们的账号,这个是通过其他的手段(比如 session)做到的,并不是http协议能做到的。 66 | 67 | 68 | ## HTTP报文的组成部分 69 | 70 | ![](http://img.smyhvae.com/20180306_1400.png) 71 | 72 | 在回答此问题时,我们要按照顺序回答: 73 | 74 | - 先回答的是,http报文包括:**请求报文**和**响应报文**。 75 | 76 | - 再回答的是,每个报文包含什么部分。 77 | 78 | - 最后回答,每个部分的内容是什么 79 | 80 | ### 请求报文包括: 81 | 82 | ![](http://img.smyhvae.com/20180228_1505.jpg) 83 | 84 | - 请求行:包括请求方法、请求的url、http协议及版本。 85 | 86 | - 请求头:一大堆的键值对。 87 | 88 | - **空行**指的是:当服务器在解析请求头的时候,如果遇到了空行,则表明,后面的内容是请求体。 89 | 90 | - 请求体:数据部分。 91 | 92 | ### 响应报文包括: 93 | 94 | ![](http://img.smyhvae.com/20180228_1510.jpg) 95 | 96 | 97 | - 状态行:http协议及版本、状态码及状态描述。 98 | 99 | - 响应头 100 | 101 | - 空行 102 | 103 | - 响应体 104 | 105 | 106 | ## HTTP方法 107 | 108 | 包括: 109 | 110 | - GET:获取资源 111 | 112 | - POST:传输资源 113 | 114 | - put:更新资源 115 | 116 | - DELETE:删除资源 117 | 118 | - HEAD:获得报文首部 119 | 120 | HTTP方法有很多,但是上面这五个方法,要求在面试时全部说出来,不要漏掉。 121 | 122 | get 和 post 比较常见。 123 | 124 | put 和 delete 在实际应用中用的很少。况且,业务中,一般不删除服务器端的资源。 125 | 126 | head 可能偶尔用的到。 127 | 128 | 129 | ## get 和 post的区别 130 | 131 | ![](http://img.smyhvae.com/20180306_1415.png) 132 | 133 | 区别有很多,如果记不住,面试时,至少要任意答出其中的三四条。 134 | 135 | 有一点要强调,**get是相对不隐私的,而post是相对隐私的**。 136 | 137 | 我们大概要记住以下几点: 138 | 139 | 1、浏览器在回退时,get**不会重新请求**,但是post会重新请求。【重要】 140 | 141 | 2、get请求会被浏览器**主动缓存**,而post不会。【重要】 142 | 143 | 3、get请求的参数,会报**保留**在浏览器的**历史记录**里,而post不会。做业务时要注意。为了防止CSRF攻击,很多公司把get统一改成了post。 144 | 145 | 4、get请求在url中传递的参数有大小限制,基本是2kb,不同的浏览器略有不同。而post没有注意。 146 | 147 | 5、get的参数是直接暴露在url上的,相对不安全。而post是放在请求体中的。 148 | 149 | 150 | ## http状态码 151 | 152 | http状态码分类: 153 | 154 | ![](http://img.smyhvae.com/20180306_1430.png) 155 | 156 | 常见的http状态码: 157 | 158 | ![](http://img.smyhvae.com/20180306_1431.png) 159 | 160 | 161 | 部分解释: 162 | 163 | - 206的应用:`range`指的是请求的范围,客户端只请求某个大文件里的一部分内容。比如说,如果播放视频地址或音频地址的前面一部分,可以用到206。 164 | 165 | 166 | - 301:重定向(永久)。 167 | 168 | - 302:重定向(临时)。 169 | 170 | - 304:我这个服务器告诉客户端,你已经有缓存了,不需要从我这里取了。 171 | 172 | 173 | ![](http://img.smyhvae.com/20180306_1440.png) 174 | 175 | 400和401用的不多。403指的是请求被拒绝。404指的是资源不存在。 176 | 177 | ## 持久链接/http长连接 178 | 179 | > 如果你能答出持久链接,这是面试官很想知道的一个点。 180 | 181 | 182 | - **轮询**:http1.0中,客户端每隔很短的时间,都会对服务器发出请求,查看是否有新的消息,只要轮询速度足够快,例如1秒,就能给人造成交互是实时进行的印象。这种做法是无奈之举,实际上对服务器、客户端双方都造成了大量的性能浪费。 183 | 184 | 185 | - **长连接**:HTTP1.1中,通过使用Connection:keep-alive进行长连接,。客户端只请求一次,但是服务器会将继续保持连接,当再次请求时,避免了重新建立连接。 186 | 187 | 注意,HTTP 1.1默认进行持久连接。在一次 TCP 连接中可以完成多个 HTTP 请求,但是对**每个请求仍然要单独发 header**,Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。 188 | 189 | 190 | ## 长连接中的管线化 191 | 192 | > 如果能答出**管线化**,则属于加分项。 193 | 194 | ### 管线化的原理 195 | 196 | 长连接时,**默认**的请求这样的: 197 | 198 | ``` 199 | 请求1 --> 响应1 -->请求2 --> 响应2 --> 请求3 --> 响应3 200 | ``` 201 | 202 | 长连接中的管线化,请求是这样的: 203 | 204 | ``` 205 | 请求1 --> 请求2 --> 请求3 --> 响应1 --> 响应2 --> 响应3 206 | ``` 207 | 208 | 209 | 管线化就是,我把现在的请求打包,一次性发过去,你也给我一次响应回来。 210 | 211 | 212 | ### 管线化的注意事项 213 | 214 | 215 | 面试时,不会深究管线化。如果真要问你,就回答:“我没怎么研究过,准备回去看看~” 216 | 217 | -------------------------------------------------------------------------------- /02-CSS基础/others.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ```html 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Document 12 | 13 | 108 | 109 | 110 | 112 | 114 | 116 | 118 | 121 | 123 | 124 | 125 | 126 | ``` -------------------------------------------------------------------------------- /04-JavaScript基础/21-this.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## this 4 | 5 | 解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象我们称为函数执行的 上下文对象。 6 | 7 | 根据函数的调用方式的不同,this会指向不同的对象:【重要】 8 | 9 | - 1.以函数的形式调用时,this永远都是window。比如`fun();`相当于`window.fun();` 10 | 11 | - 2.以方法的形式调用时,this是调用方法的那个对象 12 | 13 | - 3.以构造函数的形式调用时,this是新创建的那个对象 14 | 15 | - 4.使用call和apply调用时,this是指定的那个对象 16 | 17 | 18 | **针对第1条的举例**: 19 | 20 | ```javascript 21 | function fun() { 22 | console.log(this); 23 | console.log(this.name); 24 | } 25 | 26 | var obj1 = { 27 | name: "smyh", 28 | sayName: fun 29 | }; 30 | 31 | var obj2 = { 32 | name: "vae", 33 | sayName: fun 34 | }; 35 | 36 | var name = "全局的name属性"; 37 | 38 | //以函数形式调用,this是window 39 | fun(); //可以理解成 window.fun() 40 | ``` 41 | 42 | 43 | 打印结果: 44 | 45 | ``` 46 | Window 47 | 全局的name属性 48 | ``` 49 | 50 | 51 | 上面的举例可以看出,this指向的是window对象,所以 this.name 指的是全局的name。 52 | 53 | 54 | **第2条的举例**: 55 | 56 | ```javascript 57 | function fun() { 58 | console.log(this); 59 | console.log(this.name); 60 | } 61 | 62 | var obj1 = { 63 | name: "smyh", 64 | sayName: fun 65 | }; 66 | 67 | var obj2 = { 68 | name: "vae", 69 | sayName: fun 70 | }; 71 | 72 | var name = "全局的name属性"; 73 | 74 | //以方法的形式调用,this是调用方法的对象 75 | obj2.sayName(); 76 | 77 | ``` 78 | 79 | 打印结果: 80 | 81 | ``` 82 | Object 83 | vae 84 | ``` 85 | 86 | 上面的举例可以看出,this指向的是 对象 obj2 ,所以 this.name 指的是 obj2.name。 87 | 88 | **箭头函数中this的指向**: 89 | 90 | ES6中的箭头函数并不会使用上面四条标准的绑定规则,而是会继承外层函数调用的this绑定(无论this绑定到什么)。 91 | 92 | ## 类数组 arguments 93 | 94 | > 这部分,小白可能看不懂。所以,这一段,暂时可以忽略。 95 | 96 | 在调用函数时,浏览器每次都会传递进两个隐含的参数: 97 | 98 | - 1.函数的上下文对象 this 99 | 100 | - 2.**封装实参的对象** arguments 101 | 102 | 103 | 例如: 104 | 105 | ```javascript 106 | function foo() { 107 | console.log(arguments); 108 | console.log(typeof arguments); 109 | } 110 | 111 | foo(); 112 | ``` 113 | 114 | ![](http://img.smyhvae.com/20180315_0903.png) 115 | 116 | 117 | 118 | arguments是一个类数组对象,它可以通过索引来操作数据,也可以获取长度。 119 | 120 | **arguments代表的是实参**。在调用函数时,我们所传递的实参都会在arguments中保存。有个讲究的地方是:arguments**只在函数中使用**。 121 | 122 | 123 | 124 | 125 | ### 1、返回函数**实参**的个数:arguments.length 126 | 127 | 128 | arguments.length可以用来获取**实参的长度**。 129 | 130 | 举例: 131 | 132 | ```javascript 133 | fn(2,4); 134 | fn(2,4,6); 135 | fn(2,4,6,8); 136 | 137 | function fn(a,b) { 138 | console.log(arguments); 139 | console.log(fn.length); //获取形参的个数 140 | console.log(arguments.length); //获取实参的个数 141 | 142 | console.log("----------------"); 143 | } 144 | ``` 145 | 146 | 打印结果: 147 | 148 | ![](http://img.smyhvae.com/20180125_2140.png) 149 | 150 | 我们即使不定义形参,也可以通过arguments来使用实参(只不过比较麻烦):arguments[0] 表示第一个实参、arguments[1] 表示第二个实参... 151 | 152 | ### 2、返回正在执行的函数:arguments.callee 153 | 154 | arguments里边有一个属性叫做callee,这个属性对应一个函数对象,就是当前正在指向的函数对象。 155 | 156 | ```javascript 157 | function fun() { 158 | 159 | console.log(arguments.callee == fun); //打印结果为true 160 | } 161 | 162 | fun("hello"); 163 | ``` 164 | 165 | 在使用函数**递归**调用时,推荐使用arguments.callee代替函数名本身。 166 | 167 | ### 3、arguments可以修改元素 168 | 169 | 之所以说arguments是伪数组,是因为:**arguments可以修改元素,但不能改变数组的长短**。举例: 170 | 171 | ```javascript 172 | fn(2,4); 173 | fn(2,4,6); 174 | fn(2,4,6,8); 175 | 176 | function fn(a,b) { 177 | arguments[0] = 99; //将实参的第一个数改为99 178 | arguments.push(8); //此方法不通过,因为无法增加元素 179 | } 180 | 181 | ``` 182 | 183 | ## 我的公众号 184 | 185 | 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 186 | 187 | 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: 188 | 189 | ![](http://img.smyhvae.com/2016040102.jpg) 190 | 191 | 192 | -------------------------------------------------------------------------------- /14-前端面试/05-01.创建对象和原型链.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 前言 4 | 5 | ### 面向对象的三大特性 6 | 7 | - 封装 8 | 9 | - 继承 10 | 11 | - 多态 12 | 13 | ### 原型链的知识 14 | 15 | 16 | 原型链是面向对象的基础,是非常重要的部分。有以下几种知识: 17 | 18 | - 创建对象有几种方法 19 | 20 | - 原型、构造函数、实例、原型链 21 | 22 | - `instanceof`的原理 23 | 24 | - new 运算符 25 | 26 | 27 | 28 | ## 创建对象有几种方法 29 | 30 | ### 方式一:字面量 31 | 32 | ```javascript 33 | var obj11 = {name: 'qianguyihao'}; 34 | var obj12 = new Object(name: 'qianguyihao'); //内置对象(内置的构造函数) 35 | ``` 36 | 37 | 上面的两种写法,效果是一样的。因为,第一种写法,`obj11`会指向`Object`。 38 | 39 | - 第一种写法是:字面量的方式。 40 | 41 | - 第二种写法是:内置的构造函数 42 | 43 | 44 | ### 方式二:通过构造函数 45 | 46 | 47 | ```javascript 48 | var M = function (name) { 49 | this.name = name; 50 | } 51 | var obj3 = new M('smyhvae'); 52 | ``` 53 | 54 | ### 方法三:Object.create 55 | 56 | ```javascript 57 | var p = {name:'smyhvae'}; 58 | var obj3 = Object.create(p); //此方法创建的对象,是用原型链连接的 59 | ``` 60 | 61 | 第三种方法,很少有人能说出来。这种方式里,obj3是实例,p是obj3的原型(name是p原型里的属性),构造函数是`Objecet` 。 62 | 63 | ![](http://img.smyhvae.com/20180306_1633.png) 64 | 65 | 66 | ## 原型、构造函数、实例,以及原型链 67 | 68 | 69 | ![](http://img.smyhvae.com/20180306_1540.png) 70 | 71 | PS:任何一个函数,如果在前面加了new,那就是构造函数。 72 | 73 | ### 原型、构造函数、实例三者之间的关系 74 | 75 | ![](http://img.smyhvae.com/20180306_2107.png) 76 | 77 | - 1、构造函数通过 new 生成实例 78 | 79 | - 2、构造函数也是函数,构造函数的`prototype`指向原型。(所有的函数有`prototype`属性,但实例没有 `prototype`属性) 80 | 81 | - 3、原型对象中有 constructor,指向该原型的构造函数。 82 | 83 | 上面的三行,代码演示: 84 | 85 | ``` 86 | var Foo = function (name) { 87 | this.name = name; 88 | } 89 | 90 | var foo = new Foo('smyhvae'); 91 | ``` 92 | 93 | 上面的代码中,`Foo.prototype.constructor === Foo`的结果是`true`: 94 | 95 | ![](http://img.smyhvae.com/20180306_2120.png) 96 | 97 | 98 | - 4、实例的`__proto__`指向原型。也就是说,`foo.__proto__ === Foo.prototype`。 99 | 100 | 声明:所有的**引用类型**(数组、对象、函数)都有`__proto__`这个属性。 101 | 102 | `Foo.__proto__ === Function.prototype`的结果为true,说明Foo这个普通的函数,是Function构造函数的一个实例。 103 | 104 | 105 | 106 | ### 原型链 107 | 108 | **原型链的基本原理**:任何一个**实例**,通过原型链,找到它上面的**原型**,该原型对象中的方法和属性,可以被所有的原型实例共享。 109 | 110 | 111 | Object是原型链的顶端。 112 | 113 | 原型可以起到继承的作用。原型里的方法都可以被不同的实例共享: 114 | 115 | ``` 116 | //给Foo的原型添加 say 函数 117 | Foo.prototype.say = function () { 118 | console.log(''); 119 | } 120 | ``` 121 | 122 | **原型链的关键**:在访问一个实例的时候,如果实例本身没找到此方法或属性,就往原型上找。如果还是找不到,继续往上一级的原型上找。 123 | 124 | 125 | ### `instanceof`的原理 126 | 127 | ![](http://img.smyhvae.com/20180306_2209.png) 128 | 129 | 130 | `instanceof`的**作用**:用于判断**实例**属于哪个**构造函数**。 131 | 132 | `instanceof`的**原理**:判断实例对象的`__proto__`属性,和构造函数的`prototype`属性,是否为同一个引用(是否指向同一个地址)。 133 | 134 | **注意1**:虽然说,实例是由构造函数 new 出来的,但是实例的`__proto__`属性引用的是构造函数的`prototype`。也就是说,实例的`__proto__`属性与构造函数本身无关。 135 | 136 | **注意2**:在原型链上,原型的上面可能还会有原型,以此类推往上走,继续找`__proto__`属性。这条链上如果能找到, instanceof 的返回结果也是 true。 137 | 138 | 比如说: 139 | 140 | - `foo instance of Foo`的结果为true,因为`foo.__proto__ === Foo.prototype`为true。 141 | 142 | - **`foo instance of Objecet`的结果也为true**,因为`Foo.prototype.__proto__ === Object.prototype`为true。 143 | 144 | 145 | 但我们不能轻易的说:`foo 一定是 由Object创建的实例`。这句话是错误的。我们来看下一个问题就明白了。 146 | 147 | ### 分析一个问题 148 | 149 | **问题:**已知A继承了B,B继承了C。怎么判断 a 是由A**直接生成**的实例,还是B直接生成的实例呢?还是C直接生成的实例呢? 150 | 151 | 分析:这就要用到原型的`constructor`属性了。 152 | 153 | - `foo.__proto__.constructor === Foo`的结果为true,但是 `foo.__proto__.constructor === Object`的结果为false。 154 | 155 | 所以,用 consturctor判断就比用 instanceof判断,更为严谨。 156 | 157 | 158 | ## new 运算符 159 | 160 | 当new Foo()时发生了什么: 161 | 162 | (1)创建一个**新的空对象实例**。 163 | 164 | (2)将此空对象的隐式原型指向其构造函数的显示原型。 165 | 166 | (3)执行构造函数(传入相应的参数,如果没有参数就不用传),同时 this 指向这个新实例。 167 | 168 | (4)如果返回值是一个新对象,那么直接返回该对象;如果无返回值或者返回一个非对象值,那么就将步骤(1)创建的对象返回。 169 | 170 | 参考《JS高程》6.2.2 171 | 172 | 173 | ## 类继承和原型继承的区别 174 | 175 | 176 | 177 | 178 | 179 | ```javascript 180 | 181 | 182 | 183 | 184 | 185 | ``` 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /14-前端面试/07-安全问题:CSRF和XSS.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前言 3 | 4 | 面试中的安全问题,明确来说,就两个方面: 5 | 6 | - CSRF:基本概念、攻击方式、防御措施 7 | 8 | - XSS:基本概念、攻击方式、防御措施 9 | 10 | 这两个问题,一般不会问太难。 11 | 12 | 有人问:SQL注入算吗?答案:这个其实跟前端的关系不是很大。 13 | 14 | 15 | ## CSRF 16 | 17 | 问的不难,一般问: 18 | 19 | - CSRF的基本概念、缩写、全称 20 | 21 | - 攻击原理 22 | 23 | - 防御措施 24 | 25 | 如果把**攻击原理**和**防御措施**掌握好,基本没什么问题。 26 | 27 | 28 | ### 1、CSRF的基本概念、缩写、全称 29 | 30 | CSRF(Cross-site request forgery):**跨站请求伪造**。 31 | 32 | PS:中文名一定要记住。英文全称,如果记不住也拉倒。 33 | 34 | 35 | ### 2、CSRF的攻击原理 36 | 37 | ![](http://img.smyhvae.com/20180307_1735.png) 38 | 39 | 用户是网站A的注册用户,且登录进去,于是网站A就给用户下发cookie。 40 | 41 | 从上图可以看出,要完成一次CSRF攻击,受害者必须满足两个必要的条件: 42 | 43 | (1)登录受信任网站A,并在本地生成Cookie。(如果用户没有登录网站A,那么网站B在诱导的时候,请求网站A的api接口时,会提示你登录) 44 | 45 | (2)在不登出A的情况下,访问危险网站B(其实是利用了网站A的漏洞)。 46 | 47 | 我们在讲CSRF时,一定要把上面的两点说清楚。 48 | 49 | 温馨提示一下,cookie保证了用户可以处于登录状态,但网站B其实拿不到 cookie。 50 | 51 | 举个例子,前段时间里,微博网站有个api接口有漏洞,导致很多用户的粉丝暴增。 52 | 53 | ### 3、CSRF如何防御 54 | 55 | **方法一、Token 验证:**(用的最多) 56 | 57 | 58 | (1)服务器发送给客户端一个token; 59 | 60 | (2)客户端提交的表单中带着这个token。 61 | 62 | (3)如果这个 token 不合法,那么服务器拒绝这个请求。 63 | 64 | 65 | **方法二:隐藏令牌:** 66 | 67 | 把 token 隐藏在 http 的 head头中。 68 | 69 | 70 | 方法二和方法一有点像,本质上没有太大区别,只是使用方式上有区别。 71 | 72 | 73 | **方法三、Referer 验证:** 74 | 75 | Referer 指的是页面请求来源。意思是,**只接受本站的请求,服务器才做响应**;如果不是,就拦截。 76 | 77 | 78 | ## XSS 79 | 80 | ### 1、XSS的基本概念 81 | 82 | XSS(Cross Site Scripting):**跨域脚本攻击**。 83 | 84 | 85 | 接下来,我们详细讲一下 XSS 的内容。 86 | 87 | > 预备知识:HTTP、Cookie、Ajax。 88 | 89 | 90 | 91 | ### XSS的攻击原理 92 | 93 | XSS攻击的核心原理是:不需要你做任何的登录认证,它会通过合法的操作(比如在url中输入、在评论框中输入),向你的页面注入脚本(可能是js、hmtl代码块等)。 94 | 95 | 最后导致的结果可能是: 96 | 97 | - 盗用Cookie 98 | 99 | - 破坏页面的正常结构,插入广告等恶意内容 100 | 101 | - D-doss攻击 102 | 103 | ### XSS的攻击方式 104 | 105 | - 1、反射型 106 | 107 | 发出请求时,XSS代码出现在url中,作为输入提交到服务器端,服务器端解析后响应,XSS代码随响应内容一起传回给浏览器,最后浏览器解析执行XSS代码。这个过程像一次反射,所以叫反射型XSS。 108 | 109 | - 2、存储型 110 | 111 | 存储型XSS和反射型XSS的差别在于,提交的代码会存储在服务器端(数据库、内存、文件系统等),下次请求时目标页面时不用再提交XSS代码。 112 | 113 | ### XSS的防范措施(encode + 过滤) 114 | 115 | XSS的防范措施主要有三个: 116 | 117 | **1、编码**: 118 | 119 | 对用户输入的数据进行`HTML Entity`编码。 120 | 121 | 如上图所示,把字符转换成 转义字符。 122 | 123 | 124 | Encode的作用是将`$var`等一些字符进行转化,使得浏览器在最终输出结果上是一样的。 125 | 126 | 比如说这段代码: 127 | 128 | ``` 129 | 130 | ``` 131 | 132 | 若不进行任何处理,则浏览器会执行alert的js操作,实现XSS注入。 133 | 134 | 进行编码处理之后,L在浏览器中的显示结果就是``,实现了将$var作为纯文本进行输出,且不引起JavaScript的执行。 135 | 136 | 参考链接:[4类防御XSS的有效方法](https://www.jianshu.com/p/599fcd03fd3b) 137 | 138 | 139 | **2、过滤:** 140 | 141 | - 移除用户输入的和事件相关的属性。如onerror可以自动触发攻击,还有onclick等。(总而言之,过滤掉一些不安全的内容) 142 | 143 | - 移除用户输入的Style节点、Script节点、Iframe节点。(尤其是Script节点,它可是支持跨域的呀,一定要移除)。 144 | 145 | **3、校正** 146 | 147 | - 避免直接对`HTML Entity`进行解码。 148 | 149 | - 使用`DOM Parse`转换,校正不配对的DOM标签。 150 | 151 | 备注:我们应该去了解一下`DOM Parse`这个概念,它的作用是把文本解析成DOM结构。 152 | 153 | 154 | 比较常用的做法是,通过第一步的编码转成文本,然后第三步转成DOM对象,然后经过第二步的过滤。 155 | 156 | **还有一种简洁的答案:** 157 | 158 | 首先是encode,如果是富文本,就白名单。 159 | 160 | 161 | ## CSRF 和 XSS 的区别 162 | 163 | 面试官还可能喜欢问二者的区别。 164 | 165 | 区别一: 166 | 167 | - CSRF:需要用户先登录网站A,获取 cookie。 168 | 169 | - XSS:不需要登录。 170 | 171 | 172 | 区别二:(原理的区别) 173 | 174 | - CSRF:是利用网站A本身的漏洞,去请求网站A的api。 175 | 176 | - XSS:是向网站 A 注入 JS代码,然后执行 JS 里的代码,篡改网站A的内容。 177 | 178 | 179 | ## 其他 180 | 181 | ### XSS 182 | 183 | 关于XSS,推荐几个网站: 184 | 185 | - 186 | 187 | 里面列出了很多XSS的例子,可以长见识。如果你专门研究XSS,可以看看。 188 | 189 | - [FreeBuf网站上的专栏作者:Black-Hole](http://www.freebuf.com/author/black-hole) 190 | 191 | 比如,他的第一篇文章就讲到了[XSS的原理分析与解剖](http://www.freebuf.com/articles/web/40520.html)。有句话摘抄如下:弹窗只是测试xss的存在性和使用性。 192 | 193 | 比如,这个人还有篇文章写[自动化检测CSRF(第一章)](http://www.freebuf.com/articles/web/107207.html)。大公司做网站,一般会做嗅探服务(比如自动化工具做CSRF的检测、自动化的方式控制安全风险)。 194 | 195 | 另外,可能还有些工具,可以扫描代码本身有没有一些安全问题。 196 | 197 | - [GitHub | Cure53](https://github.com/cure53) 198 | 199 | 这是GitHub上的一个德国组织。 200 | 201 | 上面的项目都跟安全相关,有些仓库是可以直接运行的。如果你不需要定制,就可以直接用别人的,没必要自己写XSS库、XSS的过滤之类的,避免麻烦。 202 | 203 | 204 | -------------------------------------------------------------------------------- /03-CSS进阶/02-CSS布局.md: -------------------------------------------------------------------------------- 1 | 2 | ## 前言 3 | 4 | ### 常见的布局属性 5 | 6 | (1)`display` 确定元素的显示类型: 7 | 8 | - block:块级元素。 9 | 10 | - inline:行内元素。 11 | 12 | - inline-block:对外的表现是行内元素(不会独占一行),对内的表现是块级元素(可以设置宽高)。 13 | 14 | (2)`positon` 确定元素的位置: 15 | 16 | - static:默认属性值。 17 | 18 | - relative:相对定位。相对于元素本身进行偏移,**不会改变它所占据的空间**。 19 | 20 | - absolute:绝对定位。相对于父元素中最近的 relative/absolute 进行偏移,会脱离文档流。音标:[ˈæbsəluːt]。 21 | 22 | - fixed:固定定位。相对于可视区域固定,会脱离文档流。 23 | 24 | `relative`、`absolute`、`fixed`这三个属性,可以结合 z-index 来设置层级。 25 | 26 | ### 常见的布局方法 27 | 28 | 1、**table 表格布局**:早期使用的布局,如今用得很少。 29 | 30 | 2、**float 浮动 + margin**:为了兼容低版本的IE浏览器,很多网站(比如腾讯新闻、网易新闻、淘宝等)都会采用 float 布局。 31 | 32 | 3、**inline-block 布局**:对外的表现是行内元素(不会独占一行),对内的表现是块级元素(可以设置宽高)。 33 | 34 | 4、**flex 布局**:为布局而生,非常灵活,是最为推荐的布局写法。 35 | 36 | 唯一的缺点是兼容性问题: 37 | 38 | ![](http://img.smyhvae.com/20191005_1200.png) 39 | 40 | 上图中可以看到, flex 布局不支持 IE9 及以下的版本。如果你的页面不需要处理 IE浏览器的兼容性问题,则可以放心大胆地使用 flex 布局。 41 | 42 | flex 是一种现代的布局方式,是 W3C 第一次提供真正用于布局的 CSS 规范。 43 | 44 | 5、响应式布局。 45 | 46 | ## float 布局 47 | 48 | 是 CSS 中一种比较麻烦的属性,涉及到 BFC 和清除浮动(面试的重点)。 49 | 50 | ### float 属性的特点 51 | 52 | - 元素浮动 53 | 54 | - **脱离文档流,但不脱离文本流** 55 | 56 | 代码举例: 57 | 58 | 下面这两个并列的`div1`和`div2`,默认是在标准流中的: 59 | 60 | ![](http://img.smyhvae.com/20191005_2029.png) 61 | 62 | 在此基础之上,如果给`div1`增加`float: left`属性后,效果如下: 63 | 64 | ![](http://img.smyhvae.com/20191005_2037.png) 65 | 66 | 上图中,可以看到,`div1`设置为浮动后,会脱离文档流,不会对`div2`的布局造成影响;但是`div1`不会脱离文本流,它会影响`div2`中文字的排列。 67 | 68 | 其实,这正是 float 属性的作用。float 本身是用来做图文混排、文字环绕的效果。 69 | 70 | ### float 所带来的影响 71 | 72 | **1、对自身的影响**: 73 | 74 | - 形成“块”(BFC) 75 | 76 | - 位置尽量靠上 77 | 78 | - 位置尽量靠左/右 79 | 80 | 下面这两个并列的`div1`和`div2`,设置为浮动之后的效果:(都是尽量靠左显示的) 81 | 82 | ![](http://img.smyhvae.com/20191005_2130.png) 83 | 84 | 在上方代码的基础之上,增加 `div2`的宽度之后,会发现,`div2`掉下来了: 85 | 86 | ![](http://img.smyhvae.com/20191005_2135.png) 87 | 88 | **2、对兄弟元素的影响**: 89 | 90 | - 不影响其他块级元素的位置 91 | 92 | - 影响其他块级元素的内部文本 93 | 94 | **3、对父级元素的影响**: 95 | 96 | - 从父级的布局中“消失” 97 | 98 | - 造成父级元素的高度塌陷:父级元素撑开 div1 之后(父级元素里没有其他元素的情况下),如果设置 div1 为 float 之后,,会让父级元素的高度变为0。 99 | 100 | ## inline-block 布局 101 | 102 | 对外的表现是行内元素(不会独占一行),对内的表现是块级元素(可以设置宽高)。 103 | 104 | **思路**:像文本一样去排列 block 元素,没有清除浮动等问题。 105 | 106 | **存在的问题**:需要处理间隙。代码举例如下: 107 | 108 | ```html 109 | 110 | 111 | 112 | 113 | 114 | 115 | Document 116 | 117 | 142 | 143 | 144 |
145 |
div1的inline-block 属性
146 |
div2的inline-block 属性
147 |
148 | 琴棋书画不会,洗衣做饭嫌累。 149 |
150 |
151 | 152 | 153 | 154 | ``` 155 | 156 | ![](http://img.smyhvae.com/20191005_2200.png) 157 | 158 | 上面的代码,存在两个问题。 159 | 160 | **问题一**:如果设置`div2`的宽度为 200px 之后,`div2` 掉下来。 161 | 162 | **问题二**:`div1`和`div2`设置为 inline-block之后,这两个盒子之间存在了间隙。这是因为,此时的 `div1`和`div2` 已经被当成文本了。文本和文本之间,本身就会存在间隙。 163 | 164 | 为了去掉这个间隙,可以有几种解决办法: 165 | 166 | 办法1:设置父元素`container`的字体大小为0,即`font-size: 0`,然后设置子元素 `div1`、`div2`的字体`font-size: 12px`。 167 | 168 | 办法2:在写法上,去掉`div1`和`div2`之间的换行。改为: 169 | 170 | ```html 171 |
div1的inline-block 属性
div2的inline-block 属性
172 | ``` 173 | 174 | ## 响应式布局 175 | 176 | 移动端用得较多,本文暂时先不讲。 177 | 178 | 179 | -------------------------------------------------------------------------------- /04-JavaScript基础/44-client(可视区)相关属性.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## client 家族的组成 5 | 6 | ### clientWidth 和 clientHeight 7 | 8 | 元素调用时: 9 | 10 | - clientWidth:获取元素的可见宽度(width + padding)。 11 | 12 | - clientHeight:获取元素的可见高度(height + padding)。 13 | 14 | 15 | body/html 调用时: 16 | 17 | - clientWidth:获取网页可视区域宽度。 18 | 19 | - clientHeight:获取网页可视区域高度。 20 | 21 | **声明**: 22 | 23 | - `clientWidth` 和 `clientHeight` 属性是只读的,不可修改。 24 | 25 | - `clientWidth` 和 `clientHeight` 的值都是不带 px 的,返回的都是一个数字,可以直接进行计算。 26 | 27 | 28 | ### clientX 和 clientY 29 | 30 | event调用: 31 | 32 | - clientX:鼠标距离可视区域左侧距离。 33 | 34 | - clientY:鼠标距离可视区域上侧距离。 35 | 36 | 37 | 38 | ### clientTop 和 clientLeft 39 | 40 | - clientTop:盒子的上border。 41 | 42 | - clientLeft:盒子的左border。 43 | 44 | 45 | ## 三大家族 offset/scroll/client 的区别 46 | 47 | ### 区别1:宽高 48 | 49 | - offsetWidth = width + padding + border 50 | - offsetHeight = height + padding + border 51 | 52 | - scrollWidth = 内容宽度(不包含border) 53 | - scrollHeight = 内容高度(不包含border) 54 | 55 | - clientWidth = width + padding 56 | - clientHeight = height + padding 57 | 58 | 59 | ### 区别2:上左 60 | 61 | 62 | offsetTop/offsetLeft: 63 | 64 | - 调用者:任意元素。(盒子为主) 65 | - 作用:距离父系盒子中带有定位的距离。 66 | 67 | 68 | scrollTop/scrollLeft: 69 | 70 | - 调用者:document.body.scrollTop(window调用)(盒子也可以调用,但必须有滚动条) 71 | - 作用:浏览器无法显示的部分(被卷去的部分)。 72 | 73 | 74 | clientY/clientX: 75 | 76 | - 调用者:event 77 | - 作用:鼠标距离浏览器可视区域的距离(左、上)。 78 | 79 | 80 | 81 | 82 | ## 函数封装:获取浏览器的宽高(可视区域) 83 | 84 | 函数封装如下: 85 | 86 | ```javascript 87 | //函数封装:获取屏幕可视区域的宽高 88 | function client() { 89 | if (window.innerHeight !== undefined) { 90 | //ie9及其以上的版本的写法 91 | return { 92 | "width": window.innerWidth, 93 | "height": window.innerHeight 94 | } 95 | } else if (document.compatMode === "CSS1Compat") { 96 | //标准模式的写法(有DTD时) 97 | return { 98 | "width": document.documentElement.clientWidth, 99 | "height": document.documentElement.clientHeight 100 | } 101 | } else { 102 | //没有DTD时的写法 103 | return { 104 | "width": document.body.clientWidth, 105 | "height": document.body.clientHeight 106 | } 107 | } 108 | } 109 | 110 | ``` 111 | 112 | 113 | **案例:根据浏览器的可视宽度,给定不同的背景的色。** 114 | 115 | > PS:这个可以用来做响应式。 116 | 117 | 代码如下:(需要用到上面的封装好的方法) 118 | 119 | ```html 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 148 | 149 | 150 | ``` 151 | 152 | 153 | 上当代码中,`window.onresize`事件指的是:在窗口或框架被调整大小时发生。各个事件的解释如下: 154 | 155 | - window.onscroll 屏幕滑动 156 | 157 | - window.onresize 浏览器大小变化 158 | 159 | - window.onload 页面加载完毕 160 | 161 | - div.onmousemove 鼠标在盒子上移动(注意:不是盒子移动) 162 | 163 | 164 | 165 | ## 获取显示器的分辨率 166 | 167 | 比如,我的电脑的显示器分辨率是:1920*1080。 168 | 169 | 170 | 获取显示器的分辨率: 171 | 172 | ```javascript 173 | window.onresize = function () { 174 | document.title = window.screen.width + " " + window.screen.height; 175 | } 176 | ``` 177 | 178 | 显示效果: 179 | 180 | 181 | ![](http://img.smyhvae.com/20180203_2155.png) 182 | 183 | 184 | 上图中,不管我如何改变浏览器的窗口大小,title栏显示的值永远都是我的显示器分辨率:1920*1080。 185 | 186 | 187 | 188 | 189 | ## 我的公众号 190 | 191 | 想学习**代码之外的技能**?不妨关注我的微信公众号:**千古壹号**(id:`qianguyihao`)。 192 | 193 | 扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: 194 | 195 | ![](http://img.smyhvae.com/20190101.png) 196 | 197 | 198 | -------------------------------------------------------------------------------- /16-前端进阶/前端的几道题目.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 几道面试题 4 | 5 | ## 页面布局 6 | 7 | ### 如何实现一个三栏布局,要求两边固定宽度、中间自适应。 8 | 9 | 此题可以考察的知识点: 10 | 11 | - 圣杯布局 12 | 13 | - 双飞翼布局 14 | 15 | - flex布局(css3) 16 | 17 | 18 | ### 让元素垂直居中 19 | 20 | **方式一:**如果宽高已知,可以利用绝对定位。 21 | 22 | **方式二:**用 translate 位移来做。(在宽高未知的情况下,也可以这样做) 23 | 24 | ```css 25 | div { 26 | background-color: red; 27 | position: absolute; 绝对定位的盒子 28 | top: 50%; 首先,让上边线居中 29 | transform: translateY(-50%); 然后,利用translate,往上走自己宽度的一半【推荐写法】 30 | } 31 | ``` 32 | 33 | 34 | **方式三:**flex 布局 35 | 36 | ```css 37 | parentElement{ 38 | display: flex;/*Flex布局*/ 39 | display: -webkit-flex; /* Safari */ 40 | align-items: center;/*设置子元素在侧轴方向上的布局*/ 41 | } 42 | ``` 43 | 44 | 45 | 参考链接: 46 | 47 | - 48 | 49 | - [水平垂直居中方案与flexbox布局](https://www.cnblogs.com/coco1s/p/4444383.html) 50 | 51 | 52 | 53 | 54 | ## 变量提升 55 | 56 | 57 | **问题**:说一下你对JavaScript变量提升的理解。 58 | 59 | **定义**: 60 | 61 | 在函数体内部,声明变量,会把该变量提升到函数体的最顶端。注意:**只提升变量声明,不赋值**。 62 | 63 | **代码1**: 64 | 65 | ```javascript 66 | fn(); 67 | 68 | function fn() { 69 | var x = 1; 70 | var y = 2; 71 | } 72 | ``` 73 | 74 | 75 | 上方代码中: 76 | 77 | (1)给fn创建函数上下文,找到fn中**所有**用var声明的变量(即x和y); 78 | 79 | (2)将这些变量初始化为undefined; 80 | 81 | (3)将x赋值为1,将y赋值为2。 82 | 83 | 84 | **代码2**: 85 | 86 | 87 | ```javascript 88 | fn2(); 89 | 90 | function fn2() { 91 | console.log(2); 92 | 93 | } 94 | ``` 95 | 96 | 97 | 上方代码中: 98 | 99 | (1)创建全局上下文,找到所有用function声明的变量,在环境中“创建”这些变量。 100 | 101 | (2)将这些变量**初始化**,并**赋值**为 `function(){ console.log(2) }`(并不是undefined) 102 | 103 | (3)开始执行代码`fn2();` 104 | 105 | **代码3**:(let的出现) 106 | 107 | ```javascript 108 | { 109 | let x = 1 110 | x = 2 111 | } 112 | ``` 113 | 114 | 115 | 上方代码中: 116 | 117 | (1)找到所有用 let 声明的变量,在环境中「创建」这些变量 118 | 119 | (2)开始执行代码(注意现在还没有初始化) 120 | 121 | (3)执行 x = 1,将 x 「初始化」为 1(这并不是一次赋值,如果代码是 let x,就将 x 初始化为 undefined) 122 | 123 | (4)执行 x = 2,对 x 进行「赋值」 124 | 125 | 126 | 127 | 代码4: 128 | 129 | ```javascript 130 | let x = 'global' 131 | { 132 | console.log(x) // Uncaught ReferenceError: x is not defined 133 | let x = 1 134 | } 135 | ``` 136 | 137 | 原因有两个: 138 | 139 | - console.log(x) 中的 x 指的是下面的 x,而不是全局的 x 140 | 141 | - 执行 log 时 x 还没「初始化」,所以不能使用(也就是所谓的暂时死区) 142 | 143 | 看到这里,你应该明白了 let 到底有没有提升: 144 | 145 | - let 的「创建」过程被提升了,但是初始化没有提升。 146 | 147 | - var 的「创建」和「初始化」都被提升了。 148 | 149 | - function 的「创建」「初始化」和「赋值」都被提升了。 150 | 151 | 152 | 参考链接: 153 | 154 | - [我用了两个月的时间才理解 let](https://zhuanlan.zhihu.com/p/28140450) 155 | 156 | 157 | ### this 158 | 159 | 问题:下方代码的打印结果是什么? 160 | 161 | ```javascript 162 | function A() { 163 | this.name = 'smyhvae'; 164 | } 165 | 166 | A.prototype.test = function () { 167 | setTimeout(function () { 168 | console.log(this.name); 169 | }, 1) 170 | } 171 | 172 | var a = new A(); 173 | a.test(); 174 | ``` 175 | 176 | 打印结果是window.name,但实际的结果是空的。 177 | 178 | 这个神奇的特性,被用来解决跨域数据传递。(网上可以查一下iframe相关) 179 | 180 | 181 | 182 | **总结1**:this永远指向**函数运行时所在的对象**,而不是函数被创建时所在的对象。即:**谁调用**,指向谁。 183 | 184 | **举例**: 185 | 186 | ```javascript 187 | var name = '全局'; 188 | 189 | function getName() { 190 | var name = '局部'; 191 | return this.name; 192 | }; 193 | 194 | alert(getName()); 195 | 196 | ``` 197 | 198 | 上方代码的打印结果是:`全局`。 199 | 200 | 分析:`getName()`这个函数其实是window调用的,所以this指向的window,因为外部有name这个变量,所以打印结果为`全局`。 201 | 202 | 203 | **总结2**:没有明确的当前对象时,this永远指向window。这个在setTimeout里比较常见。 204 | 205 | 206 | 207 | ### apply、call、bind的区别 208 | 209 | 210 | 211 | 212 | 213 | ## 链式调用 214 | 215 | **问题**:如何实现类似jQuery的链式调用? 216 | 217 | 答案:一直return `this`就好了。 218 | 219 | 220 | ## Yslow和pageSpeed 221 | 222 | 223 | Yslow和pageSpeed你知道怎么用吗?你记得其中多少规则? 224 | 225 | 226 | 227 | ## DNS的查询时间 228 | 229 | **问题:**前端怎样拿到DNS的查询时间? 230 | 231 | ### H5中的方法:performance.timing 232 | 233 | window.performance这个api可以用来做前端性能监控。其中,timing这个方法。。 234 | 235 | 236 | 参考链接: 237 | 238 | - 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /06-前端基本功:CSS和DOM练习/05-DOM操作练习:访问关系的封装.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 访问关系的函数封装 5 | 6 | (1)函数封装 7 | 8 | 新建一个文件名叫`tools.js`,然后在里面封装访问关系。代码如下。 9 | 10 | 11 | 12 | tools.js: 13 | 14 | ```javascript 15 | /** 16 | * Created by smyhvae on 2018/01/28. 17 | */ 18 | 19 | function getEle(id){ 20 | return document.getElementById(id); 21 | } 22 | 23 | /** 24 | * 功能:给定元素查找他的第一个元素子节点,并返回 25 | * @param ele 26 | * @returns {Element|*|Node} 27 | */ 28 | function getFirstNode(ele){ 29 | var node = ele.firstElementChild || ele.firstChild; 30 | return node; 31 | } 32 | 33 | /** 34 | * 功能:给定元素查找他的最后一个元素子节点,并返回 35 | * @param ele 36 | * @returns {Element|*|Node} 37 | */ 38 | function getLastNode(ele){ 39 | return ele.lastElementChild || ele.lastChild; 40 | } 41 | 42 | /** 43 | * 功能:给定元素查找他的下一个元素兄弟节点,并返回 44 | * @param ele 45 | * @returns {Element|*|Node} 46 | */ 47 | function getNextNode(ele){ 48 | return ele.nextElementSibling || ele.nextSibling; 49 | } 50 | 51 | /** 52 | * 功能:给定元素查找他的上一个兄弟元素节点,并返回 53 | * @param ele 54 | * @returns {Element|*|Node} 55 | */ 56 | function getPrevNode(ele){ 57 | return ele.previousElementSibling || ele.previousSibling; 58 | } 59 | 60 | /** 61 | * 功能:给定元素和索引值查找指定索引值的兄弟元素节点,并返回 62 | * @param ele 元素节点 63 | * @param index 索引值 64 | * @returns {*|HTMLElement} 65 | */ 66 | function getEleOfIndex(ele,index){ 67 | return ele.parentNode.children[index]; 68 | } 69 | 70 | /** 71 | * 功能:给定元素查找他的所有兄弟元素,并返回数组 72 | * @param ele 73 | * @returns {Array} 74 | */ 75 | function getAllSiblings(ele){ 76 | //定义一个新数组,装所有的兄弟元素,将来返回 77 | var newArr = []; 78 | var arr = ele.parentNode.children; 79 | for(var i=0;i 119 | 120 | 121 | 122 | 123 | 132 | 133 | 134 | 135 |
    136 |
  • 137 |
  • 138 |
  • 139 |
  • 140 |
  • 141 |
142 | 143 | 170 | 171 | 172 | 173 | ``` 174 | 175 | 注意:上方代码中,我们引用到了`tools.js`这个工具类。 176 | 177 | 178 | 179 | 180 | 181 | ``` 182 | 183 | 184 | ``` 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | ``` 194 | 195 | 196 | ``` 197 | 198 | 199 | 200 | 201 | ``` 202 | 203 | 204 | ``` 205 | 206 | 207 | -------------------------------------------------------------------------------- /00-前端工具/04-WebStorm的使用.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## WebStorm的简单设置 5 | 6 | #### 1、主题修改: 7 | 8 | 可能大家会觉得软件的界面不太好看,我们可以换一下主题。选择菜单栏“File--settings--apperance--theme”,主题选择Darcula: 9 | 10 | ![](http://img.smyhvae.com/20180118_1600.png) 11 | 12 | #### 2、导入第三方主题: 13 | 14 | 系统提供的两种主题可能都不太好看,我们可以进入网站来获取第三方主题,这里推荐两个主题,大家二选一即可: 15 | 16 | - [Sublime](https://github.com/y3sh/Intellij-Colors-Sublime-Monokai) 17 | 18 | - [Material](https://github.com/ChrisRM/material-theme-jetbrains) 19 | 20 | ![](http://img.smyhvae.com/20180118_1636.png) 21 | 22 | ![](http://img.smyhvae.com/20180118_1637.png) 23 | 24 | 上图中,在网站中将主题下载之后,是一个jar包。那怎么导入到WebStorm呢? 25 | 26 | 别着急,回到WebStorm,选择菜单栏“ File-Import Settings”,将下载好的jar包导入即可。 27 | 28 | 29 | 30 | #### 3、代码字体修改: 31 | 32 | 选择菜单栏“File--settings--Editor--Font”: 33 | 34 | ![](http://img.smyhvae.com/20180118_1627.png) 35 | 36 | 上图中,点击红框部分,然后弹出如下界面: 37 | 38 | ![](http://img.smyhvae.com/20180118_1628.png) 39 | 40 | 我们在上图中修改代码的字体。 41 | 42 | 修改完之后发现 WebStorm 的一些默认字体(比如侧边栏的工程目录的字体)并没有发生变化,如果想改的话,也可以改(我个人一般是不改的)。 43 | 44 | 45 | 46 | #### 4、关闭更新: 47 | 48 | 如下图所示: 49 | 50 | ![](http://img.smyhvae.com/20180118_1646.png) 51 | 52 | #### 5、快捷键习惯的修改: 53 | 54 | 55 | 56 | 57 | #### 7、配置代码的自动提示: 58 | 59 | 60 | 61 | #### 14、修改文件编码为UTF-8: 62 | 63 | WebStorm 2017.3.3版本的默认编码方式是 GBK,我们还是统一设置为UTF-8吧,不要坑队友哦: 64 | 65 | ![](http://img.smyhvae.com/20180124_1856.png) 66 | 67 | 68 | ### 新建一个空的项目 69 | 70 | 配置完成后,可以开始新建一个项目文件夹(站点),项目通常包含如下内容: 71 | 72 | - 首页:index.html 73 | 74 | - 样式:css文件夹 75 | - index.css 76 | - 相同样式:全局样式、公共样式。起名为:base.css(基本样式)或者 global.css (全局样式) 77 | 78 | - 图片:images文件夹、文件 79 | 80 | - 特效:js文件夹、js文件 81 | 82 | **步骤如下:** 83 | 84 | (1)新建一个空的项目: 85 | ![](http://img.smyhvae.com/20180118_1720.png) 86 | 87 | (2)然后新建一个html文件: 88 | 89 | ![](http://img.smyhvae.com/20180118_1602.png) 90 | 91 | (3)新建一个空的文件夹,命名为`css`: 92 | 93 | ![](http://img.smyhvae.com/20180118_1725.png) 94 | 95 | 然后在这个css文件夹中,新建样式表:(比如index.css\base.css) 96 | 97 | ![](http://img.smyhvae.com/20180118_1730.png) 98 | 99 | (4)最后新建一个images文件夹,用于存放土片。这样的话,一个基本的项目结构就搭建好了: 100 | 101 | ![](http://img.smyhvae.com/20180118_1733.png) 102 | 103 | 接下来,开始运用起你们的前端知识吧。 104 | 105 | 106 | 107 | (5)如果要新建JS文件的话,操作如下: 108 | 109 | ![](http://img.smyhvae.com/20180124_1859.png) 110 | 111 | 112 | 113 | ## 使用技巧 114 | 115 | 116 | 117 | #### 多光标编辑 118 | 119 | 我们可以按住鼠标不松手,选中多个光标,然后同时编辑: 120 | 121 | 122 | #### 随时在浏览器中看代码效果 123 | 124 | 20180118_1658.png 125 | 126 | 如上图所示,我们可以点击右上角的浏览器图标,在各个浏览器中看效果。 127 | 128 | 129 | #### 实时查看颜色 130 | 131 | 写代码时如果想输入颜色,会自动提示颜色的预览。 132 | 133 | ![](http://img.smyhvae.com/20180118_1702.png) 134 | 135 | 点击最左侧的颜色预览,还能弹出调色板: 136 | 137 | ![](http://img.smyhvae.com/20180118_1710.gif) 138 | 139 | 140 | 141 | 142 | 143 | 144 | ## 代码的自动补齐 145 | 146 | 147 | (1)在html文档中,输入`div*10`,按tab键后,弹出的效果如下: 148 | 149 | ```html 150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | ``` 161 | 162 | 163 | 164 | (2)在html文档中,输入如下部分: 165 | 166 | ``` 167 | .search-logo+.search-input+.search-car+.search-moreA 168 | ``` 169 | 170 | 按tab键后,弹出的效果如下: 171 | 172 | ```html 173 | 174 |
175 |
176 |
177 | ``` 178 | 179 | 你看,京东的搜索框就包含了这几个div: 180 | 181 | 20180122_1045.png 182 | 183 | (3)方法的注释: 184 | 185 | 方法写完之后(注意,一定要先写完整),我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。 186 | 187 | 比如: 188 | 189 | ```javascript 190 | /** 191 | * 功能:给定元素查找他的第一个元素子节点,并返回 192 | * @param ele 193 | * @returns {Element|*|Node} 194 | */ 195 | function getFirstNode(ele){ 196 | var node = ele.firstElementChild || ele.firstChild; 197 | return node; 198 | } 199 | ``` 200 | 201 | 202 | ## 常用快捷键 203 | 204 | #### 标签环绕 205 | 206 | 输入一段字符后,按住`Ctrl + Alt + T`,可以用标签将这段字符环绕: 207 | 208 | ![](http://img.smyhvae.com/20180118_1719.gif) 209 | 210 | 211 | 212 | #### 选中正行中的文本 213 | 214 | 比如下面这行: 215 | 216 | ``` 217 | text-align: center; /*让 li 里面的文本水平方向居中*/ 218 | 219 | ``` 220 | 221 | 如果直接按 【ctrl+C】的话,复制的是整行的内容,把前面的空格也包含进去了。如果不想复制空格,有另外一个办法:将光标放在行尾,然后按住【shift+home】,就能选中你想要的内容了。 222 | 223 | 224 | 225 | 226 | -------------------------------------------------------------------------------- /05-JavaScript进阶/创建对象和继承.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 创建对象的几种方式 5 | 6 | ### 通过Object 7 | 8 | ```html 9 | 10 | 11 | 12 | 13 | 01_Object构造函数模式 14 | 15 | 16 | 22 | 43 | 44 | 45 | 46 | ``` 47 | 48 | 49 | ### 方式二:对象字面量 50 | 51 | ```html 52 | 53 | 54 | 55 | 56 | 02_对象字面量 57 | 58 | 59 | 65 | 88 | 89 | 90 | ``` 91 | 92 | 93 | 94 | ### 方式三:工厂模式 95 | 96 | - 方式:通过工厂函数动态创建对象并返回。 97 | 98 | 返回一个对象的函数,就是**工厂函数**。 99 | 100 | - 适用场景: 需要创建多个对象。 101 | 102 | - 问题: 对象没有一个具体的类型,都是Object类型。 103 | 104 | 由于这个问题的存在,工厂模式用得不多。 105 | 106 | ```html 107 | 108 | 109 | 110 | 111 | 03_工厂模式 112 | 113 | 114 | 120 | 152 | 153 | 154 | 155 | ``` 156 | 157 | 158 | 159 | ### 方式四:自定义构造函数 160 | 161 | ```html 162 | 163 | 164 | 165 | 166 | 04_自定义构造函数模式 167 | 168 | 169 | 170 | 176 | 204 | 205 | 206 | 207 | ``` 208 | 209 | 210 | 方式四引入了继承。 211 | 212 | ## 继承的几种方式 213 | 214 | 215 | ### 通过构造函数继承 216 | 217 | 在子类型构造函数中通用call()调用父类型构造函数 218 | 219 | 220 | ### 原型链继承 221 | 222 | 子类型的原型为父类型的一个实例对象 223 | 224 | 225 | 226 | ### 组合继承 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /11-Node.js和模块化/02-JavaScript模块化02:AMD.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## AMD的基本语法 4 | 5 | ### AMD的概念 6 | 7 | **AMD**(Asynchronous Module Definition):异步模块定义。AMD专门用于浏览器端,模块的加载是异步的。 8 | 9 | [**AMD规范**](https://github.com/amdjs/amdjs-api):是 **[RequireJS](http://requirejs.org/)** 在推广过程中对模块化定义的规范化产出。 10 | 11 | RequireJS:一个基于AMD规范实现的模块化开发解决方案。 12 | 13 | 14 | ### 暴露模块的方式 15 | 16 | **定义没有依赖的模块**:(参数只有一个 function) 17 | 18 | ```javascript 19 | define(function () { 20 | 21 | return 模块 22 | 23 | }) 24 | ``` 25 | 26 | 27 | **定义有依赖的模块**:(参数有两个:模块名、function) 28 | 29 | ```javascript 30 | //定义有依赖的模块:第一个参数为数组 31 | define(['module1', 'module2'], function (m1, m2) { 32 | 33 | return 模块 34 | 35 | }) 36 | ``` 37 | 38 | 代码解释: 39 | 40 | - 第一个参数必须是数组,里面存放的是,需要依赖的其他的模块。 41 | 42 | - 第二个参数是function,里面带了形参 m1 和 m2,分别代表了 module1 和 module2。这个形参的作用是,前面依赖的模块一旦声明了,就可以一一对应地注入到 function中去,从而在 function 内部使用依赖的模块。这种方式称之为**显式声明依赖注入**。 43 | 44 | ### 引入模块的方式 45 | 46 | 在主模块中引入其他的模块: 47 | 48 | 49 | ```javascript 50 | //在主模块中引入其他的模块 51 | require(['module1', 'module2'], function (m1, m2) { 52 | 53 | 使用m1 / m2 54 | 55 | }) 56 | ``` 57 | 58 | ### RequireJS:是AMD的实现 59 | 60 | - 61 | 62 | - 63 | 64 | ## RequireJS的使用举例(自定义模块) 65 | 66 | ### 1、创建项目结构 67 | 68 | 在工程文件中新建如下目录: 69 | 70 | 71 | ``` 72 | js 73 | | libs 74 | 75 | | modules 76 | | alerter.js 77 | | dataService.js 78 | | main.js 79 | 80 | index.html 81 | ``` 82 | 83 | 所有的代码写完之后,项目结构如下: 84 | 85 | ![](http://img.smyhvae.com/20180411_1331.png) 86 | 87 | 88 | ### 2、下载require.js,并导入 89 | 90 | - 官网: 91 | 92 | - GitHub: 93 | 94 | 在官网下载`require.js`文件: 95 | 96 | ![](http://img.smyhvae.com/20180411_1127.png) 97 | 98 | 然后将`require.js`文件拷贝到项目的`js/libs/`目录中。 99 | 100 | 这样的话,就导入成功了。 101 | 102 | ### 3、自定义模块 103 | 104 | (1)dataService.js: 105 | 106 | ```javascript 107 | //定义没有依赖的模块 108 | define(function () { 109 | let name = '我是 dataService.js中的内容'; 110 | function getName() { 111 | return name; 112 | } 113 | 114 | //暴露模块 115 | return { getName }; 116 | }); 117 | ``` 118 | 119 | 120 | 这模块没有依赖。 121 | 122 | (2)alerter.js: 123 | 124 | ```javascript 125 | //定义有依赖的模块 126 | define(['myDataService'], function (dataService) { 127 | let msg = '我是 aleter.js中的内容'; 128 | function showMsg() { 129 | console.log(dataService.getName()); //调用了 myDataService 模块中的内容 130 | console.log(msg); 131 | } 132 | 133 | //暴露模块 134 | return { showMsg }; 135 | 136 | }); 137 | ``` 138 | 139 | 这个模块,依赖了`myDataService`这个模块,模块名是我自己起的。稍后,我们会在main.js中做映射,将`myDataService`这个名字和`dataService.js`文件关联起来。 140 | 141 | (3)main.js: 142 | 143 | > 这个是主模块。 144 | 145 | ```javascript 146 | requirejs.config({ 147 | //baseUrl: 'js/', //基本路径 148 | paths: { //配置路径 149 | myDataService: './modules/dataService', 150 | myAlerter: './modules/alerter' 151 | } 152 | }); 153 | 154 | requirejs(['myAlerter'], function (alerter) { 155 | alerter.showMsg(); 156 | })(); 157 | ``` 158 | 159 | 这个模块,依赖了`myAlerter`这个模块,模块名是我自己起的。并且,我们在文件的上方做了映射,将`myAlerter`这个名字和`alerter.js`文件关联了起来。 160 | 161 | 162 | 我们来讲一下最上方的几行代码(即`requirejs.config`里的内容)的意思: 163 | 164 | - 我们可以看到,文件(3)依赖了文件(2),文件(2)依赖了文件(1)。 165 | 166 | - `paths`里做的就是映射:将键`myDataService`和文件`dataService.js`进行关联,将键`myAlerter`和文件`alerter.js`进行关联。 167 | 168 | 另外,再讲一下注释里的`baseUrl`的用法:如果没有这个注释,那么`paths`里的路径,是从**当前这个文件**(main.js)的角度出发的;如果加了一行`baseUrl`,表明它是 paths 里所有路径的最开头的部分,`baseUrl`的路径是从**项目的根目录**的角度出发的。 169 | 170 | (4)index.html: 171 | 172 | 这个是入口文件。 173 | 174 | 175 | ```html 176 | 177 | 178 | 179 | 180 | 181 | 182 | Document 183 | 184 | 185 | 186 | 187 | 188 | 189 | ``` 190 | 191 | 注意,上面的代码中,我们直接通过`src`属性引入`requre.js `文件,一旦这个文件发挥作用了,会去找`data-main`属性里的指向,它正好指向的是主模块。 192 | 193 | 有了上面这种引入的方式,我们就不用再老土地引入多个` 72 | 73 | 74 | 75 | 76 | 77 | ``` 78 | 79 | **注意**,上方代码中,我们引入的是`dist`目录下的 js 文件。 80 | 81 | 然后我们新建文件 `src/index.js`: 82 | 83 | ```javascript 84 | let a = 'smyhvae'; 85 | const b = 'qianguyihao'; 86 | 87 | console.log(a); 88 | console.log(b); 89 | ``` 90 | 91 | 92 | 这个文件是一个 ES6语法 的js文件,稍后,我们尝试把这个 ES6 语法的 js 文件转化为 ES5 的 js 文件。 93 | 94 | PS:我们在写代码时,能用单引号尽量用单引号,而不是双引号,前者在压缩之后,程序执行会更快。 95 | 96 | ### 全局安装 Babel-cli 97 | 98 | (1)初始化项目: 99 | 100 | 在安装Babel之前,需要先用 npm init 先初始化我们的项目。打开终端或者通过cmd打开命令行工具,进入项目目录,输入如下命令: 101 | 102 | 103 | ```bash 104 | npm init -y 105 | ``` 106 | 107 | 上方代码中,`-y` 代表全部默认同意,就不用一次次按回车了(稍后再根据需要,在文件中手动修改)。命令执行完成后,会在项目的根目录下生成package.json文件: 108 | 109 | ```json 110 | { 111 | "name": "es6demo", 112 | "version": "1.0.0", 113 | "description": "", 114 | "main": "index.js", 115 | "scripts": { 116 | "test": "echo \"Error: no test specified\" && exit 1" 117 | }, 118 | "author": "smyhvae", 119 | "license": "ISC" 120 | } 121 | 122 | ``` 123 | 124 | 125 | PS:VS Code 里打开终端的快捷键是:`Contol + ~`。 126 | 127 | (2)全局安装 Babel-cli: 128 | 129 | 在终端中输入以下命令: 130 | 131 | ```bash 132 | npm install -g babel-cli 133 | ``` 134 | 135 | 136 | ![](http://img.smyhvae.com/20180304_1305.png) 137 | 138 | 如果安装比较慢的话,Mac 下可以使用`cnpm`进行安装 ,windows 下可以使用`nrm`切换到 taobao 的镜像。 139 | 140 | 141 | (3)本地安装 babel-preset-es2015 和 babel-cli: 142 | 143 | ```bash 144 | npm install --save-dev babel-preset-es2015 babel-cli 145 | ``` 146 | 147 | ![](http://img.smyhvae.com/20180304_1307.png) 148 | 149 | 安装完成后,会发现`package.json`文件,已经多了 devDependencies 选项: 150 | 151 | ![](http://img.smyhvae.com/20180304_1308.png) 152 | 153 | (4)新建.babelrc: 154 | 155 | 在根目录下新建文件`.babelrc`,输入如下内容: 156 | 157 | ``` 158 | { 159 | "presets":[ 160 | "es2015" 161 | ], 162 | "plugins":[] 163 | } 164 | ``` 165 | 166 | 167 | (5)开始转换: 168 | 169 | 现在,我们应该可以将 ES6 的文件转化为 ES5 的文件了,命令如下:(此命令略显复杂) 170 | 171 | ``` 172 | babel src/index.js -o dist/index.js 173 | ``` 174 | 175 | 我们可以将上面这个命令进行简化一下。操作如下: 176 | 177 | 在文件 `package.json` 中修改键 `scripts`中的内容: 178 | 179 | 180 | ```json 181 | "scripts": { 182 | "build": "babel src/index.js -o dist/index.js" 183 | }, 184 | ``` 185 | 186 | 修改后的效果如下: 187 | 188 | ![](http://img.smyhvae.com/20180304_1315.png) 189 | 190 | 目前为止,环境配置好了。以后,我们执行如下命令,即可将`src/index.js`这个 ES6 文件转化为 `dist/index.js`这个 ES5 文件: 191 | 192 | 193 | ```bash 194 | npm run build 195 | ``` 196 | 197 | 198 | 我们执行上面的命令之后,会发现, dist目录下会生成 ES5 的 js 文件: 199 | 200 | index.js: 201 | 202 | ```javascript 203 | 'use strict'; 204 | 205 | var a = 'smyhvae'; 206 | var b = 'qianguyihao'; 207 | 208 | console.log(a); 209 | console.log(b); 210 | 211 | ``` 212 | 213 | 当我们打开网页后,就可以在浏览器的控制台,看到代码的输出结果。 214 | 215 | 本段内容的参考链接: 216 | 217 | - [技术胖带你玩转ES6视频教程 (共18集)](http://jspang.com/2017/06/03/es6/) 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /00-前端工具/02-Git的使用.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## 常见操作 6 | 7 | ### 全局配置用户信息 8 | 9 | ``` 10 | git config --global user.name "smyhvae" 11 | 12 | git config --global user.email "smyhvae@163.com" 13 | ``` 14 | 15 | 16 | ## 分支的合并 17 | 18 | 19 | ### 场景:基于master分支的代码,开发一个新的特性 20 | 21 | 如果你直接在master分支上开发这个新特性,是不好的,万一你在开发`特性1`的时候,领导突然又要叫你去开发`特性2`,就不好处理了。难道开发的两个特性都提交到master?一会儿提交特性1的commit,一会儿提交特性2的commit?这会导致commit记录很混乱。 22 | 23 | 所以,我给你的建议做法是:给每个特性都单独建一个的新的分支。 24 | 25 | 比如说,我专门给`特性1`建一个分支`feature_item_recommend`。具体做法如下: 26 | 27 | (1)基于master分支,创建一个新的分支,起名为`feature_item_recommend`: 28 | 29 | ``` 30 | $ git checkout -b feature_item_recommend 31 | 32 | Switched to a new branch 'feature_item_recommend' 33 | ``` 34 | 35 | 上面这行命令,相当于: 36 | 37 | 38 | ```bash 39 | $ git branch feature_item_recommend // 创建新的分支 40 | 41 | $ git checkout feature_item_recommend //切换到新的分支 42 | ``` 43 | 44 | 45 | (2)在新的分支`feature_item_recommend`上,完成开发工作,并 commit 、push。 46 | 47 | (3)将分支`feature_item_recommend`上的开发进度**合并**到master分支: 48 | 49 | ```bash 50 | $ git checkout master //切换到master分支 51 | 52 | $ git merge feature_item_recommend //将分支 feature_item_recommend 的开发进度合并到 master 分支 53 | 54 | ``` 55 | 56 | 57 | 合并之后,`master`分支和`feature_item_recommend`分支会指向同一个位置。 58 | 59 | 60 | (3)删除分支`feature_item_recommend`: 61 | 62 | > 既然 特性1 开发完了,也放心地提交到master了,那我们就可以将这个分支删除了。 63 | 64 | ``` 65 | git branch -d feature_item_recommend 66 | ``` 67 | 68 | 注意,我们当前是处于`master`分支的位置,来删除`feature_item_recommend`分支。如果当前是处于`feature_item_recommend`分支,是没办法删除它自己的。 69 | 70 | 同理,当我转身去开发`特性2`的时候,也是采用同样的步骤。 71 | 72 | 73 | ### 合并分支时,如果存在分叉 74 | 75 | 76 | ![](http://img.smyhvae.com/20180610_1650.png) 77 | 78 | 79 | 比如说上面这张图中,最早的时候,master分支是位于`C2`节点。我基于`C2`节点,new出一个新的分支`iss53`,我在`iss53`上提交了好几个commit。 80 | 81 | 现在,我准备把`iss53`上的几个commit合并到master上,此时发现,master分支已经前进到C4了。那该怎么合并呢? 82 | 83 | 合并的命令仍然是: 84 | 85 | ```bash 86 | $ git checkout master 87 | 88 | $ git merge iss53 89 | ``` 90 | 91 | **解释**: 92 | 93 | 这次合并的实现,并不同于简单的并入方式。这一次,我的开发历史是从更早的地方开始分叉的。 94 | 95 | 由于当前 master 分支所指向的commit (C4)并非想要并入分支(iss53)的直接祖先,Git 不得不进行一些处理。就此例而言,Git 会用两个分支的末端(C4 和C5)和它们的共同祖先(C2)进行一次简单的三方合并计算。 96 | 97 | Git 没有简单地把分支指针右移,而是对三方合并的结果作一新的快照,并自动创建一个指向它的commit(C6)(如下图所示)。我们把这个特殊的commit 称作合并提交(mergecommit),因为它的祖先不止一个。 98 | 99 | 值得一提的是Git 可以自己裁决哪个共同祖先才是最佳合并基础;这和CVS 或Subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让Git 的合并操作比其他系统都要简单不少。 100 | 101 | ![](http://img.smyhvae.com/20180610_1710.png) 102 | 103 | ### 解决合并时发生的冲突 104 | 105 | ![](http://img.smyhvae.com/20180610_1740.png) 106 | 107 | 如果 feature1和feature2修改的是同一个文件中**代码的同一个位置**,那么,把feature1合并到feature2时,就会产生冲突。这个冲突需要人工解决。步骤如下: 108 | 109 | (1)手动修改文件:手动修改冲突的那个文件,决定到底要用哪个分支的代码。 110 | 111 | (2)git add:解决好冲突后,输入`git status`,会提示`Unmerged paths`。这个时候,输入`git add`即可,表示:**修改冲突成功,加入暂存区**。 112 | 113 | (3)git commit 提交。 114 | 115 | 然后,我们可以继续把 feature1 分支合并到 master分支,最后删除feature1、feature2。 116 | 117 | **注意**:两个分支的同一个文件的不同地方合并时,git会自动合并,不会产生冲突。 118 | 119 | 比如分支feture1对index.html原来的第二行之前加入了一段代码。 120 | 分支feature2对index.html在原来的最后一行的后面加入了一段代码。 121 | 这个时候在对两个分支合并,git不会产生冲突,因为两个分支是修改同一文件的不同位置。 122 | git自动合并成功。不管是git自动合并成功,还是在人工解决冲突下合并成功,提交之前,都要对代码进行测试。 123 | 124 | ## 日常操作积累 125 | 126 | ### 修改密码(曲线救国) 127 | 128 | 129 | > 网上查了很久,没找到答案。最终,在cld童鞋的提示下,采取如下方式进行曲线救国。 130 | 131 | ```bash 132 | # 设置当前仓库的用户名为空 133 | git config user.name "" 134 | ``` 135 | 136 | 137 | 然后,当我们再输入`git pull`等命令行时,就会被要求重新输入*新的*账号密码。此时,密码就可以修改成功了。最后,我们还要输入如下命令,还原当前仓库的用户名: 138 | 139 | ``` 140 | git config user.name "smyhvae" 141 | ``` 142 | 143 | 144 | ### 修改已经push的某次commit的作者信息 145 | 146 | 已经push的记录,如果要修改作者信息的话,只能 通过--force命令。我反正是查了很久,但最终还是不敢用公司的仓库尝试。 147 | 148 | 参考链接: 149 | 150 | 151 | - [git 修改已提交的某一次的邮箱和用户信息](https://segmentfault.com/q/1010000006999861) 152 | 153 | 看最后一条答案。 154 | 155 | - [修改 git repo 历史提交的 author](http://baurine.github.io/2015/08/22/git_update_author.html) 156 | 157 | 158 | 159 | ### 将 `branch1`的某个`commit1`合并到`branch2`当中 160 | 161 | 切换到branch2中,然后执行如下命令: 162 | 163 | ``` 164 | git cherry-pick commit1 165 | ``` 166 | 167 | 168 | ### 20190118-修改GitHub已提交的用户名和邮箱 169 | 170 | 参考链接:(亲测有效) 171 | 172 | - [修改Git全部Commit提交记录的用户名Name和邮箱Email](https://cloud.tencent.com/developer/article/1352623) 173 | 174 | - [Mac 运行sh文件,也就是传说中的shell脚本](https://blog.csdn.net/yusufolu9/article/details/53706269) 175 | 176 | 177 | ## git客户端推荐 178 | 179 | 市面上的Git客户端我基本都用过了,我最推荐的一款Git客户端是:[Tower](https://www.git-tower.com) 或者 [Fork](https://git-fork.com)。 180 | 181 | - GitUp: 182 | 183 | 20180623时,网上看了下Git客户端的推荐排名: 184 | 185 | ![](http://img.smyhvae.com/20180623_1210.png) 186 | 187 | **SmartGit**: 188 | 189 | 商业用途收费, 个人用户免费: 190 | s 191 | ![](http://img.smyhvae.com/20180623_1305.png) 192 | 193 | 194 | 195 | 196 | 197 | ## 推荐书籍 198 | 199 | - 《pro.git中文版》 200 | 201 | 202 | 203 | ## 推荐连接 204 | 205 | 206 | ### 2018-06 207 | 208 | - [聊下git pull --rebase](https://www.cnblogs.com/wangiqngpei557/p/6056624.html) 209 | 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /10-ES6/09-ES6:字符串、数组、对象的扩展.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 字符串的扩展 4 | 5 | ES6中的字符串扩展,用得少,而且逻辑相对简单。如下: 6 | 7 | - `includes(str)`:判断是否包含指定的字符串 8 | 9 | - `startsWith(str)`:判断是否以指定字符串开头 10 | 11 | - `endsWith(str)`:判断是否以指定字符串结尾 12 | 13 | - `repeat(count)`:重复指定次数 14 | 15 | 16 | 举例如下: 17 | 18 | ```javascript 19 | let str = 'abcdefg'; 20 | 21 | console.log(str.includes('a'));//true 22 | console.log(str.includes('h'));//false 23 | 24 | //startsWith(str) : 判断是否以指定字符串开头 25 | console.log(str.startsWith('a'));//true 26 | console.log(str.startsWith('d'));//false 27 | 28 | //endsWith(str) : 判断是否以指定字符串结尾 29 | console.log(str.endsWith('g'));//true 30 | console.log(str.endsWith('d'));//false 31 | 32 | //repeat(count) : 重复指定次数a 33 | console.log(str.repeat(5)); 34 | ``` 35 | 36 | 打印结果: 37 | 38 | ![](http://img.smyhvae.com/20180402_1050.png) 39 | 40 | ## Number 的扩展 41 | 42 | - 二进制与八进制数值表示法: 二进制用`0b`, 八进制用`0o`。 43 | 44 | 举例: 45 | 46 | ```javascript 47 | console.log(0b1010);//10 48 | console.log(0o56);//46 49 | ``` 50 | 51 | - `Number.isFinite(i)`:判断是否为有限大的数。比如`Infinity`这种无穷大的数,返回的就是false。 52 | 53 | - `Number.isNaN(i)`:判断是否为NaN。 54 | 55 | - `Number.isInteger(i)`:判断是否为整数。 56 | 57 | - `Number.parseInt(str)`:将字符串转换为对应的数值。 58 | 59 | - `Math.trunc(i)`:去除小数部分。 60 | 61 | 举例: 62 | 63 | ```javascript 64 | //Number.isFinite(i) : 判断是否是有限大的数 65 | console.log(Number.isFinite(NaN)); //false 66 | console.log(Number.isFinite(5)); //true 67 | console.log(Number.isFinite(Infinity)); //false 68 | 69 | //Number.isNaN(i) : 判断是否是NaN 70 | console.log(Number.isNaN(NaN));//true 71 | console.log(Number.isNaN(5));//falsse 72 | 73 | //Number.isInteger(i) : 判断是否是整数 74 | console.log(Number.isInteger(5.23));//false 75 | console.log(Number.isInteger(5.0));//true 76 | console.log(Number.isInteger(5));//true 77 | 78 | //Number.parseInt(str) : 将字符串转换为对应的数值 79 | console.log(Number.parseInt('123abc'));//123 80 | console.log(Number.parseInt('a123abc'));//NaN 81 | 82 | // Math.trunc(i) : 直接去除小数部分 83 | console.log(Math.trunc(13.123));//13 84 | ``` 85 | 86 | ## 数组的扩展 87 | 88 | > 下面提到的数组的几个方法,更详细的内容,可以看《04-JavaScript基础/17-数组的常见方法.md》。 89 | 90 | ### 扩展1:Array.from() 91 | 92 | ```javascript 93 | Array.from(伪数组/可遍历的对象) 94 | ``` 95 | 96 | **作用**:将**伪数组**或可遍历对象转换为**真数组**。 97 | 98 | 99 | ### 扩展2:Array.of() 100 | 101 | ```javascript 102 | Array.of(value1, value2, value3) 103 | ``` 104 | 105 | **作用**:将一系列值转换成数组。 106 | 107 | ### 扩展3:find() 和 findIndex() 108 | 109 | **方法1**: 110 | 111 | 112 | ```javascript 113 | find(function(item, index, arr){return true}) 114 | ``` 115 | 116 | **作用**:找出**第一个**满足「指定条件返回true」的元素。 117 | 118 | **方法2**: 119 | 120 | ```javascript 121 | findIndex(function(item, index, arr){return true}) 122 | ``` 123 | 124 | **作用**:找出第一个满足「指定条件返回true」的元素的index。 125 | 126 | ## 对象的扩展 127 | 128 | ### 扩展1 129 | 130 | 131 | ```javascript 132 | Object.is(v1, v2) 133 | ``` 134 | 135 | **作用:**判断两个数据是否完全相等。底层是通过**字符串**来判断的。 136 | 137 | 我们先来看下面这两行代码的打印结果: 138 | 139 | 140 | ```javascript 141 | console.log(0 == -0); 142 | console.log(NaN == NaN); 143 | ``` 144 | 145 | 打印结果: 146 | 147 | ``` 148 | true 149 | false 150 | ``` 151 | 152 | 上方代码中,第一行代码的打印结果为true,这个很好理解。第二行代码的打印结果为false,因为NaN和任何值都不相等。 153 | 154 | 但是,如果换成下面这种方式来比较: 155 | 156 | ```javascript 157 | console.log(Object.is(0, -0)); 158 | console.log(Object.is(NaN, NaN)); 159 | ``` 160 | 161 | 打印结果却是: 162 | 163 | ``` 164 | false 165 | true 166 | ``` 167 | 168 | 代码解释:还是刚刚说的那样,`Object.is(v1, v2)`比较的是字符串是否相等。 169 | 170 | ### 扩展2(重要) 171 | 172 | ```javascript 173 | Object.assign(目标对象, 源对象1, 源对象2...) 174 | ``` 175 | 176 | **作用:** 将源对象的属性追加到目标对象上。如果对象里属性名相同,会被覆盖。 177 | 178 | 其实可以理解成:将多个对象**合并**为一个新的对象。 179 | 180 | 181 | 182 | 举例: 183 | 184 | ```javascript 185 | let obj1 = { name: 'smyhvae', age: 26 }; 186 | let obj2 = { city: 'shenzhen' }; 187 | let obj3 = {}; 188 | 189 | Object.assign(obj3, obj1, obj2); 190 | console.log(obj3); 191 | ``` 192 | 193 | 打印结果: 194 | 195 | ![](http://img.smyhvae.com/20180404_2240.png) 196 | 197 | 上图显示,成功将obj1和obj2的属性复制给了obj3。 198 | 199 | 200 | 201 | ### 扩展3:`__proto__`属性 202 | 203 | 举例: 204 | 205 | ```javascript 206 | let obj1 = {name:'smyhvae'}; 207 | let obj2 = {}; 208 | 209 | obj2.__proto__ = obj1; 210 | 211 | console.log(obj1); 212 | console.log(obj2); 213 | console.log(obj2.name); 214 | ``` 215 | 216 | 打印结果: 217 | 218 | ![](http://img.smyhvae.com/20180404_2251.png) 219 | 220 | 上方代码中,obj2本身是没有属性的,但是通过`__proto__`属性和obj1产生关联,于是就可以获得obj1里的属性。 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | ```javascript 254 | 255 | ``` 256 | 257 | 258 | 259 | -------------------------------------------------------------------------------- /14-前端面试/09-02.js运行机制:异步和单线程.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 前言 5 | 6 | 7 | 面试时,关于`同步和异步`,可能会问以下问题: 8 | 9 | - 同步和异步的区别是什么?分别举一个同步和异步的例子 10 | 11 | - 一个关于 setTimeout 的笔试题 12 | 13 | - 前端使用异步的场景哪些? 14 | 15 | 16 | 17 | 面试时,关于`js运行机制`,需要注意以下几个问题: 18 | 19 | - 如何理解JS的**单线程** 20 | 21 | - 什么是**任务队列** 22 | 23 | - 什么是 EventLoop 24 | 25 | - 理解哪些语句会放入异步任务队列 26 | 27 | - 理解语句放入异步任务队列的**时机** 28 | 29 | 30 | 31 | 32 | ## JS的异步和单线程 33 | 34 | > 因为是单线程,所以必须异步。 35 | 36 | 我们通过题目来解释以下。 37 | 38 | ### 题目一:异步 39 | 40 | 现有如下代码: 41 | 42 | ```javascript 43 | console.log(1); 44 | setTimeout(function () { 45 | console.log(2); 46 | }, 1000); 47 | console.log(3); 48 | console.log(4); 49 | 50 | ``` 51 | 52 | 53 | 上面的代码中,我们很容易知道,打印的顺序是`1,3,4,2`。因为你会想到,要等一秒之后再打印`2`。 54 | 55 | 可如果我把延时的时间从`1000`改成`0`: 56 | 57 | 58 | ```javascript 59 | console.log(1); 60 | setTimeout(function () { 61 | console.log(2); 62 | }, 0); 63 | console.log(3); 64 | console.log(4); 65 | ``` 66 | 67 | 68 | 上方代码中,打印的顺序仍然是`1,3,4,2`。这是为什么呢?我们来分析一下。 69 | 70 | **总结:** 71 | 72 | js 是单线程(同一时间只能做一件事),而且有一个**任务队列**:全部的同步任务执行完毕后,再来执行异步任务。第一行代码和最后一行代码是同步任务;但是,**`setTimeout`是异步任务**。 73 | 74 | 于是,执行的顺序是: 75 | 76 | - 先执行同步任务`console.log(1)` 77 | 78 | - 遇到异步任务`setTimeout`,要**挂起** 79 | 80 | - 执行同步任务`console.log(3)` 81 | 82 | - **全部的同步任务执行完毕后,再来执行异步任务**`console.log(2)`。 83 | 84 | 很多人会把这个题目答错,这是因为他们不懂 js 的运行机制。 85 | 86 | 注意上面那句话:同步任务执行完毕后,再来执行异步任务。也就是说,**如果同步任务没有执行完,异步任务是不会执行的**。为了解释这句话,我们来看下面这个例子。 87 | 88 | 89 | ### 题目二:异步 90 | 91 | 现有如下代码: 92 | 93 | ```javascript 94 | console.log('A'); 95 | while (1) { 96 | 97 | } 98 | console.log('B'); 99 | ``` 100 | 101 | 我们很容易想到,上方代码的打印结果是`A`,因为while是同步任务,代码会陷入死循环里出不来,自然也就无法打印`B`。可如果我把代码改成下面的样子: 102 | 103 | ```javascript 104 | console.log('A'); 105 | 106 | setTimeout(function () { 107 | console.log('B'); 108 | }) 109 | 110 | while (1) { 111 | 112 | } 113 | 114 | ``` 115 | 116 | 117 | 上方代码的打印结果仍然是`A`。因为while是同步任务,setTimeout是异步任务,所以还是那句话:**如果同步任务没有执行完,队列里的异步任务是不会执行的**。 118 | 119 | 120 | ### 题目三:同步 121 | 122 | ```javascript 123 | console.log('A'); 124 | 125 | alert('haha'); //1秒之后点击确认 126 | 127 | console.log('B'); 128 | 129 | ``` 130 | 131 | `alert`函数是同步任务,我只有点击了确认,才会继续打印`B`。 132 | 133 | ### 同步和异步的对比 134 | 135 | 我们在上面列举了异步和同步的例子。现在来描述一下区别:【重要】 136 | 137 | 因为`setTimeout`是**异步任务**,所以程序并不会卡在那里,而是继续向下执行(即使settimeout设置了倒计时一万秒);但是`alert`函数是**同步**任务,程序会**卡在那里**,如果它没有执行,后面的也不会执行(卡在那里,自然也就造成了**阻塞**)。 138 | 139 | 140 | 141 | ### 前端使用异步的场景 142 | 143 | 什么时候需要**等待**,就什么时候用异步。 144 | 145 | - 定时任务:setTimeout(定时炸弹)、setInterval(循环执行) 146 | 147 | - 网络请求:ajax请求、动态``加载 148 | 149 | - 事件绑定(比如说,按钮绑定点击事件之后,用户爱点不点。我们不可能卡在按钮那里,什么都不做。所以,应该用异步) 150 | 151 | - ES6中的Promise 152 | 153 | 154 | 代码举例: 155 | 156 | ```javascript 157 | console.log('start'); 158 | var img = document.createElement('img'); 159 | img.onload = function () { 160 | console.log('loaded'); 161 | } 162 | img.src = '/xxx.png'; 163 | console.log('end'); 164 | ``` 165 | 166 | 上图中,先打印`start`,然后执行`img.src = '/xxx.png'`,然后打印`end`,最后打印`loaded`。 167 | 168 | 169 | ## 任务队列和Event Loop(事件循环) 170 | 171 | ### 任务队列 172 | 173 | 所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 174 | 175 | 176 | 总结:**只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制**。【重要】 177 | 178 | 179 | ### Event Loop 180 | 181 | 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。 182 | 183 | ![](http://img.smyhvae.com/20180310_1840.png) 184 | 185 | 186 | 在理解Event Loop时,要理解两句话: 187 | 188 | - 理解哪些语句会放入异步任务队列 189 | 190 | - 理解语句放入异步任务队列的**时机** 191 | 192 | 193 | ### 容易答错的题目 194 | 195 | ```javascript 196 | for (var i = 0; i < 3; i++) { 197 | setTimeout(function () { 198 | console.log(i); 199 | }, 1000); 200 | } 201 | ``` 202 | 203 | 很多人以为上面的题目,答案是`0,1,2,3`。其实,正确的答案是:`3,3,3,3`。 204 | 205 | 分析:for 循环是同步任务,setTimeout是异步任务。for循环每次遍历的时候,遇到settimeout,就先暂留着,等同步任务全部执行完毕(此时,i已经等于3了),再执行异步任务。 206 | 207 | 208 | 我们把上面的题目再加一行代码。最终代码如下: 209 | 210 | ```javascript 211 | for (var i = 0; i < 3; i++) { 212 | setTimeout(function () { 213 | console.log(i); 214 | }, 1000); 215 | } 216 | console.log(i); 217 | ``` 218 | 219 | 如果我们约定,用箭头表示其前后的两次输出之间有 1 秒的时间间隔,而逗号表示其前后的两次输出之间的时间间隔可以忽略,代码实际运行的结果该如何描述?可能会有两种答案: 220 | 221 | - A. 60% 的人会描述为:`3 -> 3 -> 3 -> 3`,即每个 3 之间都有 1 秒的时间间隔; 222 | 223 | - B. 40% 的人会描述为:`3 -> 3,3,3`,即第 1 个 3 直接输出,1 秒之后,连续输出 3 个 3。 224 | 225 | 循环执行过程中,几乎同时设置了 3 个定时器,这些定时器都会在 1 秒之后触发,而循环完的输出是立即执行的,显而易见,正确的描述是 B。 226 | 227 | 上面这个题目的参考链接: 228 | 229 | - [80% 应聘者都不及格的 JS 面试题](https://juejin.im/post/58cf180b0ce4630057d6727c) 230 | 231 | - [深入浅出Javascript事件循环机制(上)](https://zhuanlan.zhihu.com/p/26229293) 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | -------------------------------------------------------------------------------- /09-Ajax/03-函数封装:Ajax发送http请求(get&post).md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## 函数封装 6 | 7 | ajax_tool.js: 8 | 9 | ```javascript 10 | // 方法:ajax get 五部曲 11 | function ajax_get(url,data) { 12 | // 异步对象 13 | var ajax = new XMLHttpRequest(); 14 | 15 | // url 方法 16 | // 如果是get发送数据 发送的格式为 xxx.php?name=jack&age=18 17 | // 所以 这里 需要拼接 url 18 | if (data) { 19 | // 如果有值 需要拼接字符串 20 | // 拼接为xxx.php?name=jack&age=18 21 | url+='?'; 22 | url+=data; 23 | }else{ 24 | } 25 | 26 | ajax.open('get',url); 27 | // 发送 28 | ajax.send(); 29 | 30 | // 注册事件 31 | ajax.onreadystatechange = function () { 32 | // 在事件中 获取数据 并修改界面显示 33 | if (ajax.readyState==4&& ajax.status==200) { 34 | console.log(ajax.responseText); 35 | } 36 | } 37 | } 38 | 39 | 40 | // 方法:ajax_post五部曲 41 | function ajax_post(url,data) { 42 | // 异步对象 43 | var ajax = new XMLHttpRequest(); 44 | 45 | // url 方法 46 | ajax.open('post',url); 47 | 48 | // 设置 请求报文 49 | ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 50 | 51 | // 发送 52 | if (data) { 53 | // 如果 有值 post请求 是在 send中 发送给服务器 54 | ajax.send(data); 55 | }else{ 56 | ajax.send(); 57 | } 58 | 59 | 60 | // 注册事件 61 | ajax.onreadystatechange = function () { 62 | // 在事件中 获取数据 并修改界面显示 63 | if (ajax.readyState==4&&ajax.status==200) { 64 | console.log(ajax.responseText); 65 | } 66 | } 67 | 68 | } 69 | 70 | 71 | // 方法:将 get 跟post 封装到一起 72 | /* 73 | 参数1:url 74 | 参数2:数据 75 | 参数3:请求的方法 76 | 参数4:数据成功获取以后,调用的方法 77 | */ 78 | function ajax_tool(url,data,method,success) { 79 | // 异步对象 80 | var ajax = new XMLHttpRequest(); 81 | 82 | // get 跟post 需要分别写不同的代码 83 | if (method=='get') { 84 | // get请求 85 | if (data) { 86 | // 如果有值 87 | url+='?'; 88 | url+=data; 89 | }else{ 90 | 91 | } 92 | // 设置 方法 以及 url 93 | ajax.open(method,url); 94 | 95 | // send即可 96 | ajax.send(); 97 | }else{ 98 | // post请求 99 | // post请求 url 是不需要改变 100 | ajax.open(method,url); 101 | 102 | // 需要设置请求报文 103 | ajax.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 104 | 105 | // 判断data send发送数据 106 | if (data) { 107 | // 如果有值 从send发送 108 | ajax.send(data); 109 | }else{ 110 | // 木有值 直接发送即可 111 | ajax.send(); 112 | } 113 | } 114 | 115 | // 注册事件 116 | ajax.onreadystatechange = function () { 117 | // 在事件中 获取数据 并修改界面显示 118 | if (ajax.readyState==4&&ajax.status==200) { 119 | // console.log(ajax.responseText); 120 | 121 | // 将 数据 让 外面可以使用 122 | // return ajax.responseText; 123 | 124 | // 当 onreadystatechange 调用时 说明 数据回来了 125 | // ajax.responseText; 126 | 127 | // 数据成功获取以后,执行方法success()。 128 | //我们把获取的数据作为 success()的参数,意思是: 129 | //success方法是外面的,数据是里面给的。那数据就变相地传递到了外面去【重要】 130 | success(ajax.responseText); 131 | } 132 | } 133 | 134 | } 135 | 136 | ``` 137 | 138 | 139 | ## 函数调用(get方法) 140 | 141 | test_get.html: 142 | 143 | ```html 144 | 145 | 146 | 147 | 148 | Document 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 172 | ``` 173 | 174 | 175 | test_get.php: 176 | 177 | 178 | ```php 179 | 183 | ``` 184 | 185 | ## 函数调用(post方法) 186 | 187 | test_post.html: 188 | 189 | ```html 190 | 191 | 192 | 193 | 194 | Document 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 226 | ``` 227 | 228 | test_post.php: 229 | 230 | ```php 231 | 235 | 236 | ``` 237 | 238 | 工程文件: 239 | 240 | - 2018-02-28-Ajax请求封装.rar -------------------------------------------------------------------------------- /04-JavaScript基础/原型链.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## 常见概念 4 | 5 | - 构造函数 6 | 7 | - 构造函数-扩展 8 | 9 | - 原型规则和示例 10 | 11 | - 原型链 12 | 13 | - instanceof 14 | 15 | ## 构造函数 16 | 17 | 任何一个函数都可以被new,new了之后,就成了构造方法。 18 | 19 | 如下: 20 | 21 | ```javascript 22 | function Foo(name, age) { 23 | this.name = name; 24 | this.age = age; 25 | //retrun this; //默认有这一行。new一个构造函数,返回一个对象 26 | 27 | } 28 | 29 | var fn1 = new Foo('smyhvae', 26); 30 | var fn2 = new Foo('vae',30); //new 多个实例对象 31 | ``` 32 | 33 | 与普通函数相比,构造函数有以下明显特点: 34 | 35 | - 用new关键字调用。 36 | 37 | - 不需要用return显式返回值的,默认会返回this,也就是新的实例对象。 38 | 39 | - 建议函数名的首字母大写,与普通函数区分开。 40 | 41 | 参考链接: 42 | 43 | - [JavaScript中的普通函数与构造函数](http://www.cnblogs.com/SheilaSun/p/4398881.html) 44 | 45 | 当new之后,this会先变成一个空对象,然后通过`this.name = name`来赋值。 46 | 47 | ### 构造函数的扩展 48 | 49 | ![](http://img.smyhvae.com/20180306_1633.png) 50 | 51 | 上图中发现,数组、对象、函数也有构造函数,它们的构造函数是Array、Object、funtion。实际开发中,都推荐前面的书写方式。 52 | 53 | ## 原型规则 54 | 55 | 原型规则是学习原型链的基础。原型规则有五条,下面来讲解。 56 | 57 | ### 规则1 58 | 59 | 所有的引用类型(数组、对象、函数),都具有对象特性,都可以**自由扩展属性**。null除外。 60 | 61 | 举例: 62 | 63 | ![](http://img.smyhvae.com/20180306_1651.png) 64 | 65 | 66 | ### 规则2 67 | 68 | 所有的**引用类型**(数组、对象、函数),都有一个`_proto_`属性,属性值是一个**普通的对象**。`_proto_`的含义是隐式原型。 69 | 70 | ![](http://img.smyhvae.com/20180306_1656.png) 71 | 72 | 其实,规则2是规则1的特例,只不过,js语法帮我们自动加了 规则2。 73 | 74 | ### 规则三 75 | 76 | 所有的**函数**(不包括数组、对象),都有一个`prototype`属性,属性值是一个**普通的对象**。`prototype`的含义是**显式原型**。(实例没有这个属性) 77 | 78 | ![](http://img.smyhvae.com/20180306_1659.png) 79 | 80 | 81 | ### 规则四 82 | 83 | 所有的**引用类型**(数组、对象、函数),`_proto_`属性指向它的**构造函数**的`prototype`值。 84 | 85 | ![](http://img.smyhvae.com/20180306_1701.png) 86 | 87 | 总结:以上四条,要先理解清楚,然后再来看下面的第五条。 88 | 89 | ### 规则五 90 | 91 | 当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的`_proto_`中寻找(即它的构造函数的`prototype`)。 92 | 93 | `举例代码1`: 94 | 95 | ```javascript 96 | //创建方法 97 | function Foo(name) { 98 | this.name = name; 99 | } 100 | 101 | Foo.prototype.alertName = function () {// 既然 Foo.prototype 是普通的对象,那也允许给它添加额外的属性 alertName 102 | console.log(this.name); 103 | } 104 | 105 | 106 | var fn = new Foo('smyhvae'); 107 | fn.printName = function () { 108 | console.log(this.name); 109 | } 110 | 111 | //测试 112 | fn.printName(); //输出结果:smyhvae 113 | fn.alertName(); //输出结果:smyhvae 114 | ``` 115 | 116 | 上方代码中,虽然 alertName 不是 fn 自身的属性,但是会从它的构造函数的`prototype`里面找。 117 | 118 | **扩展:**遍历循环对象自身的属性 119 | 120 | 我们知道,`for ... in`循环可以遍历对象。针对上面的那个fn对象,它自身有两个属性:`name`、`printName`,另外从原型中找到了第三个属性`alertName`。现在,如果我们对fn进行遍历,能遍历到两个属性还是三个属性呢? 121 | 122 | 答案:两个。因为,**高级浏览器中已经在 `for ... in`循环中屏蔽了来自原型的属性。但是,为了保证代码的健壮性,我们最好自己加上判断**,手动将第三个属性屏蔽掉: 123 | 124 | ```javascript 125 | for (var item in fn) { 126 | if (fn.hasOwnProperty(item)) { 127 | console.log(item); 128 | } 129 | } 130 | 131 | ``` 132 | 133 | 134 | ## 原型链 135 | 136 | 还是拿上面的``举例代码1``举例,如果此时在最后面加一行代码: 137 | 138 | ``` 139 | fn.toString(); //去 fn._proto_._proto_ 中查找 toString()方法 140 | ``` 141 | 142 | 上面的代码中,fn直接调用了 toString()方法,这是因为它通过**原型链**,去`_proto_`的`_proto_`里找到了`Object`,而`Object`是由`toString()`方法的。 143 | 144 | ### instanceof 145 | 146 | 格式: 147 | 148 | ```javascript 149 | 对象 instanceof 构造函数 150 | ``` 151 | 152 | `instanceof`的作用:用于判断**引用类型**属于哪个**构造函数**。 153 | 154 | 例1:判断一个变量是否为数组: `变量 instanceof Array` 155 | 156 | 例2: 157 | 158 | ```javascript 159 | function Person(){ 160 | } 161 | 162 | //p--->Person.prototype--->Object.prototype--->null 163 | var p = new Person(); 164 | //构造函数的**原型**是否在 p 对象的原型链上! 165 | console.log(p instanceof Person); 166 | ``` 167 | 168 | 例3: 169 | 170 | ```javascript 171 | fn instanceof Foo 172 | ``` 173 | 174 | 上面这句话,判断逻辑是:**fn 的`_proto_`一层一层往上找,看能否对应到 Foo.prototype**。 175 | 176 | 原型链如下:(重要) 177 | 178 | ![](http://img.smyhvae.com/20180306_1853.png) 179 | 180 | 181 | 注意,Object这个构造方法的显式原型是null,这是一个特例。 182 | 183 | 184 | ## 常见题目 185 | 186 | - 如何准确判断一个变量时数组类型 187 | 188 | - 写一个原型链继承的例子 189 | 190 | - 描述 new 一个对象的过程 191 | 192 | - zepto(或其他框架)源码中如何使用原型链 193 | 194 | 下面分别讲解。 195 | 196 | ### 题目一:如何准确判断一个变量时数组类型 197 | 198 | 答案: 199 | 200 | ```javascript 201 | var arr1 = []; 202 | 203 | console.log(arr1 instanceof Array); //打印结果:true。 204 | console.log(typeof arr1); //打印结果:object。提示:typeof 方法无法判断是否为数组 205 | ``` 206 | 207 | 上方代码表明,只能通过 instanceof 来判断是否为数组。而 typeof 的打印结果是 object。 208 | 209 | ### 题目二:写一个原型链继承的例子 210 | 211 | 来看个基础的代码: 212 | 213 | ![](http://img.smyhvae.com/20180306_1931.png) 214 | 215 | 上面这个例子是基础,但是,在回答面试官的问题时,不要写上面的例子。要写成下面这个例子:(更贴近实战) 216 | 217 | **举例:**写一个封装DOM查询的例子 218 | 219 | > 这个例子有点像 jQuery 操作DOM节点。 220 | 221 | 表示这个例子,略难。 222 | 223 | ### 题目三:描述 new 一个对象的过程 224 | 225 | (1)创建一个新对象 226 | 227 | (2)this 指向这个新对象 228 | 229 | (3)执行代码(对this 赋值) 230 | 231 | (4)返回this 232 | 233 | 234 | 参考链接: 235 | 236 | - [原型、原型链、继承模式](https://my.oschina.net/u/2600761/blog/1524617) 237 | 238 | -------------------------------------------------------------------------------- /11-Node.js和模块化/02-JavaScript模块化03:CMD.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## CMD的基本语法 5 | 6 | ### CMD的概念 7 | 8 | **CMD**(Common Module Definition):同步模块定义。CMD专门用于浏览器端,模块的加载是同步的。模块在使用时才会加载执行。 9 | 10 | [**CMD规范**]():是 **[SeaJS](http://seajs.org/)** 在推广过程中对模块化定义的规范化产出。 11 | 12 | 13 | ### SeaJS 14 | 15 | SeaJS:一个基于CMD规范实现的模块化开发解决方案。 16 | 17 | 官网链接: 18 | 19 | - 20 | 21 | - 22 | 23 | 推荐学习链接: 24 | 25 | - 26 | 27 | - 28 | 29 | 30 | ### 暴露模块的方式 31 | 32 | > 不管是定义没有依赖的模块,还是定义有依赖的模块,参数只有一个,那就是 function。 33 | 34 | **定义没有依赖的模块**: 35 | 36 | ```javascript 37 | define(function (require, exports, module) { 38 | 39 | exports.xxx = value 40 | 41 | //暴露模块 42 | module.exports = value 43 | 44 | }) 45 | ``` 46 | 47 | 参数只有一个,那就是 function。function 里有三个参数: 48 | 49 | 50 | **定义有依赖的模块**: 51 | 52 | ```javascript 53 | //定义有依赖的模块 54 | define(function (require, exports, module) { 55 | 56 | //引入依赖的模块(同步的方式) 57 | var module2 = require('./module2') 58 | 59 | //引入依赖的模块(异步的方式) 60 | require.async('./module3', function (m3) { 61 | 62 | }) 63 | 64 | //暴露模块 65 | exports.xxx = value 66 | }) 67 | 68 | ``` 69 | 70 | 上面的代码可以看到,在引入依赖的模块时,有两种引入的方式:同步和异步。 71 | 72 | 73 | ### 引入模块的方式 74 | 75 | ```javascript 76 | define(function (require) { 77 | 78 | var m1 = require('./module1') 79 | var m4 = require('./module4') 80 | 81 | m1.show() 82 | m4.show() 83 | }) 84 | ``` 85 | 86 | 87 | 88 | 89 | ## SeaJS的使用举例(自定义模块) 90 | 91 | 92 | 93 | ### 1、创建项目结构 94 | 95 | 96 | 在工程文件中新建如下目录: 97 | 98 | 99 | ``` 100 | js 101 | | libs 102 | | sea.js 103 | | modules 104 | | module1.js 105 | | module2.js 106 | | module3.js 107 | | module4.js 108 | | main.js //主模块 109 | index.html 110 | ``` 111 | 112 | 113 | ### 2、下载SeaJS,并导入 114 | 115 | - 官网: 116 | 117 | - GitHub: 118 | 119 | 在官网下载`sea.js`文件,然后将其拷贝到项目的`js/libs/`目录中。这样的话,就导入成功了。 120 | 121 | 122 | ### 3、自定义模块 123 | 124 | 125 | (1)module1.js: 126 | 127 | 128 | 129 | ```javascript 130 | //定义没有依赖的模块 131 | define(function (require, exports, module) { 132 | let name = '我是 module1 中的内容'; 133 | function foo1() { 134 | return name; 135 | } 136 | 137 | //暴露模块 138 | module.exports = { foo1 }; //暴露出去的是 foo1这个函数对象 139 | }); 140 | ``` 141 | 142 | 143 | (2)module2.js: 144 | 145 | ```javascript 146 | //定义没有依赖的模块 147 | define(function (require, exports, module) { 148 | let name = '我是 module2 中的内容'; 149 | function foo2() { 150 | console.log(name); 151 | } 152 | 153 | //暴露模块 154 | module.exports = foo2; //可以理解成:exports就是 foo2 这个函数 155 | }); 156 | ``` 157 | 158 | (3)module3.js: 159 | 160 | ```javascript 161 | //定义没有依赖的模块 162 | define(function (require,exports,module) { 163 | let data = '我是 module3 中的内容'; 164 | function foo3() { 165 | console.log(data); 166 | } 167 | 168 | //暴露模块 169 | exports.module3 = { foo3 }; //可以理解成:给 export 对象暴露了 module3 这个属性,这个属性里有foo3 这个函数。 170 | }); 171 | ``` 172 | 173 | (4)module4.js: 174 | 175 | 这个模块依赖了 module2 和 module3。 176 | 177 | ```javascript 178 | //定义有依赖的模块 179 | define(function (require, exports, module) { 180 | let name = '我是 module4 中的内容'; 181 | 182 | //同步的方式引入 module2 183 | let myModule2 = require('./module2'); 184 | myModule2(); 185 | 186 | //异步的方式引入 module3 187 | require.async('./module3', function (myModule3) { 188 | myModule3.module3.foo3(); 189 | }); 190 | 191 | function foo4() { 192 | console.log(name); 193 | } 194 | 195 | exports.foo4 = foo4; 196 | }) 197 | ``` 198 | 199 | (5)main.js: 200 | 201 | - `module1.js`没有依赖其他的模块,它是独立的 202 | 203 | - `module4.js`依赖了`module2`和`module3`。 204 | 205 | 因此,让`main.js`依赖`module1.js`和`module4`就够了。 206 | 207 | main.js: 208 | 209 | ```javascript 210 | //主模块(主模块不需要导出) 211 | define(function (require) { 212 | 213 | //导入 module1 214 | let module1 = require('./module1'); 215 | console.log(module1.foo1()); //执行foo1函数后,将返回值打印 216 | 217 | //导入 module4 218 | let module4 = require('./module4'); 219 | module4.foo4(); 220 | 221 | }); 222 | 223 | ``` 224 | 225 | 226 | (6)index.html: 227 | 228 | 229 | ```html 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | Document 238 | 239 | 240 | 241 | 242 | 243 | 247 | 248 | 249 | 250 | 251 | ``` 252 | 253 | 打印结果: 254 | 255 | ![](http://img.smyhvae.com/20180412_1955.png) 256 | -------------------------------------------------------------------------------- /12-Vue基础/02-Vue实例的生命周期函数.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## 介绍 5 | 6 | 7 | 8 | - [vue实例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#实例生命周期):从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。 9 | 10 | 11 | - [生命周期钩子](https://cn.vuejs.org/v2/api/#选项-生命周期钩子):就是生命周期事件的别名而已。 12 | 13 | 生命周期钩子 = 生命周期函数 = 生命周期事件。 14 | 15 | 16 | ## 生命周期函数的主要分类 17 | 18 | ![](http://img.smyhvae.com/20180422_1650.png) 19 | 20 | 根据上面这张图,我们把生命周期函数主要分为三类。 21 | 22 | 23 | ### 1、创建期间的生命周期函数 24 | 25 | - beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性 26 | 27 | - created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板。我们可以在这里进行Ajax请求。 28 | 29 | - beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中 30 | 31 | - mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示。(mounted之后,表示**真实DOM渲染完了,可以操作DOM了**) 32 | 33 | 34 | **举例**: 35 | 36 | 37 | ```html 38 | 39 | 40 | 41 | 42 | 43 | Title 44 | 45 | 46 | 47 | 48 | 49 |
50 |
51 | 52 | 53 | 86 | 87 | 88 | ``` 89 | 90 | 打印结果: 91 | 92 | ![](http://img.smyhvae.com/20180610_1500.png) 93 | 94 | ### 运行期间的生命周期函数 95 | 96 | - beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点 97 | 98 | - updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了。 99 | 100 | PS:数据发生变化时,会触发这两个方法。不过,我们一般用watch来做。 101 | 102 | 103 | **举例**: 104 | 105 | ```html 106 | 107 | 108 | 109 | 110 | 111 | Title 112 | 113 | 114 | 115 | 116 | 117 |
118 | 119 |

{{ flag }}

120 |
121 | 122 | 123 | 157 | 158 | 159 | ``` 160 | 161 | 162 | 当我们点击按钮后,运行效果是: 163 | 164 | ![](http://img.smyhvae.com/20180610_1528.png) 165 | 166 | 可以看出: 167 | 168 | - 当执行 beforeUpdate 的时候,页面中的显示的数据还是旧的,但此时 data 数据是最新的 169 | 170 | - updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的 171 | 172 | 173 | 174 | ### 3、销毁期间的生命周期函数 175 | 176 | - beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。 177 | 178 | - destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 179 | 180 | PS:可以在beforeDestory里**清除定时器、或清除事件绑定**。 181 | 182 | 183 | ## 生命周期函数图解 184 | 185 | ![](http://img.smyhvae.com/20180611_2130.png) 186 | 187 | PS:图片来自网络。 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /01-html/07-HTML基础回顾.md: -------------------------------------------------------------------------------- 1 | 2 | ## 本文主要内容 3 | 4 | - html 的常见元素 5 | 6 | - html 元素的分类 7 | 8 | - html 元素的嵌套关系 9 | 10 | - html 元素的默认样式和 CSS Reset 11 | 12 | - html 常见面试题 13 | 14 | ## html 的常见元素 15 | 16 | html 的常见元素主要分为两类:head 区域的元素、body 区域的元素。下面来分别介绍。 17 | 18 | ### 1、head 区域的 html 元素 19 | 20 | > head 区域的 html 元素,不会在页面上留下直接的内容。 21 | 22 | - meta 23 | 24 | - title 25 | 26 | - style 27 | 28 | - link 29 | 30 | - script 31 | 32 | - base 33 | 34 | **base元素的介绍**: 35 | 36 | ```html 37 | 38 | ``` 39 | 40 | base 标签用于指定基础的路径。指定之后,所有的 a 链接都是以这个路径为基准。 41 | 42 | ### 2、html 元素(body 区域) 43 | 44 | > body 区域的 html 元素,会直接出现在页面上。 45 | 46 | - div、section、article、aside、header、footer 47 | 48 | - p 49 | 50 | - span、em、strong 51 | 52 | - 表格元素:table、thead、tbody、tr、td 53 | 54 | - 列表元素:ul、ol、dl、dt、dd 55 | 56 | - a 57 | 58 | - 表单元素:form、input、select、textarea、button 59 | 60 | div 是最常见的元素,大多数场景下,都可以用div(实在不行就多包几层div)。可见,**div 是比较通用的元素,这也决定了 div 的的语义并不是很明确**。 61 | 62 | **常见标签的重要属性**: 63 | 64 | - a[href,target] 65 | - img[src,alt] 66 | - table td[colspan,rowspan]。设置当前单元格占据几行几列。在合并单元格时,会用到。 67 | - form[target,method,enctype] 68 | - input[type,value] 69 | - button[type] 70 | - selection>option[value] 71 | - label[for] 72 | 73 | ### html 文档的大纲 74 | 75 | 我们平时在写论文或者其他文档的时候,一般会先列出大纲,然后再写具体的内容。 76 | 77 | 同样,html 网页也可以看成是一种文档,也有属于它的大纲。 78 | 79 | 一个常见的html文档,它的结构可以是: 80 | 81 | ```html 82 |
83 |

一级标题

84 | 85 |
86 |

二级标题

87 |

段落内容

88 |
89 | 90 |
91 |

二级标题

92 |

段落内容

93 |
94 | 95 | 98 | 99 |
100 | 101 |
102 |

某某公司出品

103 |
104 | ``` 105 | 106 | ### 查看网页大纲的工具 107 | 108 | 我们可以通过 这个工具查看一个网页的大纲。 109 | 110 | **使用方法**: 111 | 112 | (1)将网址 保存到书签栏 113 | 114 | (2)去目标网页,点击书签栏的网址,即可查看该网页的大纲。 115 | 116 | 这个工具非常好用,既可以查看网页的大纲,也可以查看 markdown 在线文档的结构。 117 | 118 | ## html 元素的分类 119 | 120 | 按照样式分类: 121 | 122 | - 块级元素 123 | 124 | - 行内元素 125 | 126 | - inline-block:比如`form`表单元素。对外的表现是行内元素(不会独占一行),对内的表现是块级元素(可以设置宽高)。 127 | 128 | 按照内容分类: 129 | 130 | ![](http://img.smyhvae.com/20191003_1946.png) 131 | 132 | 图片来源: 133 | 134 | ## html 元素的嵌套关系 135 | 136 | - 块级元素可以包含行内元素。 137 | 138 | - 块级元素**不一定**能包含块级元素。比如 div 中可以包含 div,但 p 标签中不能包含 div。 139 | 140 | - 行内元素**一般**不能包含块级元素。比如 span 中不能包含 div。但有个特例:在 HTML5 中, a 标签中可以包含 div。 141 | 142 | **注意**:在 HTML5 中 `a > div` 是合法的, `div > a > div`是不合法的 ;但是在 html 4.0.1 中, `a > div` 仍然是不合法的。 143 | 144 | ## html 元素的默认样式和 CSS Reset 145 | 146 | 比如下拉框这种比较复杂的元素,是自带默认样式的。如果没有这个默认样式,则该元素在页面上不会有任何表现,则必然增加一些工作量。 147 | 148 | 同时,默认样式也会带来一些问题:比如,有些默认样式我们是不需要的;有些默认样式甚至无法去掉。 149 | 150 | 如果我们不需要默认的样式,这里就需要引入一个概念:**CSS Reset**。 151 | 152 | ### 常见的 CSS Reset 方案 153 | 154 | **方案一**: 155 | 156 | CSS Tools: Reset CSS。链接: 157 | 158 | **方案二**: 159 | 160 | 雅虎的 CSS Reset。链接: 161 | 162 | 我们可以直接通过 CDN 的方式引入: 163 | 164 | ```html 165 | 166 | ``` 167 | **方式三**:(比较有争议) 168 | 169 | ```css 170 | *{ 171 | margin: 0; 172 | padding: 0; 173 | } 174 | 175 | ``` 176 | 上面何种写法,比较简洁,但也有争议。有争议的地方在于,可能会导致 css 选择器的性能问题。 177 | 178 | ### Normalize.css 179 | 180 | 上面的几种 css reset 的解决思路是:将所有的默认样式清零。 181 | 182 | 但是,[Normalize.css](https://necolas.github.io/normalize.css/) 的思路是:既然浏览器提供了这些默认样式,那它就是有意义的。**既然不同浏览器的默认样式不一致,那么,`Normalize.css`就将这些默认样式设置为一致**。 183 | 184 | ## html 常见面试题 185 | 186 | ### doctype 的意义是什么 187 | 188 | - 让浏览器以标准模式渲染 189 | 190 | - 让浏览器知道元素的合法性 191 | 192 | ### HTML、XHTML、HTML5的区别 193 | 194 | - HTML 属于 SGML 195 | 196 | - XHTML 属于 XML,是 HTML 进行 XML 严格化的结果 197 | 198 | - HTML5 不属于SGML,也不属于 XML(HTML5有自己独立的一套规范),比 XHTML 宽松。 199 | 200 | ### HTML5 有什么新的变化 201 | 202 | - 新的语义化元素 203 | 204 | - 表单增强 205 | 206 | - 新的API:离线、音视频、图形、实时通信、本地存储、设备能力等。 207 | 208 | ### em 和 i 的区别 209 | 210 | 共同点:二者都是表示斜体。 211 | 212 | 区别: 213 | 214 | - em 是语义化的标签,表示强调。 215 | 216 | - i 是纯样式的标签,表示斜体。HTML5 中不推荐使用。 217 | 218 | ### 语义化的意义是什么 219 | 220 | - 开发者容易理解,便于维护。 221 | 222 | - 机器(搜索引擎、读屏软件等)容易理解结构 223 | 224 | - 有助于 SEO 225 | 226 | ### 哪些元素可以自闭和 227 | 228 | > 自闭和的元素中不能再嵌入别的元素。且 HTML5 中要求加斜杠。 229 | 230 | - 表单元素 input 231 | 232 | - 图片 img 233 | 234 | - br、hr 235 | 236 | - meta、link 237 | 238 | ### form 表单的作用 239 | 240 | - 直接提交表单 241 | 242 | - 使用 submit / reset 按钮 243 | 244 | - 便于浏览器保存表单 245 | 246 | - 第三方库(比如 jQuery)可以整体获取值 247 | 248 | - 第三方库可以进行表单验证 249 | 250 | 所以,如果我们是通过 Ajax 提交表单数据,也建议加上 form。 251 | 252 | --------------------------------------------------------------------------------