├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── README.md
├── docs
├── GMTC
│ └── readme.md
├── README.md
├── algorithm
│ └── README.md
├── architecture
│ └── README.md
├── css3
│ ├── BFC.md
│ ├── CSS实现自适应九宫格布局.md
│ ├── README.md
│ └── 居中布局.md
├── data-structure
│ ├── README.md
│ ├── assets
│ │ └── 数据结构.mindnode
│ └── 初识数据结构.md
├── design-patterns
│ ├── README.md
│ └── 单例模式.md
├── fe-engineering
│ └── code-quality.md
├── html5
│ └── README.md
├── hybrid
│ ├── README.md
│ └── hybrid架构设计.md
├── javascript
│ ├── README.md
│ ├── this关键字各种使用情况.md
│ ├── 前端跨域.md
│ ├── 浏览器环境的事件循环.md
│ ├── 深度优先搜索以及广度优先搜索.md
│ ├── 深拷贝与浅拷贝.md
│ └── 防抖与节流.md
├── linux
│ └── shell.md
├── nginx
│ └── Nginx学习之路.md
├── node
│ └── README.md
├── pwa
│ └── README.md
├── security
│ └── README.md
├── tcpIp
│ ├── HTTP缓存.md
│ ├── README.md
│ ├── TCP三次握手.md
│ ├── TCP四次挥手.md
│ └── network
│ │ ├── Part1: 浏览器生成消息.md
│ │ └── 网络是如何链接的.md
├── vue
│ ├── README.md
│ ├── Vue最佳实践.md
│ ├── Vue源码: Vue.use, vm.$delete内部原理.md
│ ├── Vue源码: vm.$mount内部原理.md
│ ├── Vue源码: vm.$set原理分析.md
│ ├── Vue源码: 事件相关的实例方法.md
│ ├── Vue源码: 关于vm.$watch内部原理.md
│ ├── Vue源码: 关于对Array的数据侦听.md
│ ├── Vue源码: 构造函数入口.md
│ └── Vue源码: 架构和目录设计.md
├── webpack
│ ├── README.md
│ └── 一个合格的Webpack4配置工程师素养.md
└── yarn
│ └── 调试.md
├── images
└── readme.md
├── pdf
├── 03-复杂度.pdf
├── 04-动态数组.pdf
├── 05-链表.pdf
├── 06-栈.pdf
├── 07-队列.pdf
├── 08-二叉树.pdf
├── 09-二叉搜索树.pdf
├── 10-平衡二叉搜索树.pdf
├── 11-AVL树.pdf
├── 12-B树.pdf
├── 13-红黑树.pdf
├── 14-集合.pdf
├── 15-映射.pdf
├── 16-哈希表.pdf
├── 17-二叉堆.pdf
├── 18-优先级队列.pdf
├── 19-哈夫曼树.pdf
├── 20-Trie.pdf
├── 21-总结.pdf
├── readme.md
└── 趣学算法 01.pdf
└── utils
└── readme.md
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v1
12 | - name: Run a one-line script
13 | run: echo Hello, world!
14 | - name: Run a multi-line script
15 | run: |
16 | echo Add other actions to build,
17 | echo test, and deploy your project.
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Blog
2 |
3 | 世界很大, 多踏出一步, 就进步一步。✊!!欢迎技术交流。
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/docs/GMTC/readme.md:
--------------------------------------------------------------------------------
1 | # GMTC
2 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ## 目录结构
2 |
3 | - algorithm: 算法
4 | - architecture: 架构
5 | - css3
6 | - data-structure: 数据结构
7 | - design-patterns: 设计模式
8 | - html5
9 | - hybrid: 混合开发
10 | - javascript
11 | - node
12 | - pwa
13 | - securoty: 安全
14 | - tcpip: TCP/IP
15 | - vue
16 | - webpack
17 |
--------------------------------------------------------------------------------
/docs/algorithm/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NuoHui/fe-note/c212689953baa051ba1de8f6fe1cdf26e53e9715/docs/algorithm/README.md
--------------------------------------------------------------------------------
/docs/architecture/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NuoHui/fe-note/c212689953baa051ba1de8f6fe1cdf26e53e9715/docs/architecture/README.md
--------------------------------------------------------------------------------
/docs/css3/BFC.md:
--------------------------------------------------------------------------------
1 | ## 什么是BFC
2 |
3 | BFC(块格式化上下文): 是Web页面可视化渲染CSS的一部分, 是布局过程中生成块级盒子的区域。也是浮动元素与其他元素的交互限定区域。
4 |
5 | 简单理解就是具备BFC特性的元素, 就像被一个容器所包裹, 容器内的元素在布局上不会影响外面的元素。
6 |
7 | ## BFC常见应用
8 |
9 | ### 解决普通文档流块元素的外边距折叠问题
10 |
11 | ```
12 |
30 |
34 | ```
35 |
36 | 
37 |
38 | 可见两个块元素外边距为20px。
39 |
40 | 我们可以使用BFC来解决这个问题,只需要把两个元素置于不同的BFC中进行隔离。
41 |
42 | ```
43 |
64 |
65 |
68 |
71 | ```
72 |
73 | 
74 |
75 |
76 | ### BFC清除浮动
77 |
78 | demo演示:
79 | ```
80 |
95 |
96 |
99 | ```
100 | 可见容器元素内子元素浮动,脱离文档流,容器元素高度只有2px。
101 |
102 | 
103 |
104 | 解决方法:
105 |
106 | ```
107 | .demo {
108 | border: 1px solid pink;
109 | overflow: hidden;
110 | }
111 | ```
112 |
113 |
114 | 
115 |
116 |
117 | ### 阻止普通文档流元素被浮动元素覆盖
118 |
119 | demo演示:
120 | ```
121 |
138 |
139 |
140 |
我是一个左侧浮动元素
141 |
我是一个没有设置浮动, 也没有触发BFC的元素
142 |
143 | ```
144 |
145 | demo2部分区域被浮动元素demo1覆盖, 但是文字没有覆盖, 即文字环绕效果。
146 | 
147 |
148 | 解决办法就是触发demo2的BFC。
149 |
150 | ```
151 | .demo2 {
152 | width: 200px;
153 | height: 200px;
154 | background: blue;
155 | overflow: hidden;
156 | }
157 | ```
158 |
159 |
160 | 
161 |
162 | ### 自适应两栏布局
163 |
164 |
165 | demo演示:
166 |
167 | ```
168 |
189 |
190 |
191 |
192 | 浮动元素
193 |
194 |
195 | 自适应
196 |
197 |
198 | ```
199 |
200 |
201 | 
202 |
203 | ## 如何触发BFC
204 |
205 |
206 | ```
207 | 1. 根元素或包含根元素的元素
208 | 2. 浮动元素(元素的 float 不是 none)
209 | 3. 绝对定位元素(元素的 position 为 absolute 或 fixed)
210 | 4. 行内块元素(元素的 display 为 inline-block)
211 | 5. 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
212 | 6. 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
213 | 7. 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
214 | 8. overflow 值不为 visible 的块元素
215 | 9. display 值为 flow-root 的元素
216 | 10. contain 值为 layout、content或 strict 的元素
217 | 11. 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
218 | 12. 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
219 | 13. 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
220 | 14. column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
221 |
222 | ```
223 |
--------------------------------------------------------------------------------
/docs/css3/CSS实现自适应九宫格布局.md:
--------------------------------------------------------------------------------
1 | # 九宫格布局
2 |
3 | 分析布局特点:
4 |
5 | ```
6 | 1. 九宫格的容器是宽高相等的容器
7 | 2. 每个小格子也是宽高相等
8 | ```
9 |
10 | 实现方式也很多, 比如flex, grid, float等, 这里只举一个例子
11 |
12 | ## 使用flex布局
13 |
14 |
15 | ```
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | CSS实现自shiying九宫格(flex布局)
24 |
67 |
68 |
69 |
70 |
71 |
72 | - 1
73 | - 2
74 | - 3
75 | - 4
76 | - 5
77 | - 6
78 | - 7
79 | - 8
80 | - 9
81 |
82 |
83 |
84 |
85 |
86 |
87 | ```
88 |
89 | [效果图](https://codepen.io/nuohui/pen/rgzVar)
90 |
--------------------------------------------------------------------------------
/docs/css3/README.md:
--------------------------------------------------------------------------------
1 | - [居中布局](https://github.com/NuoHui/fe-note/blob/master/docs/css3/%E5%B1%85%E4%B8%AD%E5%B8%83%E5%B1%80.md)
2 | - [BFC](https://github.com/NuoHui/fe-note/blob/master/docs/css3/BFC.md)
3 | - [CSS实现自适应九宫格布局](https://github.com/NuoHui/fe-note/blob/master/docs/css3/CSS%E5%AE%9E%E7%8E%B0%E8%87%AA%E9%80%82%E5%BA%94%E4%B9%9D%E5%AE%AB%E6%A0%BC%E5%B8%83%E5%B1%80.md)
4 |
--------------------------------------------------------------------------------
/docs/css3/居中布局.md:
--------------------------------------------------------------------------------
1 | ## 水平居中
2 |
3 | ### 行内元素水平居中
4 |
5 | 方法: 给行内元素父元素使用text-align: center
6 |
7 | ```
8 |
23 |
24 | 行内元素水平居中
25 |
26 | ```
27 |
28 | 
29 |
30 | ### 块级元素水平居中
31 |
32 | 方法: 块级元素使用margin: 0 auto。
33 |
34 | ```
35 |
51 |
54 | ```
55 |
56 | 
57 |
58 | ### fit-content + margin: 0 auto
59 |
60 | 若子元素包含float,为了让子元素水平居中,可让父元素宽度设置为fit-content,并且配合margin。
61 |
62 | ```
63 |
81 |
82 |
块级元素水平居中: 子元素浮动
83 |
84 | ```
85 |
86 | 
87 |
88 | 关于fit-content推荐阅读[理解CSS3 max/min-content及fit-content等width值](https://www.zhangxinxu.com/wordpress/2016/05/css3-width-max-contnet-min-content-fit-content/)
89 |
90 | ### flex + justify-content: center
91 |
92 | ```
93 |
110 |
111 |
flex + justify-content: center
112 |
113 | ```
114 |
115 | 
116 |
117 | ### absolute + transform
118 |
119 | ```
120 |
137 |
138 |
宽度未知: absolute + transform
139 |
140 | ```
141 |
142 |
143 | 
144 |
145 | 关于transform使用推荐阅读[理解SVG transform坐标变换](https://www.zhangxinxu.com/wordpress/2015/10/understand-svg-transform/)
146 |
147 |
148 | ### 已知宽度: absolute + 负值的margin-left
149 |
150 | ```
151 |
169 |
170 |
宽度已知: absolute + 负值的margin-left
171 |
172 | ```
173 |
174 | 
175 |
176 |
177 | ### 宽度已知: absolute + left:0;right:0;margin:0 auto
178 |
179 | ```
180 |
199 |
200 |
宽度已知: absolute + left:0;right:0;margin:0 auto
201 |
202 | ```
203 |
204 | 
205 |
206 | ## 垂直居中
207 |
208 | ### 已知父元素高度情况: line-height: height
209 |
210 | 若元素是单行文本, 则可设置 line-height 等于父元素高度。
211 |
212 | ```
213 |
228 |
229 |
已知父元素高度情况: line-height: height
230 |
231 | ```
232 |
233 | 
234 |
235 |
236 | ### 已经父元素高度: 若元素是行内块级元素如img, 可以使用display: inline-block, vertical-align: middle和一个伪元素。
237 |
238 | ```
239 |
259 |
260 |

261 |
262 | ```
263 |
264 |
265 | 
266 |
267 | ### flex + align-items: center
268 |
269 |
270 | 
271 |
272 | ### absolute + transform
273 |
274 | ```
275 |
293 |
294 |
absolute + transform
295 |
296 | ```
297 |
298 |
299 | 
300 |
301 |
302 | ### display: table
303 |
304 | ```
305 |
322 |
325 | ```
326 |
327 |
328 | 
329 |
330 | ## 水平垂直居中
331 |
332 | ### absolute + transform
333 |
334 | ```
335 |
354 |
355 |
absolute + transform
356 |
357 | ```
358 |
359 | 
360 |
361 | ### flex
362 |
363 |
364 | 
365 |
366 | ### table水平垂直居中
367 |
368 | 方法: inline-block + text-align + table-cell + vertical-align
369 |
370 | ```
371 |
392 |
393 |
块级元素: table水平垂直居中
394 |
395 |
396 | 行内元素: table水平垂直居中
397 |
398 | ```
399 |
400 |
401 | 
402 |
403 |
404 | ### 知道父元素高度,子元素高度
405 |
406 | 方法: 绝对定位方式+四个方向置0 + margin: auto
407 |
408 | ```
409 |
431 |
432 |
绝对定位方式+四个方向置0
433 |
434 | ```
435 |
436 | 
437 |
--------------------------------------------------------------------------------
/docs/data-structure/README.md:
--------------------------------------------------------------------------------
1 | - [初识数据结构](https://github.com/NuoHui/fe-note/blob/master/docs/data-structure/%E5%88%9D%E8%AF%86%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84.md)
2 |
--------------------------------------------------------------------------------
/docs/data-structure/assets/数据结构.mindnode:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NuoHui/fe-note/c212689953baa051ba1de8f6fe1cdf26e53e9715/docs/data-structure/assets/数据结构.mindnode
--------------------------------------------------------------------------------
/docs/data-structure/初识数据结构.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 |
--------------------------------------------------------------------------------
/docs/design-patterns/README.md:
--------------------------------------------------------------------------------
1 | - [单例模式](https://github.com/NuoHui/fe-note/blob/master/docs/design-patterns/%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F.md)
2 |
--------------------------------------------------------------------------------
/docs/design-patterns/单例模式.md:
--------------------------------------------------------------------------------
1 | # 单例模式
2 |
3 | 定义: 单例模式确保某个类永远只有一个实例, 并且提供一个全局访问的方法。
4 |
5 | ## UML类图
6 |
7 |
8 | 
9 |
10 | 如果借助TypeScript来实现的话如下:
11 |
12 | ```
13 | namespace SingletonPattern {
14 | export class Singleton {
15 | // A variable which stores the singleton object. Initially,
16 | // the variable acts like a placeholder
17 | private static singleton: Singleton;
18 |
19 | // private constructor so that no instance is created
20 | private constructor() {
21 | }
22 |
23 | // This is how we create a singleton object
24 | public static getInstance(): Singleton {
25 | // check if an instance of the class is already created
26 | if (!Singleton.singleton) {
27 | // If not created create an instance of the class
28 | // store the instance in the variable
29 | Singleton.singleton = new Singleton();
30 | }
31 | // return the singleton object
32 | return Singleton.singleton;
33 | }
34 | }
35 | }
36 |
37 | ```
38 |
39 | ## JS实现方式
40 |
41 | 当某些对象我们只需要创建一个的时候就可以考虑单例模式。
42 |
43 | ### 一个标准的单例模式
44 |
45 | ```
46 | function Singleton (name) {
47 | this.instance = null
48 | this.name = name
49 | }
50 |
51 | Singleton.prototype.getName = function () {
52 | console.log(this.name)
53 | }
54 |
55 | Singleton.getInstance = function (name) {
56 | return this.instance || (this.instance = new Singleton(name))
57 | }
58 |
59 | const s1 = Singleton.getInstance('kobe')
60 | const s2 = Singleton.getInstance('kobe2')
61 |
62 | console.log(s1 === s2) // true
63 | ```
64 |
65 | 或者
66 |
67 | ```
68 | function Singleton (name) {
69 | this.name = name
70 | }
71 |
72 | Singleton.prototype.getName = function () {
73 | console.log(this.name)
74 | }
75 |
76 | Singleton.getInstance = (function (name) {
77 | let instance = null
78 | return function (name) {
79 | return instance || (instance = new Singleton(name))
80 | }
81 | })()
82 |
83 | const s1 = Singleton.getInstance('kobe')
84 | const s2 = Singleton.getInstance('kobe2')
85 |
86 | console.log(s1 === s2) // true
87 | ```
88 |
89 | 上述的代码有个缺点就是不透明性, 即使用者需要知道通过Singleton.getInstance()方法去获取。这个与我们传统的new Constructor()创建实例方法不同。
90 |
91 |
92 | ### 惰性单例模式
93 |
94 | 我们都知道JS作为一门动态类型语言, 所以我们应该使用JS的方式来实现惰性单例, 充分利用JS的灵活性。
95 |
96 | 惰性单例: 即表示等需要创建实例时候才创建。
97 |
98 | #### 通用的核心代码
99 |
100 | ```
101 | // fn: 具体执行的创建实例业务代码
102 | function getInstance(fn) {
103 | let instance
104 | return function (...args) {
105 | return instance || (instance = fn.apply(this, args))
106 | }
107 | }
108 | ```
109 |
110 | demo需求: 点击按钮永远只会导入一个iframe(指向百度的)
111 |
112 | ```
113 |
114 |
115 |
116 |
117 |
118 |
119 | 单例模式
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | ```
128 |
129 | ```
130 | window.onload = function () {
131 | // fn: 具体执行的创建实例业务代码
132 | function getInstance(fn) {
133 | let instance
134 | return function (...args) {
135 | return instance || (instance = fn.apply(this, args))
136 | }
137 | }
138 | const createEle = function (tagName) {
139 | const ele = document.createElement(tagName)
140 | ele.style.display = 'none'
141 | document.body.appendChild(ele)
142 | return ele
143 | }
144 | const createSingleIframe = getInstance(createEle)
145 | document.querySelector('#login').onclick = function () {
146 | const iframe = createSingleIframe('iframe')
147 | iframe.src = 'http://www.baidu.com'
148 | iframe.style.display = 'block'
149 | }
150 | }
151 |
152 | ```
153 |
--------------------------------------------------------------------------------
/docs/fe-engineering/code-quality.md:
--------------------------------------------------------------------------------
1 | ## What
2 |
3 | ### 什么是代码本身的质量?
4 |
5 | 代码本身的质量: 包括复杂度, 重复率, 代码风格等。
6 |
7 | - 复杂度: 项目代码量,模块大小,耦合度等
8 | - 重复率: 重复出现的代码区块占比,通常要求在5%以下(借助平台化工具如Sonar)
9 | - 代码风格: 代码风格是否统一(动态语言代码如JS, Python风格不受约束)
10 |
11 |
12 | ### 代码质量下降恶性循环
13 |
14 | 常见的代码质量下降的原因:
15 |
16 | - 破罐破摔: 在烂代码上迭代代码罪恶感比较小
17 | - 传染性: 不在意代码质量, 只关注业务的产出
18 | - 心有余而力不足
19 |
20 | 常见的导致恶性循环的场景:
21 |
22 | - 业务压力太大
23 |
24 | 烂代码产生的常见原因是业务压力大,导致没有时间或意愿讲究代码质量。因为向业务压力妥协而生产烂代码之后,开发效率会随之下降,进而导致业务压力更大,形成一种典型的恶性循环。
25 |
26 |
27 | 
28 |
29 | - 通过增加人力解决业务压力
30 |
31 | 为了应对业务压力,常见的做法就是向项目中增加人力,但是单纯地增加人力的话,会因为风格不一致、沟通成本上升等原因导致烂代码更多。
32 |
33 |
34 | 
35 |
36 | 那么我们应该如何解决呢?
37 |
38 |
39 | 
40 |
41 | 这是一个长期坚持的过程。
42 |
43 | ### 代码质量管控四个阶段
44 |
45 | - 规范化
46 |
47 | 建立代码规范与Code Review制度
48 |
49 | 1. [airbnb](https://github.com/airbnb/javascript)
50 | 2. [standard](https://github.com/standard/standard)
51 | 3. [node-style-guide](https://github.com/felixge/node-style-guide)
52 | 4. [google javascript style guide](https://google.github.io/styleguide/jsguide.html)
53 | 5. [google html/css style guide](https://google.github.io/styleguide/htmlcssguide.html)
54 | 6. [Vue风格指南](https://cn.vuejs.org/v2/style-guide/)
55 |
56 | 我觉得统一项目目录结构也是规范化的一种(比如我们用脚手架创建项目模板), 一个规范化的目录结构大大降低新人的上手成本。
57 |
58 | - 自动化
59 |
60 | 使用工具(linters)自动检查代码质量。
61 |
62 |
63 | 
64 |
65 | - 流程化
66 |
67 | 将代码质量检查与代码流动过程绑定。
68 |
69 |
70 | 
71 |
72 | 质量检查与代码流动绑定后的效果:
73 |
74 |
75 | 
76 |
77 |
78 | ```
79 | 备注:
80 |
81 | 1. 编辑时候: 通过编辑器插件, 实时查看质量检查
82 |
83 | 2. 可以利用CI(Jekins/Travis)把构建发布过程搬到线上, 先跑代码扫描, 测试代码等, 然后没有错误再进行build, build成功通过ssh推到服务器。
84 | ```
85 |
86 | - 中心化
87 |
88 | 以团队整体为视角,集中管理代码规范,并实现质量状况透明化。
89 |
90 | 当团队规模越来越大,项目越来越多时,代码质量管控就会面临以下问题:
91 |
92 | 1. 不同项目使用的代码规范不一样
93 |
94 | 2. 部分项目由于放松要求,没有接入质量检查,或者存在大量未修复的缺陷
95 |
96 | 3. 无法从团队整体层面上体现各个项目的质量状况对比
97 |
98 | 为了应对以上问题,需要建设中心化的代码质量管控体系,要点包括:
99 |
100 | 代码规范统一管理。通过脚手架命令垂直管理代码扫描配置规则集, 自动安装,不在本地写规则。一个团队、一类项目、一套规则。
101 |
102 | * * *
103 |
104 |
105 | * [待定] 使用统一的持续集成服务(Jekins/Travis等)。质量检查不通过的项目不能上线。
106 |
107 | * [待定] 建立代码质量评分制度(借助Sonar)。让项目与项目之间能够横向对比,项目自身能够纵向对比,并且进行汇总反馈。
108 |
109 | ## Why
110 |
111 | > 代码质量是团队技术水平和管理水平的直接体现。
112 |
113 | > 看代码的时间远远多于写代码的时间
114 |
115 | ### 目前前端项目出现的问题
116 |
117 | - 书写风格不统一, 阅读体验差
118 | - 维护性差, 复用性差(Code Review互相进步)
119 | - 容易出现低质量代码, 代码返工率高
120 | - git commit不规范
121 |
122 |
123 | ## How
124 |
125 | 通过哪些手段来保证代码质量?
126 |
127 | ### EditorConfig
128 |
129 | [EditorConfig]( https://editorconfig.org/)在多人协作开发项目时候, 支持跨编辑器, IDE来支持维护一致的编码样式(文件格式)。
130 |
131 | VSCode插件EditorConfig for VS Code提供一键生成.editorconfig。
132 |
133 | 查看[实例](https://editorconfig.org/#example-file)。
134 |
135 | ### TypeScript
136 |
137 | - [官网介绍](https://www.typescriptlang.org/
138 | )。
139 | - [中文awesome-typescript](https://github.com/semlinker/awesome-typescript)
140 | - [TypeScript体系调研报告](https://juejin.im/post/59c46bc86fb9a00a4636f939)
141 | - [2018年度JS趋势报告](https://2018.stateofjs.com/javascript-flavors/overview/)
142 |
143 | ### Git Hooks
144 |
145 | Git能在特定的重要动作发生时触发自定义脚本。 有两组这样的钩子:客户端的和服务器端的。 客户端钩子由诸如提交和合并这样的操作所调用,而服务器端钩子作用于诸如接收被推送的提交这样的联网操作, 我们目前使用的大多数是客户端钩子。
146 |
147 | 通过[husky](https://github.com/typicode/husky)集成[git hooks](https://git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-Git-%E9%92%A9%E5%AD%90), 如果对git想有更全面的理解推荐阅读[GIt文档](https://git-scm.com/book/zh/v2)。
148 |
149 | husky会安装一系列的git hook到项目的.git/hook目录中。
150 |
151 | 下面两张图分别对比没有安装husky与安装了husky的git目录区别:
152 |
153 |
154 | 
155 |
156 | 
157 |
158 | 当你用 git init 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本(.sample结尾的文件)。
159 |
160 | #### pre-commit
161 |
162 |
163 | pre-commit 钩子在键入提交信息前运行。 它用于检查即将提交的快照,你可以利用该钩子,来检查代码风格是否一致(运行类似 lint 的程序。
164 |
165 |
166 | - [lint-staged](https://github.com/okonet/lint-staged): 可以获取所有被提交的文件并执行配置好的任务命令,各种lint校验工具可以配置好lint-staged任务中。
167 | - [prettier](https://prettier.io/): 可以配置到lint-staged中, 实现自动格式化编码风格。
168 | - [stylelint](https://github.com/stylelint/stylelint)
169 | - [eslint](https://cn.eslint.org/)
170 | - [tslint](https://github.com/palantir/tslint)
171 | - [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue): Vue.js官方推荐的lint工具
172 |
173 |
174 | 关于[为什么选择prettier, 以及eslint 与prettier区别?](https://zhuanlan.zhihu.com/p/62542268)。
175 |
176 | 关于[prettier配置](https://prettier.io/docs/en/configuration.html)。
177 | 关于[stylelint配置](https://stylelint.io/user-guide/configuration/)。
178 | 关于[eslint配置](https://cn.eslint.org/docs/user-guide/configuring)。
179 |
180 | #### commit-msg
181 |
182 |
183 | - [commitlint](https://github.com/conventional-changelog/commitlint)。
184 |
185 |
186 | commit-msg 可以用来在提交通过前验证项目状态或提交信息, 使用该钩子来核对提交信息是否遵循指定的模板。
187 |
188 | 关于git hooks在package.json配置:
189 |
190 |
191 | 
192 |
193 | ### 测试
194 |
195 | #### unittest
196 |
197 | - [Jest](https://jestjs.io/
198 | )
199 | - [Mocha](https://mochajs.org/
200 | )
201 |
202 | #### e2e
203 |
204 | - [Nightwatch](http://nightwatchjs.org/
205 | )
206 | - [Cypress](https://www.cypress.io/
207 | )
208 |
209 |
210 | ### CHANGELOG
211 |
212 | 更新日志, [standard-version](https://github.com/conventional-changelog/standard-version)。
213 |
214 | ### Code Review
215 |
216 | * [待定] Review制度,我们目前公司在代码merge时候多人审核才通过。
217 |
218 |
219 | ## 如何快速落地到当前业务
220 |
221 |
222 | ### 前端脚手架(xx-cli)
223 |
224 | 采用中心化集中管理代码扫描配置文件的思路, 把code lint配置文件做成一个npm包发到内网, 然后扩展脚手架命令一键执行下发远程配置文件到本地项目, 并且把新增的package.json依赖打进来, 大家后面再安装新的依赖即可。
225 |
226 | 所谓中心化管理: 所有项目代码配置文件以远程配置文件为准, 如果你本地有同名配置会被删除, 这样方便后续我们更新配置文件比如(增加vw/vh适配), 以及所有业务同步问题。
227 |
228 | ```
229 | 目前只有基于vue.js项目的lint脚本命令, 后续有别的项目, 考虑通过
230 |
231 | dc-cli lint -- vue
232 | dc-cli lint -- node
233 | 扩展
234 | ```
235 |
236 |
237 | ### demo演示
238 |
239 | demo演示如何在旧项目中植入代码质量检测?
240 | 由于这部分是在内网演示就不发不出来了。
241 |
242 | 至于脚手架可以参考我之前的demo[easy-cli](https://github.com/NuoHui/easy-cli)。这是比较全的demo。
243 |
244 |
245 | ## Future
246 |
247 | ### Jekins自动化
248 |
249 |
250 | ### [Sonar](https://www.sonarqube.org/)
251 |
252 | [Github:](https://github.com/SonarSource/sonarqube)
253 |
254 | SonarQube 是一款领先的持续代码质量监控平台,开源在github 上,可以轻松配置在内网服务器,实时监控代码,帮助了解提升提升团队项目代码质量。通过插件机制,SonarQube可以继承不同的测试工具,代码分析工具,以及持续集成工具。
255 |
256 | 与持续集成工具(例如 Hudson/Jenkins 等)不同,SonarQube 并不是简单地把不同的代码检查工具结果(例如 FindBugs,PMD 等)直接显示在 Web 页面上,而是通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。
257 |
258 | 行业内提到"代码质量管理, 自动化质量管理", 一般指的都是通过Sonar来实现。
259 |
260 | 用Sonar能够实现什么?
261 | - 技术债务(sonar根据"规则"扫描出不符合规则的代码)
262 | - 覆盖率(单元测试覆盖率)
263 | - 重复(重复的代码, 有利于提醒封装)
264 | - 结构
265 | - …
266 |
267 | ### sonarjs
268 |
269 | sonar支持多种编程语言, 其中包括JavaScript. 如[sonarjs](https://www.sonarsource.com/products/codeanalyzers/sonarjs.html)
270 |
271 |
272 | ## 最后打个广告,欢迎关注我的公众号 全栈小窝。
273 |
--------------------------------------------------------------------------------
/docs/html5/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NuoHui/fe-note/c212689953baa051ba1de8f6fe1cdf26e53e9715/docs/html5/README.md
--------------------------------------------------------------------------------
/docs/hybrid/README.md:
--------------------------------------------------------------------------------
1 | - [hybrid架构设计](https://github.com/NuoHui/fe-note/blob/master/docs/hybrid/hybrid%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1.md)
2 |
--------------------------------------------------------------------------------
/docs/hybrid/hybrid架构设计.md:
--------------------------------------------------------------------------------
1 | ## 什么是Hybrid
2 |
3 | Hybrid故名思义: 混合开发, 即App端+前端混合开发模式,Hybrid App 底层依赖 Native 端的 Web 容器(UIWebview 和 WKWebview),上层使用前端 Html5、CSS、Javascript 做业务开发。
4 |
5 | ## Hybrid带来哪些好处?
6 |
7 | 一套好的Hybrid App设计能够即拥有原生App流畅的体验, 又拥有前端H5快速灵活的开发模式, 如跨平台能力, 热更新机制。
8 |
9 | Hybrid解决的痛点: 我觉得最主要的就是快速版本迭代。
10 |
11 | ## Hybrid适合的场景
12 |
13 | - 需求频繁变更的
14 | - 对交互体验,性能要求不是特别高的
15 |
16 |
17 | ## Webview
18 |
19 | 我们都知道Webview是一个App端组件, 我们使用WebView 作为容器直接承载 Web页面。
20 |
21 |
22 |
23 |
24 | 这里推荐阅读
25 | - [如何设计一个优雅健壮的Android WebView?(上)](https://juejin.im/post/5a94f9d15188257a63113a74)
26 | - [如何设计一个优雅健壮的Android WebView?(下)](https://juejin.im/post/5a94fb046fb9a0635865a2d6)
27 | - [深入剖析 iOS 与 JS 交互](https://zhuanlan.zhihu.com/p/31368159)
28 |
29 |
30 |
31 |
32 |
33 | ## App接入H5的方式
34 |
35 | 把H5接入到App中有两种方式:
36 |
37 | ### 在线H5
38 |
39 | 这是一种非常常见的部署方式, 我们只需要把H5代码单独部署在服务器, 当App通过Webview渲染H5时候, 我们只需要提供对应H5 URL即可, Webview直接load这个URL。
40 |
41 | - 优点
42 |
43 | ```
44 | 1. 具备独立部署/开发/调试/上线能力
45 | 2. 资源部署在远程服务器, 不会影响App包体积
46 | 3. 接入成本低
47 | ```
48 |
49 | - 缺点
50 |
51 | ```
52 | 1. 依赖于网络, 首屏渲染慢, 需要进一步优化页面性能
53 | 2. 不支持离线访问
54 | ```
55 | - 适用业务场景
56 |
57 | 适用于一些功能性不强,不太需要复杂的功能协议,且不需要离线使用的业务。
58 |
59 | ### App内置包H5
60 |
61 | 这是一种本地化嵌入方式, 服务端会把我们打包后的前端代码资源下发到App端,然后App端解压到本地。
62 |
63 |
64 |
65 | 当然这里还需要一套版本管理机制, 只当App端本地资源不是最新的才去拉去服务器的资源。
66 |
67 |
68 |
69 |
70 | - 优点
71 |
72 | ```
73 | 1. 首屏加载快, 用户体验好
74 | 2. 不依赖网络, 支持离线访问
75 | ```
76 |
77 | - 缺点
78 |
79 | ```
80 | 1. 开发流畅/更新机制复杂, 需要三方协作
81 | 2. 会增加App包的体积
82 | ```
83 |
84 | ## Schema协议
85 |
86 | ### 什么是Schema协议
87 |
88 | scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面。
89 |
90 | ### Scheme链接格式样式
91 |
92 | ```
93 | [scheme]://[host]/[path]?[query]
94 | ```
95 | 在前端使用Schema协议
96 |
97 | ```
98 | 打开叮咚app
99 | ```
100 |
101 |
102 | ### Schem协议使用场景
103 |
104 | - 通过小程序,利用Scheme协议打开原生app
105 | - H5页面点击锚点,根据锚点具体跳转路径APP端跳转具体的页面
106 | - APP端收到服务器端下发的PUSH通知栏消息,根据消息的点击跳转路径跳转相关页面
107 | - APP根据URL跳转到另外一个APP指定页面
108 | - 通过短信息中的url短链打开原生app
109 |
110 | ## JS Bridge设计
111 |
112 | App与前端的通信方式。
113 |
114 |
115 |
116 |
117 | ### JS Bridge源码
118 |
119 | 待补充
120 |
--------------------------------------------------------------------------------
/docs/javascript/README.md:
--------------------------------------------------------------------------------
1 | - [前端跨域](https://github.com/NuoHui/fe-note/blob/master/docs/javascript/%E5%89%8D%E7%AB%AF%E8%B7%A8%E5%9F%9F.md)
2 |
3 | - [this关键字各种使用情况](https://github.com/NuoHui/fe-note/blob/master/docs/javascript/this%E5%85%B3%E9%94%AE%E5%AD%97%E5%90%84%E7%A7%8D%E4%BD%BF%E7%94%A8%E6%83%85%E5%86%B5.md)
4 |
5 | - [浏览器环境的事件循环](https://github.com/NuoHui/fe-note/blob/master/docs/javascript/%E6%B5%8F%E8%A7%88%E5%99%A8%E7%8E%AF%E5%A2%83%E7%9A%84%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF.md)
6 |
7 | - [节流与防抖](https://github.com/NuoHui/fe-note/blob/master/docs/javascript/%E9%98%B2%E6%8A%96%E4%B8%8E%E8%8A%82%E6%B5%81.md)
8 |
9 | - [浅拷贝与深拷贝](https://github.com/NuoHui/fe-note/blob/master/docs/javascript/%E6%B7%B1%E6%8B%B7%E8%B4%9D%E4%B8%8E%E6%B5%85%E6%8B%B7%E8%B4%9D.md)
10 |
--------------------------------------------------------------------------------
/docs/javascript/this关键字各种使用情况.md:
--------------------------------------------------------------------------------
1 | this关键字是js中最复杂的机制之一, 因为它是自动被定义在函数作用域中。但是如果我们真正的搞懂了this的工作机制, 其实没有那么复杂。
2 |
3 | ## 为什么需要使用this?
4 |
5 | ```
6 | function sayName () {
7 | console.log(this.name)
8 | }
9 |
10 | const xm = {
11 | name: 'xm'
12 | }
13 |
14 | const ml = {
15 | name: 'ml'
16 | }
17 |
18 | sayName.call(xm) // xm
19 | sayName.call(ml) // ml
20 |
21 | ```
22 | 你会发现, 在不同的上下午对象中可以复用同一个函数, 如果不使用this, 我们只能显示指定对象参数。
23 |
24 | ```
25 | function sayName (ctx) {
26 | console.log(ctx.name)
27 | }
28 |
29 | const xm = {
30 | name: 'xm'
31 | }
32 |
33 | const ml = {
34 | name: 'ml'
35 | }
36 |
37 | sayName(xm) // xm
38 | sayName(ml) // ml
39 |
40 | ```
41 | 可见this会隐式传递一个对象引用, 这样可以使函数的设计可以更简洁优雅。
42 |
43 | ## 误解之一: this总是指向自身
44 |
45 |
46 | ```
47 | function fo (i) {
48 | console.log('fo', i)
49 | console.log(this === window) // true
50 | this.count++
51 | }
52 |
53 | fo.count = 0
54 |
55 | for (var i = 0; i < 5; i++) {
56 | fo(i)
57 | }
58 | console.log(fo.count, count) // 0, NaN
59 |
60 | ```
61 | 针对上述问题我们怎么修改可以获得预期效果?
62 | ```
63 | // 回避this的使用
64 | function fo (i) {
65 | console.log('fo', i)
66 | console.log(this === window) // true
67 | fo.count++
68 | }
69 |
70 | fo.count = 0
71 |
72 | for (var i = 0; i < 5; i++) {
73 | fo(i)
74 | }
75 | console.log(fo.count) // 5
76 | ```
77 |
78 | 简而言之, this是在运行时候绑定的, 不是由定义时候指定, this的上下文取决于由谁在哪里调用。
79 |
80 |
81 | ## this的绑定规则
82 |
83 | > 默认绑定
84 |
85 | 最常用的函数调用方式就是独立函数调用, 因此我们可以称为默认绑定。
86 | 默认绑定this指向window。
87 |
88 | ```
89 | function a () {
90 | console.log(this.name)
91 | }
92 | var name = 'a'
93 |
94 | a() // 默认不带任何修饰的调用 == 普通调用 输出a
95 | a.call(null) // 输出a
96 | a.call(undefined) // 输出a
97 |
98 | ```
99 | 但是需要注意函数体是严格模式下的默认绑定中this指向undefined。
100 |
101 | ```
102 | function a () {
103 | "use strict"
104 | console.log(this === undefined, this === null) // true, false
105 | console.log(this.name) // Cannot read property 'name' of undefined
106 | }
107 | var name = 'a'
108 |
109 | a()
110 | a.call(null)
111 | a.call(undefined)
112 |
113 | ```
114 |
115 | > 隐式绑定
116 |
117 | 规则: 有时候我们需要考虑调用位置是否有上下文对象,或者是否被某个对象所包含。
118 |
119 | ```
120 | // 先定义再添加引用属性
121 |
122 | function test () {
123 | console.log(this.name)
124 | }
125 |
126 | var obj = {
127 | name: 'kobe',
128 | test: test
129 | }
130 |
131 | obj.test() // 'kobe'
132 |
133 | ```
134 |
135 | ```
136 | // 直接作为对象的方法
137 |
138 | var obj = {
139 | name: 'kobe',
140 | test: function () {
141 | console.log(this.name)
142 | }
143 | }
144 |
145 | obj.test() // 'kobe'
146 |
147 | ```
148 |
149 | 箭头函数的this是指向它的父级执行环境
150 | ```
151 | // 注意箭头函数的this指向
152 | var name = 'global'
153 | var obj = {
154 | name: 'kobe',
155 | test: () => {
156 | console.log(this === window) // true
157 | console.log(this.name) // global
158 | }
159 | }
160 |
161 | obj.test()
162 |
163 | ```
164 |
165 | ```
166 | // 对象属性引用链的调用(只有最顶层与最后一层才会影响调用位置)
167 |
168 | function foo () {
169 | console.log(this.name)
170 | }
171 | var c = {
172 | name: 'c',
173 | foo: foo
174 | }
175 | var b = {
176 | name: 'b',
177 | c: c
178 | }
179 |
180 | var a = {
181 | name: 'a',
182 | b: b
183 | }
184 |
185 | a.b.c.foo() // c
186 |
187 | ```
188 |
189 | > 隐式丢失
190 |
191 | 一个常见的this绑定出现的问题就是: 被隐式绑定的函数容易丢失绑定对象, 最后应用默认绑定。
192 |
193 | ```
194 | function a () {
195 | console.log(this.name)
196 | }
197 |
198 | var obj = {
199 | name: 'obj',
200 | a: a
201 | }
202 |
203 | var temp = obj.a
204 | var name = 'global'
205 | temp() // this绑定丢失, 应用默认绑定, 指向全局window => 'global'
206 | obj.a() // 'obj'
207 |
208 | ```
209 |
210 | 另外需要注意参数传递也是一种隐式赋值。
211 |
212 | ```
213 | function a () {
214 | console.log(this.name)
215 | }
216 |
217 | var obj = {
218 | name: 'obj',
219 | a: a
220 | }
221 |
222 | var name = 'global'
223 |
224 | function fx (cb) {
225 | cb()
226 | }
227 |
228 | fx(obj.a) // this绑定丢失, 应用默认绑定, 指向全局window => 'global'
229 |
230 | /**
231 | * fx(obj.a) === 等于 var fn = obj.a; fx(fn)
232 | */
233 |
234 | ```
235 | 如果你把函数传入语言内置的函数, 结果其实也是一样。
236 |
237 | ```
238 | var obj = {
239 | name: 'obj',
240 | a: function () {
241 | console.log(this.name)
242 | }
243 | }
244 | var name = 'global'
245 | setTimeout(obj.a, 10) // 传参是隐式赋值
246 |
247 | ```
248 |
249 | > 显示绑定
250 |
251 | 显示绑定主要通过call(), apply()
252 |
253 | call()与apply()方法第一个参数指的是绑定对象,即它们会把对象绑定到this, 然后调用函数时候指向这个this, 因此通过直接指定this的绑定对象方法叫做显示绑定。
254 |
255 | ```
256 | function test () {
257 | console.log(this.name)
258 | }
259 |
260 | var o = {
261 | name: 'o'
262 | }
263 | test.call(o) // o
264 |
265 | ```
266 |
267 | 如果你传入的第一个参数是原始值, 来作为this绑定对象, 那么该原始值会通过new String(), new Boolean(), new Number()转为对象形式, 这个操作又叫做装箱。
268 |
269 |
270 | > 硬绑定
271 |
272 | 显示绑定依然无法解决this绑定丢失问题, 但是我们可以通过一些方法来解决该问题。
273 |
274 | - 显示绑定变种实现
275 |
276 | ```
277 | function test () {
278 | console.log(this.name)
279 | }
280 |
281 | var o = {
282 | name: 'o',
283 | test: test
284 | };
285 | // 通过创建一个包裹函数
286 | function bindThis () {
287 | test.call(o)
288 | }
289 | var name = 'global'
290 | setTimeout(bindThis) // o
291 |
292 | ```
293 |
294 | 通过bind()实现硬绑定, 来解决丢失this绑定问题。
295 | bind()会返回一个硬编码的新函数, 并且把参数设置为this的上下文。
296 |
297 | ```
298 | function test () {
299 | console.log(this.name)
300 | }
301 |
302 | var o = {
303 | name: 'o',
304 | test: test
305 | };
306 |
307 | var name = 'global'
308 | setTimeout(o.test.bind(o)) // o
309 |
310 | ```
311 |
312 | 此外很多第三方库或者JS内置函数都允许传递一个可选参数作为上下文对象。
313 | 其作用就是类似bind, 确保你的回调函数中this指向的是该上下文对象。
314 |
315 | ```
316 | function test (item) {
317 | console.log(item, this.id)
318 | }
319 |
320 | var obj = {
321 | id: 'id'
322 | };
323 |
324 | [1,2,3,4].forEach(test, obj)
325 |
326 | ```
327 |
328 | > new 绑定
329 |
330 | 我们一般创建一个对象实例通过new Constructor()
331 |
332 | new 一个构造函数其实会执行以下过程。
333 | ```
334 | 1. 创建一个全新的对象
335 | 2. 该新对象执行原型链接, 把该对象绑定到this
336 | 3. 执行函数中代码
337 | 4. 如果没有其他返回, 默认返回该新对象
338 | ```
339 |
340 | ```
341 | function Person () {
342 | this.name = '2'
343 | }
344 |
345 | console.log(new Person().name) // 2
346 |
347 | ```
348 |
349 | > 绑定规则优先级
350 |
351 |
352 | ```
353 | 1. 默认绑定优先级最低
354 | ```
355 |
356 | 比较显示绑定与隐式绑定: 显示绑定优先于隐式绑定
357 |
358 | ```
359 | function test () {
360 | console.log(this.name)
361 | }
362 |
363 | var a = {
364 | name: 'a',
365 | test: test
366 | }
367 |
368 | var b = {
369 | name: 'b',
370 | test: test
371 | }
372 |
373 | // 隐式绑定
374 | a.test() // a
375 | b.test() // b
376 |
377 | // 显示绑定
378 | a.test.call(b) // b
379 | b.test.call(a) // a
380 |
381 | ```
382 |
383 | 比较new绑定与隐式绑定: new绑定优先级高于隐式绑定
384 |
385 | ```
386 | function test (thing) {
387 | this.thing = thing
388 | }
389 |
390 | var obj1 = {
391 | test: test
392 | }
393 |
394 | var obj2 = {}
395 |
396 | // 隐式绑定
397 | obj1.test(2)
398 | console.log(obj1.thing) // 2
399 |
400 | // 显示绑定
401 | obj1.test.call(obj2, 3)
402 | console.log(obj2.thing) // 3
403 |
404 |
405 | // 可见new绑定优先级高于隐式绑定, 如果不是的化 test.thing=2
406 | var test = new obj1.test(4)
407 | console.log(obj1.thing) // 2
408 | console.log(test.thing) // 4
409 |
410 | ```
411 |
412 | 那么最后我们比较new绑定跟硬绑定: new绑定优先与硬绑定
413 | 注意: new绑定不能跟call, apply一起使用。
414 |
415 |
416 | ```
417 | function test (thing) {
418 | this.thing = thing
419 | }
420 |
421 | var o = {}
422 |
423 | var binds = test.bind(o)
424 | binds(3)
425 | // 硬绑定
426 | console.log(o.thing) // 3
427 |
428 | var thing = new binds(4)
429 | console.log(thing.thing) // 4
430 | console.log(o.thing) // 3, 么有改变说明 new绑定优先级高
431 |
432 | ```
433 |
434 | 总结:
435 |
436 | ```
437 | 1. 如果函数是通过new调用(new绑定), 那么this指向新创建的对象
438 | 2. 函数是否通过call, apply, bind等显示绑定,或者硬绑定, 是的化this指向指定的对象
439 | 3. 函数是在某个上下文中调用(隐式绑定), 那么this绑定的是那个上下文对象
440 | 4. 如果以上都不是, 那么默认是默认绑定, this指向全局对象, 如果函数体是严格模式指向undefined
441 |
442 | ```
443 |
444 |
445 | ## 特殊情况下的绑定
446 |
447 | - 被忽略的this
448 |
449 | 即就是bind, call, apply时候, 把undefined或者null作为绑定对象。
450 |
451 | ```
452 | var a = 2
453 | function test () {
454 | console.log(this.a)
455 | }
456 | test.call(null) // 2
457 | test.call(undefined) // 2
458 |
459 | ```
460 |
461 | ```
462 | function test (a, b) {
463 | console.log(a, b)
464 | }
465 |
466 | test.apply(null, [3,4]) // 3,4
467 | var temp = test.bind(null, 2)
468 | temp(4) // 2, 4
469 |
470 | ```
471 | - 更安全的this
472 |
473 |
474 | 但是很多时候我们不建议把null或者undefined作为空对象的占位符,因为它们默认会指向全局对象, 容易产生副作用, 最好使用Object.create(null)。
475 |
476 | ```
477 | function test (a, b) {
478 | console.log(a, b)
479 | }
480 |
481 | test.apply(Object.create(null), [3,4]) // 3,4
482 | var temp = test.bind(Object.create(null), 2)
483 | temp(4) // 2, 4
484 |
485 | ```
486 | - 间接引用
487 |
488 | 有时候我们可能会无意创建这个函数是的间接引用, 这种情况下, 调用这个函数默认会使用默认规则。
489 |
490 | ```
491 | // 间接引用最容易在赋值时候发生
492 |
493 | var name = 'global'
494 | function test () {
495 | console.log(this.name)
496 | }
497 |
498 | var o = {
499 | name: 'o',
500 | test: test
501 | }
502 | var a = {
503 | name: 'a'
504 | };
505 | o.test();// o
506 | (a.test = o.test)() // global
507 |
508 | // 如果是
509 | // a.test = o.test
510 | // a.test() // a
511 | ```
512 |
513 | ## 面试题
514 |
515 | ```
516 | var name = 'global'
517 |
518 | var obj = {
519 | name: 'obj',
520 | test: function () {
521 | (() => {
522 | var name = '2'
523 | console.log(this.name)
524 | })()
525 | }
526 | }
527 |
528 | obj.test() // obj
529 |
530 | ```
531 |
532 | ```
533 | function foo () {
534 | return () => {
535 | console.log(this.name)
536 | }
537 | }
538 |
539 | var obj1 = {
540 | name: 'obj1'
541 | }
542 |
543 | var obj2 = {
544 | name: 'obj2'
545 | }
546 |
547 | var temp = foo.call(obj1)
548 | temp.call(obj2) // obj1
549 |
550 | ```
551 |
--------------------------------------------------------------------------------
/docs/javascript/前端跨域.md:
--------------------------------------------------------------------------------
1 | ## 前端跨域
2 |
3 | > 什么是跨域?
4 |
5 | 跨域是指从一个域下的文档或者脚本去请求另外一个域下的资源,当然这里是广义上说的跨域。
6 |
7 | 广义上的跨域
8 |
9 | ```
10 | 资源嵌入: 、
72 |