-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
419 lines (261 loc) · 377 KB
/
atom.xml
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
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
61
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
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
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>JawnHa的博客</title>
<link href="/atom.xml" rel="self"/>
<link href="https://jawn-ha.github.com/"/>
<updated>2020-06-24T07:23:24.044Z</updated>
<id>https://jawn-ha.github.com/</id>
<author>
<name>JawnHa</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>Redis 数据类型以及命令总结</title>
<link href="https://jawn-ha.github.com/2020/01/15/yuque/Redis%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E4%BB%A5%E5%8F%8A%E5%91%BD%E4%BB%A4%E6%80%BB%E7%BB%93/"/>
<id>https://jawn-ha.github.com/2020/01/15/yuque/Redis%20%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E4%BB%A5%E5%8F%8A%E5%91%BD%E4%BB%A4%E6%80%BB%E7%BB%93/</id>
<published>2020-01-15T11:52:11.000Z</published>
<updated>2020-06-24T07:23:24.044Z</updated>
<content type="html"><![CDATA[<p><img src="https://cdn.nlark.com/yuque/0/2020/png/267618/1579089338294-3f9d163c-f62f-4047-9069-1e46a406963a.png#align=left&display=inline&height=130&name=%E4%B8%8B%E8%BD%BD.png&originHeight=130&originWidth=389&size=4911&status=done&style=none&width=389" alt="下载.png"><br>Redis是一个开源的高性能键值对数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,并借助许多高层级的接口使其可以胜任如缓存、队列系统等不同的角色。</p><p>Redis是REmote DIctionary Server(远程字典服务器)的缩写,它以字典结构存储数据(key,value的形式),并允许其他应用通过TCP协议读写字典中的内容。同大多数脚本语言中的字典一样,Redis字典中的键值除了可以是字符串,还可以是其他数据类型。到目前为止Redis支持的键值数据类型如下:</p><ul><li>字符串类型</li><li>散列类型</li><li>列表类型</li><li>集合类型</li><li>有序集合类型</li></ul><p>本文总结了 Redis 常用的命令,根据数据类型对他们进行分类<br><a id="more"></a></p><p><a name="ekrdj"></a></p><h3 id="字符串类型"><a href="#字符串类型" class="headerlink" title="字符串类型"></a>字符串类型</h3><ul><li>_key value_SET 赋值</li><li>GET <em>key</em> 取值 GETGET</li><li>INCR <em>key</em> 递增数字</li><li>INCRBY <em>key increment</em> 增加指定的整数</li><li>DECR <em>key</em> 递减数字</li><li>DECR <em>key decrement</em> 减少指定的整数</li><li>INCRBYFLOAT <em>key increment</em> 增加指定的浮点数</li><li>APPEND <em>key value</em> 向尾部追加值</li><li>STRLEN <em>key</em> 获取字符串长度</li><li>MGET <em>key</em> [<em>key</em> …] 同时获得多个健值</li><li>MSET <em>key value</em> [<em>key value</em> …] 同时设置多个健值</li></ul><p><a name="6Ledd"></a></p><h3 id="散列类型"><a href="#散列类型" class="headerlink" title="散列类型"></a>散列类型</h3><p>散列类型(hash)的键值也是一种字典结构,有点类似于javascript的对象,其存储了字段(field)和字段值的映射,但字段值只能是字符串,不支持其他数据类型,换句话说,散列类型不能嵌套其他的数据类型。一个散列类型键可以包含至多232-1个字段。<br><img src="https://cdn.nlark.com/yuque/0/2020/png/267618/1579400048673-563edafd-d00e-4458-8a99-fb82b312d0a5.png#align=left&display=inline&height=220&name=image.png&originHeight=518&originWidth=1104&size=90856&status=done&style=none&width=469" alt="image.png"></p><ul><li>HSET <em>key field value</em> 给健的字段赋值,不区分插入和更新操作</li><li>HGET <em>key field</em> 获得健里字段的值</li><li>HMSET <em>key field value</em> [<em>field value</em> …] 同时给多个字段赋值</li><li>HMGET <em>key field</em> [<em>field</em> ..] 同时取多个字段的值</li><li>HMGETALL <em>key</em> 获取健中所有字段和字段值</li><li>HEXISTS <em>key field</em> 判断字段是否存在</li><li>HSETNX <em>key field value</em> 当字段不存在是赋值</li><li>HINCRBY <em>key field increment</em> 增加数字</li><li>HDEL <em>key field</em> [<em>field</em> …] 删除一个或多个字段</li><li>HKEYS <em>key</em> 只获取全部字段名</li><li>HVALS <em>key</em> 只获取全部字段值</li><li>HLEN <em>key</em> 获取健的字段数量</li></ul><p><a name="3rXT3"></a></p><h3 id="列表类型"><a href="#列表类型" class="headerlink" title="列表类型"></a>列表类型</h3><p>列表类型(list)可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素,或者获得列表的某一个片段。列表类型内部是使用双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度为O(1),获取越接近两端的元素速度就越快。这意味着即使是一个有几千万个元素的列表,获取头部或尾部的10条记录也是极快的(和从只有20个元素的列表中获取头部或尾部的10条记录的速度是一样的。<br>与散列类型键最多能容纳的字段数量相同,一个列表类型键最多能容纳232-1个元素。</p><ul><li>LPUSH <em>key value</em> [<em>value</em> …] 向列表左边增加元素,返回值表示增加元素后列表的长度</li><li>RPUSH <em>key value</em> [<em>value</em> …] 向列表右边增加元素的话则使用RPUSH命令,其用法和LPUSH命令一样</li><li>LPOP <em>key</em> 从列表左边弹出一个元素,返回被移除的元素值</li><li>RPOP <em>key</em> 从列表右边弹出一个元素,返回被移除的元素值</li><li>LLEN <em>key</em> 获取列表中的元素个数,当键不存在时LLEN会返回0</li><li><p>LRANGE <em>key start stop</em> 获得列表索引从start到stop之间的所有元素(包含两端的元素)但不会删除该片段,起始索引为0,”-1”表示最右边第一个元素。</p><blockquote><p>(1)如果start的索引位置比stop的索引位置靠后,则会返回空列表。<br>(2)如果stop大于实际的索引范围,则会返回到列表最右边的元素。</p></blockquote></li><li><p>LREM <em>key count value</em> 删除列表中前count个值为value的元素,返回值是实际删除的元素个数</p><blockquote><ul><li>当count > 0时LREM命令会从列表左边开始删除前 count个值为 value的元素;</li><li>当count < 0时LREM命令会从列表右边开始删除前|count|个值为value的元素;</li><li>当count = 0是LREM命令会删除所有值为value的元素。例如:</li></ul></blockquote></li><li><p>LINDEX <em>key index</em> 获得指定索引的元素值</p></li><li>LSET <em>key index value</em> 设置指定索引的元素值,它会将索引为index的元素赋值为value</li><li>LTRIM <em>key start end</em> 删除指定索引范围之外的所有元素,其指定列表范围的方法和LRANGE命令相同</li><li>LINSERT <em>key</em> BEFORE|AFTER <em>privot value</em> 向列表中插入元素,LINSERT命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数是BEFORE还是AFTER来决定将value插入到该元素的前面还是后面。LINSERT命令的返回值是插入后列表的元素个数</li><li>RPOPLPUSH <em>source destination</em> 将元素从一个列表转到另一个列表</li></ul><p><a name="SuRu1"></a></p><h3 id="集合类型"><a href="#集合类型" class="headerlink" title="集合类型"></a>集合类型</h3><p>集合的概念高中的数学课就学习过。在集合中的每个元素都是不同的,且没有顺序。一个集合类型(set)键可以存储至多232 -1个(相信这个数字对大家来说已经很熟悉了)字符串。集合类型和列表类型有相似之处,但很容易将它们区分开来<br><img src="https://cdn.nlark.com/yuque/0/2020/png/267618/1579401596775-d43f3389-6897-47ec-9953-7e14075e8a8a.png#align=left&display=inline&height=256&name=image.png&originHeight=256&originWidth=1564&size=87360&status=done&style=none&width=1564" alt="image.png"><br>集合类型的常用操作是向集合中加入或删除元素、判断某个元素是否存在等,由于集合类型在Redis内部是使用值为空的散列表(hash table)实现的,所以这些操作的时间复杂度都是O(1)。最方便的是多个集合类型键之间还可以进行并集、交集和差集运算</p><ul><li>SADD <em>key member</em> [<em>member</em> …] 向集合中增加一个或多个元素,如果键不存在则会自动创建,返回值是成功加入的元素数量</li><li>SREM <em>key member</em> [<em>member</em> …] 从集合中删除一个或多个元素,并返回删除成功的个数</li><li>SMEMBERS <em>key</em> 获得集合中的所有元素</li><li>SISMEMBER <em>key</em> 判断元素是否在集合中</li><li>SDIFF <em>key</em> [<em>key</em> …] 用来对多个集合执行差集运算。集合A与集合B的差集表示为A-B,代表所有属于A且不属于B的元素构成的集合</li><li>SINTER <em>key</em> [<em>key</em> …] 用来对多个集合执行交集运算。集合A与集合B的交集表示为A ∩ B,代表所有属于A且属于B的元素构成的集合,即A ∩ B = {x | x ∈ A且x∈B}</li><li>SUNION <em>key</em> [<em>key</em> …] SUNION命令用来对多个集合执行并集运算。集合A与集合B的并集表示为A∪B,代表所有属于A或属于B的元素构成的集合(如图3-15所示),即A∪B = {x | x∈A或x ∈B}</li><li>SCARD <em>key</em> 获取集合中元素个数</li><li>SDIFFSTORE <em>destination key</em> [<em>key</em> …] SDIFFSTORE命令和SDIFF命令功能一样,唯一的区别就是前者不会直接返回运算结果,而是将结果存储在destination键中。 </li><li>SINTERSTORE <em>destination key</em> [<em>key</em> …] SDIFFSTORE命令常用于需要进行多步集合运算的场景中,如需要先计算差集再将结果和其他键计算交集。</li><li>SUNIONSTORE <em>destination key</em> [<em>key</em> …] SINTERSTORE和SUNIONSTORE命令与之类似,不再赘述。</li><li><p>SRANDMEMBER <em>key</em> [<em>count</em>] 用来随机从集合中获取一个元素,还可以传递count参数来一次随机获得多个元素</p><blockquote><p>(1)当count为正数时,SRANDMEMBER会随机从集合里获得count个不重复的元素。如果count的值大于集合中的元素个数,则SRANDMEMBER会返回集合中的全部元素。<br>(2)当 count 为负数时,SRANDMEMBER会随机从集合里获得|count|个的元素,这些元素有可能相同。</p></blockquote></li><li><p>SPOP <em>key</em> 会从集合中随机选择一个元素弹出并在原集合中删除它</p></li></ul><p><a name="tYGvY"></a></p><h3 id="有序集合类型"><a href="#有序集合类型" class="headerlink" title="有序集合类型"></a>有序集合类型</h3><p>在集合类型的基础上有序集合类型为集合中的每个元素都关联了一个分数,这使得我们不仅可以完成插入、删除和判断元素是否存在等集合类型支持的操作,还能够获得分数最高(或最低)的前N个元素、获得指定分数范围内的元素等与分数有关的操作。虽然集合中每个元素都是不同的,但是它们的分数却可以相同。<br>有序集合类型在某些方面和列表类型有些相似。<br>(1)二者都是有序的。<br>(2)二者都可以获得某一范围的元素。但是二者有着很大的区别,<br>这使得它们的应用场景也是不同的。<br>(1)列表类型是通过链表实现的,获取靠近两端的数据速度极快,而当元素增多后,访问中间数据的速度会较慢,所以它更加适合实现如“新鲜事”或“日志”这样很少访问中间元素的应用。<br>(2)有序集合类型是使用散列表和跳跃表(Skip list)实现的,所以即使读取位于中间部分的数据速度也很快(时间复杂度是O(log(N)))。<br>(3)列表中不能简单地调整某个元素的位置,但是有序集合可以(通过更改这个元素的分数)。<br>(4)有序集合要比列表类型更耗费内存。</p><ul><li>ZADD <em>key score member</em> [ <em>score member</em> …] ZADD命令用来向有序集合中加入一个元素和该元素的分数,如果该元素已经存在则会用新的分数替换原有的分数。ZADD命令的返回值是新加入到集合中的元素个数(不包含之前已经存在的元素),分数不仅可以是整数,还支持双精度浮点数</li><li>ZSCORE <em>key member</em> 获得元素的分数</li><li>ZRANGE <em>key start stop</em> [WITHSCORES] 按照元素分数从小到大的顺序返回索引从start到stop之间的所有元素(包含两端的元素), 如果需要同时获得元素的分数的话可以在ZRANGE命令的尾部加上WITHSCORES参数</li><li>ZREVRANGE <em>key start stop</em> [WITHSCORES] 和ZRANGE的唯一不同在于ZREVRANGE命令是按照元素分数从大到小的顺序给出结果的。</li><li>ZRANGEBYSCORE <em>key min max</em> [WITHSCORES] [LIMIT <em>offset count</em>] 参数虽然多,但是都很好理解。该命令按照元素分数从小到大的顺序返回分数在min和max之间(包含min和max)的元素,如果希望分数范围不包含端点值,可以在分数前加上“(”符号,min和max还支持无穷大,同ZADD命令一样,-inf和+inf分别表示负无穷和正无穷</li><li>ZINCRBY <em>key increment member</em> 增加某个元素的分数</li><li>ZCARD <em>key</em> 获得集合元素的数量</li><li>ZCOUNT <em>key min max</em> 获取指定分数范围内的元素个数</li><li>ZREM <em>key member</em> [<em>member</em> …] 删除一个或多个元素,返回值是成功删除的元素数量(不包含本来就不存在的)</li><li>ZREMRANGEBYRANK <em>key start stop</em> 按照元素分数从小到大的顺序(即索引0表示最小的值)删除处在指定排名范围内的所有元素,并返回删除的元素数量</li><li>ZREMRANGEBYSCORE <em>key min max</em> 删除指定分数范围内的所有元素</li><li>ZRANK <em>key member</em> 会按照元素分数从小到大的顺序获得指定的元素的排名(从0开始,即分数最小的元素排名为0)</li><li>ZREVRANK <em>key member</em> ZREVRANK命令则相反(分数最大的元素排名为0)</li><li>ZINTERSTORE <em>destination numkeys key</em> [<em>key</em> …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX] 用来计算多个有序集合的交集并将结果存储在destination键中(同样以有序集合类型存储),返回值为destination键中的元素个数。ZINTERSTORE命令还能够通过WEIGHTS参数设置每个集合的权重,每个集合在参与计算时元素的分数会被乘上该集合的权重<blockquote><ol><li>当AGGREGATE是SUM时(也就是默认值),destination键中元素的分数是每个参与计算的集合中该元素分数的和</li><li>当AGGREGATE是MIN时,destination键中元素的分数是每个参与计算的集合中该元素分数的最小值</li><li>当AGGREGATE是MAX时,destination键中元素的分数是每个参与计算的集合中该元素分数的最大值</li></ol></blockquote></li></ul><p>另外还有一个命令与ZINTERSTORE命令的用法一样,名为ZUNIONSTORE,它的作用是计算集合间的并集,这里不再赘述。</p><p><a name="HwxYl"></a></p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>以上就是 Redis 常用的数据类型以及命令总结拾遗,学习和使用的时候要多对比,才能更加融会贯通</p>]]></content>
<summary type="html">
<p><img src="https://cdn.nlark.com/yuque/0/2020/png/267618/1579089338294-3f9d163c-f62f-4047-9069-1e46a406963a.png#align=left&amp;display=inline&amp;height=130&amp;name=%E4%B8%8B%E8%BD%BD.png&amp;originHeight=130&amp;originWidth=389&amp;size=4911&amp;status=done&amp;style=none&amp;width=389" alt="下载.png"><br>Redis是一个开源的高性能键值对数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,并借助许多高层级的接口使其可以胜任如缓存、队列系统等不同的角色。</p>
<p>Redis是REmote DIctionary Server(远程字典服务器)的缩写,它以字典结构存储数据(key,value的形式),并允许其他应用通过TCP协议读写字典中的内容。同大多数脚本语言中的字典一样,Redis字典中的键值除了可以是字符串,还可以是其他数据类型。到目前为止Redis支持的键值数据类型如下:</p>
<ul>
<li>字符串类型</li>
<li>散列类型</li>
<li>列表类型</li>
<li>集合类型</li>
<li>有序集合类型</li>
</ul>
<p>本文总结了 Redis 常用的命令,根据数据类型对他们进行分类<br>
</summary>
</entry>
<entry>
<title>利用Nginx部署多个Vue项目</title>
<link href="https://jawn-ha.github.com/2019/10/16/yuque/%E5%88%A9%E7%94%A8Nginx%E9%83%A8%E7%BD%B2%E5%A4%9A%E4%B8%AAVue%E9%A1%B9%E7%9B%AE/"/>
<id>https://jawn-ha.github.com/2019/10/16/yuque/%E5%88%A9%E7%94%A8Nginx%E9%83%A8%E7%BD%B2%E5%A4%9A%E4%B8%AAVue%E9%A1%B9%E7%9B%AE/</id>
<published>2019-10-16T09:35:46.000Z</published>
<updated>2020-06-24T07:23:24.048Z</updated>
<content type="html"><![CDATA[<p>最近在公司帮忙孵化一个项目,有一个PC端的Web用户系统以及一些手机端的页面,本着PC和手机分离的原则,我用vue-cli起了两个SPA项目开始了愉快的coding过程,但是coding完了在部署的时候却遇到了难题,因为没有申请多的域名,只有一个可以使用的二级域名,但是有两个vue项目,合到一起又会有许多兼容性问题,所以在想能不能实现通过域名后面输入不同的目录进入不同的项目的效果<br><a id="more"></a><br><a name="ThVEP"></a></p><h2 id="Nginx-配置"><a href="#Nginx-配置" class="headerlink" title="Nginx 配置"></a>Nginx 配置</h2><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">server</span> {</span><br><span class="line"> <span class="attribute">listen</span> <span class="number">8000</span>;</span><br><span class="line"> server_name 192.168.11.16; //你的ip或域名</span><br><span class="line"><span class="attribute">access_log</span> logs/8000access.log;</span><br><span class="line"> <span class="attribute">location</span> / {</span><br><span class="line"> <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ /index.html;</span><br><span class="line"> <span class="attribute">root</span> /app/web/dist/;</span><br><span class="line"> }</span><br><span class="line">location /wap { //注意此处 关键!!!</span><br><span class="line"><span class="attribute">root</span> /app/web/dist;</span><br><span class="line"> <span class="attribute">try_files</span> <span class="variable">$uri</span> <span class="variable">$uri</span>/ /wap/index.html;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p><a name="lP1VZ"></a></p><h2 id="vue项目配置"><a href="#vue项目配置" class="headerlink" title="vue项目配置"></a>vue项目配置</h2><p>两个项目分别是PC以及wap<br><a name="LZmpK"></a></p><h3 id="1、修改wap项目的vue配置文件"><a href="#1、修改wap项目的vue配置文件" class="headerlink" title="1、修改wap项目的vue配置文件"></a>1、修改wap项目的vue配置文件</h3><p>我所使用的是vue-cli3,在vue.config.js 中增加</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">publicPath: <span class="string">'/wap/'</span>, <span class="comment">//方便调试</span></span><br><span class="line">outputDir: <span class="string">'wap'</span>, <span class="comment">//修改打包输出目录</span></span><br></pre></td></tr></table></figure><p>这里wap是我所使用的路由,你也可以根据你的情况进行相应的修改<br>参考链接:<br><a href="https://cli.vuejs.org/zh/config/#publicpath" target="_blank" rel="noopener">https://cli.vuejs.org/zh/config/#publicpath</a><br><a href="https://cli.vuejs.org/zh/config/#outputdir" target="_blank" rel="noopener">https://cli.vuejs.org/zh/config/#outputdir</a><br><a name="YFosD"></a></p><h3 id="2、修改wap项目router的base"><a href="#2、修改wap项目router的base" class="headerlink" title="2、修改wap项目router的base"></a>2、修改wap项目router的base</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> router = <span class="keyword">new</span> Router({</span><br><span class="line"> mode: <span class="string">'history'</span>,</span><br><span class="line"> base: <span class="string">'/wap/'</span>, <span class="comment">//这里做修改</span></span><br><span class="line"> routes</span><br><span class="line">})</span><br></pre></td></tr></table></figure><p><a name="f3WFU"></a></p><h3 id="3、对两个项目分别打包"><a href="#3、对两个项目分别打包" class="headerlink" title="3、对两个项目分别打包"></a>3、对两个项目分别打包</h3><p>将wap项目生成的wap的文件夹放入PC项目打包生成的dist文件夹中,压缩上传部署重启nginx</p><p>这样访问<a href="http://192.168.11.16:8000就是PC端的页面,访问[http://192.168.11.16:8000](http://192.168.11.16:8000)/wap" target="_blank" rel="noopener">http://192.168.11.16:8000就是PC端的页面,访问[http://192.168.11.16:8000](http://192.168.11.16:8000)/wap</a> 就是手机端(另一个vue项目)的页面了<br><a name="whzrd"></a></p><h3 id="需要注意的点:"><a href="#需要注意的点:" class="headerlink" title="需要注意的点:"></a>需要注意的点:</h3><p>1.最好使用history模式<br>2.PC项目的vue-router不要对wap进行操作</p>]]></content>
<summary type="html">
<p>最近在公司帮忙孵化一个项目,有一个PC端的Web用户系统以及一些手机端的页面,本着PC和手机分离的原则,我用vue-cli起了两个SPA项目开始了愉快的coding过程,但是coding完了在部署的时候却遇到了难题,因为没有申请多的域名,只有一个可以使用的二级域名,但是有两个vue项目,合到一起又会有许多兼容性问题,所以在想能不能实现通过域名后面输入不同的目录进入不同的项目的效果<br>
</summary>
</entry>
<entry>
<title>Angular.js1.X 学习笔记——自定义指令</title>
<link href="https://jawn-ha.github.com/2018/08/29/Angular-js1-X-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E2%80%94%E2%80%94%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4/"/>
<id>https://jawn-ha.github.com/2018/08/29/Angular-js1-X-%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E2%80%94%E2%80%94%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8C%87%E4%BB%A4/</id>
<published>2018-08-29T21:25:59.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h1 id="Angular-js1-X-学习笔记——自定义指令"><a href="#Angular-js1-X-学习笔记——自定义指令" class="headerlink" title="Angular.js1.X 学习笔记——自定义指令"></a>Angular.js1.X 学习笔记——自定义指令</h1><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>指令(Directive)可以说是 AngularJS 的核心,与Vue不同,angular.js的指令涵盖的vue的组件功能,你可以把它简单的理解为在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。例如,ng-click可以让一个元素能够监听click事件,并在接收到事件的时候执行AngularJS表达式。我们也可以自己创造新的指令。</p><a id="more"></a><h3 id="指令定义"><a href="#指令定义" class="headerlink" title="指令定义"></a>指令定义</h3><p>directive() 方法可以接受两个参数:</p><ul><li>name(字符串)<br>指令的名字,用来在视图中引用特定的指令。</li><li>factory_function (函数)<br>这个函数返回一个对象,其中定义了指令的全部行为。在DOM调用指令时来构造指令的行为。<br>angular.application(‘myApp’, [])<figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">angular.application(<span class="string">'myApp'</span>, [])</span><br><span class="line">.directive(<span class="string">'myDirective'</span>, <span class="function"><span class="keyword">function</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="comment">// 一个指令定义对象</span></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> <span class="comment">// 通过设置项来定义指令,在这里进行覆写</span></span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure></li></ul><h3 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h3><p>从 AngularJS 的官方文档中看到指令的参数如下:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> priority: <span class="number">0</span>,</span><br><span class="line"> template: <span class="string">'<div></div>'</span>, // <span class="keyword">or</span> // <span class="function"><span class="keyword">function</span><span class="params">(tElement, tAttrs)</span></span> { ... },</span><br><span class="line"> // <span class="keyword">or</span></span><br><span class="line"> // templateUrl: <span class="string">'directive.html'</span>, // <span class="keyword">or</span> // <span class="function"><span class="keyword">function</span><span class="params">(tElement, tAttrs)</span></span> { ... },</span><br><span class="line"> transclude: <span class="literal">false</span>,</span><br><span class="line"> restrict: <span class="string">'A'</span>,</span><br><span class="line"> scope: <span class="literal">false</span>,</span><br><span class="line"> controller: <span class="function"><span class="keyword">function</span><span class="params">($scope, $element, $attrs, $transclude, otherInjectables)</span></span> { ... },</span><br><span class="line"> controllerAs: <span class="string">'stringAlias'</span>,</span><br><span class="line"> <span class="built_in">require</span>: <span class="string">'siblingDirectiveName'</span>, // <span class="keyword">or</span> // [<span class="string">'^parentDirectiveName'</span>, <span class="string">'?optionalDirectiveName'</span>, <span class="string">'?^optionalParent'</span>],</span><br><span class="line"> compile: <span class="function"><span class="keyword">function</span> <span class="title">compile</span><span class="params">(tElement, tAttrs, transclude)</span></span> {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> pre: <span class="function"><span class="keyword">function</span> <span class="title">preLink</span><span class="params">(scope, iElement, iAttrs, controller)</span></span> { ... },</span><br><span class="line"> post: <span class="function"><span class="keyword">function</span> <span class="title">postLink</span><span class="params">(scope, iElement, iAttrs, controller)</span></span> { ... }</span><br><span class="line"> }</span><br><span class="line"> // <span class="keyword">or</span></span><br><span class="line"> // <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="title">postLink</span><span class="params">( ... )</span></span> { ... }</span><br><span class="line"> },</span><br><span class="line"> // <span class="keyword">or</span></span><br><span class="line"> // link: {</span><br><span class="line"> // pre: <span class="function"><span class="keyword">function</span> <span class="title">preLink</span><span class="params">(scope, iElement, iAttrs, controller)</span></span> { ... },</span><br><span class="line"> // post: <span class="function"><span class="keyword">function</span> <span class="title">postLink</span><span class="params">(scope, iElement, iAttrs, controller)</span></span> { ... }</span><br><span class="line"> // }</span><br><span class="line"> // <span class="keyword">or</span></span><br><span class="line"> // link: <span class="function"><span class="keyword">function</span> <span class="title">postLink</span><span class="params">( ... )</span></span> { ... }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h4 id="restrict(字符串)"><a href="#restrict(字符串)" class="headerlink" title="restrict(字符串)"></a>restrict(字符串)</h4><p>restrict是一个可选的参数。它告诉AngularJS这个指令在DOM中可以何种形式被声明。默认AngularJS认为restrict的值是A,即以属性的形式来进行声明。<br>可选值如下:<br><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">E(元素)</span><br><span class="line"><<span class="keyword">my</span>-directive></<span class="keyword">my</span>-directive></span><br><span class="line">A(属性,默认值)</span><br><span class="line"><<span class="keyword">div</span> <span class="keyword">my</span>-directive=<span class="string">"expression"</span>></<span class="keyword">div</span>></span><br><span class="line">C(类名)</span><br><span class="line"><<span class="keyword">div</span> <span class="built_in">class</span>=<span class="string">"my-directive:expression;"</span>></<span class="keyword">div</span>></span><br><span class="line">M(注释)</span><br><span class="line"><<span class="comment">--directive:my-directive expression--></span></span><br></pre></td></tr></table></figure></p><p>这些选项可以单独使用,也可以混合在一起使用:<br><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">angular.module(<span class="string">'myDirective'</span>, <span class="function"><span class="keyword">function</span><span class="params">()</span></span>{</span><br><span class="line"><span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'EA'</span> <span class="comment">// 输入元素或属性</span></span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure></p><p>上面的配置可以同时用属性或注释的方式来声明指令:<br><-- 作为一个属性 --></--></p><p><div my-directive></div><br><-- 或者作为一个元素 --></--></p><p><my-directive></my-directive></p><h4 id="priority-Number"><a href="#priority-Number" class="headerlink" title="priority(Number)"></a>priority(Number)</h4><p>指令执行的优先级,用于多个指令同时作用于同一个元素时。例如:<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">select</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">option</span> <span class="attr">ng-repeat</span>=<span class="string">"i in [1, 2]"</span> <span class="attr">ng-bind</span>=<span class="string">"i"</span>></span><span class="tag"></<span class="name">option</span>></span></span><br><span class="line"><span class="tag"></<span class="name">select</span>></span></span><br></pre></td></tr></table></figure></p><p>上面的例子中,<code>ng-repeat</code> 指令和 <code>ng-bind</code> 指令同时作用于 <code>option</code> 元素,由于 <code>ng-repeat</code> 的 priority 为1000,<code>ng-bind</code> 的 priority 为0,因此先执行 <code>ng-repeat</code>,然后变量 i 的值才能用于 ng-bind 中。</p><h4 id="template-String-or-Function"><a href="#template-String-or-Function" class="headerlink" title="template(String or Function)"></a>template(String or Function)</h4><p>HTML模板内容,用于下列情况之一:</p><ul><li><p>替换元素的内容(默认情况)。</p></li><li><p>替换元素本身(如果 replace 选项为 true)。</p></li><li><p>将元素的内容包裹起来(如果 transclude 选项为 true,后面会细说)。</p></li></ul><p>值可以是:</p><ul><li><p>一个 HTML 字符串。例如:<code><div>my name is </div></code>。</p></li><li><p>一个函数,接收两个参数 tElement(元素本身) 和 tAttrs(元素的属性集合),返回 HTML 字符串。</p></li></ul><h4 id="templateUrl-String-or-Function"><a href="#templateUrl-String-or-Function" class="headerlink" title="templateUrl(String or Function)"></a>templateUrl(String or Function)</h4><p>templateUrl 和 template 作用相同,但模板内容是从 $templateCache 服务或远程 url 加载。</p><p>值可以是:</p><ul><li><p>一个字符串,<code>AngularJS</code> 会先从 <code>$templateCache</code> 中查找是否缓存了对应值,如果没有则尝试 ajax 加载。例如:在页面中有如下 script:</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/ng-template"</span> <span class="attr">id</span>=<span class="string">"Hello.html"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="handlebars"><span class="xml"> <span class="tag"><<span class="name">p</span>></span>Hello<span class="tag"></<span class="name">p</span>></span></span></span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure><p>AngularJS 会将 <code>type="text/ng-template"</code> 的 <code>script</code> 标签中的内容以 id 值为 key 缓存到 $templateCache 服务中,此时可以设置 <code>templateUrl: 'Hello.html'</code>。</p></li><li><p>一个函数,接收两个参数 tElement(元素本身) 和 tAttrs(元素的属性集合),返回 url 地址。</p></li></ul><h4 id="transclude-Boolean"><a href="#transclude-Boolean" class="headerlink" title="transclude(Boolean)"></a>transclude(Boolean)</h4><p>官方文档的解释为:编译元素的内容,使其在指令内部可用。该选项一般和 <code>ng-transclude</code> 指令一起使用。</p><p>如果 transclude 设置为 true,则元素的内容会被放到模板中设置了 <code>ng-transclude</code> 指令的元素中。例如:</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">app.directive(<span class="string">'testTransclude'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'E'</span>,</span><br><span class="line"> transclude: <span class="literal">true</span>,</span><br><span class="line"> template:</span><br><span class="line"> <span class="string">'<div>\</span></span><br><span class="line"><span class="string"> <p>指令内部段落</p>\</span></span><br><span class="line"><span class="string"> <div ng-transclude></div>\</span></span><br><span class="line"><span class="string"> </div>'</span></span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">test-transclude</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">p</span>></span>该段落会被放到指令内部<span class="tag"></<span class="name">p</span>></span></span><br><span class="line"><span class="tag"></<span class="name">test-transclude</span>></span></span><br></pre></td></tr></table></figure><p>上面生成后的 DOM 结构为:<br><img src="https://upload-images.jianshu.io/upload_images/13716859-0286a30aad3a9848.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><h4 id="scope-Boolean-or-Object"><a href="#scope-Boolean-or-Object" class="headerlink" title="scope(Boolean or Object)"></a>scope(Boolean or Object)</h4><p>关于 scope 选项将会在后面的指令 scope 中细说。</p><h4 id="controller-Function"><a href="#controller-Function" class="headerlink" title="controller(Function)"></a>controller(Function)</h4><p>一般情况下不需要使用指令的 <code>controller</code>,只要使用 <code>link</code> 就够了,后面会细说 link 函数。</p><p>用 <code>controller</code> 的场景是该指令(a)会被其他指令(b)<code>require</code> 的时候,在 b 的指令里可以传入 a 的这个 controller,目的是为了指令间的复用和交流。而 <code>link</code> 只能在指令内部中定义行为,无法做到这样。</p><h4 id="controllerAs-String"><a href="#controllerAs-String" class="headerlink" title="controllerAs(String)"></a>controllerAs(String)</h4><p>为控制器指定别名,这样可以在需要控制器的地方使用该名字进行注入。</p><h4 id="require-String-or-Array"><a href="#require-String-or-Array" class="headerlink" title="require(String or Array)"></a>require(String or Array)</h4><p>表示指令依赖于一个或多个指令,并注入所依赖指令的控制器到 <code>link</code> 函数的第四个参数中。如果所依赖的指令不存在,或所依赖指令的控制器不存在则会报错。</p><p>依赖名称前缀可以为:</p><ul><li><p>(没有前缀) - 在当前元素中查找依赖指令的控制器,如果不存在则报错。</p></li><li><p><code>?</code> - 在当前元素中查找依赖指令的控制器,如果不存在传 <code>null</code> 到 <code>link</code> 中。</p></li><li><p><code>^</code> - 在当前元素及父元素中查找依赖指令的控制器,如果不存在则报错。</p></li><li><p><code>?^</code> - 在当前元素及父元素中查找依赖指令的控制器,如果不存在传 <code>null</code> 到 <code>link</code> 中。</p></li></ul><p>例子:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">app.directive(<span class="string">'validate'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'A'</span>,</span><br><span class="line"> <span class="keyword">require</span>: <span class="string">'ngModel'</span>,</span><br><span class="line"> link: <span class="function"><span class="keyword">function</span> <span class="params">(scope, ele, attrs, ngModelCtrl)</span> </span>{</span><br><span class="line"> <span class="comment">// 监听值变化</span></span><br><span class="line"> ngModelCtrl.$viewChangeListeners.push(<span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> scope.validateResult = ngModelCtrl.$viewValue === <span class="string">'Heron'</span>;</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line">app.controller(<span class="string">'myCtrl'</span>, [</span><br><span class="line"> <span class="string">'$scope'</span>,</span><br><span class="line"> <span class="string">'$cookieStore'</span>,</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">($scope, $cookieStore)</span> </span>{</span><br><span class="line"> $scope.name = <span class="string">'Heron'</span>;</span><br><span class="line"></span><br><span class="line"> $scope.sayHi = <span class="function"><span class="keyword">function</span> <span class="params">(name, age)</span> </span>{</span><br><span class="line"> alert(<span class="string">'Hello '</span> + name + <span class="string">', your age is '</span> + age);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">ng-controller</span>=<span class="string">"myCtrl"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">ng-model</span>=<span class="string">"name"</span> <span class="attr">validate</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> validate 结果:</span><span class="template-variable">{{validateResult}}</span><span class="xml"></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><p>运行结果如图:</p><p><img src="https://upload-images.jianshu.io/upload_images/13716859-f2a6713c69bb51b9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><h4 id="compile-Function-和-link-Function"><a href="#compile-Function-和-link-Function" class="headerlink" title="compile(Function) 和 link(Function)"></a>compile(Function) 和 link(Function)</h4><p>创建的创建过程可以分为编译(compile)阶段和链接(link)阶段,因此两者放一起讲。</p><p>两者区别在于:</p><ul><li><p><code>compile</code> 函数的作用是对指令的模板进行转换。</p></li><li><p><code>link</code> 函数的作用是在视图和模型之间建立关联,包括注册事件监听函数和更新 <code>DOM</code> 操作。</p></li><li><p><code>scope</code> 在链接阶段才会被绑定到元素上,因此 <code>compile</code> 函数中没有入参 <code>scope</code>。</p></li><li><p>对于同一个指令的多个示例,<code>compile</code> 函数只会执行一次,而 <code>link</code> 函数在每个实例中都会执行。</p></li><li><p>如果自定义了 <code>compile</code> 函数,则自定义的 <code>link</code> 函数 无效,而是使用 <code>compile</code> 函数 返回的 <code>link</code> 函数。</p></li></ul><h3 id="指令-scope"><a href="#指令-scope" class="headerlink" title="指令 scope"></a>指令 scope</h3><p>scope 选项有三种值:</p><ul><li><p><code>false</code> - 使用父 <code>scope</code>。改变父 <code>scope</code> 会影响指令 <code>scope</code>,反之亦然。</p></li><li><p><code>true</code> - 继承父 <code>scope</code>,并创建自己的 <code>scope</code>。改变父 <code>scope</code> 会影响指令 <code>scope</code>,而改变指令 <code>scope</code> 不会影响父 <code>scope</code>。</p></li><li><p><code>{}</code> - 不继承父 <code>scope</code>,创建独立的 <code>scope</code>。如果不使用双向绑定策略(后面会讲),改变父 <code>scope</code> 不会影响指令 <code>scope</code>,反之亦然。</p></li></ul><p>例子:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">app.controller(<span class="string">'myCtrl'</span>, [</span><br><span class="line"> <span class="string">'$scope'</span>,</span><br><span class="line"> <span class="string">'$cookieStore'</span>,</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">($scope, $cookieStore)</span> </span>{</span><br><span class="line"> $scope.scopeFalse = <span class="string">'Heron'</span>;</span><br><span class="line"> $scope.scopeTrue = <span class="string">'Heron'</span>;</span><br><span class="line"> $scope.scopeObject = <span class="string">'Heron'</span>;</span><br><span class="line"> }</span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line">app.directive(<span class="string">'directiveFalse'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'EA'</span>,</span><br><span class="line"> scope: <span class="keyword">false</span>,</span><br><span class="line"> template: </span><br><span class="line"> <span class="string">'<div>\</span></span><br><span class="line"><span class="string"> <p>\</span></span><br><span class="line"><span class="string"> <span>指令 scope: </span>\</span></span><br><span class="line"><span class="string"> <input type="text" ng-model="scopeFalse">\</span></span><br><span class="line"><span class="string"> </p>\</span></span><br><span class="line"><span class="string"> </div>'</span></span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br><span class="line">app.directive(<span class="string">'directiveTrue'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'EA'</span>,</span><br><span class="line"> scope: <span class="keyword">true</span>,</span><br><span class="line"> template: </span><br><span class="line"> <span class="string">'<div>\</span></span><br><span class="line"><span class="string"> <p>\</span></span><br><span class="line"><span class="string"> <span>指令 scope: </span>\</span></span><br><span class="line"><span class="string"> <input type="text" ng-model="scopeTrue">\</span></span><br><span class="line"><span class="string"> </p>\</span></span><br><span class="line"><span class="string"> </div>'</span></span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br><span class="line">app.directive(<span class="string">'directiveObject'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'EA'</span>,</span><br><span class="line"> scope: {},</span><br><span class="line"> template: </span><br><span class="line"> <span class="string">'<div>\</span></span><br><span class="line"><span class="string"> <p>\</span></span><br><span class="line"><span class="string"> <span>指令 scope: </span>\</span></span><br><span class="line"><span class="string"> <input type="text" ng-model="scopeObject">\</span></span><br><span class="line"><span class="string"> </p>\</span></span><br><span class="line"><span class="string"> </div>'</span>,</span><br><span class="line"> link: <span class="function"><span class="keyword">function</span> <span class="params">(scope)</span> </span>{</span><br><span class="line"> <span class="comment">// 由于使用独立scope,因此需要自己定义变量</span></span><br><span class="line"> scope.scopeObject = <span class="string">'Heron'</span>;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">ng-controller</span>=<span class="string">"myCtrl"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h3</span>></span>scope: false<span class="tag"></<span class="name">h3</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">span</span>></span>父 scope: <span class="tag"></<span class="name">span</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">ng-model</span>=<span class="string">"scopeFalse"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">directive-false</span>></span><span class="tag"></<span class="name">directive-false</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h3</span>></span>scope: true<span class="tag"></<span class="name">h3</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">span</span>></span>父 scope: <span class="tag"></<span class="name">span</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">ng-model</span>=<span class="string">"scopeTrue"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">directive-true</span>></span><span class="tag"></<span class="name">directive-true</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">h3</span>></span>scope: </span><span class="template-variable">{}</span><span class="xml"><span class="tag"></<span class="name">h3</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">span</span>></span>父 scope: <span class="tag"></<span class="name">span</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">ng-model</span>=<span class="string">"scopeObject"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"></<span class="name">p</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">directive-object</span>></span><span class="tag"></<span class="name">directive-object</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><p>运行结果如图:<br><img src="https://upload-images.jianshu.io/upload_images/13716859-d1e2bad6b2bbc42b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><p>针对独立 scope,可以通过在对象中声明如何从外部传入参数。有以下三种绑定策略:</p><ul><li><p><code>@</code> - 使用 DOM 属性值单项绑定到指令 <code>scope</code> 中。此时绑定的值总是一个字符串,因为 <code>DOM</code> 的属性值是一个字符串。</p><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="params"><div my-directive age="<span class="number">26</span>"></span><span class="params"></div></span></span><br><span class="line"></span><br><span class="line"><span class="symbol">scope:</span> {</span><br><span class="line"><span class="symbol"> age:</span> <span class="string">'@'</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p><code>=</code> - 在父 <code>scope</code> 和指令 <code>scope</code> 之间建立双向绑定。</p><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="params"><div my-directive age="age"></span><span class="params"></div></span></span><br><span class="line"></span><br><span class="line"><span class="symbol">scope:</span> {</span><br><span class="line"><span class="symbol"> age:</span> <span class="string">'='</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p><code>&</code> - 使用父 <code>scope</code> 的上下文执行函数。一般用于绑定函数。</p><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="params"><div my-directive sayHi="sayHi()"></span><span class="params"></div></span></span><br><span class="line"></span><br><span class="line"><span class="symbol">scope:</span> {</span><br><span class="line"><span class="symbol"> sayHi:</span> <span class="string">'&'</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p>绑定函数时,有时需要向指令外部传递参数,如下:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">app.controller(<span class="string">'myCtrl'</span>, [</span><br><span class="line"> <span class="string">'$scope'</span>,</span><br><span class="line"> <span class="string">'$cookieStore'</span>,</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">($scope, $cookieStore)</span> </span>{</span><br><span class="line"> $scope.name = <span class="string">'Heron'</span>;</span><br><span class="line"></span><br><span class="line"> $scope.sayHi = <span class="function"><span class="keyword">function</span> <span class="params">(name, age)</span> </span>{</span><br><span class="line"> alert(<span class="string">'Hello '</span> + name + <span class="string">', your age is '</span> + age);</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br><span class="line"></span><br><span class="line">app.directive(<span class="string">'myDirective'</span>, [</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> restrict: <span class="string">'E'</span>,</span><br><span class="line"> replace: <span class="keyword">true</span>,</span><br><span class="line"> scope: {</span><br><span class="line"> clickMe: <span class="string">'&'</span></span><br><span class="line"> },</span><br><span class="line"> template: </span><br><span class="line"> <span class="string">'<div>\</span></span><br><span class="line"><span class="string"> <button class="btn btn-info" ng-click="clickMe({ age: age })">点我</button>\</span></span><br><span class="line"><span class="string"> </div>'</span>,</span><br><span class="line"> link: <span class="function"><span class="keyword">function</span> <span class="params">(scope)</span> </span>{</span><br><span class="line"> scope.age = <span class="number">26</span>;</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><<span class="keyword">div</span> ng-controller=<span class="string">"myCtrl"</span>></span><br><span class="line"> <<span class="keyword">my</span>-directive click-<span class="keyword">me</span>=<span class="string">"sayHi(name, age)"</span>></<span class="keyword">my</span>-directive></span><br><span class="line"></<span class="keyword">div</span>></span><br></pre></td></tr></table></figure><p>运行结果如图:</p><p><img src="https://upload-images.jianshu.io/upload_images/13716859-a9bd2316c61b6ed4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></p><p>说明一下:首先声明 <code>clickMe: '&'</code> 使用父 scope 的环境执行 clickMe 函数,然后在传递给指令时声明 <code>click-me="sayHi(name, age)"</code>,表示父 scope 的 <code>sayHi</code> 方法需要两个参数,一个是 name,一个是 age,然后再指令中使用对象 {} 的方式向外传递参数,如 <code>ng-click="clickMe({ age: age })"</code>,表示向指令外传递 age 参数,sayHi 方法从指令拿到 age 参数,再从自己的上下文中拿到 name 参数。</p><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>AngularJS 指令的开发和使用千变万化,也有许多坑,希望大家留意。</p>]]></content>
<summary type="html">
<h1 id="Angular-js1-X-学习笔记——自定义指令"><a href="#Angular-js1-X-学习笔记——自定义指令" class="headerlink" title="Angular.js1.X 学习笔记——自定义指令"></a>Angular.js1.X 学习笔记——自定义指令</h1><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>指令(Directive)可以说是 AngularJS 的核心,与Vue不同,angular.js的指令涵盖的vue的组件功能,你可以把它简单的理解为在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。例如,ng-click可以让一个元素能够监听click事件,并在接收到事件的时候执行AngularJS表达式。我们也可以自己创造新的指令。</p>
</summary>
<category term="Angular.js" scheme="https://jawn-ha.github.com/tags/Angular-js/"/>
</entry>
<entry>
<title>git命令总结</title>
<link href="https://jawn-ha.github.com/2018/08/25/git%E5%91%BD%E4%BB%A4%E6%80%BB%E7%BB%93/"/>
<id>https://jawn-ha.github.com/2018/08/25/git%E5%91%BD%E4%BB%A4%E6%80%BB%E7%BB%93/</id>
<published>2018-08-25T10:50:49.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>有些东西真是学的快,不用的话忘的也快,博主决定抽个周六再重新回顾一下 git 常用的命令以及含义。见笑见笑~~</p><a id="more"></a><p>git init 把当前目录变成git可以管理的仓库</p><p>git add 文件名 把文件添加到仓库</p><p>git commit -m “说明” <code>git commit</code>命令,<code>-m</code>后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。</p><p>git status <code>git status</code>命令可以让我们时刻掌握仓库当前的状态</p><p>git diff 如果<code>git status</code>告诉你有文件被修改过,用<code>git diff</code>可以查看修改内容。</p><p>git log 显示从最近到最远的提交日志,如果嫌输出信息太多,看得眼花缭乱的,可以试试加上<code>--pretty=oneline</code>参数:只显示commit id</p><p>git reset 回退版本,在Git中,用<code>HEAD</code>表示当前版本,也就是最新的提交<code>1094adb...</code>(注意我的提交ID和你的肯定不一样),上一个版本就是<code>HEAD^</code>,上上一个版本就是<code>HEAD^^</code>,当然往上100个版本写100个<code>^</code>比较容易数不过来,所以写成<code>HEAD~100</code>。</p><p>eg:<code>git rest --hard HEAD^</code> <code>--hard</code>参数</p><p>git reflog 用来记录你的每一次命令,以便回退版本后确定要回到未来的哪个版本。</p><p>git checkout – 文件名 把文件在工作区的修改全部撤销,这里有两种情况:</p><p>一种是文件自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;</p><p>一种是文件已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。</p><p>总之,就是让这个文件回到最近一次<code>git commit</code>或<code>git add</code>时的状态。</p><p>git reset HEAD <file> 可以把暂存区的修改撤销掉(unstage),重新放回工作区</file></p><p>git rm <file> 从版本库中删除该文件</file></p><p>git remote add origin <a href="mailto:[email protected]" target="_blank" rel="noopener">[email protected]</a>:<github账户名>/<仓库名>.git 把一个已有的本地仓库与github仓库关联</p><p>git push -u origin master 把本地库的内容推送到远程,用<code>git push</code>命令,实际上是把当前分支<code>master</code>推送到远程。由于远程库是空的,我们第一次推送<code>master</code>分支时,加上了<code>-u</code>参数,Git不但会把本地的<code>master</code>分支内容推送的远程新的<code>master</code>分支,还会把本地的<code>master</code>分支和远程的<code>master</code>分支关联起来,在以后的推送或者拉取时就可以简化命命令。此后,每次本地提交后,只要有必要,就可以使用命令<code>git push origin master</code>推送最新修改。</p><p>git clone 从远程库克隆一个本地库</p><p>git chekout -b dev 创建<code>dev</code>分支 <code>git checkout</code>命令加上<code>-b</code>参数表示创建并切换,相当于以下两条命令<code>git branch dev</code>,<code>git checkout dev</code></p><p>git branch 查看当前分支</p><p>git branch <name> 创建分支</name></p><p>git checkout <name> 切换分支</name></p><p>git merge dev 把<code>dev</code>分支的工作成果合并到<code>master</code>分支上,<code>git merge</code>命令用于合并指定分支到当前分支<br>合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。</p><p>git branch -d dev 删除<code>dev</code>分支</p><p>git log –graph –pretty=oneline –abbrev-commit 查看分支的合并情况,用git log –graph命令可以看到分支合并图。<br>当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再提交。</p><p>git stash 可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作<br>git stash list 查看存储的工作现场<br>git stash apply 恢复工作现场,但是恢复后,stash内容并不删除,需要用git stash drop来删除<br>git stash pop 恢复的同时把stash内容也删了<br>git branch -D <name> 如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。<br>git remote 查看远程库的信息,用git remote -v显示更详细的信息:<br>git push origin <分支名> 推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支<br>git branch –set-upstream-to=origin/dev dev 设置dev和origin/dev的链接<br>git pull 把最新的提交从origin/dev抓下来(解决冲突可用)<br>因此,多人协作的工作模式通常是这样:</name></name></p><ol><li>首先,可以试图用git push origin <branch-name>推送自己的修改;</branch-name></li><li>如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;</li><li>如果合并有冲突,则解决冲突,并在本地提交;</li><li>如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream-to <branch-name> origin/<branch-name>。</branch-name></branch-name></li></ol><p>这就是多人协作的工作模式,一旦熟悉了,就非常简单。<br>没有冲突或者解决掉冲突后,再用git push origin <branch-name>推送就能成功!</branch-name></p>]]></content>
<summary type="html">
<p>有些东西真是学的快,不用的话忘的也快,博主决定抽个周六再重新回顾一下 git 常用的命令以及含义。见笑见笑~~</p>
</summary>
<category term="git" scheme="https://jawn-ha.github.com/tags/git/"/>
</entry>
<entry>
<title>Hexo博客搭建之在文章中插入图片</title>
<link href="https://jawn-ha.github.com/2018/08/23/Hexo%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA%E4%B9%8B%E5%9C%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E6%8F%92%E5%85%A5%E5%9B%BE%E7%89%87/"/>
<id>https://jawn-ha.github.com/2018/08/23/Hexo%E5%8D%9A%E5%AE%A2%E6%90%AD%E5%BB%BA%E4%B9%8B%E5%9C%A8%E6%96%87%E7%AB%A0%E4%B8%AD%E6%8F%92%E5%85%A5%E5%9B%BE%E7%89%87/</id>
<published>2018-08-23T22:10:40.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>在写文章时,常常有配图说明的需求。Hexo有多种图片插入方式,可以将图片存放在本地引用或者将图片放在CDN上引用。</p><a id="more"></a><h3 id="本地引用"><a href="#本地引用" class="headerlink" title="本地引用"></a>本地引用</h3><h4 id="绝对路径"><a href="#绝对路径" class="headerlink" title="绝对路径"></a>绝对路径</h4><p>当Hexo项目中只用到少量图片时,可以将图片统一放在<code>source/images</code>文件夹中,通过markdown语法访问它们。</p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">source</span><span class="regexp">/images/im</span>age.jpg![](<span class="regexp">/images/im</span>age.jpg)</span><br></pre></td></tr></table></figure><p>图片既可以在首页内容中访问到,也可以在文章正文中访问到。</p><h4 id="相对路径"><a href="#相对路径" class="headerlink" title="相对路径"></a>相对路径</h4><p>图片除了可以放在统一的<code>images</code>文件夹中,还可以放在文章自己的目录中。文章的目录可以通过配置<code>_config.yml</code>来生成。</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="module-access"><span class="module"><span class="identifier">_config</span>.</span></span>ymlpost_asset_folder: <span class="literal">true</span></span><br></pre></td></tr></table></figure><p>将<code>_config.yml</code>文件中的配置项<code>post_asset_folder</code>设为<code>true</code>后,执行命令<code>$ hexo new post_name</code>,在<code>source/_posts</code>中会生成文章<code>post_name.md</code>和同名文件夹<code>post_name</code>。将图片资源放在<code>post_name</code>中,文章就可以使用相对路径引用图片资源了。</p><figure class="highlight sqf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable">_posts</span>/post_name/<span class="built_in">image</span>.jpg![](<span class="built_in">image</span>.jpg)</span><br></pre></td></tr></table></figure><p>上述是markdown的引用方式,图片只能在文章中显示,但无法在首页中正常显示。</p><p>如果希望图片在文章和首页中同时显示,可以使用标签插件语法。</p><figure class="highlight maxima"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">_posts/post_name/<span class="built_in">image</span>.jpg{<span class="symbol">%</span> asset_img <span class="built_in">image</span>.jpg This <span class="built_in">is</span> an <span class="built_in">image</span> <span class="symbol">%</span>}</span><br></pre></td></tr></table></figure><h3 id="CDN引用"><a href="#CDN引用" class="headerlink" title="CDN引用"></a>CDN引用</h3><p>除了在本地存储图片,还可以将图片上传到一些免费的CDN服务中。比如<a href="http://cloudinary.com/" target="_blank" rel="noopener">Cloudinary</a>提供的图片CDN服务,在Cloudinary中上传图片后,会生成对应的url地址,将地址直接拿来引用即可。</p>]]></content>
<summary type="html">
<p>在写文章时,常常有配图说明的需求。Hexo有多种图片插入方式,可以将图片存放在本地引用或者将图片放在CDN上引用。</p>
</summary>
<category term="hexo" scheme="https://jawn-ha.github.com/tags/hexo/"/>
</entry>
<entry>
<title>Javascript toString()、toLocaleString()、valueOf()三个方法的区别</title>
<link href="https://jawn-ha.github.com/2018/08/21/Javascript-toString-%E3%80%81toLocaleString-%E3%80%81valueOf-%E4%B8%89%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84%E5%8C%BA%E5%88%AB/"/>
<id>https://jawn-ha.github.com/2018/08/21/Javascript-toString-%E3%80%81toLocaleString-%E3%80%81valueOf-%E4%B8%89%E4%B8%AA%E6%96%B9%E6%B3%95%E7%9A%84%E5%8C%BA%E5%88%AB/</id>
<published>2018-08-21T22:16:53.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>最近在复习JavaScript 基础,打算把ES5, ES6重过一遍,也算是查漏补缺吧。最近看高程的时候,发现后面几章写的都是精华啊,可是以前图样图森破(好吧,其实主要看不懂)没看,所以决定再从头好好看一下。可能最近的内容都比较简单琐碎,以后抽时间做个系统的整理。今天先总结一哈toString()、toLocaleString()、valueOf()三个方法的区别。</p><a id="more"></a><h4 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> array = <span class="keyword">new</span> <span class="built_in">Array</span>(<span class="string">"jawn"</span>,<span class="number">1</span>,<span class="literal">true</span>);</span><br><span class="line"><span class="built_in">console</span>.log(array.valueOf());<span class="comment">//[ 'jawn', 1, true ]</span></span><br><span class="line"><span class="built_in">console</span>.log(array.toString());<span class="comment">//jawn,1,true</span></span><br><span class="line"><span class="built_in">console</span>.log(array.toLocaleString());<span class="comment">//jawn,1,true</span></span><br></pre></td></tr></table></figure><ul><li>valueOf:返回数组本身</li><li>toString():把数组转换为字符串,并返回结果,每一项以逗号分割。</li><li>toLocalString():把数组转换为本地数组,并返回结果。</li></ul><h4 id="Boolean"><a href="#Boolean" class="headerlink" title="Boolean"></a>Boolean</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> boolean = <span class="keyword">new</span> <span class="built_in">Boolean</span>();</span><br><span class="line"><span class="built_in">console</span>.log(boolean.valueOf()); <span class="comment">//false</span></span><br><span class="line"><span class="built_in">console</span>.log(boolean.toString()); <span class="comment">//false</span></span><br></pre></td></tr></table></figure><ul><li>valueOf:返回 Boolean 对象的原始值。</li><li>toString():根据原始布尔值或者 booleanObject 对象的值返回字符串 “true” 或 “false”。默认为”false”。</li><li>toLocalString():Boolean对象没有toLocalString()方法。但是在Boolean对象上使用这个方法也不会报错。</li></ul><h4 id="Date"><a href="#Date" class="headerlink" title="Date"></a>Date</h4><figure class="highlight lasso"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">var</span> <span class="built_in">date</span> = <span class="literal">new</span> <span class="built_in">Date</span>();</span><br><span class="line">console.<span class="keyword">log</span>(<span class="built_in">date</span>.valueOf());<span class="comment">//1534862077184</span></span><br><span class="line">console.<span class="keyword">log</span>(<span class="built_in">date</span>.toString());<span class="comment">// Tue Aug 21 2018 22:34:37 GMT+0800 (CST)</span></span><br><span class="line">console.<span class="keyword">log</span>(<span class="built_in">date</span>.toLocaleString()); <span class="comment">//2018/8/21 下午10:34:37</span></span><br></pre></td></tr></table></figure><ul><li><p>valueOf:返回 Date 对象的原始值,以毫秒表示。</p></li><li><p>toString():把 Date 对象转换为字符串,并返回结果。使用本地时间表示。</p></li><li><p>toLocalString():可根据本地时间把 Date 对象转换为字符串,并返回结果,返回的字符串根据本地规则格式化。</p></li></ul><h4 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h4><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Math</span>.</span><span class="module"><span class="identifier">PI</span>.</span></span>value<span class="constructor">Of()</span>); <span class="comment">//3.141592653589793</span></span><br></pre></td></tr></table></figure><ul><li>valueOf:返回 Math 对象的原始值。 </li></ul><h4 id="Number"><a href="#Number" class="headerlink" title="Number"></a>Number</h4><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ar num = <span class="keyword">new</span> <span class="constructor">Number(1337)</span>;</span><br><span class="line">console.log(num.value<span class="constructor">Of()</span>);<span class="comment">//1337</span></span><br><span class="line">console.log(num.<span class="keyword">to</span><span class="constructor">String()</span>);<span class="comment">//1337</span></span><br><span class="line">console.log(num.<span class="keyword">to</span><span class="constructor">LocaleString()</span>);<span class="comment">//1,337</span></span><br></pre></td></tr></table></figure><ul><li>valueOf:返回一个 Number 对象的基本数字值。</li><li>toString():把数字转换为字符串,使用指定的基数。</li><li>toLocalString():把数字转换为字符串,使用本地数字格式顺序</li></ul><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><ul><li>toLocalString()是调用每个数组元素的 toLocaleString() 方法,然后使用地区特定的分隔符把生成的字符串连接起来,形成一个字符串。</li><li>toString()方法获取的是String(传统字符串),而toLocaleString()方法获取的是LocaleString(本地环境字符串)。</li><li>如果你开发的脚本在世界范围都有人使用,那么将对象转换成字符串时请使用toString()方法来完成。</li><li>LocaleString()会根据你机器的本地环境来返回字符串,它和toString()返回的值在不同的本地环境下使用的符号会有微妙的变化。</li><li>所以使用toString()是保险的,返回唯一值的方法,它不会因为本地环境的改变而发生变化。如果是为了返回时间类型的数据,推荐使用LocaleString()。若是在后台处理字符串,请务必使用toString()。</li></ul>]]></content>
<summary type="html">
<p>最近在复习JavaScript 基础,打算把ES5, ES6重过一遍,也算是查漏补缺吧。最近看高程的时候,发现后面几章写的都是精华啊,可是以前图样图森破(好吧,其实主要看不懂)没看,所以决定再从头好好看一下。可能最近的内容都比较简单琐碎,以后抽时间做个系统的整理。今天先总结一哈toString()、toLocaleString()、valueOf()三个方法的区别。</p>
</summary>
<category term="JavaScript" scheme="https://jawn-ha.github.com/tags/JavaScript/"/>
</entry>
<entry>
<title>浅析 Js 事件循环</title>
<link href="https://jawn-ha.github.com/2018/08/20/%E6%B5%85%E6%9E%90-Js-%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF/"/>
<id>https://jawn-ha.github.com/2018/08/20/%E6%B5%85%E6%9E%90-Js-%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF/</id>
<published>2018-08-20T22:28:49.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>在讲 Event Loop (事件循环)之前,我们先来了解点东西。</p><h4 id="进程与线程"><a href="#进程与线程" class="headerlink" title="进程与线程"></a>进程与线程</h4><p>进程是操作系统分配资源的基本单位,而线程是可以被处理器独立调度与分配的最小单元,线程自己基本上不拥有资源,只拥有一点在运行时必不可少的资源(如程序计数器、一组寄存器和栈),但它可以与同属一个进程的其他线程共享进程拥有的全部资源。举个例子,浏览器就是一个进程,但其用户界面,引擎,渲染引擎都是浏览器进程里的线程。</p><a id="more"></a><h5 id="浏览器渲染引擎"><a href="#浏览器渲染引擎" class="headerlink" title="浏览器渲染引擎"></a>浏览器渲染引擎</h5><p>渲染引擎内部是多线程的,内部包含 ui 线程和 js 线程</p><p>js 线程 ui 线程 这两个线程互斥的,目的就是为了保证不产生冲突。</p><p>ui 线程会把更改的放到队列中,当 js 线程空闲下来的时候,ui 线程在继续渲染</p><h5 id="webworker-多线程"><a href="#webworker-多线程" class="headerlink" title="webworker 多线程"></a>webworker 多线程</h5><p>它和 js 主线程不是平级的,主线程可以控制 webworker,但是 webworker不能操作 DOM,不能获取 document,window</p><h5 id="其它线程"><a href="#其它线程" class="headerlink" title="其它线程"></a>其它线程</h5><p>浏览器事件触发线程(用来控制事件循环,存放 setTimeout、浏览器事件、ajax 的回调函数)<br>定时触发器线程(setTimeout 定时器所在线程)<br>异步 HTTP 请求线程(ajax 请求线程)</p><h5 id="js-单线程"><a href="#js-单线程" class="headerlink" title="js 单线程"></a>js 单线程</h5><p>作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。假如不是单线程的话,在一个线程当我们在给某个DOM节点增加内容的时候,另一个线程正在删除这个DOM节点的内容,页面会很混乱,这里所谓的单线程指的是主线程是单线程的,所以在 Node 中主线程依旧是单线程的。</p><h4 id="同步和异步:"><a href="#同步和异步:" class="headerlink" title="同步和异步:"></a>同步和异步:</h4><p>虽然javascript是单线程,但是javascript中有同步和异步的概念,解决了js阻塞的问题。</p><h5 id="同步:"><a href="#同步:" class="headerlink" title="同步:"></a>同步:</h5><p>如果在一个函数返回的时候,调用者就能够得到预期结果(即拿到了预期的返回值或者看到了预期的效果),那么这个函数就是同步的。</p><p>用代码解释一下:</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">console.<span class="built_in">log</span>('Hello');</span><br><span class="line">复制代码</span><br></pre></td></tr></table></figure><p>如果在函数返回时,就看到了预期的效果:在控制台打印了Hello</p><h5 id="异步:"><a href="#异步:" class="headerlink" title="异步:"></a>异步:</h5><p>如果在函数返回的时候,调用者还不能够得到预期结果,而是需要在将来通过一定的手段得到,那么这个函数就是异步的。</p><p>代码解释:</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">fs.read<span class="constructor">File('<span class="params">test</span>.<span class="params">txt</span>', '<span class="params">utf8</span>', <span class="params">function</span>(<span class="params">err</span>, <span class="params">data</span>)</span> {</span><br><span class="line"> console.log(data);</span><br><span class="line">});</span><br><span class="line">复制代码</span><br></pre></td></tr></table></figure><p>在上面的代码中,我们希望通过fs.readFile函数读取文件foo.txt中的内容,并打印出来。但是在fs.readFile函数返回时,我们期望的结果并不会发生,而是要等到文件全部读取完成之后。如果文件很大的话可能要很长时间。</p><h5 id="小总结:"><a href="#小总结:" class="headerlink" title="小总结:"></a>小总结:</h5><ol><li>同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后续的行为。</li><li>异步方法调用更像一个消息传递,一旦开始,方法调用就会立即返回,调用者就可以继续后续的操作。而,异步方法通常会在另外一个线程中,“真实”地执行着。整个过程,不会阻碍调用者的工作。</li></ol><h6 id="javascript就可以进行同步任务和异步任务。把读文件这种操作,ajax请求这些需要耗时的任务放到任务队列中,我还是能够一步步的继续下面的任务。所以啊,javascript还是可以很6。那么异步任务里面只是放要进行异步操作的任务吗,里面会发生啥呢?"><a href="#javascript就可以进行同步任务和异步任务。把读文件这种操作,ajax请求这些需要耗时的任务放到任务队列中,我还是能够一步步的继续下面的任务。所以啊,javascript还是可以很6。那么异步任务里面只是放要进行异步操作的任务吗,里面会发生啥呢?" class="headerlink" title="javascript就可以进行同步任务和异步任务。把读文件这种操作,ajax请求这些需要耗时的任务放到任务队列中,我还是能够一步步的继续下面的任务。所以啊,javascript还是可以很6。那么异步任务里面只是放要进行异步操作的任务吗,里面会发生啥呢?"></a>javascript就可以进行同步任务和异步任务。把读文件这种操作,ajax请求这些需要耗时的任务放到任务队列中,我还是能够一步步的继续下面的任务。所以啊,javascript还是可以很6。那么异步任务里面只是放要进行异步操作的任务吗,里面会发生啥呢?</h6><h4 id="任务队列:"><a href="#任务队列:" class="headerlink" title="任务队列:"></a>任务队列:</h4><p>上面说过了javascript里面的任务有两种,同步任务和异步任务。</p><p>同步任务是指:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。</p><p>异步任务指的是,不进入主线程、而进入”任务队列”的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。</p><p>先看个小栗子吧:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"a"</span>);</span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">"b"</span>);</span><br><span class="line">},<span class="number">0</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"c"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//a</span></span><br><span class="line"><span class="comment">//c</span></span><br><span class="line"><span class="comment">//b</span></span><br><span class="line">复制代码</span><br></pre></td></tr></table></figure><p>js中代码从上往下执行,执行第一行代码的时候控制台输出a,执行到第二行代码的时候遇到了setTimeout函数,因为setTimeout函数是个异步函数,所以,浏览器会记住这个事件,添加到时间表中,之后把这个事件的回调函数入栈到任务队列中。而此时主线程程序继续往下运行,到了第五行:console.log(“c”),执行这条,控制台输出c。这时候主线程空了,他会到任务队列里面去查找是否有可以执行的任务,有的话直接拿出来执行,没有的话会一直去询问,等到有可以执行的。</p><h4 id="浏览器中的Event-Loop"><a href="#浏览器中的Event-Loop" class="headerlink" title="浏览器中的Event Loop"></a>浏览器中的Event Loop</h4><p><img src="1.jpg" alt="浏览器中的Event Loop"></p><p>事件循环其实就是入栈出栈的循环。上面例子中说到了setTimeout,那setInterval呢,Promise呢等等等等,有很多异步的函数。但是这些异步任务有分宏任务(macro-task)和微任务(micro-task):</p><p>macro-task包括: setTimeout, setInterval, setImmediate, I/O, UI rendering。 </p><p>micro-task包括:process.nextTick, Promises, Object.observe, MutationObserver。</p><p>每一次Event Loop触发时:</p><ol><li>执行完主执行线程中的任务。</li><li>取出micro-task中任务执行直到清空。</li><li>取出macro-task中一个任务执行。</li><li>取出micro-task中任务执行直到清空。</li><li>重复3和4。</li></ol><h5 id="其实promise的then和catch才是microtask,本身的内部代码不是。"><a href="#其实promise的then和catch才是microtask,本身的内部代码不是。" class="headerlink" title="其实promise的then和catch才是microtask,本身的内部代码不是。"></a>其实promise的then和catch才是microtask,本身的内部代码不是。</h5><h3 id="注意:"><a href="#注意:" class="headerlink" title="注意:"></a>注意:</h3><ol><li>在浏览器浏览器和node中的执行不一样。</li><li>任务队列里面是“先入先出”的。</li></ol><h6 id="那来个小栗子测试一下你是不是已经完全理解啦:"><a href="#那来个小栗子测试一下你是不是已经完全理解啦:" class="headerlink" title="那来个小栗子测试一下你是不是已经完全理解啦:"></a>那来个小栗子测试一下你是不是已经完全理解啦:</h6><figure class="highlight matlab"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">console.<span class="built_in">log</span>(<span class="string">'global'</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (var <span class="built_in">i</span> = <span class="number">1</span>;<span class="built_in">i</span> <= <span class="number">5</span>;<span class="built_in">i</span> ++) {</span><br><span class="line"> setTimeout(<span class="function"><span class="keyword">function</span><span class="params">()</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="built_in">i</span>)</span><br><span class="line"> },<span class="built_in">i</span>*<span class="number">1000</span>)</span><br><span class="line"> console.<span class="built_in">log</span>(<span class="built_in">i</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">new Promise(<span class="function"><span class="keyword">function</span> <span class="params">(resolve)</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="string">'promise1'</span>)</span><br><span class="line"> resolve()</span><br><span class="line"> }).then(<span class="function"><span class="keyword">function</span> <span class="params">()</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="string">'then1'</span>)</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> <span class="params">()</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="string">'timeout2'</span>)</span><br><span class="line"> new Promise(<span class="function"><span class="keyword">function</span> <span class="params">(resolve)</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="string">'timeout2_promise'</span>)</span><br><span class="line"> resolve()</span><br><span class="line"> }).then(<span class="function"><span class="keyword">function</span> <span class="params">()</span> {</span></span><br><span class="line"> console.<span class="built_in">log</span>(<span class="string">'timeout2_then'</span>)</span><br><span class="line"> })</span><br><span class="line">}, <span class="number">1000</span>)</span><br></pre></td></tr></table></figure><p> 控制台输出:</p><p><img src="2.png" alt></p><p> 总结: </p><p>这里主要是讲了在浏览器端js事件循环。这篇文章可以帮助更好的理解node和浏览器环境下不同的事件循环:<a href="https://link.juejin.im/?target=https%3A%2F%2Fjuejin.im%2Fpost%2F5aa5dcabf265da239c7afe1e" target="_blank" rel="noopener">浏览器和Node不同的事件循环(Event Loop)</a></p>]]></content>
<summary type="html">
<p>在讲 Event Loop (事件循环)之前,我们先来了解点东西。</p>
<h4 id="进程与线程"><a href="#进程与线程" class="headerlink" title="进程与线程"></a>进程与线程</h4><p>进程是操作系统分配资源的基本单位,而线程是可以被处理器独立调度与分配的最小单元,线程自己基本上不拥有资源,只拥有一点在运行时必不可少的资源(如程序计数器、一组寄存器和栈),但它可以与同属一个进程的其他线程共享进程拥有的全部资源。举个例子,浏览器就是一个进程,但其用户界面,引擎,渲染引擎都是浏览器进程里的线程。</p>
</summary>
<category term="JavaScript" scheme="https://jawn-ha.github.com/tags/JavaScript/"/>
</entry>
<entry>
<title>const定义的对象属性是否可以改变</title>
<link href="https://jawn-ha.github.com/2018/07/23/const%E5%AE%9A%E4%B9%89%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%B1%9E%E6%80%A7%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E6%94%B9%E5%8F%98/"/>
<id>https://jawn-ha.github.com/2018/07/23/const%E5%AE%9A%E4%B9%89%E7%9A%84%E5%AF%B9%E8%B1%A1%E5%B1%9E%E6%80%A7%E6%98%AF%E5%90%A6%E5%8F%AF%E4%BB%A5%E6%94%B9%E5%8F%98/</id>
<published>2018-07-23T19:21:13.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>今天面试,面试官提了一个问题,问 const 定义一个对象后是否可以给属性赋值,当时候没有考虑就直接回答不可以了。回去后感觉不对,于是赶紧翻开了阮大神的《ES6 入门》查看了一下,原文是这样说的:</p><blockquote><p><code>const</code>实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,<code>const</code>只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。</p></blockquote><a id="more"></a><p>不懂的话再来段代码压压惊!</p><p><img src="1.png" alt></p><p>so…没有报错</p><p>再给他赋一个值相同的变量看看!</p><p><img src="2.png" alt></p><p>看到这儿大家应该明白了吧</p><p>因为对象是引用类型的,jawnha中保存的仅是对象的指针,这就意味着,const仅保证指针不发生改变,修改对象的属性不会改变对象的指针,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。</p>]]></content>
<summary type="html">
<p>今天面试,面试官提了一个问题,问 const 定义一个对象后是否可以给属性赋值,当时候没有考虑就直接回答不可以了。回去后感觉不对,于是赶紧翻开了阮大神的《ES6 入门》查看了一下,原文是这样说的:</p>
<blockquote>
<p><code>const</code>实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,<code>const</code>只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。</p>
</blockquote>
</summary>
<category term="ES6" scheme="https://jawn-ha.github.com/tags/ES6/"/>
</entry>
<entry>
<title>面试总结——JS</title>
<link href="https://jawn-ha.github.com/2018/07/23/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93%E2%80%94%E2%80%94JS/"/>
<id>https://jawn-ha.github.com/2018/07/23/%E9%9D%A2%E8%AF%95%E6%80%BB%E7%BB%93%E2%80%94%E2%80%94JS/</id>
<published>2018-07-23T12:06:10.000Z</published>
<updated>2020-06-24T07:22:51.137Z</updated>
<content type="html"><![CDATA[<ul><li>介绍一下 JS 的基本数据类型。</li></ul><figure class="highlight mathematica"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Undefined</span>、<span class="keyword">Null</span>、Boolean、<span class="keyword">Number</span>、<span class="keyword">String</span>、<span class="keyword">Symbol</span>(ES6新增)</span><br></pre></td></tr></table></figure><ul><li>如何控制alert中的换行?</li></ul><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">\n</span> alert(“p<span class="string">\np”);</span></span><br></pre></td></tr></table></figure><a id="more"></a><ul><li>null 和 undefined 有何区别?</li></ul><blockquote><p>null 表示一个对象被定义了,值为“空值”;</p><p> undefined 表示不存在这个值。</p><p> typeof undefined //“undefined” </p><p>undefined :是一个表示”无”的原始值或者说表示”缺少值”,就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined; 例如变量被声明了,但没有赋值时,就等于undefined。</p><p> typeof null //“object” null : 是一个对象(空对象, 没有任何属性和方法); 例如作为函数的参数,表示该函数的参数不是对象; </p><p>注意: 在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined</p></blockquote><ul><li>call和apply,bind的作用是什么?区别是什么?</li></ul><blockquote><p>call和apply的功能基本相同,都是实现继承或者转换对象指针的作用;<br>唯一不通的是前者参数是罗列出来的,后者是存到数组中的;<br>call或apply功能就是实现继承的;与面向对象的继承extends功能相似;但写法不同;<br>语法:<br>.call(对象[,参数1,参数2,….]);//此地参数是指的是对象的参数,非方法的参数;<br>.apply(对象,参数数组)//参数数组的形式:[参数1,参数2,……]</p><p>通过bind改变this作用域会返回一个新的函数,这个函数不会马上执行</p></blockquote><ul><li>push()-pop()-shift()-unshift()分别是什么功能?</li></ul><blockquote><p>push 方法 将新元素添加到一个数组中,并返回数组的新长度值。 var a=[1,2,3,4]; a.push(5);</p><p> pop 方法 移除数组中的最后一个元素并返回该元素。 var a=[1,2,3,4]; a.pop(); </p><p>shift 方法 移除数组中的第一个元素并返回该元素。 var a=[1,2]; alert(a.shift());</p><p> unshift 方法 将指定的元素插入数组开始位置并返回该数组。</p></blockquote><ul><li>new 操作符具体干了什么呢?</li></ul><blockquote><p>1、创建了一个空对象</p><p>var obj = new object();</p><p>2、设置原型链</p><p>obj.<em>proto</em> = fn.prototype;</p><p>3、让fn的this指向obj,并执行fn的函数体</p><p>var result = fn.call(obj);</p><p>4、判断fn的返回值类型,如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象</p><p>if (typeof(result) == “object”){ </p><p> fnObj = result; </p><p> } else { </p><p> fnObj = obj;</p><p>}</p></blockquote><ul><li>闭包</li></ul><blockquote><p>一句话可以概括:闭包就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。</p></blockquote><ul><li>如何理解 JavaScript 的原型</li></ul><blockquote><p>所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(null除外)</p><p> 所有的引用类型(数组、对象、函数),都有一个<strong>proto</strong>属性,属性值是一个普通的对象 </p><p>所有的函数,都有一个prototype属性,属性值也是一个普通的对象 </p><p>所有的引用类型(数组、对象、函数),<strong>proto</strong>属性值指向它的构造函数的prototype属性值</p><p><strong>当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的<strong>proto</strong>(即它的构造函数的prototype)中寻找</strong>。</p></blockquote><ul><li>JavaScript 中,有一个函数,执行对象查找时,永远不会去查找原型,这个函数是哪个?</li></ul><blockquote><p>hasOwnProperty </p><p>// </p><p>JavaScript 中 hasOwnProperty 函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。</p><p> // </p><p>使用方法:object.hasOwnProperty(proName)其中参数object是必选项,一个对象的实例。proName是必选项,一个属性名称的字符串值。</p><p> // </p><p>如果 object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回 true,反之则返回 false。</p></blockquote><ul><li>JavaScript 有几种类型的值?能否画一下它们的内存图?</li></ul><blockquote><ul><li>栈:原始数据类型(Undefined,Null,Boolean,Number,String)</li><li>堆:引用数据类型(对象、数组、函数) 两种类型的区别: </li></ul><p>//存储位置不同</p><ul><li>原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储; </li><li>引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。</li></ul></blockquote><ul><li>JavaScript 如何实现继承?</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br></pre></td><td class="code"><pre><span class="line">ES5</span><br><span class="line">(<span class="number">1</span>)类的创建(es5):<span class="keyword">new</span>一个<span class="function"><span class="keyword">function</span>,在这个<span class="title">function</span>的<span class="title">prototype</span>里面增加属性和方法。</span></span><br><span class="line"><span class="function">下面来创建一个<span class="title">Animal</span>类:</span></span><br><span class="line"><span class="function">// 定义一个动物类</span></span><br><span class="line"><span class="function"><span class="title">function</span> <span class="title">Animal</span> (<span class="params">name</span>) </span>{</span><br><span class="line"> <span class="comment">// 属性</span></span><br><span class="line"> <span class="keyword">this</span>.name = name || <span class="string">'Animal'</span>;</span><br><span class="line"> <span class="comment">// 实例方法</span></span><br><span class="line"> <span class="keyword">this</span>.sleep = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.name + <span class="string">'正在睡觉!'</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 原型方法</span></span><br><span class="line">Animal.prototype.eat = <span class="function"><span class="keyword">function</span>(<span class="params">food</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.name + <span class="string">'正在吃:'</span> + food);</span><br><span class="line">};</span><br><span class="line">复制代码</span><br><span class="line">这样就生成了一个Animal类,实力化生成对象后,有方法和属性。</span><br><span class="line">(<span class="number">2</span>)类的继承——原型链继承</span><br><span class="line">--原型链继承</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params"></span>)</span>{ }</span><br><span class="line">Cat.prototype = <span class="keyword">new</span> Animal();</span><br><span class="line">Cat.prototype.name = <span class="string">'cat'</span>;</span><br><span class="line"><span class="comment">//&emsp;Test Code</span></span><br><span class="line"><span class="keyword">var</span> cat = <span class="keyword">new</span> Cat();</span><br><span class="line"><span class="built_in">console</span>.log(cat.name);</span><br><span class="line"><span class="built_in">console</span>.log(cat.eat(<span class="string">'fish'</span>));</span><br><span class="line"><span class="built_in">console</span>.log(cat.sleep());</span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Animal); <span class="comment">//true </span></span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Cat); <span class="comment">//true</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">介绍:在这里我们可以看到<span class="keyword">new</span>了一个空对象,这个空对象指向Animal并且Cat.prototype指向了这个空对象,这种就是基于原型链的继承。</span><br><span class="line">特点:基于原型链,既是父类的实例,也是子类的实例</span><br><span class="line">缺点:无法实现多继承</span><br><span class="line"></span><br><span class="line">(<span class="number">3</span>)构造继承:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name</span>)</span>{</span><br><span class="line"> Animal.call(<span class="keyword">this</span>);</span><br><span class="line"> <span class="keyword">this</span>.name = name || <span class="string">'Tom'</span>;</span><br><span class="line">}</span><br><span class="line"><span class="comment">// Test Code</span></span><br><span class="line"><span class="keyword">var</span> cat = <span class="keyword">new</span> Cat();</span><br><span class="line"><span class="built_in">console</span>.log(cat.name);</span><br><span class="line"><span class="built_in">console</span>.log(cat.sleep());</span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Animal); <span class="comment">// false</span></span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Cat); <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line">特点:可以实现多继承</span><br><span class="line">缺点:只能继承父类实例的属性和方法,不能继承原型上的属性和方法。</span><br><span class="line"></span><br><span class="line">(<span class="number">4</span>)实例继承和拷贝继承</span><br><span class="line">实例继承:为父类实例添加新特性,作为子类实例返回</span><br><span class="line">拷贝继承:拷贝父类元素上的属性和方法</span><br><span class="line">上述两个实用性不强,不一一举例。</span><br><span class="line">(<span class="number">5</span>)组合继承:相当于构造继承和原型链继承的组合体。通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name</span>)</span>{</span><br><span class="line"> Animal.call(<span class="keyword">this</span>);</span><br><span class="line"> <span class="keyword">this</span>.name = name || <span class="string">'Tom'</span>;</span><br><span class="line">}</span><br><span class="line">Cat.prototype = <span class="keyword">new</span> Animal();</span><br><span class="line">Cat.prototype.constructor = Cat;</span><br><span class="line"><span class="comment">// Test Code</span></span><br><span class="line"><span class="keyword">var</span> cat = <span class="keyword">new</span> Cat();</span><br><span class="line"><span class="built_in">console</span>.log(cat.name);</span><br><span class="line"><span class="built_in">console</span>.log(cat.sleep());</span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Animal); <span class="comment">// true</span></span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Cat); <span class="comment">// true</span></span><br><span class="line">复制代码</span><br><span class="line"></span><br><span class="line">特点:可以继承实例属性/方法,也可以继承原型属性/方法</span><br><span class="line">缺点:调用了两次父类构造函数,生成了两份实例</span><br><span class="line"></span><br><span class="line">(<span class="number">6</span>)寄生组合继承:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Cat</span>(<span class="params">name</span>)</span>{</span><br><span class="line"> Animal.call(<span class="keyword">this</span>);</span><br><span class="line"> <span class="keyword">this</span>.name = name || <span class="string">'Tom'</span>;</span><br><span class="line">}</span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="comment">// 创建一个没有实例方法的类</span></span><br><span class="line"> <span class="keyword">var</span> Super = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{};</span><br><span class="line"> Super.prototype = Animal.prototype;</span><br><span class="line"> <span class="comment">//将实例作为子类的原型</span></span><br><span class="line"> Cat.prototype = <span class="keyword">new</span> Super();</span><br><span class="line">})();</span><br><span class="line"><span class="comment">// Test Code</span></span><br><span class="line"><span class="keyword">var</span> cat = <span class="keyword">new</span> Cat();</span><br><span class="line"><span class="built_in">console</span>.log(cat.name);</span><br><span class="line"><span class="built_in">console</span>.log(cat.sleep());</span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Animal); <span class="comment">// true</span></span><br><span class="line"><span class="built_in">console</span>.log(cat <span class="keyword">instanceof</span> Cat); <span class="comment">//true</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">ES6</span><br><span class="line"><span class="class"><span class="keyword">class</span> 是一种新的语法形式,是<span class="title">class</span> <span class="title">Name</span> </span>{...}这种形式,和函数的写法完全不一样</span><br><span class="line">两者对比,构造函数函数体的内容要放在 <span class="class"><span class="keyword">class</span> 中的<span class="title">constructor</span>函数中,<span class="title">constructor</span>即构造器,初始化实例时默认执行</span></span><br><span class="line"><span class="class"><span class="title">class</span> 中函数的写法是<span class="title">add</span>() </span>{...}这种形式,并没有<span class="function"><span class="keyword">function</span>关键字</span></span><br><span class="line"><span class="function">使用 <span class="title">class</span> 来实现继承就更加简单了,至少比构造函数实现继承简单很多。看下面例子...</span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">class</span> <span class="title">Animal</span> </span>{</span><br><span class="line"> <span class="keyword">constructor</span>(name) {</span><br><span class="line"> <span class="keyword">this</span>.name = name</span><br><span class="line"> }</span><br><span class="line"> eat() {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`<span class="subst">${<span class="keyword">this</span>.name}</span> eat`</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>{</span><br><span class="line"> <span class="keyword">constructor</span>(name) {</span><br><span class="line"> <span class="keyword">super</span>(name)</span><br><span class="line"> <span class="keyword">this</span>.name = name</span><br><span class="line"> }</span><br><span class="line"> say() {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`<span class="subst">${<span class="keyword">this</span>.name}</span> say`</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">const</span> dog = <span class="keyword">new</span> Dog(<span class="string">'哈士奇'</span>)</span><br><span class="line">dog.say()</span><br><span class="line">dog.eat()</span><br><span class="line">注意以下两点:</span><br><span class="line"></span><br><span class="line">使用extends即可实现继承,更加符合经典面向对象语言的写法,如 Java</span><br><span class="line">子类的<span class="keyword">constructor</span>一定要执行super(),以调用父类的<span class="keyword">constructor</span>...</span><br></pre></td></tr></table></figure><ul><li>Ajax 是什么?如何创建一个 Ajax ?</li></ul><blockquote><p>ajax的全称:Asynchronous Javascript And XML,异步传输+js+xml。 </p><p>所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验。</p><p> // </p><p>(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象 </p><p>(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息 </p><p>(3)设置响应HTTP请求状态变化的函数 </p><p>(4)发送HTTP请求</p><p> (5)获取异步调用返回的数据 </p><p>(6)使用JavaScript和DOM实现局部刷新</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">> <span class="keyword">var</span> xmlHttp = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">> xmlHttp.open(<span class="string">"GET"</span>,demo.php,<span class="string">"true"</span>);</span><br><span class="line">> xmlHttp.send();</span><br><span class="line">> xmlHttp.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line">> <span class="keyword">if</span>(xmlHttp.readyState === <span class="number">4</span> & xmlHttp.status=== <span class="number">200</span>){</span><br><span class="line">> ...</span><br><span class="line">> }</span><br><span class="line">> }</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote><blockquote></blockquote><ul><li><p>前端中的事件流</p><blockquote><p>HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件onclick、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。想要知道这些事件是在什么时候进行调用的,就需要了解一下“事件流”的概念。</p><p>什么是事件流:事件流描述的是从页面中接收事件的顺序,DOM2级事件流包括下面几个阶段。</p><ul><li>事件捕获阶段</li><li>处于目标阶段</li><li>事件冒泡阶段</li></ul><p><strong>addEventListener</strong>:<strong>addEventListener</strong> 是DOM2 级事件新增的指定事件处理程序的操作,这个方法接收3个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序。</p><p><strong>IE只支持事件冒泡</strong>。</p></blockquote></li><li><p>如何让事件先冒泡后捕获</p></li></ul><blockquote><p>在DOM标准事件模型中,是先捕获后冒泡。但是如果要实现先冒泡后捕获的效果,对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获之间。</p></blockquote><ul><li>事件委托</li></ul><blockquote><ul><li>简介:事件委托指的是,不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。</li><li>举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。</li><li>好处:比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。</li></ul></blockquote><ul><li>如何实现sleep的效果(es5或者es6)<blockquote><p>(1)while循环的方式</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">> <span class="keyword">function</span> sleep(ms){</span><br><span class="line">> var start=<span class="type">Date</span>.now(),expire=<span class="keyword">start</span>+ms;</span><br><span class="line">> <span class="keyword">while</span>(<span class="type">Date</span>.now()<expire);</span><br><span class="line">> console.log(<span class="string">'1111'</span>);</span><br><span class="line">> <span class="keyword">return</span>;</span><br><span class="line">> }</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote></li></ul><blockquote><p>执行sleep(1000)之后,休眠了1000ms之后输出了1111。上述循环的方式缺点很明显,容易造成死循环。</p><p> (2)通过promise来实现</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">></span><span class="bash"> <span class="keyword">function</span> sleep(ms){</span></span><br><span class="line"><span class="meta">></span><span class="bash"> var temple=new Promise(</span></span><br><span class="line"><span class="meta">></span><span class="bash"> (resolve)=>{</span></span><br><span class="line"><span class="meta">></span><span class="bash"> console.log(111);setTimeout(resolve,ms)</span></span><br><span class="line"><span class="meta">></span><span class="bash"> });</span></span><br><span class="line"><span class="meta">></span><span class="bash"> <span class="built_in">return</span> temple</span></span><br><span class="line"><span class="meta">></span><span class="bash"> }</span></span><br><span class="line"><span class="meta">></span><span class="bash"> sleep(500).<span class="keyword">then</span>(<span class="function"><span class="title">function</span></span>(){</span></span><br><span class="line"><span class="meta">></span><span class="bash"> //console.log(222)</span></span><br><span class="line"><span class="meta">></span><span class="bash"> })</span></span><br><span class="line"><span class="meta">></span><span class="bash"> //先输出了111,延迟500ms后输出222</span></span><br><span class="line"><span class="meta">></span><span class="bash"> 复制代码</span></span><br><span class="line"><span class="meta">></span><span class="bash"></span></span><br></pre></td></tr></table></figure></blockquote><blockquote><p> (3)通过async封装</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">> <span class="function"><span class="keyword">function</span> <span class="title">sleep</span>(<span class="params">ms</span>)</span>{</span><br><span class="line">> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>)=></span>setTimeout(resolve,ms));</span><br><span class="line">> }</span><br><span class="line">> <span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params"></span>)</span>{</span><br><span class="line">> <span class="keyword">var</span> temple=<span class="keyword">await</span> sleep(<span class="number">1000</span>);</span><br><span class="line">> <span class="built_in">console</span>.log(<span class="number">1111</span>)</span><br><span class="line">> <span class="keyword">return</span> temple</span><br><span class="line">> }</span><br><span class="line">> test();</span><br><span class="line">> <span class="comment">//延迟1000ms输出了1111</span></span><br><span class="line">> 复制代码</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote><blockquote><p>(4).通过generate来实现</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">> <span class="function"><span class="keyword">function</span>* <span class="title">sleep</span>(<span class="params">ms</span>)</span>{</span><br><span class="line">> <span class="keyword">yield</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="keyword">function</span>(<span class="params">resolve,reject</span>)</span>{</span><br><span class="line">> <span class="built_in">console</span>.log(<span class="number">111</span>);</span><br><span class="line">> setTimeout(resolve,ms);</span><br><span class="line">> }) </span><br><span class="line">> }</span><br><span class="line">> sleep(<span class="number">500</span>).next().value.then(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{<span class="built_in">console</span>.log(<span class="number">2222</span>)})</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote><blockquote></blockquote><ul><li>简单的实现一个promise<blockquote><p>首先明确什么是promiseA+规范,参考规范的地址:</p><p><a href="https://link.juejin.im/?target=https%3A%2F%2Fpromisesaplus.com%2F" target="_blank" rel="noopener">primiseA+规范</a></p><p>如何实现一个promise,参考文章:</p><p><a href="https://link.juejin.im/?target=https%3A%2F%2Fgithub.com%2Fforthealllight%2Fblog%2Fissues%2F4" target="_blank" rel="noopener">实现一个完美符合Promise/A+规范的Promise</a></p></blockquote></li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">myPromise</span>(<span class="params">constructor</span>)</span>{</span><br><span class="line"> <span class="keyword">let</span> self=<span class="keyword">this</span>;</span><br><span class="line"> self.status=<span class="string">"pending"</span> <span class="comment">//定义状态改变前的初始状态</span></span><br><span class="line"> self.value=<span class="literal">undefined</span>;<span class="comment">//定义状态为resolved的时候的状态</span></span><br><span class="line"> self.reason=<span class="literal">undefined</span>;<span class="comment">//定义状态为rejected的时候的状态</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">resolve</span>(<span class="params">value</span>)</span>{</span><br><span class="line"> <span class="comment">//两个==="pending",保证了状态的改变是不可逆的</span></span><br><span class="line"> <span class="keyword">if</span>(self.status===<span class="string">"pending"</span>){</span><br><span class="line"> self.value=value;</span><br><span class="line"> self.status=<span class="string">"resolved"</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">reject</span>(<span class="params">reason</span>)</span>{</span><br><span class="line"> <span class="comment">//两个==="pending",保证了状态的改变是不可逆的</span></span><br><span class="line"> <span class="keyword">if</span>(self.status===<span class="string">"pending"</span>){</span><br><span class="line"> self.reason=reason;</span><br><span class="line"> self.status=<span class="string">"rejected"</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//捕获构造异常</span></span><br><span class="line"> <span class="keyword">try</span>{</span><br><span class="line"> <span class="keyword">constructor</span>(resolve,reject);</span><br><span class="line"> }catch(e){</span><br><span class="line"> reject(e);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//同时,需要在myPromise的原型上定义链式调用的then方法:</span></span><br><span class="line"></span><br><span class="line">myPromise.prototype.then=<span class="function"><span class="keyword">function</span>(<span class="params">onFullfilled,onRejected</span>)</span>{</span><br><span class="line"> <span class="keyword">let</span> self=<span class="keyword">this</span>;</span><br><span class="line"> <span class="keyword">switch</span>(self.status){</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"resolved"</span>:</span><br><span class="line"> onFullfilled(self.value);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">"rejected"</span>:</span><br><span class="line"> onRejected(self.reason);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>: </span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>请编写一个JavaScript函数 parseQueryString,它的用途是把URL参数解析为一个对象,如:<br>var url = “<a href="https://link.jianshu.com/?t=http://witmax.cn/index.php?key0=0&key1=1&key2=2" target="_blank" rel="noopener">http://witmax.cn/index.php?key0=0&key1=1&key2=2</a>″;</li></ul><figure class="highlight qml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">parseQueryString</span>(<span class="params">url</span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> params = {},</span><br><span class="line"> arr = <span class="built_in">url</span>.split(<span class="string">"?"</span>);</span><br><span class="line"> <span class="keyword">if</span> (arr.length <= <span class="number">1</span>)</span><br><span class="line"> <span class="keyword">return</span> params;</span><br><span class="line"> arr = arr[<span class="number">1</span>].split(<span class="string">"&"</span>);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>, l=arr.length; i<l; i++){</span><br><span class="line"> <span class="keyword">var</span> a = arr[i].split(<span class="string">"="</span>);</span><br><span class="line"> params[a[<span class="number">0</span>]] = a[<span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> params;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> <span class="built_in">url</span> = <span class="string">"http://witmax.cn/index.php?key0=0&key1=1&key2=2"</span>,</span><br><span class="line"> ps = parseQueryString(<span class="built_in">url</span>);</span><br><span class="line"><span class="built_in">console</span>.log(ps[<span class="string">"key1"</span>]);</span><br></pre></td></tr></table></figure><ul><li>如何获取光标的水平位置?</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getX</span>(<span class="params">e</span>)</span>{</span><br><span class="line"> e = e || <span class="built_in">window</span>.event;</span><br><span class="line"> <span class="comment">//先检查非IE浏览器,在检查IE的位置</span></span><br><span class="line"> <span class="keyword">return</span> e.pageX || e.clentX + <span class="built_in">document</span>.body.scrollLeft;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ul><li>如何规避javascript多人开发函数重名问题?</li></ul><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(<span class="number">1</span>) 可以开发前规定命名规范,根据不同开发人员开发的功能在函数前加前缀</span><br><span class="line">(<span class="number">2</span>) 将每个开发人员的函数封装到类中,调用的时候就调用类的函数,即使函数重名只要类名不重复就行</span><br></pre></td></tr></table></figure><ul><li>AJAX请求总共有多少种CALLBACK</li></ul><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Ajax请求总共有八种Callback</span><br><span class="line"><span class="keyword">on</span>Success</span><br><span class="line"><span class="keyword">on</span>Failure</span><br><span class="line"><span class="keyword">on</span>Uninitialized</span><br><span class="line"><span class="keyword">on</span>Loading</span><br><span class="line"><span class="keyword">on</span>Loaded</span><br><span class="line"><span class="keyword">on</span>Interactive</span><br><span class="line"><span class="keyword">on</span>Complete</span><br><span class="line"><span class="keyword">on</span>Exception</span><br></pre></td></tr></table></figure><ul><li>数组去重</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">方法一:</span><br><span class="line"><span class="keyword">var</span> arr1=[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">2</span>,<span class="number">1</span>,<span class="number">2</span>];</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">repeat1</span>(<span class="params">arr</span>)</span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>,arr2=[];i<arr.length;i++){</span><br><span class="line"> <span class="keyword">if</span>(arr2.indexOf(arr[i])==<span class="number">-1</span>){</span><br><span class="line"> arr2.push(arr[i]);</span><br><span class="line"> }</span><br><span class="line"> }<span class="comment">//(遍历结束)</span></span><br><span class="line"> <span class="keyword">return</span> arr2;</span><br><span class="line">}</span><br><span class="line">方法二:hash</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">repeat2</span>(<span class="params">arr</span>)</span>{</span><br><span class="line"> <span class="comment">//遍历arr中每个元素,同时声明hash</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>,hash={};i<arr.length;i++){</span><br><span class="line"> <span class="comment">//hash中是否包含当前元素值的建</span></span><br><span class="line"> <span class="comment">//如果不包含,就hash添加一个新元素,以当前元素值为key,value默认为1</span></span><br><span class="line"> <span class="keyword">if</span>(hash[arr[i]]===<span class="literal">undefined</span>){</span><br><span class="line"> hash[arr[i]]=<span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> }<span class="comment">//(遍历结束)</span></span><br><span class="line"> <span class="comment">//将hash转为索引:</span></span><br><span class="line"> <span class="keyword">var</span> i=<span class="number">0</span>;</span><br><span class="line"> <span class="keyword">var</span> arr2=[];</span><br><span class="line"> <span class="keyword">for</span>(arr2[i++] <span class="keyword">in</span> hash);</span><br><span class="line"> <span class="keyword">return</span> arr2;</span><br><span class="line">}</span><br><span class="line">方法三:</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">repeat3</span>(<span class="params">arr</span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> arr.sort()</span><br><span class="line"> .join(<span class="string">",,"</span>)</span><br><span class="line"> .replace(</span><br><span class="line"> /(^|,,)([^,]+)(,,\<span class="number">2</span>)*<span class="regexp">/g,</span></span><br><span class="line"><span class="regexp"> "$1$2")</span></span><br><span class="line"><span class="regexp"> .split(",,");</span></span><br><span class="line"><span class="regexp"> }</span></span><br><span class="line"><span class="regexp"> console.log(repeat3(arr1));</span></span><br></pre></td></tr></table></figure><ul><li>快速排序:</li></ul><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">function <span class="built_in">quickSort</span>(arr){</span><br><span class="line"> <span class="comment">//如果arr的length<=1</span></span><br><span class="line"> <span class="keyword">if</span>(arr.length<=<span class="number">1</span>){</span><br><span class="line"> <span class="keyword">return</span> arr;<span class="comment">//就直接返回arr</span></span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//计算参照位p</span></span><br><span class="line"> <span class="keyword">var</span> p=<span class="type">Math</span>.floor(arr.length/<span class="number">2</span>);</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">left</span>=[];</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">right</span>=[];</span><br><span class="line"> <span class="comment">//删除p位置的元素</span></span><br><span class="line"> <span class="keyword">var</span> center=arr.splice(p,<span class="number">1</span>)[<span class="number">0</span>];</span><br><span class="line"> <span class="comment">//遍历arr中每个元素</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<arr.length;i++){</span><br><span class="line"> <span class="keyword">if</span>(arr[i]>=center){</span><br><span class="line"> <span class="keyword">right</span>.push(arr[i]);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">left</span>.push(arr[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">quickSort</span>(<span class="keyword">left</span>) .concat(center,<span class="built_in">quickSort</span>(<span class="keyword">right</span>))</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> sortedArr=<span class="built_in">quickSort</span>(arr);</span><br></pre></td></tr></table></figure><ul><li>深克隆原理</li></ul><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Object</span>.clone=<span class="function"><span class="keyword">function</span>(<span class="params">obj</span>)</span>{<span class="comment">//深克隆</span></span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">typeof</span>(obj)==<span class="string">"object"</span>){<span class="comment">//如果obj是对象</span></span><br><span class="line"> <span class="keyword">var</span> o=<span class="comment">//有必要区分数组和普通对象</span></span><br><span class="line"> <span class="built_in">Object</span>.prototype.toString.call(obj)==<span class="string">"[object Array]"</span>?[]:{};</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> key <span class="keyword">in</span> obj){<span class="comment">//遍历obj的自有属性</span></span><br><span class="line"> <span class="comment">//如果key是obj的自有属性</span></span><br><span class="line"> <span class="keyword">if</span>(obj.hasOwnProperty(key)){</span><br><span class="line"> o[key]=<span class="built_in">arguments</span>.callee(obj[key]);<span class="comment">//arguments.callee调的是当前的Object.clone函数</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> o;</span><br><span class="line"> }<span class="keyword">else</span>{<span class="comment">//如果obj是原始类型的值,就直接返回副本</span></span><br><span class="line"> <span class="keyword">return</span> obj;</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><p> bind函数的实现原理</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">Function</span>.prototype.bind2=<span class="function"><span class="keyword">function</span>(<span class="params">obj<span class="regexp">/*,参数列表*/</span></span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> fun=<span class="keyword">this</span>;<span class="comment">//留住this</span></span><br><span class="line"> <span class="comment">//*****将类数组对象,转化为普通数组</span></span><br><span class="line"> <span class="keyword">var</span> args=<span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">arguments</span>,<span class="number">1</span>);</span><br><span class="line"> <span class="comment">//args保存的就是提前绑定的参数列表</span></span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="comment">//将后传入的参数值,转为普通数组 </span></span><br><span class="line"> <span class="keyword">var</span> innerArgs=<span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">arguments</span>);<span class="comment">//将之前绑定的参数值和新传入的参数值,拼接为完整参数之列表</span></span><br><span class="line"> <span class="keyword">var</span> allArgs=args.concat(innerArgs)</span><br><span class="line"> <span class="comment">//调用原始函数fun,替换this为obj,传入所有参数</span></span><br><span class="line"> fun.apply(obj,allArgs);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><ul><li>字符串转数字的方法</li></ul><blockquote><ol><li><p>js提供了parseInt()和parseFloat()两个转换函数</p></li><li><p>强制类型转换</p><p>ECMAScript中可用的3种强制类型转换如下: Boolean(value)——把给定的值转换成Boolean型; Number(value)——把给定的值转换成数字(可以是整数或浮点数); String(value)——把给定的值转换成字符串。</p></li><li><p>利用js变量弱类型转换</p></li></ol></blockquote><ul><li>重绘和回流(考察频率:中)</li></ul><blockquote><ul><li>重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。</li><li>回流:当Render Tree(DOM)中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。</li><li>回流要比重绘消耗性能开支更大。</li><li>回流必将引起重绘,重绘不一定会引起回流。</li><li>请给出异步加载js方案,不少于两种</li></ul></blockquote><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">异步加载方式:</span><br><span class="line">defer,只支持IE</span><br><span class="line"><span class="keyword">async</span>:</span><br><span class="line">创建script,插入到DOM中,加载完毕后callBack,见代码:</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">loadScript</span>(<span class="params">url, callback</span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> script = <span class="built_in">document</span>.createElement(<span class="string">"script"</span>)</span><br><span class="line"> script.type = <span class="string">"text/javascript"</span>;</span><br><span class="line"> <span class="keyword">if</span>(script.readyState){ <span class="comment">//IE</span></span><br><span class="line"> script.onreadystatechange = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">if</span> (script.readyState == <span class="string">"loaded"</span> ||script.readyState == <span class="string">"complete"</span>){</span><br><span class="line"> script.onreadystatechange = <span class="literal">null</span>;</span><br><span class="line"> callback();</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"><span class="comment">//Others: Firefox, Safari, Chrome, and Opera</span></span><br><span class="line"> script.onload = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> callback();</span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line"> script.src = url;</span><br><span class="line"> <span class="built_in">document</span>.body.appendChild(script);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Promise Promise是 CommonJS 提出来的这一种规范,有多个版本,在 ES6 当中已经纳入规范,原生支持 Promise 对象,非 ES6 环境可以用类似 Bluebird、Q 这类库来支持。 Promise 可以将回调变成链式调用写法,流程更加清晰,代码更加优雅。 简单归纳下 Promise:三个状态、两个过程、一个方法,快速记忆方法:3-2-1 三个状态:pending、fulfilled、rejected 两个过程: pending→fulfilled(resolve) pending→rejected(reject) 一个方法:then 当然还有其他概念,如catch、 Promise.all/race,这里就不展开了。</p>]]></content>
<summary type="html">
<ul>
<li>介绍一下 JS 的基本数据类型。</li>
</ul>
<figure class="highlight mathematica"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">Undefined</span>、<span class="keyword">Null</span>、Boolean、<span class="keyword">Number</span>、<span class="keyword">String</span>、<span class="keyword">Symbol</span>(ES6新增)</span><br></pre></td></tr></table></figure>
<ul>
<li>如何控制alert中的换行?</li>
</ul>
<figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">\n</span> alert(“p<span class="string">\np”);</span></span><br></pre></td></tr></table></figure>
</summary>
<category term="面试" scheme="https://jawn-ha.github.com/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>最近面试题总结 HTML+CSS篇</title>
<link href="https://jawn-ha.github.com/2018/07/18/%E6%9C%80%E8%BF%91%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93/"/>
<id>https://jawn-ha.github.com/2018/07/18/%E6%9C%80%E8%BF%91%E9%9D%A2%E8%AF%95%E9%A2%98%E6%80%BB%E7%BB%93/</id>
<published>2018-07-18T21:41:23.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h3 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h3><ul><li>Doctype作用?严格模式与混杂模式如何区分?它们有何意义?</li></ul><blockquote><p>(1)<!DOCTYPE>声明位于HTML文档中的第一行,处于<html>标签之前,用于告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。 (2)标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。 (3)如果HTML文档包含形式完整的DOCTYPE,那么他一般以标准模式呈现。对于HTML4.01文档,包含严格DTD的DOCTYPE常常导致页面已标准模式呈现。DOCTYPE不存在或者格式不正确会导致文档已混杂模式呈现。</html></p></blockquote><a id="more"></a><ul><li>HTML5 为什么只需要写 <!DOCTYPE HTML>?<blockquote><p>(1)HTML5不基于SGML,因此不需要对DTD进行引用,但是需要DOCTYPE来规范浏览器的行为(让浏览器按照它们应该的方式来运行);<br>(2)HTML4.01基于SGML,所以需要对DTD进行引用,才能让浏览器知道该文档所使用的文档类型。</p></blockquote></li></ul><ul><li>介绍一下你对浏览器内核的理解?常见的浏览器内核有哪些?</li></ul><blockquote><p>浏览器最重要或者说核心的部分是“Rendering Engine”,可大概译为“渲染引擎”,不过我们一般习惯将之称为“浏览器内核”。负责对网页语法的解释(如标准通用标记语言下的一个应用HTML、JavaScript)并渲染(显示)网页。 所以,通常所谓的浏览器内核也就是浏览器所采用的渲染引擎,渲染引擎决定了浏览器如何显示网页的内容以及页面的格式信息。不同的浏览器内核对网页编写语法的解释也有不同,因此同一网页在不同的内核的浏览器里的渲染(显示)效果也可能不同,这也是网页编写者需要在不同内核的浏览器中测试网页显示效果的原因。</p><p> Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML] Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等。 Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;] Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)] EdgeHTML内核:Microsoft Edge。 [此内核其实是从MSHTML fork而来,删掉了几乎所有的IE私有特性]</p></blockquote><ul><li>html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 ?</li></ul><blockquote><p>新增了以下的几大类元素<br>内容元素,article、footer、header、nav、section。<br>表单控件,calendar、date、time、email、url、search。<br> 控件元素,webworker, websockt, Geolocation。<br> 移出的元素有下列这些<br> 显现层元素:basefont,big,center,font, s,strike,tt,u。<br> 性能较差元素:frame,frameset,noframes。<br> 新的技术 canvas,svg,webworker, websocket, Geolocation….<br> HTML5已形成了最终的标准,概括来讲,它主要是关于图像,位置,存储,多任务等功能的增加。 新增的元素有绘画 canvas ,用于媒介回放的 video 和 audio 元素,本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失,而sessionStorage的数据在浏览器关闭后自动删除</p></blockquote><ul><li>简述一下你对HTML语义化的理解。</li></ul><blockquote><p>(1)HTML语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析; (2)即使在没有样式CSS的情况下也能以一种文档格式显示,并且是容易阅读的; (3)搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,有利于SEO; </p><p>(4)使阅读源代码的人更容易将网站分块,便于阅读、维护和理解。</p></blockquote><ul><li>请描述一下 cookies,sessionStorage 和 localStorage 的区别?</li></ul><blockquote><p>Web Storage有两种形式:LocalStorage(本地存储)和sessionStorage(会话存储)。这两种方式都允许开发者使用js设置的键值对进行操作,在在重新加载不同的页面的时候读出它们。这一点与cookie类似。 (1)与cookie不同的是:Web Storage数据完全存储在客户端,不需要通过浏览器的请求将数据传给服务器,因此x相比cookie来说能够存储更多的数据,大概5M左右。 (2)LocalStorage和sessionStorage功能上是一样的,但是存储持久时间不一样。 LocalStorage:浏览器关闭了数据仍然可以保存下来,并可用于所有同源(相同的域名、协议和端口)窗口(或标签页); sessionStorage:数据存储在窗口对象中,窗口关闭后对应的窗口对象消失,存储的数据也会丢失。 注意:sessionStorage 都可以用localStorage 来代替,但需要记住的是,在窗口或者标签页关闭时,使用sessionStorage 存储的数据会丢失。 (3)使用 local storage和session storage主要通过在js中操作这两个对象来实现,分别为window.localStorage和window.sessionStorage. 这两个对象均是Storage类的两个实例,自然也具有Storage类的属性和方法。</p></blockquote><ul><li>iframe 有哪些缺点?</li></ul><blockquote><p>(1)iframe会阻塞主页面的Onload事件; (2)搜索引擎的检索程序无法解读这种页面,不利于SEO; (3)iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。 (4)使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好通过JavaScript动态给iframe添加src属性值,这样可以绕开以上两个问题。</p></blockquote><ul><li>Label的作用是什么?如何使用?</li></ul><blockquote><p>label标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。 <label for="Name">Number:</label> <input type="text" name="Name" id="Name"> <label>Date:<input type="text" name="B"></label></p></blockquote><ul><li>如何实现浏览器内多个标签页之间的通信?</li></ul><blockquote><p>调用 localStorage、cookies 等本地存储方式<br>方法一:使用localStorage</p></blockquote><p>使用localStorage.setItem(key,value);添加内容</p><p>使用storage事件监听添加、修改、删除的动作 </p><p>window.addEventListener(“storage”,function(event){<br> $(“#name”).val(event.key+”=”+event.newValue);<br>});<br>方法二、使用cookie+setInterval</p><p>HTML代码</p><p><inputid=”name”><input type=”button” id=”btnOK”value=”发送”><br>JS代码-页面1 </p><p> $(function(){<br> $(“#btnOK”).click(function(){<br> varname=$(“#name”).val();<br> document.cookie=”name=”+name;<br> });<br> });<br>JS代码-页面2</p><pre><code>//获取Cookie天的内容function getKey(key) { return JSON.parse("{\""+ document.cookie.replace(/;\s+/gim,"\",\"").replace(/=/gim, "\":\"") +"\"}")[key];}//每隔1秒获取Cookie的内容setInterval(function(){ console.log(getKey("name")); },1000);</code></pre><h3 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h3><ul><li>怎么让一个不定宽高的 DIV,垂直水平居中?</li></ul><blockquote><p><strong>使用Flex</strong></p><ul><li>只需要在父盒子设置:display: flex; justify-content: center;align-items: center;</li></ul><p><strong>使用 CSS3 transform</strong></p><ul><li>父盒子设置:<code>display:relative</code></li><li>Div 设置: <code>transform: translate(-50%,-50%);position: absolute;top: 50%;left: 50%;</code></li></ul><p><strong>使用 display:table-cell 方法</strong></p><ul><li>父盒子设置:<code>display:table-cell; text-align:center;vertical-align:middle</code>;</li><li>Div 设置: <code>display:inline-block;vertical-align:middle</code>;</li></ul></blockquote><ul><li>position 几个属性的作用</li></ul><blockquote><p>position 的常见四个属性值: relative,absolute,fixed,static。一般都要配合”left”、”top”、”right” 以及 “bottom” 属性使用。</p><ul><li><strong>static:默认位置</strong>,在一般情况下,我们不需要特别的去声明它,但有时候遇到继承的情况,我们不愿意见到元素所继承的属性影响本身,从而可以用Position:static取消继承,即还原元素定位的默认值。设置为 static 的元素,它始终会处于页面流给予的位置(static 元素会忽略任何 top、 bottom、left 或 right 声明)。一般不常用。</li><li><strong>relative:相对定位</strong>,相对定位是相对于元素默认的位置的定位,它偏移的 top,right,bottom,left 的值都以它原来的位置为基准偏移,而不管其他元素会怎么 样。注意 relative 移动后的元素在原来的位置仍占据空间。</li><li><strong>absolute:绝对定位</strong>,设置为 absolute 的元素,如果它的 父容器设置了 position 属性,并且 position 的属性值为 absolute 或者 relative,那么就会依据父容器进行偏移。如果其父容器没有设置 position 属性,那么偏移是以 body 为依据。注意设置 absolute 属性的元素在标准流中不占位置。</li><li><strong>fixed:固定定位</strong>,位置被设置为 fixed 的元素,可定位于相对于浏览器窗口的指定坐标。不论窗口滚动与否,元素都会留在那个位置。它始终是以 body 为依据的。 注意设置 fixed 属性的元素在标准流中不占位置。</li></ul></blockquote><ul><li>清除浮动的方法</li></ul><blockquote><p><strong>方法1:给父级div定义 高度</strong> 原理:给父级DIV定义固定高度(height),能解决父级DIV 无法获取高度得问题。 优点:代码简洁 缺点:高度被固定死了,是适合内容固定不变的模块。(不推荐使用)</p><p><strong>方法二:使用空元素,如<div class="clear"></div> (.clear{clear:both})</strong> 原理:添加一对空的DIV标签,利用css的clear:both属性清除浮动,让父级DIV能够获取高度。 优点:浏览器支持好 缺点:多出了很多空的DIV标签,如果页面中浮动模块多的话,就会出现很多的空置DIV了,这样感觉视乎不是太令人满意。(不推荐使用)</p><p><strong>方法三:让父级div 也一并浮起来</strong> 这样做可以初步解决当前的浮动问题。但是也让父级浮动起来了,又会产生新的浮动问题。 不推荐使用</p><p><strong>方法四:父级div定义 display:table</strong> 原理:将div属性强制变成表格 优点:不解 缺点:会产生新的未知问题。(不推荐使用)</p><p><strong>方法五:父元素设置 overflow:hidden、auto;</strong> 原理:这个方法的关键在于触发了BFC。在IE6中还需要触发 hasLayout(zoom:1) 优点:代码简介,不存在结构和语义化问题 缺点:无法显示需要溢出的元素(亦不太推荐使用)</p><p><strong>方法六:父级div定义 伪类:after 和 zoom</strong></p><figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">> <span class="selector-class">.clearfix</span>:after{</span><br><span class="line">> <span class="attribute">content</span>:<span class="string">'.'</span>;</span><br><span class="line">> <span class="attribute">display</span>:block;</span><br><span class="line">> <span class="attribute">height</span>:<span class="number">0</span>;</span><br><span class="line">> <span class="attribute">clear</span>:both;</span><br><span class="line">> <span class="attribute">visibility</span>: hidden;</span><br><span class="line">> }</span><br><span class="line">> <span class="selector-class">.clearfix</span> {zoom:<span class="number">1</span>;}</span><br><span class="line">> 复制代码</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote><blockquote><p>原理:IE8以上和非IE浏览器才支持<code>:after</code>,原理和方法2有点类似,<code>zoom</code>(IE转有属性)可解决ie6,ie7浮动问题 优点:结构和语义化完全正确,代码量也适中,可重复利用率(建议定义公共类) 缺点:代码不是非常简洁(极力推荐使用)</p><p><strong>经益求精写法</strong></p><figure class="highlight scss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">> <span class="selector-class">.clearfix</span>:after {</span><br><span class="line">> <span class="attribute">content</span>:”\<span class="number">200</span>B”; </span><br><span class="line">> <span class="attribute">display</span>:block; </span><br><span class="line">> <span class="attribute">height</span>:<span class="number">0</span>; </span><br><span class="line">> <span class="attribute">clear</span>:both;</span><br><span class="line">> }</span><br><span class="line">> <span class="selector-class">.clearfix</span> { *zoom:<span class="number">1</span>; } 照顾IE6,IE7就可以了</span><br><span class="line">></span><br></pre></td></tr></table></figure></blockquote><ul><li><p>什么是 BFC</p><blockquote><p><strong>定义</strong>:BFC(Block formatting context)直译为”块级格式化上下文”。它是一个独立的渲染区域,只有 Block-level box 参 与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。</p><p><strong>BFC布局规则</strong> BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。</p><ul><li>BFC这个元素的垂直方向的边距会发生重叠,垂直方向的距离由<code>margin</code>决定,取最大值</li><li>BFC 的区域不会与浮动盒子重叠(<code>清除浮动原理</code>)。</li><li>计算 BFC 的高度时,浮动元素也参与计算。</li></ul><p><strong>哪些元素会生成 BFC</strong></p><ul><li>根元素</li><li>float 属性不为 none</li><li>position 为 absolute 或 fixed</li><li>display 为 inline-block, table-cell, table-caption, flex, inline-flex</li><li>overflow 不为 visible</li></ul></blockquote></li><li><p>box-sizing</p><blockquote><p>设置CSS盒模型为标准模型或IE模型。标准模型的宽度只包括content,二IE模型包括border和padding<br>box-sizing属性可以为三个值之一:</p><p>content-box,默认值,只计算内容的宽度,border和padding不计算入width之内</p><p> padding-box,padding计算入宽度内</p><p>border-box,border和padding计算入宽度之内</p></blockquote></li><li><p>px,em,rem 的区别</p></li></ul><blockquote><p><strong>px</strong> 像素(Pixel)。绝对单位。像素 px 是<code>相对于显示器屏幕分辨率</code>而言的,是一个虚拟长度单位,是计算 机系统的数字化图像长度单位,如果 px 要换算成物理长度,需要指定精度 DPI。</p><p><strong>em</strong> 是相对长度单位,<code>相对于当前对象内文本的字体尺寸</code>。如当前对行内文本的字体尺寸未被人为设置, 则相对于浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。</p><p><strong>rem</strong> 是 CSS3 新增的一个相对单位(root em,根 em),使用 rem 为元素设定字体大小时,仍然是相对大小, 但<code>相对的只是 HTML 根元素</code>。</p></blockquote><ul><li><p>CSS 引入的方式有哪些? link 和@import 的区别是?</p><blockquote><p>有四种:内联(元素上的style属性)、内嵌(style标签)、外链(link)、导入(@import) link和@import的区别:</p><ul><li><code>link</code>是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;<code>@import</code>属于CSS范畴,<code>只能加载CSS</code>。</li><li><code>link</code>引用CSS时,在<code>页面载入时同时加载</code>;<code>@import需要页面网页完全载入以后加载</code>。</li><li><code>link</code>是XHTML标签,<code>无兼容问题</code>;<code>@import</code>是在CSS2.1提出的,<code>低版本的浏览器不支持</code>。</li><li><code>link</code>支持使用Javascript控制DOM去<code>改变样式</code>;而<code>@import</code>不支持。 </li></ul></blockquote></li><li><p>流式布局与响应式布局的区别</p></li></ul><blockquote><p><strong>流式布局</strong> 使用非固定像素来定义网页内容,<code>也就是百分比布局</code>,通过盒子的宽度设置成百分比来根据屏幕的宽度来进 行伸缩,不受固定像素的限制,内容向两侧填充。</p><p><strong>响应式开发</strong> 利用CSS3 中的 Media Query(媒介查询),通过查询 screen 的宽度来指定某个宽度区间的网页布局。</p><ul><li>超小屏幕(移动设备) 768px 以下</li><li>小屏设备 768px-992px</li><li>中等屏幕 992px-1200px</li><li>宽屏设备 1200px 以上 </li></ul></blockquote><ul><li><p>渐进增强和优雅降级</p><blockquote><p>优雅降级一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。。<br>渐进增强针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。</p></blockquote></li><li><p>CSS隐藏元素的几种方式及区别</p><blockquote><p><strong>display:none</strong></p><ul><li>元素在页面上将彻底消失,元素本来占有的空间就会被其他元素占有,也就是说它会导致浏览器的重排和重绘。</li><li>不会触发其点击事件</li></ul><p><strong>visibility:hidden</strong></p><ul><li>和<code>display:none</code>的区别在于,<code>元素在页面消失后,其占据的空间依旧会保留着</code>,所以它<code>只会导致浏览器重绘</code>而不会重排。</li><li>无法触发其点击事件</li><li>适用于那些元素隐藏后不希望页面布局会发生变化的场景</li></ul><p><strong>opacity:0</strong></p><ul><li>将元素的透明度设置为0后,在我们用户眼中,元素也是隐藏的,这算是一种隐藏元素的方法。</li><li>和<code>visibility:hidden</code>的一个共同点是元素隐藏后依旧占据着空间,但我们都知道,设置透明度为0后,元素只是隐身了,它依旧存在页面中。</li><li>可以触发点击事件 </li></ul></blockquote></li></ul>]]></content>
<summary type="html">
<h3 id="HTML"><a href="#HTML" class="headerlink" title="HTML"></a>HTML</h3><ul>
<li>Doctype作用?严格模式与混杂模式如何区分?它们有何意义?</li>
</ul>
<blockquote>
<p>(1)&lt;!DOCTYPE&gt;声明位于HTML文档中的第一行,处于<html>标签之前,用于告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。 (2)标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。 (3)如果HTML文档包含形式完整的DOCTYPE,那么他一般以标准模式呈现。对于HTML4.01文档,包含严格DTD的DOCTYPE常常导致页面已标准模式呈现。DOCTYPE不存在或者格式不正确会导致文档已混杂模式呈现。</html></p>
</blockquote>
</summary>
<category term="面试" scheme="https://jawn-ha.github.com/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>JS二叉树的遍历</title>
<link href="https://jawn-ha.github.com/2018/07/12/JS%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/"/>
<id>https://jawn-ha.github.com/2018/07/12/JS%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E9%81%8D%E5%8E%86/</id>
<published>2018-07-12T19:02:33.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h3 id="二叉查找树(Binary-Sort-Tree)"><a href="#二叉查找树(Binary-Sort-Tree)" class="headerlink" title="二叉查找树(Binary Sort Tree)"></a>二叉查找树(Binary Sort Tree)</h3><p>今天我们将学习计算机中经常用到的一种非线性的数据结构——树(<strong>Tree</strong>),由于其存储的所有元素之间具有明显的层次特性,因此常被用来存储具有层级关系的数据,比如文件系统中的文件;也会被用来存储有序列表等。</p><p>在树结构中,每一个结点只有一个前件,称为父结点,没有前件的结点只有一个,称为树的<strong>根结点</strong>,简称树的<strong>根</strong>(root)。每一个结点可以有多个后件,称为该结点的子结点。没有后件的结点称为叶子结点。一个结点所拥有的子结点的个数称为该结点的度,所有结点中最大的度称为树的度。树的最大层次称为树的深度。</p><a id="more"></a><h3 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h3><p>二叉树是一种特殊的树,它的子节点个数不超过两个,且分别称为该结点的左子树(left subtree)与右子树(right subtree),二叉树常被用作二叉查找树和二叉堆或是二叉排序树(BST)。</p><p><img src="/images/2018-7-11/bedfd16ede6b68832ee2ab943ba32334.webp" alt="二叉树"></p><p>按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次,这个操作被称为树的遍历,是对树的一种最基本的运算。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个结点转换成为一个线性序列来表示。</p><p>按照根节点访问的顺序不同,树的遍历分为以下三种:前序遍历,中序遍历,后序遍历;</p><p>前序遍历:根节点->左子树->右子树</p><p> <img src="/images/2018-7-11/2.png" alt="先序遍历"></p><p>中序遍历:左子树->根节点->右子树</p><p><img src="/images/2018-7-11/3.png" alt></p><p>后序遍历:左子树->右子树->根节点 </p><p> <img src="/images/2018-7-11/4.png" alt></p><p>因此我们可以得之上面二叉树的遍历结果如下:<br> 前序遍历:ABDEFGC<br> 中序遍历:DEBGFAC<br> 后序遍历:EDGFBCA</p><h2 id="二叉查找树(BST)"><a href="#二叉查找树(BST)" class="headerlink" title="二叉查找树(BST)"></a>二叉查找树(BST)</h2><p>实际应用中,树的每个节点都会有一个与之相关的值对应,有时候会被称为<strong>键</strong>。因此,我们在构建二叉查找树的时候,确定子节点非常的重要,通常将相对较小的值保存在左节点中,较大的值保存在右节点中,这就使得查找的效率非常高,因此被广泛使用。</p><h2 id="二叉查找树的实现"><a href="#二叉查找树的实现" class="headerlink" title="二叉查找树的实现"></a>二叉查找树的实现</h2><p>根据上面的知识,我们了解到二叉树实际上是由多个节点组成,因此我们首先就要定义一个Node类,用于存放树的节点,其构造与前面的<a href="https://www.jianshu.com/p/f254ec665e57" target="_blank" rel="noopener">链表</a>类似。Node类的定义如下:</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//节点定义</span></span><br><span class="line"></span><br><span class="line">function Node (<span class="keyword">data</span> , left , right) {</span><br><span class="line"> <span class="keyword">this</span>.<span class="keyword">data</span> = <span class="keyword">data</span>; <span class="comment">// 数据</span></span><br><span class="line"> <span class="keyword">this</span>.left = left; <span class="comment">// 左节点</span></span><br><span class="line"> <span class="keyword">this</span>.right = right; <span class="comment">// 右节点</span></span><br><span class="line"> <span class="keyword">this</span>.show = show; <span class="comment">// 显示节点数据</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function show(){</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.<span class="keyword">data</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Node对象既保存了数据,也保存了它的左节点和右节点的链接,其中 show 方法用来显示当前保存在节点中数据。</p><p>现在我们可以创建一个类,用来表示二叉查找数(BST),我们初始化类只包含一个成员,一个表示二叉查找树根节点的 Node 对象,初始化为 null , 表示创建一个空节点。</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//二叉查找树(BST)的类</span></span><br><span class="line"></span><br><span class="line">function BST(){</span><br><span class="line"> <span class="keyword">this</span>.root = <span class="literal">null</span>; <span class="comment">// 根节点</span></span><br><span class="line"> <span class="keyword">this</span>.insert = insert; <span class="comment">// 插入节点</span></span><br><span class="line"> <span class="keyword">this</span>.preOrder = preOrder; <span class="comment">// 先序遍历</span></span><br><span class="line"> <span class="keyword">this</span>.inOrder = inOrder; <span class="comment">// 中序遍历</span></span><br><span class="line"> <span class="keyword">this</span>.postOrder = postOrder; <span class="comment">// 后序遍历</span></span><br><span class="line"> <span class="keyword">this</span>.find = find; <span class="comment">// 查找节点</span></span><br><span class="line"> <span class="keyword">this</span>.getMin = getMin; <span class="comment">// 查找最小值</span></span><br><span class="line"> <span class="keyword">this</span>.getMax = getMax; <span class="comment">// 查找最大值</span></span><br><span class="line"> <span class="keyword">this</span>.remove = remove; <span class="comment">// 删除节点</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>现在,我们需要为我们的类添加方法。</p><p>首先就是 insert 方法,向树中添加一个新节点,我们一起来看看这个方法;</p><p><strong>insert:向树中添加新节点</strong></p><p>因为添加节点会涉及到插入位置的问题,必须将其放到正确的位置上,才能保证树的正确性,整个过程较为复杂,我们一起来梳理一下:</p><p>首先要添加新的节点,首先需要创建一个Node对象,将数据传入该对象。</p><p>其次要检查当前的BST树是否有根节点,如果没有,那么表示是一棵新数,该节点就为该树的根节点,那么插入这个过程就结束了;否则,就要继续进行下一步了。</p><p>如果待插入节点不是根节点,那么就必须对BST进行遍历,找到合适的位置。该过程类似遍历链表,用一个变量存储当前节点,一层一层遍历BST,算法如下:</p><ol><li>设值当前节点为根节点</li><li>如果待插入节点保存的数据小于当前节点,则新节点为原节点的左节点,反之,执行第4步</li><li>如果当前节点的左节点为null,就将新节点放到这个位置,退出循环;反之,继续执行下一次循环</li><li>设置新节点为原节点的右节点</li><li>如果当前节点的右节点为null,就将新节点放到这个位置,退出循环;反之,继续执行下一次循环</li></ol><p>这样,就能保证每次添加的新节点能够放到正确的位置上,具体实现如下;</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//插入新节点</span></span><br><span class="line"></span><br><span class="line">function insert(<span class="keyword">data</span>) {</span><br><span class="line"> <span class="keyword">var</span> n = new Node( <span class="keyword">data</span> , <span class="literal">null</span> , <span class="literal">null</span> );</span><br><span class="line"> <span class="keyword">if</span>( <span class="keyword">this</span>.root == <span class="literal">null</span> ){</span><br><span class="line"> <span class="keyword">this</span>.root = n;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">var</span> current = <span class="keyword">this</span>.root;</span><br><span class="line"> <span class="keyword">var</span> parent;</span><br><span class="line"> <span class="keyword">while</span>( <span class="literal">true</span> ){</span><br><span class="line"> parent = current;</span><br><span class="line"> <span class="keyword">if</span>( <span class="keyword">data</span> < current.<span class="keyword">data</span> ){</span><br><span class="line"> current = current.left;</span><br><span class="line"> <span class="keyword">if</span>( current == <span class="literal">null</span> ){</span><br><span class="line"> parent.left = n ;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> current = current.right;</span><br><span class="line"> <span class="keyword">if</span>( current == <span class="literal">null</span> ){</span><br><span class="line"> parent.right = n;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>现在BST类已初步成型,但操作还仅仅限于插入节点,我们需要有遍历BST的能力,上面我们也提到了是三种遍历方式。其中中序遍历是最容易实现的,我们需要升序的方法访问树中的所有节点,先访问左子树,在访问根节点,最后是右子树,我们采用递归来实现!</p><p><strong>inOrder:中序遍历</strong></p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> // 中序遍历</span><br><span class="line"> </span><br><span class="line">function inOrder (<span class="keyword">node</span><span class="title">) {</span></span><br><span class="line"><span class="title"> if</span>( !(<span class="keyword">node</span> <span class="title">== null</span> )){</span><br><span class="line"> inOrder( <span class="keyword">node</span>.<span class="title">left</span> );</span><br><span class="line"> console.debug( <span class="keyword">node</span>.<span class="title">show</span>() + ' ');</span><br><span class="line"> inOrder( <span class="keyword">node</span>.<span class="title">right</span> );</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>怎么样,了解了原理,实现起来还是蛮简单的~</p><p>我们用一段代码来测试一下我们所写的中序遍历:</p><figure class="highlight pony"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> nums = <span class="function"><span class="keyword">new</span> <span class="title">BST</span>();</span></span><br><span class="line"><span class="function"><span class="comment">//插入数据</span></span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">23</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">45</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">16</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">37</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">3</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">99</span>);</span></span><br><span class="line"><span class="function"><span class="title">nums</span>.<span class="title">insert</span>(<span class="number">22</span>);</span></span><br></pre></td></tr></table></figure><p>上述插入数据后,会形成如下的二叉树</p><p> <img src="/images/2018-7-11/5.png" alt></p><p>中序遍历结果如下:</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//中序遍历</span></span><br><span class="line">console.log(<span class="string">"Inorder traversal: "</span>);</span><br><span class="line"><span class="keyword">in</span><span class="constructor">Order(<span class="params">nums</span>.<span class="params">root</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Inorder traversal:</span></span><br><span class="line"><span class="comment">// 3 16 22 23 37 45 99</span></span><br></pre></td></tr></table></figure><p><strong>preOrder:先序遍历</strong></p><p>有了中序遍历的基础,相信先序遍历的实现你已经想出来,怎么样?看看对吗?</p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//先序遍历</span><br><span class="line"></span><br><span class="line">function preOrder( <span class="keyword">node</span> <span class="title">) {</span></span><br><span class="line"><span class="title"> if</span>( !(<span class="keyword">node</span> <span class="title">== null</span> )){</span><br><span class="line"> console.log( <span class="keyword">node</span>.<span class="title">show</span>() + ' ');</span><br><span class="line"> preOrder( <span class="keyword">node</span>.<span class="title">left</span> );</span><br><span class="line"> preOrder( <span class="keyword">node</span>.<span class="title">right</span> );</span><br><span class="line"> } </span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>怎么样,看起来是不是和中序遍历差不多,唯一的区别就是 if 语句中代码的执行顺序,中序遍历中 show 方法放在两个递归调用之间,先序遍历则放在递归调用之前。</p><p>先序遍历结果如下:</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 先序遍历</span></span><br><span class="line"></span><br><span class="line">console.log(<span class="string">"Preorder traversal: "</span>);</span><br><span class="line">pre<span class="constructor">Order(<span class="params">nums</span>.<span class="params">root</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Preorder traversal:</span></span><br><span class="line"><span class="comment">// 23 16 3 22 45 37 99</span></span><br></pre></td></tr></table></figure><p><strong>postOrder:后序遍历</strong></p><p>后序遍历的实现和前面的基本相同,将 show 方法放在递归调用之后执行即可</p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//后序遍历</span><br><span class="line"> </span><br><span class="line">function postOrder ( <span class="keyword">node</span> <span class="title">) {</span></span><br><span class="line"><span class="title"> if</span>( !(<span class="keyword">node</span> <span class="title">== null</span> ) ){</span><br><span class="line"> postOrder( <span class="keyword">node</span>.<span class="title">left</span> );</span><br><span class="line"> postOrder( <span class="keyword">node</span>.<span class="title">right</span> );</span><br><span class="line"> console.log( <span class="keyword">node</span>.<span class="title">show</span>() + ' ');</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>后序遍历结果如下:</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 后序遍历</span></span><br><span class="line"></span><br><span class="line">console.log(<span class="string">"Postorder traversal: "</span>);</span><br><span class="line">post<span class="constructor">Order(<span class="params">nums</span>.<span class="params">root</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Postorder traversal:</span></span><br><span class="line"><span class="comment">// 3 22 16 37 99 45 23</span></span><br></pre></td></tr></table></figure><h2 id="二叉查找树的查找运算"><a href="#二叉查找树的查找运算" class="headerlink" title="二叉查找树的查找运算"></a>二叉查找树的查找运算</h2><p>对于BST通常有一下三种的查找类型:</p><ol><li>查找给定值</li><li>查找最大值</li><li>查找最小值</li></ol><p>我们接下来一起来讨论三种查找的方式的实现。</p><p>要查找BST中的最小值和最大值是非常简单的。因为较小的值总是在左子节点上,要想查找BST中的最小值,只需遍历左子树,直到找到最后一个节点即可。同理,查找最大值,只需遍历右子树,直到找到最后一个节点即可。</p><p><strong>getMin:查找最小值</strong></p><p>遍历左子树,直到左子树的某个节点的 left 为 null 时,该节点保存的即为最小值</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//查找最小值</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> getMin( ) {</span><br><span class="line"> var <span class="keyword">current</span> = this.root;</span><br><span class="line"> <span class="keyword">while</span> ( !( <span class="keyword">current</span>.left == <span class="keyword">null</span> ) ){</span><br><span class="line"> <span class="keyword">current</span> = <span class="keyword">current</span>.left;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">current</span>.<span class="keyword">show</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>getMax:查找最大值</strong></p><p>遍历右子树,直到右子树的某个节点的 right 为 null 时,该节点保存的即为最大值</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//查找最大值</span><br><span class="line"> </span><br><span class="line"><span class="keyword">function</span> getMax () {</span><br><span class="line"> var <span class="keyword">current</span> = this.root;</span><br><span class="line"> <span class="keyword">while</span> ( !( <span class="keyword">current</span>.right == <span class="keyword">null</span> ) ) {</span><br><span class="line"> <span class="keyword">current</span> = <span class="keyword">current</span>.right;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">current</span>.<span class="keyword">show</span>();</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们还是利用前面构建的树来测试:</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 最小值</span></span><br><span class="line">console.<span class="built_in">log</span>('min:' + nums.getMin() ); <span class="comment">// min : 3</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//最大值</span></span><br><span class="line">console.<span class="built_in">log</span>('max:' + nums.getMax() ); <span class="comment">// max : 99</span></span><br></pre></td></tr></table></figure><p>在BST上查找给定值,需要比较给定值和当前节点保存的值的大小,通过比较,就能确定给定值在不在当前节点,根据BST的特点,qu接下来是向左还是向右遍历;</p><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//查找给定值</span></span><br><span class="line"></span><br><span class="line">function find ( <span class="keyword">data</span> ) {</span><br><span class="line"> <span class="keyword">var</span> current = <span class="keyword">this</span>.root;</span><br><span class="line"> <span class="keyword">while</span> ( current != <span class="literal">null</span> ){</span><br><span class="line"> <span class="keyword">if</span>( current.<span class="keyword">data</span> == <span class="keyword">data</span> ){</span><br><span class="line"> <span class="keyword">return</span> current;</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>( current.<span class="keyword">data</span> < <span class="keyword">data</span> ){</span><br><span class="line"> current = current.right;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> current = current.left;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>如果找到给定值,该方法返回保存该值的节点,反之返回null;</p><figure class="highlight sqf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//查找不存在的值</span></span><br><span class="line">console.<span class="built_in">log</span>(<span class="string">'find:'</span> + nums.<span class="built_in">find</span>(<span class="number">66</span>)); <span class="comment">// find : null</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//查找存在的值</span></span><br><span class="line">console.<span class="built_in">log</span>(<span class="string">'find:'</span> + nums.<span class="built_in">find</span>(<span class="number">99</span>) ); <span class="comment">// find : [object Object]</span></span><br></pre></td></tr></table></figure><h2 id="二叉查找树的删除运算"><a href="#二叉查找树的删除运算" class="headerlink" title="二叉查找树的删除运算"></a>二叉查找树的删除运算</h2><p>从BST中删除节点的操作最为复杂,其复杂程度取决于删除的节点位置。如果待删除的节点没有子节点,那么非常简单。如果删除包含左子节点或者右子节点,就变得稍微有些复杂。如果删除包含两个节点的节点最为复杂。</p><p>我们采用递归方法,来完成复杂的删除操作,我们定义 remove() 和 removeNode() 两个方法;算法思想如下:</p><ol><li>首先判断当前节点是否包含待删除的数据,如果包含,则删除该节点;如果不包含,则比较当前节点上的数据和待删除树的的大小关系。如果待删除的数据小于当前节点的数据,则移至当前节点的左子节点继续比较;如果大于,则移至当前节点的右子节点继续比较。</li><li>如果待删除节点是叶子节点(没有子节点),那么只需要将从父节点指向它的链接指向变为null;</li><li>如果待删除节点含有一个子节点,那么原本指向它的节点需要做调整,使其指向它的子节点;</li><li>最后,如果待删除节点包含两个子节点,可以选择查找待删除节点左子树上的最大值或者查找其右子树上的最小值,这里我们选择后一种。</li></ol><p>因此,我们需要一个查找树上最小值的方法,后面会用它找到最小值创建一个临时节点,将临时节点上的值复制到待删除节点,然后再删除临时节点;</p><p>我们上面说会用到两个方法,其中 remove 方法只是简单的接收待删除数据,调用 removeNode 删除它,主要工作在 removeNode 中完成,定义如下:</p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">//删除操作</span><br><span class="line"></span><br><span class="line">function remove( data ) {</span><br><span class="line"> removeNode( this.root , data);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//查找最小值</span><br><span class="line"></span><br><span class="line">function getSmallest(<span class="keyword">node</span><span class="title">) {</span></span><br><span class="line"><span class="title"> if</span> (<span class="keyword">node</span>.<span class="title">left</span> == null) {</span><br><span class="line"> return <span class="keyword">node</span><span class="title">;</span></span><br><span class="line"><span class="title"> }</span></span><br><span class="line"><span class="title"> else</span> {</span><br><span class="line"> return getSmallest(<span class="keyword">node</span>.<span class="title">left</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//删除节点</span><br><span class="line">function removeNode( <span class="keyword">node</span> <span class="title">, data</span> ) {</span><br><span class="line"> if( <span class="keyword">node</span> <span class="title">== null</span> ) {</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> if(data == <span class="keyword">node</span>.<span class="title">data</span>) {</span><br><span class="line"> // 没有子节点的节点</span><br><span class="line"> if(<span class="keyword">node</span>.<span class="title">left</span> == null && <span class="keyword">node</span>.<span class="title">right</span> == null) {</span><br><span class="line"> return null;</span><br><span class="line"> }</span><br><span class="line"> // 没有左子节点的节点</span><br><span class="line"> if(<span class="keyword">node</span>.<span class="title">left</span> == null) {</span><br><span class="line"> return <span class="keyword">node</span>.<span class="title">right</span>;</span><br><span class="line"> }</span><br><span class="line"> // 没有右子节点的节点</span><br><span class="line"> if(<span class="keyword">node</span>.<span class="title">right</span> == null) {</span><br><span class="line"> return <span class="keyword">node</span>.<span class="title">left</span>;</span><br><span class="line"> }</span><br><span class="line"> // 有<span class="number">2</span>个子节点的节点</span><br><span class="line"> var tempNode = getSmallest(<span class="keyword">node</span>.<span class="title">right</span>);</span><br><span class="line"> <span class="keyword">node</span>.<span class="title">data</span> = tempNode.data;</span><br><span class="line"> <span class="keyword">node</span>.<span class="title">right</span> = removeNode(<span class="keyword">node</span>.<span class="title">right</span>,tempNode.data);</span><br><span class="line"> return <span class="keyword">node</span><span class="title">;</span></span><br><span class="line"><span class="title"></span></span><br><span class="line"><span class="title"> }else</span> if(data <span class="tag">< node.data) {</span></span><br><span class="line"><span class="tag"> node.left = removeNode( node.left,data);</span></span><br><span class="line"><span class="tag"> return node;</span></span><br><span class="line"><span class="tag"> }else {</span></span><br><span class="line"><span class="tag"> node.right = removeNode( node.right,data);</span></span><br><span class="line"><span class="tag"> return node;</span></span><br><span class="line"><span class="tag"> }</span></span><br><span class="line"><span class="tag">}</span></span><br></pre></td></tr></table></figure><p>现在我们来删除节点试试。</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//删除根节点</span></span><br><span class="line">nums.remove(<span class="number">23</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">in</span><span class="constructor">Order(<span class="params">nums</span>.<span class="params">root</span>)</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 3 16 22 37 45 99</span></span><br></pre></td></tr></table></figure><p>成功了!<br> 现在,我们的BST算是完整了。</p><p>我们现在已经可以利用js是实现一个简单的BST了,实际中树的使用会很广泛,希望大家能多去了解了解树的数据结构,多动手实践,相信你会有不少的收获!</p><blockquote><p>作者:Cryptic</p><p>来源:稀土掘金</p></blockquote>]]></content>
<summary type="html">
<h3 id="二叉查找树(Binary-Sort-Tree)"><a href="#二叉查找树(Binary-Sort-Tree)" class="headerlink" title="二叉查找树(Binary Sort Tree)"></a>二叉查找树(Binary Sort Tree)</h3><p>今天我们将学习计算机中经常用到的一种非线性的数据结构——树(<strong>Tree</strong>),由于其存储的所有元素之间具有明显的层次特性,因此常被用来存储具有层级关系的数据,比如文件系统中的文件;也会被用来存储有序列表等。</p>
<p>在树结构中,每一个结点只有一个前件,称为父结点,没有前件的结点只有一个,称为树的<strong>根结点</strong>,简称树的<strong>根</strong>(root)。每一个结点可以有多个后件,称为该结点的子结点。没有后件的结点称为叶子结点。一个结点所拥有的子结点的个数称为该结点的度,所有结点中最大的度称为树的度。树的最大层次称为树的深度。</p>
</summary>
<category term="数据结构" scheme="https://jawn-ha.github.com/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>JS排序算法</title>
<link href="https://jawn-ha.github.com/2018/07/12/JS%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/"/>
<id>https://jawn-ha.github.com/2018/07/12/JS%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95/</id>
<published>2018-07-12T18:58:36.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h2 id="排序算法(Sort)"><a href="#排序算法(Sort)" class="headerlink" title="排序算法(Sort)"></a>排序算法(Sort)</h2><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>我们平时对计算机中存储的数据执行的两种最常见的操作就是排序和查找,对于计算机的排序和查找的研究,自计算机诞生以来就没有停止过。如今又是大数据,云计算的时代,对数据的排序和查找的速度、效率要求更高,因此要对排序和查找的算法进行专门的数据结构设计,以便让我们对数据的操作更加简洁高效。</p><p>这一篇我们将会介绍一些数据排序的基本算法和高级算法并利用JavaScript来逐一实现,让大伙对计算机中常见的排序算法的思想和实现有基本的了解,起到一个抛砖引玉的作用。</p><a id="more"></a><h3 id="关于排序算法的说明"><a href="#关于排序算法的说明" class="headerlink" title="关于排序算法的说明"></a>关于排序算法的说明</h3><p>在介绍各个算法之前,我们有必要了解一下评估算法优劣的一些术语:</p><p><strong>稳定</strong>:如果a原本在b前面,当a=b时,排序之后a仍然在b的前面<br> <strong>不稳定</strong>:如果a原本在b的前面,当a=b时,排序之后a可能会出现在b的后面</p><p><strong>内排序</strong>:所有排序操作都在内存中完成<br> <strong>外排序</strong>:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行</p><p><strong>时间复杂度</strong>:一个算法执行所耗费的时间<br> <strong>空间复杂度</strong>:运行完一个程序所需内存的大小</p><p>有想要了解更多,关于时间空间复杂度的,我推荐一篇文章,请戳<a href="https://link.jianshu.com?t=http://blog.csdn.net/booirror/article/details/7707551/" target="_blank" rel="noopener">这里</a></p><h2 id="基本排序算法"><a href="#基本排序算法" class="headerlink" title="基本排序算法"></a>基本排序算法</h2><p>基本排序算法的核心思想就是对一组数据按照一定的顺序重新排序,其中重排时一般都会用到一组嵌套的 for 循环,外循环会遍历数组的每一项元素,内循环则用于进行元素直接的比较。</p><p> 基本排序算法的核心思想就是对一组数据按照一定的顺序重新排序,其中重排时一般都会用到一组嵌套的 for 循环,外循环会遍历数组的每一项元素,内循环则用于进行元素直接的比较。</p><p><strong>1.冒泡排序(BubbleSort)</strong></p><p>冒泡排序是比较经典的算法之一,也是排序最慢的算法之一,因为它的实现是非常的容易的。</p><p>冒泡排序的算法思想如下(升序排序):</p><ol><li>比较相邻的元素。如果第一个比第二个大,就交换它们两个;</li><li>对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样最终最大数被交换到最后的位置</li><li>除了最后一个元素以外,针对所有的元素重复以上的步骤</li><li><p>重复步骤1~3,直到排序完成</p><p>具体的JS实现如下:</p></li></ol><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//冒泡排序</span></span><br><span class="line">function bubbleSort ( <span class="keyword">data</span> ) {</span><br><span class="line"> <span class="keyword">var</span> temp = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> ( <span class="keyword">var</span> i = <span class="keyword">data</span>.length ; i > <span class="number">0</span> ; i -- ){</span><br><span class="line"> <span class="keyword">for</span>( <span class="keyword">var</span> j = <span class="number">0</span> ; j < i - <span class="number">1</span> ; j++){</span><br><span class="line"> <span class="keyword">if</span>( <span class="keyword">data</span>[j] > <span class="keyword">data</span>[j + <span class="number">1</span>] ){</span><br><span class="line"> temp = <span class="keyword">data</span>[j];</span><br><span class="line"> <span class="keyword">data</span>[j] = <span class="keyword">data</span> [j+<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">data</span>[j+<span class="number">1</span>] = temp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">data</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> 我们先设定一组数据,后面我们将都用这组数据来测试 :</p><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var dataStore = [ <span class="number">72</span> , <span class="number">1</span> , <span class="number">68</span> , <span class="number">95</span> , <span class="number">75</span> , <span class="number">54</span> , <span class="number">58</span> , <span class="number">10</span> , <span class="number">35</span> , <span class="number">6</span> , <span class="number">28</span> , <span class="number">45</span> , <span class="number">69</span> , <span class="number">13</span> , <span class="number">88</span> , <span class="number">99</span> , <span class="number">24</span> , <span class="number">28</span> , <span class="number">30</span> , <span class="number">31</span> , <span class="number">78</span> , <span class="number">2</span> , <span class="number">77</span> , <span class="number">82</span> , <span class="number">72</span> ];</span><br><span class="line"></span><br><span class="line">console.log( <span class="string">'原始数据:'</span> + dataStore );</span><br><span class="line">console.log( <span class="string">'冒泡排序:'</span> + bubbleSort( dataStore) );</span><br><span class="line"></span><br><span class="line"><span class="comment">// 原始数据:72,1,68,95,75,54,58,10,35,6,28,45,69,13,88,99,24,28,30,31,78,2,77,82,72</span></span><br><span class="line"><span class="comment">// 冒泡排序:1,2,6,10,13,24,28,28,30,31,35,45,54,58,68,69,72,72,75,77,78,82,88,95,99</span></span><br></pre></td></tr></table></figure><p> <strong>2.选择排序(SelctionSort)</strong></p><p>选择排序是一种比较简单直观的排序算法。它的算法思想是,从数组的开头开始遍历,将第一个元素和其他元素分别进行比较,记录最小的元素,等循环结束之后,将最小的元素放到数组的第一个位置上,然后从数组的第二个位置开始继续执行上述步骤。当进行到数组倒数第二个位置的时候,所有的数据就完成了排序。</p><p>选择排序同样会用到嵌套循环,外循环从数组第一个位置移到倒数第二个位置;内循环从第二个位置移动到数组最后一个位置,查找比当前外循环所指向的元素还要小的元素,每次内循环结束后,都会将最小的值放到合适的位置上。</p> <figure class="highlight fortran"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">//选择排序</span><br><span class="line"><span class="function"><span class="keyword">function</span></span> selectionSort( <span class="keyword">data</span> ) {</span><br><span class="line"> for( var i = <span class="number">0</span>; i< <span class="keyword">data</span>.length ; i++){</span><br><span class="line"> var <span class="built_in">min</span> = <span class="keyword">data</span>[i];</span><br><span class="line"> var temp;</span><br><span class="line"> var <span class="built_in">index</span> = i;</span><br><span class="line"> for( var j = i + <span class="number">1</span>; j< <span class="keyword">data</span>.length; j++){</span><br><span class="line"> <span class="keyword">if</span>( <span class="keyword">data</span>[j] < <span class="built_in">min</span> ){</span><br><span class="line"> <span class="built_in">min</span> = <span class="keyword">data</span>[j];</span><br><span class="line"> <span class="built_in">index</span> = j;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> temp = <span class="keyword">data</span>[i];</span><br><span class="line"> <span class="keyword">data</span>[i] = <span class="built_in">min</span>;</span><br><span class="line"> <span class="keyword">data</span>[<span class="built_in">index</span>]= temp;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">data</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>它的测试结果如下:</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log( '原始数据:' + dataStore )<span class="comment">;</span></span><br><span class="line">console.log( '选择排序:' + selectionSort( dataStore) )<span class="comment">;</span></span><br><span class="line"></span><br><span class="line">// 原始数据:<span class="number">72,1,68,95</span>,<span class="number">75,54,58,10</span>,<span class="number">35,6,28,45</span>,<span class="number">69,13,88,99</span>,<span class="number">24,28,30,31</span>,<span class="number">78,2,77,82</span>,<span class="number">72</span></span><br><span class="line">// 选择排序:<span class="number">1,2,6,10</span>,<span class="number">13,24,28,28</span>,<span class="number">30,31,35,45</span>,<span class="number">54,58,68,69</span>,<span class="number">72,72,75,77</span>,<span class="number">78,82,88,95</span>,<span class="number">99</span></span><br></pre></td></tr></table></figure><p> <strong>3.插入排序(insertionSort)</strong></p><p>插入排序有点类似人类按字母顺序对数据进行排序,就如同你打扑克牌一样,将摸来的扑克按大小放到合适的位置一样。它的原理就是通过嵌套循环,外循环将数组元素挨个移动,而内循环则对外循环中选中的元素及它后面的元素进行比较;如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动,为内循环中的这个元素腾出位置。</p><p>实现步骤如下:</p><ol><li>从第一个元素开始,该元素默认已经被排序</li><li>取出下一个元素,在已经排序的元素序列中从后向前扫描</li><li>如果该元素(已排序)大于新元素,将该元素移到下一位置</li><li>重复步骤3,直到找到已排序的元素小于或者等于新元素的位置</li><li>将新元素插入到该位置</li><li><p>重复步骤2~5,直到排序完成</p><p>具体实现代码如下:</p></li></ol><figure class="highlight kotlin"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//插入排序</span></span><br><span class="line"></span><br><span class="line">function insertionSort( <span class="keyword">data</span> ) {</span><br><span class="line"> <span class="keyword">var</span> len = <span class="keyword">data</span>.length;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < len; i++) {</span><br><span class="line"> <span class="keyword">var</span> key = <span class="keyword">data</span>[i];</span><br><span class="line"> <span class="keyword">var</span> j = i - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">while</span> ( j >= <span class="number">0</span> && <span class="keyword">data</span>[j] > key) {</span><br><span class="line"> <span class="keyword">data</span>[j + <span class="number">1</span>] = <span class="keyword">data</span>[j];</span><br><span class="line"> j--;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">data</span>[j + <span class="number">1</span>] = key;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">data</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>排序结果如下:</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log( '原始数据:' + dataStore )<span class="comment">;</span></span><br><span class="line">console.log( '插入排序:' + insertionSort( dataStore) )<span class="comment">;</span></span><br><span class="line"></span><br><span class="line">// 原始数据:<span class="number">72,1,68,95</span>,<span class="number">75,54,58,10</span>,<span class="number">35,6,28,45</span>,<span class="number">69,13,88,99</span>,<span class="number">24,28,30,31</span>,<span class="number">78,2,77,82</span>,<span class="number">72</span></span><br><span class="line">// 插入排序:<span class="number">1,2,6,10</span>,<span class="number">13,24,28,28</span>,<span class="number">30,31,35,45</span>,<span class="number">54,58,68,69</span>,<span class="number">72,72,75,77</span>,<span class="number">78,82,88,95</span>,<span class="number">99</span></span><br></pre></td></tr></table></figure><p> 我们已经学习了三种基本的排序算法,其中冒泡排序是最慢的,插入排序是最快的,我们可以在运行的过程中通过 console.time(‘sortName’) 和 console.timeEnd(‘sortName’) 两个输出来看他们的效率如何,我这里给出一组值作为参考,实际中需要大量的数据测试和反复实验,进行数理统计后才能被视为有效的统计;</p><p><img src="/images/2018-7-19/1.png" alt="排序时间比较"></p><h2 id="高级算法排序"><a href="#高级算法排序" class="headerlink" title="高级算法排序"></a>高级算法排序</h2><p><strong>4.希尔排序(Shell Sort)</strong></p><p>我们首先要学习的就是希尔排序,又称缩小增量排序,这个算法是在插入排序的基础上做了很大的改善,与插入排序不同的是,它首先会比较位置较远的元素,而非相邻的元素。这种方案可以使离正确位置很远的元素能够快速回到合适的位置,当算法进行遍历时,所有元素的间距会不断的减小,直到数据的末尾,此时比较的就是相邻元素了。</p><p>该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序。因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率上有较大提高。</p><p>好吧,我还是用个案例来解释,这样会更清晰,我们以下面一组数据为例:</p><p><img src="/images/2018-7-19/2.png" alt="数据集"></p><ul><li><p>第一次 gap(增量) = 10 / 2 = 5 , 会按照下面进行分组得到五组数据(49,13)、(38,27)、(65,49)、(97,55)、(26,4),这样进行组内排序之后(13,49)、(27,38)、(49,65)、(55,97)、(4,26) </p><p><img src="/images/2018-7-19/3.png" alt="第一次分组"></p></li></ul><p>此时,数据会排成如下结构</p><p><img src="/images/2018-7-19/4.png" alt="第一次排序"> </p><p> 第二次 gap = 5 / 2 = 2 , 此时可以得到两个分组,如下</p><p><img src="/images/2018-7-19/5.png" alt="第二次分组"></p><p>再通过组内排序之后,可以得到 </p><p> <img src="/images/2018-7-19/6.png" alt="第二次排序"> </p><ul><li>第三次 gap = 2 / 2 = 1 , 即不用分组,进行排序后</li></ul><p><img src="/images/2018-7-19/7.png" alt="第三次排序"></p><ul><li><p>第四次 gap = 1 / 2 = 0 ,即可得到排序完成的数组 </p><p><img src="/images/2018-7-19/8.png" alt="排序完成"> </p><p>现在,可能对希尔排序有了一定得了解了,用JS实现如下:</p></li></ul><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//希尔排序</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">shallSort</span><span class="params">(array)</span> </span>{</span><br><span class="line"> <span class="keyword">var</span> increment = <span class="keyword">array</span>.length;</span><br><span class="line"> <span class="keyword">var</span> i</span><br><span class="line"> <span class="keyword">var</span> temp; <span class="comment">//暂存</span></span><br><span class="line"> <span class="keyword">do</span> {</span><br><span class="line"> <span class="comment">//设置增量</span></span><br><span class="line"> increment = Math.floor(increment / <span class="number">3</span>) + <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span> (i = increment ; i < <span class="keyword">array</span>.length; i++) {</span><br><span class="line"> <span class="keyword">if</span> ( <span class="keyword">array</span>[i] < <span class="keyword">array</span>[i - increment]) {</span><br><span class="line"> temp = <span class="keyword">array</span>[i];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> j = i - increment; j >= <span class="number">0</span> && temp < <span class="keyword">array</span>[j]; j -= increment) {</span><br><span class="line"> <span class="keyword">array</span>[j + increment] = <span class="keyword">array</span>[j];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">array</span>[j + increment] = temp;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span> (increment > <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">array</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>效果如下:</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log( '原始数据:' + dataStore )<span class="comment">;</span></span><br><span class="line">console.log( '希尔排序:' + shallSort( dataStore) )<span class="comment">;</span></span><br><span class="line"></span><br><span class="line">// 原始数据:<span class="number">72,1,68,95</span>,<span class="number">75,54,58,10</span>,<span class="number">35,6,28,45</span>,<span class="number">69,13,88,99</span>,<span class="number">24,28,30,31</span>,<span class="number">78,2,77,82</span>,<span class="number">72</span></span><br><span class="line">// 希尔排序:<span class="number">1,2,6,10</span>,<span class="number">13,24,28,28</span>,<span class="number">30,31,35,45</span>,<span class="number">54,58,68,69</span>,<span class="number">72,72,75,77</span>,<span class="number">78,82,88,95</span>,<span class="number">99</span></span><br></pre></td></tr></table></figure><p><strong>5.归并排序(Merge Sort)</strong></p><p>将两个的有序数列合并成一个有序数列,我们称之为”归并”,归并排序的思想就是将一系列排序好的子序列合并成一个大的完整有序的序列。</p><p>实现步骤如下:</p><ol><li>把长度为n的输入序列分成两个长度为n/2的子序列;</li><li>对这两个子序列分别采用归并排序;</li><li><p>将两个排序好的子序列合并成一个最终的排序序列</p><p>具体的JS代码实现如下:</p></li></ol><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//归并排序</span></span><br><span class="line"></span><br><span class="line">function mergeSort ( array ) {</span><br><span class="line"> <span class="keyword">var</span> len = array.length;</span><br><span class="line"> <span class="keyword">if</span>( len < <span class="number">2</span> ){</span><br><span class="line"> <span class="keyword">return</span> array;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> middle = <span class="type">Math</span>.floor(len / <span class="number">2</span>),</span><br><span class="line"> <span class="keyword">left</span> = array.slice(<span class="number">0</span>, middle),</span><br><span class="line"> <span class="keyword">right</span> = array.slice(middle);</span><br><span class="line"> <span class="keyword">return</span> merge(mergeSort(<span class="keyword">left</span>), mergeSort(<span class="keyword">right</span>));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function merge(<span class="keyword">left</span>, <span class="keyword">right</span>)</span><br><span class="line">{</span><br><span class="line"> <span class="keyword">var</span> result = [];</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">left</span>.length && <span class="keyword">right</span>.length) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">left</span>[<span class="number">0</span>] <= <span class="keyword">right</span>[<span class="number">0</span>]) {</span><br><span class="line"> result.push(<span class="keyword">left</span>.shift());</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> result.push(<span class="keyword">right</span>.shift());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">left</span>.length)</span><br><span class="line"> result.push(<span class="keyword">left</span>.shift());</span><br><span class="line"> <span class="keyword">while</span> (<span class="keyword">right</span>.length)</span><br><span class="line"> result.push(<span class="keyword">right</span>.shift());</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>测试结果如下 :</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log( '原始数据:' + dataStore )<span class="comment">;</span></span><br><span class="line">console.log( '希尔排序:' + mergeSort( dataStore) )<span class="comment">;</span></span><br><span class="line"></span><br><span class="line">// 原始数据:<span class="number">72,1,68,95</span>,<span class="number">75,54,58,10</span>,<span class="number">35,6,28,45</span>,<span class="number">69,13,88,99</span>,<span class="number">24,28,30,31</span>,<span class="number">78,2,77,82</span>,<span class="number">72</span></span><br><span class="line">// 希尔排序:<span class="number">1,2,6,10</span>,<span class="number">13,24,28,28</span>,<span class="number">30,31,35,45</span>,<span class="number">54,58,68,69</span>,<span class="number">72,72,75,77</span>,<span class="number">78,82,88,95</span>,<span class="number">99</span></span><br></pre></td></tr></table></figure><p><strong>6.快速排序(Quicksort)</strong></p><p>快速排序是处理大数据最快的排序算法之一,它也是一种分而治之的算法,通过递归方式将数据依次分解为包含较小元素和较大元素的不同子序列,会不断重复这个步骤,直到所有的序列全部为有序的,最后将这些子序列一次拼接起来,就可得到排序好的数据。</p><p>该算法首先要从数列中选出一个元素作为基数(pivot)。接着所有的数据都将围绕这个基数进行,将小于改基数的元素放在它的左边,大于或等于它的数全部放在它的右边,对左右两个小数列重复上述步骤,直至各区间只有1个数。</p><p>整个排序过程如下:</p><p> <img src="/images/2018-7-19/9.png" alt="快速排序"></p><p>具体实现如下:</p><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//快速排序</span></span><br><span class="line"></span><br><span class="line">function <span class="built_in">quickSort</span>( arr ){</span><br><span class="line"> <span class="keyword">if</span> ( arr.length == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">left</span> = [];</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">right</span> = [];</span><br><span class="line"> <span class="keyword">var</span> pivot = arr[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i < arr.length; i++) {</span><br><span class="line"> <span class="keyword">if</span> (arr[i] < pivot) {</span><br><span class="line"> <span class="keyword">left</span>.push( arr[i] );</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">right</span>.push( arr[i] );</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">quickSort</span>( <span class="keyword">left</span> ).concat( pivot, <span class="built_in">quickSort</span>( <span class="keyword">right</span> ));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>测试结果如下:</p><figure class="highlight dns"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">console.log( '原始数据:' + dataStore )<span class="comment">;</span></span><br><span class="line">console.log( '快速排序:' + quickSort( dataStore) )<span class="comment">;</span></span><br><span class="line"></span><br><span class="line">// 原始数据:<span class="number">72,1,68,95</span>,<span class="number">75,54,58,10</span>,<span class="number">35,6,28,45</span>,<span class="number">69,13,88,99</span>,<span class="number">24,28,30,31</span>,<span class="number">78,2,77,82</span>,<span class="number">72</span></span><br><span class="line">// 快速排序:<span class="number">1,2,6,10</span>,<span class="number">13,24,28,28</span>,<span class="number">30,31,35,45</span>,<span class="number">54,58,68,69</span>,<span class="number">72,72,75,77</span>,<span class="number">78,82,88,95</span>,<span class="number">99</span></span><br></pre></td></tr></table></figure><p>至此,我们已基本介绍过一些常见的排序算法的思想和具体实现(基数排序在之前的文章已经介绍过,想要了解<a href="https://www.jianshu.com/p/1157aaccad36" target="_blank" rel="noopener">戳这里</a>),排序算法博大精深,我们不仅要学习理论,也要不断去实践,大家加油!</p><blockquote><p>作者:Cryptic</p><p>来源:稀土掘金</p></blockquote>]]></content>
<summary type="html">
<h2 id="排序算法(Sort)"><a href="#排序算法(Sort)" class="headerlink" title="排序算法(Sort)"></a>排序算法(Sort)</h2><h3 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h3><p>我们平时对计算机中存储的数据执行的两种最常见的操作就是排序和查找,对于计算机的排序和查找的研究,自计算机诞生以来就没有停止过。如今又是大数据,云计算的时代,对数据的排序和查找的速度、效率要求更高,因此要对排序和查找的算法进行专门的数据结构设计,以便让我们对数据的操作更加简洁高效。</p>
<p>这一篇我们将会介绍一些数据排序的基本算法和高级算法并利用JavaScript来逐一实现,让大伙对计算机中常见的排序算法的思想和实现有基本的了解,起到一个抛砖引玉的作用。</p>
</summary>
<category term="数据结构" scheme="https://jawn-ha.github.com/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>ES6 新特性总结(1)</title>
<link href="https://jawn-ha.github.com/2018/07/08/ES6-%E6%96%B0%E7%89%B9%E6%80%A7%E6%80%BB%E7%BB%93/"/>
<id>https://jawn-ha.github.com/2018/07/08/ES6-%E6%96%B0%E7%89%B9%E6%80%A7%E6%80%BB%E7%BB%93/</id>
<published>2018-07-08T21:59:51.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h3 id="1-新的声明方式"><a href="#1-新的声明方式" class="headerlink" title="1.新的声明方式"></a>1.新的声明方式</h3><p>ES6对声明的进行了扩展,现在可以有三种声明方式了。</p><p>字面理解ES6的三种声明方式:</p><ol><li>var:它是variable的简写,可以理解成变量的意思。</li><li>let:它在英文中是“让”的意思,也可以理解为一种声明的意思。</li><li>const:它在英文中也是常量的意思,在ES6也是用来声明常量的,常量你可以简单理解为不变的量。</li></ol><a id="more"></a><p>var在ES6里是用来升级全局变量的。let是局部变量声明,let声明只在区块内起作用,外部是不可以调用的。在程序开发中,有些变量是希望声明后在业务层就不再发生变化了,简单来说就是从声明开始,这个变量始终不变,就需要用const进行声明。</p><h3 id="2-解构赋值"><a href="#2-解构赋值" class="headerlink" title="2.解构赋值"></a>2.解构赋值</h3><p>ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。解构赋值在实际开发中可以大量减少我们的代码量,并且让我们的程序结构更清晰。</p><h4 id="2-1简单的数组解构"><a href="#2-1简单的数组解构" class="headerlink" title="2.1简单的数组解构"></a>2.1简单的数组解构</h4><p>以前,为变量赋值,我们只能直接指定值。比如下面的代码:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">let</span> b=<span class="number">1</span>;</span><br><span class="line"><span class="keyword">let</span> c=<span class="number">2</span>;</span><br></pre></td></tr></table></figure><p>而现在我们可以用数组解构的方式来进行赋值。</p><p><code>let [a,b,c]=[1,2,3];</code></p><p>上面的代码表示,可以从数组中提取值,按照位置的对象关系对变量赋值。</p><h4 id="2-2数组模式和赋值模式统一:"><a href="#2-2数组模式和赋值模式统一:" class="headerlink" title="2.2数组模式和赋值模式统一:"></a>2.2数组模式和赋值模式统一:</h4><p>可以简单的理解为等号左边和等号右边的形式要统一,如果不统一解构将失败。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> [a,[b,c],d]=[<span class="number">1</span>,[<span class="number">2</span>,<span class="number">3</span>],<span class="number">4</span>];</span><br></pre></td></tr></table></figure><p>如果等号两边形式不一样,很可能获得undefined或者直接报错。</p><h4 id="2-3-解构的默认值"><a href="#2-3-解构的默认值" class="headerlink" title="2.3 解构的默认值"></a>2.3 解构的默认值</h4><p>解构赋值是允许你使用默认值的,先看一个最简单的默认是的例子。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> [foo = <span class="literal">true</span>] =[];</span><br><span class="line"><span class="built_in">console</span>.log(foo); <span class="comment">//控制台打印出true</span></span><br></pre></td></tr></table></figure><p>我们来试试个多个值的数组,并给他一些默认值。</p><figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let [<span class="keyword">a</span>,b=<span class="string">"Jawnha"</span>]=[<span class="string">'单行道'</span>]</span><br><span class="line">console.<span class="built_in">log</span>(<span class="keyword">a</span>+b);<span class="comment"> //控制台显示“单行道Jawnha”</span></span><br></pre></td></tr></table></figure><p>现在我们对默认值有所了解,但仍需要注意的是<strong>undefined</strong>和<strong>null</strong>的区别。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> [a,b=<span class="string">"Jawnha"</span>]=[<span class="string">'单行道'</span>,<span class="literal">undefined</span>];</span><br><span class="line"><span class="built_in">console</span>.log(a+b); <span class="comment">//控制台显示“单行道Jawnha”</span></span><br></pre></td></tr></table></figure><p>undefined相当于什么都没有,b是默认值。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> [a,b=<span class="string">"Jawnha"</span>]=[<span class="string">'单行道'</span>,<span class="literal">null</span>];</span><br><span class="line"><span class="built_in">console</span>.log(a+b); <span class="comment">//控制台显示“Jawnhanull”</span></span><br></pre></td></tr></table></figure><p>null相当于有值,但值为null。所以b并没有取默认值,而是解构成了null。</p><h4 id="2-4对象的解构赋值"><a href="#2-4对象的解构赋值" class="headerlink" title="2.4对象的解构赋值"></a>2.4对象的解构赋值</h4><p><strong>注意:</strong>对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。</p><figure class="highlight gauss"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> {foo,<span class="built_in">bar</span>} = {foo:'Jawnha',<span class="built_in">bar</span>:'web'};</span><br><span class="line">console.log(foo+<span class="built_in">bar</span>); <span class="comment">//控制台打印出了“Jawnhaweb”</span></span><br></pre></td></tr></table></figure><h4 id="2-5圆括号的使用"><a href="#2-5圆括号的使用" class="headerlink" title="2.5圆括号的使用"></a>2.5圆括号的使用</h4><p>如果在解构之前就定义了变量,这时候你再解构会出现问题。下面是错误的代码,编译会报错。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> foo;</span><br><span class="line">{foo} ={<span class="attr">foo</span>:<span class="string">'Jawnha'</span>};</span><br><span class="line"><span class="built_in">console</span>.log(foo);</span><br></pre></td></tr></table></figure><p>要解决报错,使程序正常,我们这时候只要在解构的语句外边加一个圆括号就可以了。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> foo;</span><br><span class="line">({foo} ={<span class="attr">foo</span>:<span class="string">'Jawnha'</span>});</span><br><span class="line"><span class="built_in">console</span>.log(foo); <span class="comment">//控制台输出Jawnha</span></span><br></pre></td></tr></table></figure><h4 id="2-6字符串的解构"><a href="#2-6字符串的解构" class="headerlink" title="2.6字符串的解构"></a>2.6字符串的解构</h4><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [a,b,c,d,e,f]=<span class="string">"Jawnha"</span>;</span><br><span class="line">console.<span class="built_in">log</span>(a);</span><br><span class="line">console.<span class="built_in">log</span>(b);</span><br><span class="line">console.<span class="built_in">log</span>(c);</span><br><span class="line">console.<span class="built_in">log</span>(d);</span><br><span class="line">console.<span class="built_in">log</span>(e);</span><br><span class="line">console.<span class="built_in">log</span>(f);</span><br></pre></td></tr></table></figure><h3 id="3扩展运算符-amp-rest运算符"><a href="#3扩展运算符-amp-rest运算符" class="headerlink" title="3扩展运算符 & rest运算符"></a>3扩展运算符 & rest运算符</h3><p>展运算符和rest运算符,它们都是…(三个点)。它们可以很好的为我们解决参数和对象数组未知情况下的编程,让我们的代码更健壮和简洁。</p><h4 id="3-1对象扩展运算符-…"><a href="#3-1对象扩展运算符-…" class="headerlink" title="3.1对象扩展运算符(…)"></a>3.1对象扩展运算符(…)</h4><p>展运算符和rest运算符,它们都是…(三个点)。它们可以很好的为我们解决参数和对象数组未知情况下的编程,让我们的代码更健壮和简洁。</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">jawnha</span><span class="params">(<span class="rest_arg">...arg</span>)</span></span>{</span><br><span class="line"> console.log(arg[<span class="number">0</span>]);</span><br><span class="line"> console.log(arg[<span class="number">1</span>]);</span><br><span class="line"> console.log(arg[<span class="number">2</span>]);</span><br><span class="line"> console.log(arg[<span class="number">3</span>]);</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line">jawnha(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>);</span><br></pre></td></tr></table></figure><p>这时我们看到控制台输出了 1,2,3,undefined,这说明是可以传入多个值,并且就算方法中引用多了也不会报错。</p><p><strong>扩展运算符的用处:</strong></p><p>我们先用一个例子说明,我们声明两个数组arr1和arr2,然后我们把arr1赋值给arr2,然后我们改变arr2的值,你会发现arr1的值也改变了,因为我们这是对内存堆栈的引用,而不是真正的赋值。</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">let arr1=[<span class="string">'jawnha'</span>,<span class="string">'github'</span>,<span class="string">'io'</span>];</span><br><span class="line">let arr2=arr1;</span><br><span class="line">console.log(arr2);</span><br><span class="line">arr2.push(<span class="string">'web'</span>);</span><br><span class="line">console.log(arr1);</span><br><span class="line"><span class="regexp">//</span>输出</span><br><span class="line"><span class="regexp">//</span>[<span class="string">"jawnha"</span>,<span class="string">"github"</span>,<span class="string">"io"</span>]</span><br><span class="line"><span class="regexp">//</span>[<span class="string">"jawnha"</span>,<span class="string">"github"</span>,<span class="string">"io"</span>,<span class="string">"web"</span>]</span><br></pre></td></tr></table></figure><p>这是我们不想看到的,可以利用对象扩展运算符简单的解决这个问题,现在我们对代码进行改造。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr1=[<span class="string">'jawnha'</span>,<span class="string">'github'</span>,<span class="string">'io'</span>];</span><br><span class="line"><span class="comment">//let arr2=arr1;</span></span><br><span class="line"><span class="keyword">let</span> arr2=[...arr1];</span><br><span class="line"><span class="built_in">console</span>.log(arr2);</span><br><span class="line">arr2.push(<span class="string">'web'</span>);</span><br><span class="line"><span class="built_in">console</span>.log(arr1);</span><br></pre></td></tr></table></figure><p>现在控制台预览时,你可以看到我们的arr1并没有改变,简单的扩展运算符就解决了这个问题。</p><h4 id="3-2-rest运算符"><a href="#3-2-rest运算符" class="headerlink" title="3.2 rest运算符"></a>3.2 rest运算符</h4><p>rest运算符和扩展运算符有很多呢相似之处,甚至很多时候你不用特意去区分。它也用…(三个点)来表示,我们先来看一个例子。</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">func</span><span class="params">(first,<span class="rest_arg">...arg</span>)</span></span>{</span><br><span class="line"> console.log(arg.length);</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">func(<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>);</span><br></pre></td></tr></table></figure><p>这时候控制台打印出了7,说明我们arg里有7个数组元素,这就是rest运算符的最简单用法。</p><p>如何循环输出rest运算符</p><p>这里我们用for…of循环来进行打印出arg的值</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">func</span>(<span class="params">first,...arg</span>)</span>{</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> val <span class="keyword">of</span> arg){</span><br><span class="line"> <span class="built_in">console</span>.log(val);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">func(<span class="number">0</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>,<span class="number">7</span>);</span><br></pre></td></tr></table></figure><h3 id="4字符串模板"><a href="#4字符串模板" class="headerlink" title="4字符串模板"></a>4字符串模板</h3><p>ES6对字符串新增的操作,最重要的就是字符串模版,字符串模版的出现让我们再也不用拼接变量了,而且支持在模板里有简单计算操作。</p><h4 id="4-1字符串模版"><a href="#4-1字符串模版" class="headerlink" title="4.1字符串模版"></a>4.1字符串模版</h4><p>先来看一个在ES5下我们的字符串拼接案例:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> jawnha=<span class="string">'jawnha'</span>;</span><br><span class="line"><span class="keyword">let</span> welcome = <span class="string">'非常高兴你能看我博客,我是'</span>+jawnha+<span class="string">'。'</span>;</span><br><span class="line"><span class="built_in">document</span>.write(welcome);</span><br></pre></td></tr></table></figure><p>ES5下必须用<strong>+jawnha+</strong>这样的形式进行拼接,这样很麻烦而且很容易出错。ES6新增了字符串模版,可以很好的解决这个问题。字符串模版不再使用<strong>‘xxx’</strong>这样的单引号,而是换成了连接号。这时我们再引用jspang变量就需要用${jspang}这种形式了,我们对上边的代码进行改造。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> jawnha=<span class="string">'jawnha'</span>;</span><br><span class="line"><span class="keyword">let</span> welcome = <span class="string">`非常高兴你能看我博客,我是<span class="subst">${jawnha}</span>。`</span>;</span><br><span class="line"><span class="built_in">document</span>.write(welcome);</span><br></pre></td></tr></table></figure><p>可以看到浏览器出现了和上边代码一样的结果。而且这里边支持<strong>html标签和运算符</strong>可以试着输入一些。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> jawnha=<span class="string">'jawnha'</span>;</span><br><span class="line"><span class="keyword">let</span> a=<span class="number">10</span>;</span><br><span class="line"><span class="keyword">let</span> b=<span class="number">11</span>;</span><br><span class="line"><span class="keyword">let</span> welcome = <span class="string">`<b>非常高兴你能看我博客</b>,<br/>我是<span class="subst">${jawnha}</span>。我今年<span class="subst">${a+b}</span>岁`</span>;</span><br><span class="line"><span class="built_in">document</span>.write(welcome);</span><br></pre></td></tr></table></figure><h4 id="4-2字符串查找"><a href="#4-2字符串查找" class="headerlink" title="4.2字符串查找"></a>4.2字符串查找</h4><p>ES6还增加了字符串的查找功能,而且支持中文。</p><p><strong>查找是否存在:</strong></p><p>先来看一下ES5的写法,其实这种方法并不实用,给我们的索引位置,我们自己还要确定位置。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> blog=<span class="string">'博客'</span>;</span><br><span class="line"><span class="keyword">let</span> welcome= <span class="string">'非常高兴你能看我博客,我是jawnha。'</span>;</span><br><span class="line"><span class="built_in">document</span>.write(welcome.indexOf(blog));</span><br></pre></td></tr></table></figure><p>上述代码会返回一个索引值</p><p>ES6直接用includes就可以判断,不再返回索引值,这样的结果我们更喜欢,更直接。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> blog=<span class="string">'博客'</span>;</span><br><span class="line"><span class="keyword">let</span> welcome= <span class="string">'非常高兴你能看我博客,我是jawnha。'</span>;</span><br><span class="line"><span class="built_in">document</span>.write(welcome.includes(blog));</span><br></pre></td></tr></table></figure><p><strong>判断开头是否存在:</strong></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">blog.startsWith(jspang);</span><br></pre></td></tr></table></figure><p><strong>判断结尾是否存在:</strong></p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">blog.ends<span class="constructor">With(<span class="params">jspang</span>)</span>;</span><br></pre></td></tr></table></figure><p>需要注意的是:starts和ends 后边都要加s,我开始时经常写错,希望小伙伴们不要采坑。</p><h4 id="4-3复制字符串"><a href="#4-3复制字符串" class="headerlink" title="4.3复制字符串"></a>4.3复制字符串</h4><p>我们有时候是需要字符串重复的,比如分隔符和特殊符号,这时候复制字符串就派上用场了,语法很简单。</p><figure class="highlight delphi"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">document.<span class="keyword">write</span>(<span class="string">'jawnha|'</span>.<span class="keyword">repeat</span>(<span class="number">3</span>));</span><br></pre></td></tr></table></figure><p>当然ES6对字符串还有一些其它操作,这里就不作太多的介绍了。</p><h3 id="5-ES6数字操作"><a href="#5-ES6数字操作" class="headerlink" title="5 ES6数字操作"></a>5 ES6数字操作</h3><h4 id="5-1数字判断和转换"><a href="#5-1数字判断和转换" class="headerlink" title="5.1数字判断和转换"></a>5.1数字判断和转换</h4><p><strong>数字验证Number.isFinite( xx )</strong></p><p>可以使用Number.isFinite( )来进行数字验证,只要是数字,不论是浮点型还是整形都会返回true,其他时候会返回false。</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a= <span class="number">11</span>/<span class="number">4</span>;</span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">Finite(<span class="params">a</span>)</span>);<span class="comment">//true</span></span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">Finite('<span class="params">jspang</span>')</span>);<span class="comment">//false</span></span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">Finite(NaN)</span>);<span class="comment">//false</span></span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">Finite(<span class="params">undefined</span>)</span>);<span class="comment">//false</span></span><br></pre></td></tr></table></figure><p><strong>NaN验证</strong></p><p>NaN是特殊的非数字,可以使用Number.isNaN()来进行验证。下边的代码控制台返回了true。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Number</span>.isNaN(<span class="literal">NaN</span>));</span><br></pre></td></tr></table></figure><p><strong>判断是否为整数Number.isInteger(xx)</strong></p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a=<span class="number">123.1</span>;</span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">Integer(<span class="params">a</span>)</span>); <span class="comment">//false</span></span><br></pre></td></tr></table></figure><p><strong>整数转换Number.parseInt(xxx)和浮点型转换Number.parseFloat(xxx)</strong></p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a='<span class="number">9.18</span>';</span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>parse<span class="constructor">Int(<span class="params">a</span>)</span>); </span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>parse<span class="constructor">Float(<span class="params">a</span>)</span>);</span><br></pre></td></tr></table></figure><h4 id="5-2整数取值范围操作"><a href="#5-2整数取值范围操作" class="headerlink" title="5.2整数取值范围操作"></a>5.2整数取值范围操作</h4><p>整数的操作是有一个取值范围的,它的取值范围就是2的53次方。我们先用程序来看一下这个数字是什么.</p><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let a = Math.pow(<span class="number">2</span>,<span class="number">53</span>)<span class="number">-1</span>;</span><br><span class="line">console.log(a); <span class="comment">//9007199254740991</span></span><br></pre></td></tr></table></figure><p>在我们计算时会经常超出这个值,所以我们要进行判断,ES6提供了一个常数,叫做最大安全整数,以后就不需要我们计算了。</p><p><strong>最大安全整数</strong></p><figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.<span class="built_in">log</span>(<span class="built_in">Number</span>.MAX_SAFE_INTEGER)<span class="comment">;</span></span><br></pre></td></tr></table></figure><p><strong>最小安全整数</strong></p><figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.<span class="built_in">log</span>(<span class="built_in">Number</span>.MIN_SAFE_INTEGER)<span class="comment">;</span></span><br></pre></td></tr></table></figure><p><strong>安全整数判断isSafeInteger( )</strong></p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a= <span class="module-access"><span class="module"><span class="identifier">Math</span>.</span></span>pow(<span class="number">2</span>,<span class="number">53</span>)-<span class="number">1</span>;</span><br><span class="line">console.log(<span class="module-access"><span class="module"><span class="identifier">Number</span>.</span></span>is<span class="constructor">SafeInteger(<span class="params">a</span>)</span>);<span class="comment">//false</span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="1-新的声明方式"><a href="#1-新的声明方式" class="headerlink" title="1.新的声明方式"></a>1.新的声明方式</h3><p>ES6对声明的进行了扩展,现在可以有三种声明方式了。</p>
<p>字面理解ES6的三种声明方式:</p>
<ol>
<li>var:它是variable的简写,可以理解成变量的意思。</li>
<li>let:它在英文中是“让”的意思,也可以理解为一种声明的意思。</li>
<li>const:它在英文中也是常量的意思,在ES6也是用来声明常量的,常量你可以简单理解为不变的量。</li>
</ol>
</summary>
<category term="ES6" scheme="https://jawn-ha.github.com/tags/ES6/"/>
</entry>
<entry>
<title>JS数据结构之链表</title>
<link href="https://jawn-ha.github.com/2018/07/07/JS%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B9%8B%E9%93%BE%E8%A1%A8/"/>
<id>https://jawn-ha.github.com/2018/07/07/JS%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B9%8B%E9%93%BE%E8%A1%A8/</id>
<published>2018-07-07T23:07:37.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h3 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h3><p>在很多编程语言中,数组的长度都是固定的,如果数组已被数据填满,再要加入新的元素是非常困难的。而且,对于数组的删除和添加操作,通常需要将数组中的其他元素向前或者向后平移,这些操作也是十分繁琐的。</p><p>然而,JS中数组却不存在上述问题,主要是因为他们被实现了成了对象,但是与其他语言相比(比如C或Java),那么它的效率会低很多。</p><a id="more"></a><p>这时候,我们可以考虑使用链表(Linked-list) 来替代它,除了对数据的随机访问,链表几乎可以在任何可以使用一维数组的情况中。如果你正巧在使用C或者Java等高级语言,你会发现链表的表现要优于数组很多。</p><p>链表其实有许多的种类:单向链表、双向链表、单向循环链表和双向循环链表,接下来,我们基于对象来实现一个单向链表,因为它的使用最为广泛。</p><h3 id="链表的定义"><a href="#链表的定义" class="headerlink" title="链表的定义"></a>链表的定义</h3><p><img src="/images/2018-7-7/1.png" alt="链表结构图"></p><p>向链表中<strong>插入一个节点</strong>的效率很高,需要修改它前面的节点(前驱),使其指向新加入的节点,而将新节点指向原来前驱节点指向的节点即可。下面我将用图片演示如何在 data2 节点 后面插入 data4 节点。</p><p><img src="/images/2018-7-7/2.png" alt></p><p> 同样,从链表中删除一个节点,也很简单。只需将待删节点的前驱节点指向待删节点的,同时将待删节点指向null,那么节点就删除成功了。下面我们用图片演示如何从链表中删除 data4 节点。</p><p> <img src="/images/2018-7-7/3.png" alt="删除节点"></p><h3 id="链表的设计"><a href="#链表的设计" class="headerlink" title="链表的设计"></a>链表的设计</h3><p>我们设计链表包含两个类,一个是 Node 类用来表示节点,另一个事 LinkedList 类提供插入节点、删除节点等一些操作。</p><p><strong>Node类</strong></p><p>Node类包含连个属性: element 用来保存节点上的数据,next 用来保存指向下一个节点的链接,具体实现如下:</p> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//节点</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Node</span>(<span class="params">element</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.element = element; <span class="comment">//当前节点的元素</span></span><br><span class="line"> <span class="keyword">this</span>.next = <span class="literal">null</span>; <span class="comment">//下一个节点链接</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p><strong>LinkedList类</strong></p><p>LinkedList类提供了对链表进行操作的方法,包括插入删除节点,查找给定的值等。值得注意的是,它只有一个<br>属性,那就是使用一个 Node 对象来保存该链表的头节点。</p><p>它的构造函数的实现如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//链表类</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">LList</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.head = <span class="keyword">new</span> Node( <span class="string">'head'</span> ); <span class="comment">//头节点</span></span><br><span class="line"> <span class="keyword">this</span>.find = find; <span class="comment">//查找节点</span></span><br><span class="line"> <span class="keyword">this</span>.insert = insert; <span class="comment">//插入节点</span></span><br><span class="line"> <span class="keyword">this</span>.remove = remove; <span class="comment">//删除节点</span></span><br><span class="line"> <span class="keyword">this</span>.findPrev = findPrev; <span class="comment">//查找前一个节点</span></span><br><span class="line"> <span class="keyword">this</span>.display = display; <span class="comment">//显示链表</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>head节点的next属性初始化为 null ,当有新元素插入时,next会指向新的元素。</p><p>接下来,我们来看看具体方法的实现。</p><p><strong>insert:向链表插入一个节点</strong></p><p>我们先分析分析insert方法,想要插入一个节点,我们必须明确要在哪个节点的前面或后面插入。我们先来看看,如何在一个已知节点的后面插入一个节点。</p><p>在一个已知节点后插入新节点,我们首先得找到该节点,为此,我们需要一个 find 方法用来遍历链表,查找给定的数据。如果找到,该方法就返回保存该数据的节点。那么,我们先实现 find 方法。</p><p><strong>find:查找给定节点</strong></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//查找给定节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">find</span> (<span class="params"> item </span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( currNode.element != item ){</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> currNode;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> find 方法同时展示了如何在链表上移动。首先,创建一个新节点,将链表的头节点赋给这个新创建的节点,然后在链表上循环,如果当前节点的 element 属性和我们要找的信息不符,就将当前节点移动到下一个节点,如果查找成功,该方法返回包含该数据的节点;否则,就会返回null。</p><p>一旦找到了节点,我们就可以将新的节点插入到链表中了,将新节点的 next 属性设置为后面节点的 next 属性对应的值,然后设置后面节点的 next 属性指向新的节点,具体实现如下:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//插入节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">insert</span> (<span class="params"> newElement , item </span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> newNode = <span class="keyword">new</span> Node( newElement );</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.find( item );</span><br><span class="line"> newNode.next = currNode.next;</span><br><span class="line"> currNode.next = newNode;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p> 现在我们可以测试我们的链表了。等等,我们先来定义一个 display 方法显示链表的元素,不然我们怎么知道对不对呢?</p><p><strong>display:显示链表</strong></p> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//显示链表元素</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">display</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( !(currNode.next == <span class="literal">null</span>) ){</span><br><span class="line"> <span class="built_in">console</span>.log( currNode.next.element );</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>实现原理同上,将头节点赋给一个新的变量,然后循环链表,直到当前节点的 next 属性为 null 时停止循环,我们循环过程中将每个节点的数据打印出来就好了。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> fruits = <span class="keyword">new</span> LList();</span><br><span class="line"></span><br><span class="line">fruits.insert(<span class="string">'Apple'</span> , <span class="string">'head'</span>);</span><br><span class="line">fruits.insert(<span class="string">'Banana'</span> , <span class="string">'Apple'</span>);</span><br><span class="line">fruits.insert(<span class="string">'Pear'</span> , <span class="string">'Banana'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(fruits.display()); <span class="comment">// Apple</span></span><br><span class="line"> <span class="comment">// Banana</span></span><br><span class="line"> <span class="comment">// Pear</span></span><br></pre></td></tr></table></figure><p><strong>remove:从链表中删除一个节点</strong></p><p>从链表中删除节点时,我们先要找个待删除节点的前一个节点,找到后,我们修改它的 next 属性,使其不在指向待删除的节点,而是待删除节点的下一个节点。那么,我们就得需要定义一个 findPrevious 方法遍历链表,检查每一个节点的下一个节点是否存储待删除的数据。如果找到,返回该节点,这样就可以修改它的 next 属性了。 findPrevious 的实现如下:</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//查找带删除节点的前一个节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">findPrev</span><span class="params">( item )</span> </span>{</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="keyword">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( !( currNode.next == <span class="literal">null</span>) && ( currNode.next.element != item )){</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> currNode;</span><br><span class="line">}。</span><br></pre></td></tr></table></figure><p>这样,remove 方法的实现也就迎刃而解了</p> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//删除节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">remove</span> (<span class="params"> item </span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> prevNode = <span class="keyword">this</span>.findPrev( item );</span><br><span class="line"> <span class="keyword">if</span>( !( prevNode.next == <span class="literal">null</span> ) ){</span><br><span class="line"> prevNode.next = prevNode.next.next;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>我们接着写一段测试程序,测试一下 remove 方法:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 接着上面的代码,我们再添加一个水果</span></span><br><span class="line"></span><br><span class="line">fruits.insert(<span class="string">'Grape'</span> , <span class="string">'Pear'</span>);</span><br><span class="line"><span class="built_in">console</span>.log(fruits.display()); <span class="comment">// Apple</span></span><br><span class="line"> <span class="comment">// Banana</span></span><br><span class="line"> <span class="comment">// Pear</span></span><br><span class="line"> <span class="comment">// Grape</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 我们把香蕉吃掉</span></span><br><span class="line"></span><br><span class="line">fruits.remove(<span class="string">'Banana'</span>);</span><br><span class="line"><span class="built_in">console</span>.log(fruits.display()); <span class="comment">// Apple</span></span><br><span class="line"> <span class="comment">// Pear</span></span><br><span class="line"> <span class="comment">// Grape</span></span><br></pre></td></tr></table></figure><p>Great!成功了,现在你已经可以实现一个基本的单向链表了。</p><h3 id="双向链表"><a href="#双向链表" class="headerlink" title="双向链表"></a>双向链表</h3><p>尽管从链表的头节点遍历链表很简单,但是反过来,从后向前遍历却不容易。我们可以通过给Node类增加一个previous属性,让其指向前驱节点的链接,这样就形成了双向链表,如下图:</p><p><img src="/images/2018-7-7/4.png" alt="双向路链表"></p><h3 id="双向链表的实现"><a href="#双向链表的实现" class="headerlink" title="双向链表的实现"></a>双向链表的实现</h3><p>要实现双向链表,首先需要给 Node 类增加一个 previous 属性:</p><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//节点类</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Node</span><span class="params">(element)</span> </span>{</span><br><span class="line"> <span class="keyword">this</span>.element = element; <span class="comment">//当前节点的元素</span></span><br><span class="line"> <span class="keyword">this</span>.next = <span class="literal">null</span>; <span class="comment">//下一个节点链接</span></span><br><span class="line"> <span class="keyword">this</span>.previous = <span class="literal">null</span>; <span class="comment">//上一个节点链接</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>双向链表的 insert 方法与单链表相似,但需要设置新节点的 previous 属性,使其指向该节点的前驱,定义如下:</p><figure class="highlight haxe"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//插入节点</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">insert</span> </span>( <span class="keyword">new</span><span class="type">Element</span> , item ) {</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">new</span><span class="type">Node</span> = <span class="keyword">new</span> <span class="type">Node</span>( <span class="keyword">new</span><span class="type">Element</span> );</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.find( item );</span><br><span class="line"> <span class="keyword">new</span><span class="type">Node</span>.next = currNode.next;</span><br><span class="line"> <span class="keyword">new</span><span class="type">Node</span>.previous = currNode;</span><br><span class="line"> currNode.next = <span class="keyword">new</span><span class="type">Node</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>双向链表的删除 remove 方法比单链表效率高,不需要查找前驱节点,只要找出待删除节点,然后将该节点的前驱 next 属性指向待删除节点的后继,设置该节点后继 previous 属性,指向待删除节点的前驱即可。定义如下:</p><figure class="highlight gradle"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//删除节点</span></span><br><span class="line"></span><br><span class="line">function remove ( item ) {</span><br><span class="line"> var currNode = <span class="keyword">this</span>.<span class="keyword">find</span> ( item );</span><br><span class="line"> <span class="keyword">if</span>( !( currNode.<span class="keyword">next</span> == <span class="keyword">null</span> ) ){</span><br><span class="line"> currNode.<span class="keyword">previous</span>.<span class="keyword">next</span> = currNode.<span class="keyword">next</span>;</span><br><span class="line"> currNode.<span class="keyword">next</span>.<span class="keyword">previous</span> = currNode.<span class="keyword">previous</span>;</span><br><span class="line"> currNode.<span class="keyword">next</span> = <span class="keyword">null</span>;</span><br><span class="line"> currNode.<span class="keyword">previous</span> = <span class="keyword">null</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>还有一些反向显示链表 dispReverse,查找链表最后一个元素 findLast 等方法,相信你已经有了思路,这里我给出一个基本双向链表的完成代码,供大家参考。</p><figure class="highlight haxe"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">//节点</span></span><br><span class="line"> </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Node</span></span>(element) {</span><br><span class="line"> <span class="built_in">this</span>.element = element; <span class="comment">//当前节点的元素</span></span><br><span class="line"> <span class="built_in">this</span>.next = <span class="literal">null</span>; <span class="comment">//下一个节点链接</span></span><br><span class="line"> <span class="built_in">this</span>.previous = <span class="literal">null</span>; <span class="comment">//上一个节点链接</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//链表类</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">LList</span> </span>() {</span><br><span class="line"> <span class="built_in">this</span>.head = <span class="keyword">new</span> <span class="type">Node</span>( <span class="string">'head'</span> );</span><br><span class="line"> <span class="built_in">this</span>.find = find;</span><br><span class="line"> <span class="built_in">this</span>.findLast = findLast;</span><br><span class="line"> <span class="built_in">this</span>.insert = insert;</span><br><span class="line"> <span class="built_in">this</span>.remove = remove;</span><br><span class="line"> <span class="built_in">this</span>.display = display;</span><br><span class="line"> <span class="built_in">this</span>.dispReverse = dispReverse;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//查找元素</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">find</span> </span>( item ) {</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( currNode.element != item ){</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> currNode;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//查找链表中的最后一个元素</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">findLast</span> </span>() {</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( !( currNode.next == <span class="literal">null</span> )){</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> currNode;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//插入节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">insert</span> </span>( <span class="keyword">new</span><span class="type">Element</span> , item ) {</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">new</span><span class="type">Node</span> = <span class="keyword">new</span> <span class="type">Node</span>( <span class="keyword">new</span><span class="type">Element</span> );</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.find( item );</span><br><span class="line"> <span class="keyword">new</span><span class="type">Node</span>.next = currNode.next;</span><br><span class="line"> <span class="keyword">new</span><span class="type">Node</span>.previous = currNode;</span><br><span class="line"> currNode.next = <span class="keyword">new</span><span class="type">Node</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//显示链表元素</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">display</span> </span>() {</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.head;</span><br><span class="line"> <span class="keyword">while</span> ( !(currNode.next == <span class="literal">null</span>) ){</span><br><span class="line"> console.debug( currNode.next.element );</span><br><span class="line"> currNode = currNode.next;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//反向显示链表元素</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">dispReverse</span> </span>() {</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.findLast();</span><br><span class="line"> <span class="keyword">while</span> ( !( currNode.previous == <span class="literal">null</span> )){</span><br><span class="line"> console.log( currNode.element );</span><br><span class="line"> currNode = currNode.previous;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//删除节点</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">remove</span> </span>( item ) {</span><br><span class="line"> <span class="keyword">var</span> currNode = <span class="built_in">this</span>.find ( item );</span><br><span class="line"> <span class="keyword">if</span>( !( currNode.next == <span class="literal">null</span> ) ){</span><br><span class="line"> currNode.previous.next = currNode.next;</span><br><span class="line"> currNode.next.previous = currNode.previous;</span><br><span class="line"> currNode.next = <span class="literal">null</span>;</span><br><span class="line"> currNode.previous = <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> fruits = <span class="keyword">new</span> <span class="type">LList</span>();</span><br><span class="line"></span><br><span class="line">fruits.insert(<span class="string">'Apple'</span> , <span class="string">'head'</span>);</span><br><span class="line">fruits.insert(<span class="string">'Banana'</span> , <span class="string">'Apple'</span>);</span><br><span class="line">fruits.insert(<span class="string">'Pear'</span> , <span class="string">'Banana'</span>);</span><br><span class="line">fruits.insert(<span class="string">'Grape'</span> , <span class="string">'Pear'</span>);</span><br><span class="line"></span><br><span class="line">console.log( fruits.display() ); <span class="comment">// Apple</span></span><br><span class="line"> <span class="comment">// Banana</span></span><br><span class="line"> <span class="comment">// Pear</span></span><br><span class="line"> <span class="comment">// Grape</span></span><br><span class="line"> </span><br><span class="line">console.log( fruits.dispReverse() ); <span class="comment">// Grape</span></span><br><span class="line"> <span class="comment">// Pear</span></span><br><span class="line"> <span class="comment">// Banana</span></span><br><span class="line"> <span class="comment">// Apple</span></span><br></pre></td></tr></table></figure><h2 id="循环链表"><a href="#循环链表" class="headerlink" title="循环链表"></a>循环链表</h2><p>循环链表和单链表相似,节点类型都是一样,唯一的区别是,在创建循环链表的时候,让其头节点的 next 属性执行它本身,即</p><figure class="highlight xquery"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">head.<span class="keyword">next</span> =<span class="built_in"> head</span>;</span><br></pre></td></tr></table></figure><p>这种行为会导致链表中每个节点的 next 属性都指向链表的头节点,换句话说,也就是链表的尾节点指向了头节点,形成了一个循环链表,如下图所示:</p><p> <img src="/images/2018-7-7/5.png" alt="循环链表"></p><p>原理相信你已经懂了,循环链表这里就不贴代码了,相信你自己能独立完成!</p><p>至此,我们对链表有了比较深刻的认识,如果想让我们的链表更加健全,我们还可发挥自己的思维,给链表添加比如向前移动几个节点,向后移动几个节点,显示当前节点等方法,大家一起加油! </p><blockquote><p>作者:<a href="https://www.jianshu.com/u/4d7dd4c7e51d" target="_blank" rel="noopener">Cryptic</a></p><p>转载自掘金社区</p></blockquote>]]></content>
<summary type="html">
<h3 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h3><p>在很多编程语言中,数组的长度都是固定的,如果数组已被数据填满,再要加入新的元素是非常困难的。而且,对于数组的删除和添加操作,通常需要将数组中的其他元素向前或者向后平移,这些操作也是十分繁琐的。</p>
<p>然而,JS中数组却不存在上述问题,主要是因为他们被实现了成了对象,但是与其他语言相比(比如C或Java),那么它的效率会低很多。</p>
</summary>
<category term="数据结构" scheme="https://jawn-ha.github.com/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/"/>
</entry>
<entry>
<title>Vue指令</title>
<link href="https://jawn-ha.github.com/2018/07/05/Vue%E6%8C%87%E4%BB%A4/"/>
<id>https://jawn-ha.github.com/2018/07/05/Vue%E6%8C%87%E4%BB%A4/</id>
<published>2018-07-05T22:08:23.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<h3 id="常用指令列表"><a href="#常用指令列表" class="headerlink" title="常用指令列表"></a>常用指令列表</h3><blockquote><ol><li>v-model</li><li>v-if</li><li>v-else</li><li>v-show</li><li>v-for</li><li>v-bind —— 可简写为 :class=”qq”</li><li>v-on —— 可简写为:@click=”qq”</li><li>v-text & v-html</li><li>v-pre & v-cloak</li><li>v-once</li></ol></blockquote><a id="more"></a><h2 id="v-model-双向绑定"><a href="#v-model-双向绑定" class="headerlink" title="v-model 双向绑定"></a>v-model 双向绑定</h2><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"message"</span> /></span></span></span><br><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span>></span> </span><span class="template-variable">{{ message }}</span><span class="xml"> <span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><h2 id="v-if-条件渲染,根据表达式的真假来删除和插入元素"><a href="#v-if-条件渲染,根据表达式的真假来删除和插入元素" class="headerlink" title="v-if 条件渲染,根据表达式的真假来删除和插入元素"></a>v-if 条件渲染,根据表达式的真假来删除和插入元素</h2><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><<span class="keyword">div</span> v-<span class="keyword">if</span>=<span class="string">"true"</span>>当表达式为<span class="literal">true</span>,插入该条数据</<span class="keyword">div</span>></span><br><span class="line"><<span class="keyword">div</span> v-<span class="keyword">if</span>=<span class="string">"false"</span>>当表达式为flase,删除该条数据</<span class="keyword">div</span>></span><br><span class="line"><<span class="keyword">div</span> v-<span class="keyword">if</span>=<span class="string">"age > 25"</span>>当表达式为<span class="literal">true</span>,插入该条数据</<span class="keyword">div</span>></span><br></pre></td></tr></table></figure><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><div></span><br><span class="line"><<span class="selector-tag">p</span> v-<span class="keyword">if</span>=<span class="string">"a>18"</span>>年龄:{{ data<span class="selector-class">.age</span> }}</p></span><br><span class="line"><<span class="selector-tag">p</span> v-<span class="keyword">else</span>>年龄:属于未成年</p></span><br><span class="line"></div></span><br></pre></td></tr></table></figure><blockquote><h4 id="v-if-和v-show的区别:"><a href="#v-if-和v-show的区别:" class="headerlink" title="v-if 和v-show的区别:"></a>v-if 和v-show的区别:</h4><ul><li><p>v-if: 判断是否加载,可以减轻服务器的压力,在需要时加载。</p></li><li><p>v-show:调整css dispaly属性,可以使客户端操作更加流畅。v-else 紧跟着v-if,添加一个else块,否则将不会被识别</p></li></ul></blockquote><h2 id="v-show-条件渲染,元素会始终渲染到HTML"><a href="#v-show-条件渲染,元素会始终渲染到HTML" class="headerlink" title="v-show 条件渲染,元素会始终渲染到HTML"></a>v-show 条件渲染,元素会始终渲染到HTML</h2><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><<span class="keyword">div</span> v-show=<span class="string">"true"</span>>当表达式为<span class="literal">true</span>,显示该条数据</<span class="keyword">div</span>></span><br><span class="line"><<span class="keyword">div</span> v-show=<span class="string">"false"</span>>当表达式为<span class="literal">false</span>,隐藏该条数据</<span class="keyword">div</span>></span><br><span class="line"><<span class="keyword">div</span> v-show=<span class="string">"a > 18"</span>>当表达式为<span class="literal">true</span>,显示该条数据</<span class="keyword">div</span>></span><br></pre></td></tr></table></figure><h3 id="v-for指令基于一个数组渲染一个列表"><a href="#v-for指令基于一个数组渲染一个列表" class="headerlink" title="v-for指令基于一个数组渲染一个列表"></a>v-for指令基于一个数组渲染一个列表</h3><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">table</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"><<span class="name">tr</span>></span><span class="tag"><<span class="name">td</span>></span>姓名<span class="tag"></<span class="name">td</span>></span><span class="tag"><<span class="name">td</span>></span>年龄<span class="tag"></<span class="name">td</span>></span><span class="tag"><<span class="name">td</span>></span><span class="tag"><<span class="name">性别</span>/<span class="attr">td</span>></span><span class="tag"></<span class="name">tr</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"><<span class="name">tr</span> <span class="attr">v-for</span>=<span class="string">"persion in people"</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">td</span>></span></span><span class="template-variable">{{ persion.name }}</span><span class="xml"><span class="tag"></<span class="name">td</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">td</span>></span></span><span class="template-variable">{{ persion.age }}</span><span class="xml"><span class="tag"></<span class="name">td</span>></span></span></span><br><span class="line"><span class="xml"> <span class="tag"><<span class="name">td</span>></span></span><span class="template-variable">{{ persion.sex }}</span><span class="xml"><span class="tag"></<span class="name">td</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">tr</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">table</span>></span></span></span><br></pre></td></tr></table></figure><h2 id="v-bind指令,带一个参数,参数通常是HTML元素的特性"><a href="#v-bind指令,带一个参数,参数通常是HTML元素的特性" class="headerlink" title="v-bind指令,带一个参数,参数通常是HTML元素的特性"></a>v-bind指令,带一个参数,参数通常是HTML元素的特性</h2><figure class="highlight applescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><<span class="keyword">div</span> v-bind:<span class="built_in">class</span>=<span class="string">"active"</span>></<span class="keyword">div</span>></span><br><span class="line"><<span class="keyword">div</span> :<span class="built_in">class</span>=<span class="string">"active"</span>></<span class="keyword">div</span>></span><br></pre></td></tr></table></figure><h2 id="v-on指令用于监听DOM事件"><a href="#v-on指令用于监听DOM事件" class="headerlink" title="v-on指令用于监听DOM事件"></a>v-on指令用于监听DOM事件</h2><figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><<span class="keyword">a</span> v-<span class="keyword">on</span>:<span class="title">click</span>=<span class="string">""</span><span class="title">doSet</span>></<span class="title">a</span>></span><br><span class="line"><<span class="keyword">a</span> @:click=<span class="string">""</span>doSet></<span class="keyword">a</span>></span><br></pre></td></tr></table></figure><h3 id="v-text-amp-v-html"><a href="#v-text-amp-v-html" class="headerlink" title="v-text & v-html"></a>v-text & v-html</h3><p> 我们已经用的是,这种情况是有弊端的,就是当我们网速很慢或者javascript出错时,会暴露我们的。Vue给我们提供的v-text,就是解决这个问题的。我们来看代码: </p><p> <code><span></span>=<span v-text="message"></span><br/></code> </p><p>如果在javascript中写有html标签,用v-text是输出不出来的,这时候我们就需要用v-html标签了。</p><p><code><span v-html="msgHtml"></span></code></p><p>双大括号会将数据解释为纯文本,而非HTML。为了输出真正的HTML,你就需要使用v-html 指令。</p><h3 id="v-pre-amp-v-clak"><a href="#v-pre-amp-v-clak" class="headerlink" title="v-pre & v-clak"></a>v-pre & v-clak</h3><p>在模板中跳过vue的编译,直接输出原始值。就是在标签中加入v-pre就不会输出vue中的data值了。</p><p><code><div v-pre></div></code></p><p>v-cloak:在vue渲染完指定的整个DOM后才进行显示。它必须和CSS样式一起使用</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-attr">[v-cloak]</span> {</span><br><span class="line"> <span class="attribute">display</span>: none;</span><br><span class="line">}</span><br></pre></td></tr></table></figure> <figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">v-cloak</span>></span></span></span><br><span class="line"><span class="xml"> </span><span class="template-variable">{{ message }}</span><span class="xml"></span></span><br><span class="line"><span class="xml"><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure><h3 id="v-once指令"><a href="#v-once指令" class="headerlink" title="v-once指令"></a>v-once指令</h3><p>在第一次DOM时进行渲染,渲染完成后视为静态内容,跳出以后的渲染过程。</p><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span> <span class="attr">v-once</span>></span>第一次绑定的值:</span><span class="template-variable">{{message}}</span><span class="xml"><span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"><span class="xml"><span class="tag"><<span class="name">div</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">v-model</span>=<span class="string">"message"</span>></span><span class="tag"></<span class="name">div</span>></span></span></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="常用指令列表"><a href="#常用指令列表" class="headerlink" title="常用指令列表"></a>常用指令列表</h3><blockquote>
<ol>
<li>v-model</li>
<li>v-if</li>
<li>v-else</li>
<li>v-show</li>
<li>v-for</li>
<li>v-bind —— 可简写为 :class=”qq”</li>
<li>v-on —— 可简写为:@click=”qq”</li>
<li>v-text &amp; v-html</li>
<li>v-pre &amp; v-cloak</li>
<li>v-once</li>
</ol>
</blockquote>
</summary>
<category term="Vue" scheme="https://jawn-ha.github.com/tags/Vue/"/>
</entry>
<entry>
<title>记录一下重装 Ubuntu18.04 LTS 下的一些配置与软件</title>
<link href="https://jawn-ha.github.com/2018/07/03/%E8%AE%B0%E5%BD%95%E4%B8%80%E4%B8%8B%E9%87%8D%E8%A3%85-Ubuntu18-04-LTS-%E4%B8%8B%E7%9A%84%E4%B8%80%E4%BA%9B%E9%85%8D%E7%BD%AE%E4%B8%8E%E8%BD%AF%E4%BB%B6/"/>
<id>https://jawn-ha.github.com/2018/07/03/%E8%AE%B0%E5%BD%95%E4%B8%80%E4%B8%8B%E9%87%8D%E8%A3%85-Ubuntu18-04-LTS-%E4%B8%8B%E7%9A%84%E4%B8%80%E4%BA%9B%E9%85%8D%E7%BD%AE%E4%B8%8E%E8%BD%AF%E4%BB%B6/</id>
<published>2018-07-03T22:27:20.000Z</published>
<updated>2020-06-24T07:22:51.137Z</updated>
<content type="html"><![CDATA[<p>以前一直用着 windows 和 ubuntu 的双系统,但ubuntu可能装的软件太多且一直缺乏管理导致系统流畅性差,不稳定,于是花了一下午装了最新版的 ubuntu 的最新版本 18.04 LTS。并记录一下一些个人配置以及软件以备不时只需。希望下次能换 MAC!</p><a id="more"></a><h3 id="1-SS-科学上网"><a href="#1-SS-科学上网" class="headerlink" title="1. SS 科学上网"></a>1. SS 科学上网</h3><h4 id="1-1-Shadowsocks-qt5-客户端(推荐)"><a href="#1-1-Shadowsocks-qt5-客户端(推荐)" class="headerlink" title="1.1 Shadowsocks-qt5 客户端(推荐)"></a>1.1 Shadowsocks-qt5 客户端(推荐)</h4><ul><li>安装,终端内依次输入下面指令:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:hzwhuang/ss-qt5</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install shadowsocks-qt5</span><br></pre></td></tr></table></figure><ul><li>目前因为18.04海狸(bionic)库中还没有项目,所以报错,如下:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">忽略: http://ppa.launchpad.net/hzwhuang/ss-qt5/ubuntu bionic InRelease</span><br><span class="line">错误: http://ppa.launchpad.net/hzwhuang/ss-qt5/ubuntu bionic Release</span><br><span class="line">404 Not Found [IP:91.189.95.83 8</span><br></pre></td></tr></table></figure><ul><li>把里面的 ppa源中的bionic改成xenial就可以了,执行:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /etc/apt/sources.list.d/hzwhuang-ubuntu-ss-qt5-bionic.list</span><br></pre></td></tr></table></figure><p>把里面的bionic改成xenial保存就好了,接着安装就可以了。</p><ul><li>最后会在Dash里有启动器,图形界面非常容易配置的。</li></ul><h4 id="1-2-普通版-的-shadowsocks"><a href="#1-2-普通版-的-shadowsocks" class="headerlink" title="1.2 普通版 的 shadowsocks"></a>1.2 普通版 的 shadowsocks</h4><ul><li><p>用pip安装,在Ubuntu下打开终端依次输入以下指令:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-<span class="builtin-name">get</span> update</span><br><span class="line">sudo apt-<span class="builtin-name">get</span> install python-pip</span><br><span class="line">sudo apt-<span class="builtin-name">get</span> install python-setuptools m2crypto</span><br><span class="line">pip install shadowsocks</span><br></pre></td></tr></table></figure></li><li><p>apt安装,Python3.4之后好像不默认装pip了,可以直接apt安装:</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt <span class="keyword">install</span> shadowsocks</span><br></pre></td></tr></table></figure><p>安装时候可能有提示需要安装一些依赖比如python-setuptools m2crypto ,依照提示安装然后再安装就好。</p></li><li><p>启动shadowsocks</p><ol><li><p>用sslocal,在终端输入sslocal –help 可以查看帮助,通过帮助提示我们知道各个参数怎么配置;比如 sslocal -c 后面加上我们的json配置文件,或者像下面这样直接命令参数写上运行。比如:</p><figure class="highlight lsl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sslocal -s <span class="number">11.22</span><span class="number">.33</span><span class="number">.44</span> -p <span class="number">8388</span> -k <span class="string">"123456"</span> -l <span class="number">1080</span> -t <span class="number">600</span> -m aes<span class="number">-256</span>-cfb`</span><br></pre></td></tr></table></figure><p>-s表示服务IP, -p指的是服务端的端口,-k 是密码(要加” ”), -l是本地端口默认是1080,-t超时默认300,-m是加密方法默认aes-256-cfb。</p></li><li><p>为了方便我推荐直接用sslcoal -c 配置文件路径。 我们可以在 /home/azj/ 下新建个文件 shadowsocks.json (azj是我在我电脑上的用户名,这里路径看你自己的)。内容是这样:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"server"</span>:<span class="string">"X.X.X.X"</span>,</span><br><span class="line"> <span class="attr">"server_port"</span>:<span class="number">8388</span>,</span><br><span class="line"> <span class="attr">"local_port"</span>:<span class="number">1080</span>,</span><br><span class="line"> <span class="attr">"password"</span>:<span class="string">"123456"</span>,</span><br><span class="line"> <span class="attr">"timeout"</span>:<span class="number">300</span>,</span><br><span class="line"> <span class="attr">"method"</span>:<span class="string">"aes-256-cfb"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>server 你服务端的IP,<br>servier_port 你服务端的端口,<br>local_port 本地端口,一般默认1080,<br>password ss服务端设置的密码,<br>timeout 超时设置和服务端一样,<br>method 加密方法和服务端一样。<br>确定上面的配置文件没有问题,然后我们就可以在终端输入:<br><code>sslocal -c /home/azj/shadowsocks.json -d -start</code><br>回车运行。</p></li></ol></li></ul><h4 id="1-3配置PAC模式"><a href="#1-3配置PAC模式" class="headerlink" title="1.3配置PAC模式"></a>1.3配置PAC模式</h4><p>在系统设置里网络设置中的网络代理选项选择自动,在URL框中填入本地PAC文件路径“file:///home/jawnha/PAC/AutoProxy.pac”。 <a href="https://doub.io/ss-jc59/" target="_blank" rel="noopener">Pac文件</a>可以从这里获取。</p><h3 id="2-Chrome-浏览器"><a href="#2-Chrome-浏览器" class="headerlink" title="2.Chrome 浏览器"></a>2.Chrome 浏览器</h3><h4 id="2-1-安装"><a href="#2-1-安装" class="headerlink" title="2.1 安装"></a>2.1 安装</h4><h3 id="2-1-安装-1"><a href="#2-1-安装-1" class="headerlink" title="2.1 安装"></a>2.1 安装</h3><ol><li>私有源安装,终端内依次输入以下指令:<ol><li>将chrome下载源添加到系统的源列表: <code>sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list.d/</code></li><li>导入谷歌软件的公钥,可能等待时间比较长: <code>wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | sudo apt-key add -</code></li><li>更新系统: <code>sudo apt-get update</code></li><li>安装chrome: <code>sudo apt-get install google-chrome-stable</code><br>然后安装完成后就可以使用了,两个命令对应着不同的版本,一个是正常,一个是稳定版。<br>正常版: <code>/usr/bin/google-chrome</code><br>稳定版: <code>/usr/bin/google-chrome-stable</code></li></ol></li><li>科学上网的情况下直接去Chrome下载deb双击安装或者<code>dpkg -i \<deb包名></code>。 </li></ol><h4 id="2-3Flash-插件"><a href="#2-3Flash-插件" class="headerlink" title="2.3Flash 插件"></a>2.3Flash 插件</h4><p>1.Chrome安装完后发现flash无法播放,显示“没有安装flash插件”,因为AdobeFlash不再支持linux,So, Google便开发了PepperFlashPlayer来替代原来的AdobeFlash。<br>下面介绍 PepperFlashPlayer的安装方法:</p><ol><li><p>安装,在终端里输入下面的命令: <code>sudo apt-get install pepperflashplugin-nonfree</code></p></li><li><p>更新 ,在终端里输入下面的命令代码: <code>sudo update-pepperflashplugin-nonfree --install</code></p></li><li><p>查看安装的PepperFlashPlayer版本,在终端里输入下面的命令: <code>sudo update-pepperflashplugin-nonfree --status</code></p></li><li><p>在终端里输入下面的命令代码:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo mkdir /opt/google/chrome/PepperFlash</span><br><span class="line">sudo cp /usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so /opt/google/chrome/PepperFlash</span><br></pre></td></tr></table></figure><p>重启浏览器。</p><p>2.Chrome安装完后发现某些网页flash无法播放,显示“该插件不受支持”,一般是因为flash插件版 本低与该网站要求(grd腾讯视频最典型),一般此时更新一下flash插件就好了:</p><ol><li>可以用\1.中的方法,倘若不行则将libpepflashplayer.so文件复制到”~/.config/google-chrome/PepperFlash/30.0.0.113/“里,没有该目录就创建一个,“30.0.0.113”是当前flash插件的版本可以从\1.中指令查到或者随便写一个。重启浏览器。</li><li>倘若还不行就去AdobeFlash官网下载对应环境的tar包“flash_player_ppapi_linux.x86_64”,解压后把所有目录内文件移到”~/.config/google-chrome/PepperFlash/30.0.0.113/“里。同样重启浏览器。</li><li>或者在以上科学上网的情况下终端如下开启Chrome全局代理:<br><code>google-chrome --proxy-server="socks5://127.0.0.1:8119"</code><br>在打开的浏览器内输入:<code>chrome://components</code> 进入组件页点击更新。<br>完了重启浏览器输入:<code>chrome://flash</code> 查看flash版本。</li></ol></li></ol><h3 id="3-常用软件"><a href="#3-常用软件" class="headerlink" title="3. 常用软件"></a>3. 常用软件</h3><h4 id="3-1-文本编辑"><a href="#3-1-文本编辑" class="headerlink" title="3.1 文本编辑"></a>3.1 文本编辑</h4><h5 id="3-1-1搜狗输入法"><a href="#3-1-1搜狗输入法" class="headerlink" title="3.1.1搜狗输入法"></a>3.1.1搜狗输入法</h5><h5 id="3-1-1-搜狗Pinyin"><a href="#3-1-1-搜狗Pinyin" class="headerlink" title="3.1.1 搜狗Pinyin"></a>3.1.1 搜狗Pinyin</h5><p><a href="https://www.cnblogs.com/zhangfengfly/p/6867844.html" target="_blank" rel="noopener">配置地址</a></p><h5 id="3-1-2-剪贴板Ditto"><a href="#3-1-2-剪贴板Ditto" class="headerlink" title="3.1.2 剪贴板Ditto"></a>3.1.2 剪贴板Ditto</h5><p>搜狗自带剪切板插件可以自己配置一下。<br>Linux下的剪贴板软件感觉始终不如windows下(ditto)好用,推荐一个ClipIt:<br>保存上一个拷贝项的历史记录;<br>针对最常用功能的全局热键;<br>声明静态项;将特定项从历史记录中排除;<br>可搜索的历史记录及更多功能 ;<br>用的时候,点击任务栏上图标,选取所需片段。<br>终端安装:</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo<span class="built_in"> add-apt-repository </span>ppa:shantzu/clipit</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install clipit</span><br></pre></td></tr></table></figure><h5 id="3-1-3-WPS-安装"><a href="#3-1-3-WPS-安装" class="headerlink" title="3.1.3 WPS 安装"></a>3.1.3 WPS 安装</h5><p><a href="http://community.wps.cn/download/" target="_blank" rel="noopener">deb包官网下载地址</a><br><a href="https://blog.csdn.net/zhuiqiuk/article/details/53644545" target="_blank" rel="noopener">依赖冲突解决</a></p><h5 id="3-1-4-Markdown编辑"><a href="#3-1-4-Markdown编辑" class="headerlink" title="3.1.4 Markdown编辑"></a>3.1.4 Markdown编辑</h5><ol><li><p>有颜值又有实力的markdown编辑器 typora,安装过程如下:</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE</span><br><span class="line">sudo<span class="built_in"> add-apt-repository </span>'deb https://typora.io ./linux/'</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install typora</span><br></pre></td></tr></table></figure></li><li><p>Moeditor,简洁好用又好看,支持全平台,Menci大佬开发。支持deb包安装和自己构建安装。</p><ul><li>github上已经开源:“<a href="https://github.com/Moeditor/Moeditor%E2%80%9D" target="_blank" rel="noopener">https://github.com/Moeditor/Moeditor”</a></li><li>主页以及下载:“<a href="https://moeditor.org/%E2%80%9D" target="_blank" rel="noopener">https://moeditor.org/”</a></li></ul></li><li><p>安装VIM (大佬们的最爱,插件自己配)<br><code>apt-get install vim</code></p></li></ol><h4 id="3-2-图像处理"><a href="#3-2-图像处理" class="headerlink" title="3.2 图像处理"></a>3.2 图像处理</h4><h5 id="3-2-1-截屏软件"><a href="#3-2-1-截屏软件" class="headerlink" title="3.2.1 截屏软件"></a>3.2.1 截屏软件</h5><p>Shutter是值得推荐的一款截图软件,功能丰富,堪称神器。<br>终端安装:<code>sudo apt-get install shutter</code></p><h5 id="3-2-2-GIMP"><a href="#3-2-2-GIMP" class="headerlink" title="3.2.2 GIMP"></a>3.2.2 GIMP</h5><p><a href="https://www.linuxidc.com/Linux/2015-12/125835.htm" target="_blank" rel="noopener">安装教程</a></p><h4 id="3-3-视频音频播放器"><a href="#3-3-视频音频播放器" class="headerlink" title="3.3 视频音频播放器"></a>3.3 视频音频播放器</h4><h5 id="3-3-1-VLCMedia-Player-格式广"><a href="#3-3-1-VLCMedia-Player-格式广" class="headerlink" title="3.3.1 VLCMedia Player(格式广)"></a>3.3.1 VLCMedia Player(格式广)</h5><p>终端安装 <code>sudo apt-get install vlc</code><br>或者自带软件商店内下载。</p><h5 id="3-3-2-gnome播放器"><a href="#3-3-2-gnome播放器" class="headerlink" title="3.3.2 gnome播放器"></a>3.3.2 gnome播放器</h5><p>自带软件商店内下载。</p><h4 id="3-3-3-SMPlayer"><a href="#3-3-3-SMPlayer" class="headerlink" title="3.3.3 SMPlayer"></a>3.3.3 SMPlayer</h4><p>终端安装:</p><figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-<span class="built_in">add</span>-repository <span class="keyword">pp</span><span class="variable">a:rvm</span>/smplayer</span><br><span class="line">sudo apt-<span class="built_in">get</span> <span class="keyword">update</span></span><br><span class="line">sudo apt-<span class="built_in">get</span> install smplayer smplayer-skins smplayer-themes</span><br></pre></td></tr></table></figure><h5 id="3-3-4-网易云音乐"><a href="#3-3-4-网易云音乐" class="headerlink" title="3.3.4 网易云音乐"></a>3.3.4 网易云音乐</h5><p><a href="https://link.zhihu.com/?target=http%3A//music.163.com/%23/download" target="_blank" rel="noopener">deb包官网下载地址</a></p><h5 id="3-3-5-虾米音乐"><a href="#3-3-5-虾米音乐" class="headerlink" title="3.3.5 虾米音乐"></a>3.3.5 虾米音乐</h5><p>另外,有大神用Electron构建了Linux端虾米音乐Electron Xiami,需要的朋友自己摸索。<br><a href="https://github.com/eNkru/electron-xiami" target="_blank" rel="noopener">https://github.com/eNkru/electron-xiami</a></p><h5 id="3-3-6-FFmpeg"><a href="#3-3-6-FFmpeg" class="headerlink" title="3.3.6 FFmpeg"></a>3.3.6 FFmpeg</h5><p>很好的音频视频处理软件。终端安装:</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo<span class="built_in"> add-apt-repository </span>ppa:djcj/hybrid</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install ffmpeg</span><br></pre></td></tr></table></figure><h5 id="3-3-7-录屏软件"><a href="#3-3-7-录屏软件" class="headerlink" title="3.3.7 录屏软件"></a>3.3.7 录屏软件</h5><p>Simple Screen Recorder是一款简单的屏幕录像工具,能够在屏幕上录制视频、教程,界面简单,功能够用。终端安装:</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo<span class="built_in"> add-apt-repository </span>ppa:maarten-baert/simplescreenrecorder</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install simplescreenrecorder</span><br></pre></td></tr></table></figure><h3 id="4-系统软件"><a href="#4-系统软件" class="headerlink" title="4 系统软件"></a>4 系统软件</h3><h4 id="4-1-系统优化"><a href="#4-1-系统优化" class="headerlink" title="4.1 系统优化"></a>4.1 系统优化</h4><h5 id="4-1-1-点击图标最小化"><a href="#4-1-1-点击图标最小化" class="headerlink" title="4.1.1 点击图标最小化"></a>4.1.1 点击图标最小化</h5><p>终端输入: <code>gsettings set org.gnome.shell.extensions.dash-to-dock click-action 'minimize'</code>。</p><h4 id="4-1-2-sysmonitor"><a href="#4-1-2-sysmonitor" class="headerlink" title="4.1.2 sysmonitor"></a>4.1.2 sysmonitor</h4><p>资源监视监视器:<br><a href="https://www.cnblogs.com/EasonJim/p/7130171.html" target="_blank" rel="noopener">教程地址</a>。</p><h4 id="4-1-3-支持exfat文件"><a href="#4-1-3-支持exfat文件" class="headerlink" title="4.1.3 支持exfat文件"></a>4.1.3 支持exfat文件</h4><p>终端安装:<code>sudo apt-get install exfat-fuse exfat-utils</code>。</p><h4 id="4-1-x-装逼"><a href="#4-1-x-装逼" class="headerlink" title="4.1.x 装逼"></a>4.1.x 装逼</h4><p><a href="https://www.linuxidc.com/Linux/2013-12/94300.htm" target="_blank" rel="noopener">十个装逼有意思的玩意儿</a></p><h3 id="4-2-系统美化"><a href="#4-2-系统美化" class="headerlink" title="4.2 系统美化"></a>4.2 系统美化</h3><p>使用Tweaks对gnome进行美化,终端安装:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get <span class="keyword">install</span> gnome-tweak-tool <span class="comment">#安装tweak</span></span><br><span class="line">sudo apt-<span class="keyword">get</span> <span class="keyword">install</span> gnome-shell-extensions -y <span class="comment">#安装shell扩展</span></span><br><span class="line">sudo apt <span class="keyword">install</span> chrome-gnome-shell <span class="comment">#为了能在火狐和谷歌浏览器内安装gnome插件</span></span><br><span class="line">sudo apt-<span class="keyword">get</span> <span class="keyword">install</span> gtk2-<span class="keyword">engines</span>-pixbuf <span class="comment">#防止GTK2错误</span></span><br><span class="line">sudo apt <span class="keyword">install</span> libxml2-utils</span><br></pre></td></tr></table></figure><p>接下来安装主题和图标,主要从<a href="https://www.gnome-look.org/browse/ord/top/" target="_blank" rel="noopener">gnome-look</a>这里下载,下面举例一个。<br>我从网站找到Gnome-OSC主题,这是一款仿MAC OS的主题:</p><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir ~<span class="string">/Themes</span></span><br><span class="line"><span class="keyword">cd</span> ~<span class="string">/Downloads</span></span><br></pre></td></tr></table></figure><p>我下载的两个包是:</p><figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Gnome-OSC-HS-light-menu– <span class="number">2</span>-themes<span class="selector-class">.tar</span><span class="selector-class">.xz</span> </span><br><span class="line">Gnome-OSC-HS–<span class="number">2</span>-themes<span class="selector-class">.tar</span><span class="selector-class">.xz</span></span><br></pre></td></tr></table></figure><p>接下来解压到指定文件夹,并安装他们。</p><figure class="highlight jboss-cli"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">xz -d Gnome-OSC-HS-light-menu*<span class="string">.tar.xz</span></span><br><span class="line">tar -xvf Gnome-OSC-HS-light-menu*<span class="string">.tar</span> -C ~<span class="string">/Themes</span></span><br><span class="line">xz -d Gnome-OSC-HS<span class="params">--2</span>*<span class="string">.tar.xz</span></span><br><span class="line">tar -xvf Gnome-OSC-HS<span class="params">--2</span>*<span class="string">.tar</span> -C ~<span class="string">/Themes</span></span><br><span class="line"><span class="keyword">cd</span> ~<span class="string">/Themes</span></span><br><span class="line">sudo cp -R ~<span class="string">/Themes/Gnome-OSC</span>* <span class="string">/usr/share/themes/</span></span><br></pre></td></tr></table></figure><p>还有一款扁平化主题也不错。</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo<span class="built_in"> add-apt-repository </span>ppa:daniruiz/flat-remix</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install flat-remix-gnome</span><br></pre></td></tr></table></figure><p>图标papirus还不错</p><figure class="highlight smali"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo<span class="built_in"> add-apt-repository </span>ppa:papirus/papirus</span><br><span class="line">sudo apt update </span><br><span class="line">sudo apt-get install papirus-icon-theme</span><br></pre></td></tr></table></figure><p>重启!然后就可以在Tweak-tools里看见这些主题了。</p><h4 id="4-3-安装压缩软件"><a href="#4-3-安装压缩软件" class="headerlink" title="4.3 安装压缩软件"></a>4.3 安装压缩软件</h4><p>终端安装:<code>sudo apt-get install p7zip-full p7zip-rar rar unzip</code></p><h4 id="4-4-Htop"><a href="#4-4-Htop" class="headerlink" title="4.4 Htop"></a>4.4 Htop</h4><p>终端安装:<code>sudo apt-get install htop</code></p><h4 id="4-5-Guake-Terminal(F12…)"><a href="#4-5-Guake-Terminal(F12…)" class="headerlink" title="4.5 Guake Terminal(F12…)"></a>4.5 Guake Terminal(F12…)</h4><p>终端安装:<code>sudo apt-get install guake</code></p><h4 id="4-6-albert神器"><a href="#4-6-albert神器" class="headerlink" title="4.6 albert神器"></a>4.6 albert神器</h4><p>这个可以考虑开机启动albert:<br><a href="https://github.com/albertlauncher/albert" target="_blank" rel="noopener">项目地址</a></p><h3 id="5-开发工具安装"><a href="#5-开发工具安装" class="headerlink" title="5. 开发工具安装"></a>5. 开发工具安装</h3><h4 id="5-1-sublime编辑器"><a href="#5-1-sublime编辑器" class="headerlink" title="5.1 sublime编辑器"></a>5.1 sublime编辑器</h4><p>对于那些不喜欢snap包的人,你可以从它的官方apt库安装Sublime Text 3。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -</span><br><span class="line">echo "deb https://download.sublimetext.com/ apt/stable/" | sudo tee /etc/apt/sources.list.d/sublime-text.list</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install sublime-text</span><br></pre></td></tr></table></figure><p>卸载命令:<br><code>sudo apt-get remove sublime-text && sudo apt-get autoremove</code></p><h4 id="5-2-webstorm安装"><a href="#5-2-webstorm安装" class="headerlink" title="5.2 webstorm安装"></a>5.2 webstorm安装</h4><p>官网下载直接安装就好,网上破解方法也挺多。</p><p>感谢阅读,方法大都来源于网络,多查多问便能全部解决了!</p>]]></content>
<summary type="html">
<p>以前一直用着 windows 和 ubuntu 的双系统,但ubuntu可能装的软件太多且一直缺乏管理导致系统流畅性差,不稳定,于是花了一下午装了最新版的 ubuntu 的最新版本 18.04 LTS。并记录一下一些个人配置以及软件以备不时只需。希望下次能换 MAC!</p>
</summary>
<category term="Ubuntu" scheme="https://jawn-ha.github.com/tags/Ubuntu/"/>
</entry>
<entry>
<title>Markdown语法复习</title>
<link href="https://jawn-ha.github.com/2018/07/02/%E6%88%91%E6%96%B0%E5%8D%9A%E5%AE%A2%E7%AC%AC%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/"/>
<id>https://jawn-ha.github.com/2018/07/02/%E6%88%91%E6%96%B0%E5%8D%9A%E5%AE%A2%E7%AC%AC%E4%B8%80%E7%AF%87%E6%96%87%E7%AB%A0/</id>
<published>2018-07-02T23:26:44.000Z</published>
<updated>2020-06-24T07:22:51.133Z</updated>
<content type="html"><![CDATA[<p>好久没使用Markdown了,所以新博客的第一篇文章决定复习一下Makdown的语法</p><a id="more"></a><h3 id="标题"><a href="#标题" class="headerlink" title="标题"></a>标题</h3><p>标题是最常用的格式,在这是最为常用的格式,在平时常用的的文本编辑器中大多是这样实现的:输入文本、选中文本、设置标题格式。</p><p>而在 Markdown 中,你只需要在文本前面加上 <code>#</code> 即可,同理、你还可以增加二级标题、三级标题、四级标题、五级标题和六级标题,总共六级,只需要增加 <code>#</code> 即可,标题字号相应降低。例如</p><figure class="highlight clean"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 一级标题</span><br><span class="line">## 二级标题</span><br><span class="line">### 三级标题</span><br><span class="line">#### 四级标题</span><br><span class="line">##### 五级标题</span><br><span class="line">###### 六级标题</span><br></pre></td></tr></table></figure><p><em>注:# 和「一级标题」之间建议保留一个字符的空格,这是最标准的 Markdown 写法。</em></p><h3 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h3><p>列表格式也很常用,在Markdown中,可以通过在文字前面<code>*</code>,<code>+</code>或<code>-</code>来实现</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">+ </span>无序列表</span><br><span class="line"><span class="bullet">- </span>无序列表</span><br><span class="line"><span class="bullet">* </span>无序列表</span><br></pre></td></tr></table></figure><p>如果你希望有序列表, 也可以在文字前面加上 <code>1.</code> <code>2.</code> <code>3.</code> 就可以了,例如:</p><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">1.</span> 文本<span class="number">1</span></span><br><span class="line"><span class="number">2.</span> 文本<span class="number">2</span></span><br><span class="line"><span class="number">3.</span> 文本<span class="number">3</span></span><br></pre></td></tr></table></figure><h3 id="链接和图片"><a href="#链接和图片" class="headerlink" title="链接和图片"></a>链接和图片</h3><p>在 Markdown 中,插入链接不需要其他按钮,你只需要使用 <code>[显示文本](链接地址)</code> 这样的语法即可,例如:</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[<span class="string">JawnHa的个人博客</span>](<span class="link">https://jawn-ha.github.io</span>)</span><br></pre></td></tr></table></figure><p>在 Markdown 中,插入图片不需要其他按钮,你只需要使用 <code>![](图片链接地址)</code> 这样的语法即可.</p><p>注:插入图片的语法和链接的语法很像,只是前面多了一个 !。</p><h3 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h3><p>在我们写作的时候经常需要引用他人的文字,这个时候引用这个格式就很有必要了,在 Markdown 中,你只需要在你希望引用的文字前面加上 <code>></code> 就好了,例如:</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="quote">> 一盏灯, 一片昏黄; 一简书, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。</span></span><br></pre></td></tr></table></figure><p><em>注:> 和文本之间要保留一个字符的空格。</em></p><p>最终显示的就是:</p><blockquote><p>一盏灯, 一片昏黄; 一简书, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。</p></blockquote><h3 id="粗体和斜体"><a href="#粗体和斜体" class="headerlink" title="粗体和斜体"></a>粗体和斜体</h3><p>Markdown 的粗体和斜体也非常简单,用两个 <code>*</code> 包含一段文本就是粗体的语法,用一个 <code>*</code> 包含一段文本就是斜体的语法。例如:</p><figure class="highlight asciidoc"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="strong">*一盏灯*</span>, 一片昏黄;*<span class="strong">*一简书*</span><span class="strong">*, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。</span></span><br></pre></td></tr></table></figure><p> 最终显示的就是下文,其中「一盏灯」是斜体,「一简书」是粗体:</p><p><em>一盏灯</em>, 一片昏黄;<strong>一简书</strong>, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。</p><h3 id="代码引用"><a href="#代码引用" class="headerlink" title="代码引用"></a>代码引用</h3><p>需要引用代码时,如果引用的语句只有一段,不分行,可以用 ` 将语句包起来。 如果引用的语句为多行,可以将<figure class="highlight plain"><figcaption><span>*代码引用的案例截图:*</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">![代码引用截图](/home/jawnha/MyBlog/source/images/2018-7-3/1.jpg)</span><br><span class="line"></span><br><span class="line">### 表格</span><br></pre></td></tr></table></figure></p><table><thead><tr><th>Tables</th><th style="text-align:center">Are</th><th style="text-align:right">Cool</th></tr></thead><tbody><tr><td>col 3 is</td><td style="text-align:center">right-aligned</td><td style="text-align:right">$1600</td></tr><tr><td>col 2 is</td><td style="text-align:center">centered</td><td style="text-align:right">$12</td></tr><tr><td>zebra stripes</td><td style="text-align:center">are neat</td><td style="text-align:right">$1</td></tr></tbody></table><figure class="highlight ruby"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">显示效果: </span><br><span class="line"></span><br><span class="line"><span class="params">| Tables |</span> Are <span class="params">| Cool |</span></span><br><span class="line"><span class="params">| ------------- |</span> <span class="symbol">:-----------</span>: <span class="params">| ----: |</span></span><br><span class="line"><span class="params">| col 3 is |</span> right-aligned <span class="params">| $1600 |</span></span><br><span class="line"><span class="params">| col 2 is |</span> centered <span class="params">| $12 |</span></span><br><span class="line"><span class="params">| zebra stripes |</span> are neat <span class="params">| $1 |</span></span><br><span class="line"></span><br><span class="line"> 相关代码:</span><br></pre></td></tr></table></figure><table><thead><tr><th>dog</th><th>bird</th><th>cat</th></tr></thead><tbody><tr><td>foo</td><td>foo</td><td>foo</td></tr><tr><td>bar</td><td>bar</td><td>bar</td></tr><tr><td>baz</td><td>baz</td><td>baz</td></tr></tbody></table><p><code>`</code></p><p>显示效果:</p><table><thead><tr><th>dog</th><th>bird</th><th>cat</th></tr></thead><tbody><tr><td>foo</td><td>foo</td><td>foo</td></tr><tr><td>bar</td><td>bar</td><td>bar</td></tr><tr><td>baz</td><td>baz</td><td>baz</td></tr></tbody></table><h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><p>以上几种格式是比较常用的格式,所以我们针对这些语法做了比较详细的说明。除这些之外,Markdown 还有其他语法,如想了解和学习更多,可以参考这篇<a href="https://link.jianshu.com/?t=http://wowubuntu.com/markdown/" target="_blank" rel="noopener">『Markdown 语法说明』</a>。</p>]]></content>
<summary type="html">
<p>好久没使用Markdown了,所以新博客的第一篇文章决定复习一下Makdown的语法</p>
</summary>
<category term="MarkDown" scheme="https://jawn-ha.github.com/tags/MarkDown/"/>
</entry>
</feed>