-
Notifications
You must be signed in to change notification settings - Fork 4
/
atom.xml
513 lines (306 loc) · 419 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
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>梦魇小栈</title>
<subtitle>专注于分享</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://blog.ihoey.com/"/>
<updated>2018-05-13T09:06:27.487Z</updated>
<id>https://blog.ihoey.com/</id>
<author>
<name>Ihoey</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>记一下 pm2 常用配置及命令</title>
<link href="https://blog.ihoey.com/posts/Node/2018-05-13-pm2-study.html"/>
<id>https://blog.ihoey.com/posts/Node/2018-05-13-pm2-study.html</id>
<published>2018-05-13T08:45:46.000Z</published>
<updated>2018-05-13T09:06:27.487Z</updated>
<content type="html"><![CDATA[<p><code>PM2</code> 是 <code>node</code> 进程管理工具,可以利用它来简化很多 <code>node</code> 应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。本文就 <code>PM2</code> 进行入门性的介绍,基本涵盖了 <code>PM2</code> 的常用的功能和配置。</p><a id="more"></a><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g pm2</span><br></pre></td></tr></table></figure></div><h2 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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></pre></td><td class="code"><pre><span class="line">pm2 start [server.js]</span><br><span class="line"><span class="comment"># 启动服务</span></span><br><span class="line">pm2 list</span><br><span class="line"><span class="comment"># 查看当前所跑服务的详情</span></span><br><span class="line">pm2 show [name]</span><br><span class="line"><span class="comment"># 查看更加详细的信息这个命令可查看pm2配置 包括日志文件存放的位置等</span></span><br><span class="line">pm2 stop [id/name]</span><br><span class="line"><span class="comment"># 关闭某个服务</span></span><br><span class="line">pm2 delete [id/name]</span><br><span class="line"><span class="comment"># 删除某个服务</span></span><br><span class="line">pm2 stop all</span><br><span class="line"><span class="comment"># 关闭所有服务</span></span><br><span class="line">pm2 logs</span><br><span class="line"><span class="comment"># 查看实时日志</span></span><br><span class="line">pm2 restart [name]</span><br><span class="line"><span class="comment"># 重新启动服务</span></span><br></pre></td></tr></table></figure></div><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>参数说明:</p><ul><li><code>--watch</code>:监听应用目录的变化,一旦发生变化,自动重启。如果要精确监听、不见听的目录,最好通过配置文件。</li><li><code>-i --instances</code>:启用多少个实例,可用于负载均衡。如果 <code>-i 0</code> 或者 <code>-i max</code>,则根据当前机器核数确定实例数目。</li><li><code>--ignore-watch</code>:排除监听的目录/文件,可以是特定的文件名,也可以是正则。比如 <code>--ignore-watch="test node_modules "some scripts""</code></li><li><code>-n --name</code>:应用的名称。查看应用信息的时候可以用到。</li><li><code>-o --output <path></code>:标准输出日志文件的路径。</li><li><code>-e --error <path></code>:错误输出日志文件的路径。</li></ul><h2 id="监听"><a href="#监听" class="headerlink" title="监听"></a>监听</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">pm2 start ./bin/www --watch</span><br><span class="line"><span class="comment">#注意,这里用了--watch参数,意味着当你的应用代码发生变化时,pm2会帮你自动重启服务</span></span><br></pre></td></tr></table></figure></div><h2 id="配置及部署"><a href="#配置及部署" class="headerlink" title="配置及部署"></a>配置及部署</h2><p>部署的配置文件示例</p><figure class="highlight"><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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> // 数组中放的是需要发布的项目一些变量的定义</span><br><span class="line"> "apps": [{</span><br><span class="line"> "name": "xxx", //项目名称</span><br><span class="line"> "script": "server.js", //用来启动的脚本</span><br><span class="line"> // "instances":2,</span><br><span class="line"> // 启动项目所需要的环境变量</span><br><span class="line"> "env": {</span><br><span class="line"> "COMMON_VARIABLE": "true", //设置为true 可以在启动的时传入外部的变量进去</span><br><span class="line"> },</span><br><span class="line"> "env_production": {</span><br><span class="line"> "NODE_ENV": "production"</span><br><span class="line"> }</span><br><span class="line"> }],</span><br><span class="line"> // 部署</span><br><span class="line"> "deploy": {</span><br><span class="line"> "production": {</span><br><span class="line"> "user": "root",</span><br><span class="line"> "host": "0.0.0.0", //可以是数组 部署到多台主机</span><br><span class="line"> "ref": "origin/master", //选择拿哪个个分支的代码</span><br><span class="line"> "repo": "[email protected]:ihoey/hitalk.git", //仓库地址</span><br><span class="line"> "path": "/root/www/hitalk/production", //要发布到服务器上哪个目录下面</span><br><span class="line"> "ssh_options": "StrictHostKeyChecking=no", //避免key验证导致代码更新到远程仓库失败</span><br><span class="line"> "post-deploy": "source ~/.nvm/nvm.sh && pm2 startOrRestart ecosystem.json --env production", //发布之后执行的动作 执行开启或更新pm2运行的服务</span><br><span class="line"> "pre-deploy-local": "echo 'Deploy Done!'", //本地发布之前的动作</span><br><span class="line"> "env": { //指定部署到远程的仓库的环境 是production生产环境</span><br><span class="line"> "NODE_ENV": "production"</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><h3 id="初始化配置"><a href="#初始化配置" class="headerlink" title="初始化配置"></a>初始化配置</h3><p>第一次部署</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pm2 deploy ecosystem.json production setup</span><br></pre></td></tr></table></figure></div><h3 id="部署"><a href="#部署" class="headerlink" title="部署"></a>部署</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pm2 deploy ecosystem.json production</span><br></pre></td></tr></table></figure></div><p>好了,先记录这么多~</p>]]></content>
<summary type="html">
<p><code>PM2</code> 是 <code>node</code> 进程管理工具,可以利用它来简化很多 <code>node</code> 应用管理的繁琐任务,如性能监控、自动重启、负载均衡等,而且使用非常简单。本文就 <code>PM2</code> 进行入门性的介绍,基本涵盖了 <code>PM2</code> 的常用的功能和配置。</p>
</summary>
<category term="Node" scheme="https://blog.ihoey.com/categories/Node/"/>
<category term="pm2" scheme="https://blog.ihoey.com/tags/pm2/"/>
</entry>
<entry>
<title>(译)NPM vs Yarn 备忘手册</title>
<link href="https://blog.ihoey.com/posts/Node/2018-04-28-npm-vs-yarn-cheat-sheet.html"/>
<id>https://blog.ihoey.com/posts/Node/2018-04-28-npm-vs-yarn-cheat-sheet.html</id>
<published>2018-04-28T05:40:47.000Z</published>
<updated>2018-05-04T10:02:30.000Z</updated>
<content type="html"><![CDATA[<p>原文链接: <a href="https://shift.infinite.red/npm-vs-yarn-cheat-sheet-8755b092e5cc" target="_blank" rel="noopener">NPM vs Yarn Cheat Sheet</a></p><p>好,想必你对新的 <code>JavaScript</code> 包管理工具 <code>yarn</code> 已经有所耳闻,并已通过 <code>npm i -g yarn</code> 进行了安装,现在想知道怎么样使用吗?如果你了解 <code>npm</code>,你已经会很大一部分啦!</p><a id="more"></a><p>下面是我从 npm 切换到 yarn 的一些笔记。</p><p><strong>👍 请收藏本文,本文会随着 <code>yarn</code> 的升级而更新。</strong></p><h2 id="备忘手册-你需要知道的"><a href="#备忘手册-你需要知道的" class="headerlink" title="备忘手册 - 你需要知道的"></a>备忘手册 - 你需要知道的</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">npm install === yarn</span><br><span class="line"><span class="comment"># 默认安装行为</span></span><br><span class="line">npm install taco --save === yarn add taco</span><br><span class="line"><span class="comment"># 将 taco 安装并保存到 package.json 中</span></span><br><span class="line">npm uninstall taco --save === yarn remove taco --save</span><br><span class="line"><span class="comment"># 在 npm 中,可以使用 npm config set save true 设置 —-save 为默认行为,但这对多数开发者而言并非显而易见的。在 yarn 中,在 package.json 中添加(add)和移除(remove)等行为是默认的。</span></span><br><span class="line">npm install taco --save-dev === yarn add taco --dev</span><br><span class="line">npm update --save === yarn upgrade</span><br><span class="line"><span class="comment"># update(更新) vs upgrade(升级), 赞!upgrade 才是实际做的事!版本号提升时,发生的正是 upgrade !</span></span><br><span class="line"><span class="comment"># 注意: npm update --save 在版本 3.11 中似乎有点问题。</span></span><br><span class="line">npm install taco@latest --save === yarn add taco</span><br><span class="line">npm install taco --global === yarn global add taco</span><br><span class="line"><span class="comment"># 一如既往,请谨慎使用 global 标记。</span></span><br></pre></td></tr></table></figure></div><blockquote><p>你可以使用 <code>yarn self-update</code> 来更新它自己</p></blockquote><h2 id="相同操作的命令"><a href="#相同操作的命令" class="headerlink" title="相同操作的命令"></a>相同操作的命令</h2><p><code>registry</code> 的和 <code>NPM</code> 上是一样的。大致而言,<code>Yarn</code> 只是一个新的安装工具,<code>NPM</code> 结构和 <code>registry</code> 还是一样的。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">npm init === yarn init</span><br><span class="line">npm link === yarn link</span><br><span class="line">npm outdated === yarn outdated</span><br><span class="line">npm publish === yarn publish</span><br><span class="line">npm run === yarn run</span><br><span class="line">npm cache clean === yarn cache clean</span><br><span class="line">npm login === yarn login</span><br><span class="line"><span class="comment"># 和 logout 是一样的</span></span><br><span class="line">npm <span class="built_in">test</span> === yarn <span class="built_in">test</span></span><br><span class="line">npm install --production === yarn --production</span><br></pre></td></tr></table></figure></div><h2 id="Yarn-独有的命令"><a href="#Yarn-独有的命令" class="headerlink" title="Yarn 独有的命令"></a>Yarn 独有的命令</h2><p>我跳过了一些提醒我们不要使用的内容,如 <code>yarn clean</code>。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">yarn licenses ls </span><br><span class="line"><span class="comment"># 允许您检查您的依赖的许可证</span></span><br><span class="line">yarn licenses generate-disclaimer </span><br><span class="line"><span class="comment"># 自动创建您的许可证免责声明</span></span><br><span class="line">yarn why taco </span><br><span class="line"><span class="comment"># 确定为什么安装了 taco 检查为什么会安装 taco,详细列出依赖它的其他包(感谢 Olivier Combe).</span></span><br><span class="line">Emojis ⬆️</span><br><span class="line">速度 🏃⌁</span><br><span class="line">通过 yarn lockfile 自动实现 shrinkwrap 功能</span><br><span class="line">以安全为中心的设计</span><br><span class="line">yarn upgrade-interactive</span><br><span class="line"><span class="comment"># 允许您自己选择升级指定的包</span></span><br></pre></td></tr></table></figure></div><p><img src="https://cdn-images-1.medium.com/max/1600/1*f9lz2UdUk6rMf6Pdz8_Spw.png" alt="selectively upgrade specific packages"></p><h2 id="NPM-独有的命令"><a href="#NPM-独有的命令" class="headerlink" title="NPM 独有的命令"></a>NPM 独有的命令</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">npm xmas === NO EQUIVALENT</span><br><span class="line">npm visnup === NO EQUIVALENT</span><br></pre></td></tr></table></figure></div><h2 id="更多!"><a href="#更多!" class="headerlink" title="更多!"></a>更多!</h2><p>这篇备忘手册的 <code>PDF</code> 版本特别感谢 <a href="https://medium.com/@justinhuskey" target="_blank" rel="noopener">Justin Huskey</a></p><p><a href="https://infinite.red/files/yarn.pdf" target="_blank" rel="noopener">PDF文件链接</a></p><h2 id="相关链接"><a href="#相关链接" class="headerlink" title="相关链接"></a>相关链接</h2><p><a href="https://yarn.bootcss.com/" target="_blank" rel="noopener">https://yarn.bootcss.com/</a><br><a href="https://github.com/yarnpkg/yarn" target="_blank" rel="noopener">https://github.com/yarnpkg/yarn</a></p>]]></content>
<summary type="html">
<p>原文链接: <a href="https://shift.infinite.red/npm-vs-yarn-cheat-sheet-8755b092e5cc" target="_blank" rel="noopener">NPM vs Yarn Cheat Sheet</a></p>
<p>好,想必你对新的 <code>JavaScript</code> 包管理工具 <code>yarn</code> 已经有所耳闻,并已通过 <code>npm i -g yarn</code> 进行了安装,现在想知道怎么样使用吗?如果你了解 <code>npm</code>,你已经会很大一部分啦!</p>
</summary>
<category term="Node" scheme="https://blog.ihoey.com/categories/Node/"/>
<category term="Node" scheme="https://blog.ihoey.com/tags/Node/"/>
<category term="npm" scheme="https://blog.ihoey.com/tags/npm/"/>
<category term="yarn" scheme="https://blog.ihoey.com/tags/yarn/"/>
</entry>
<entry>
<title>用 MySQL 导入 SQL 文件</title>
<link href="https://blog.ihoey.com/posts/MySQL/2018-04-13-mysql-import-table.html"/>
<id>https://blog.ihoey.com/posts/MySQL/2018-04-13-mysql-import-table.html</id>
<published>2018-04-13T05:07:19.000Z</published>
<updated>2018-05-04T10:02:25.000Z</updated>
<content type="html"><![CDATA[<p>记录一下数据库导入文件方法~</p><a id="more"></a><blockquote><p>方案一</p></blockquote><h2 id="登录数据库"><a href="#登录数据库" class="headerlink" title="登录数据库"></a>登录数据库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql -u root -p123</span><br></pre></td></tr></table></figure></div><h2 id="检查已经存在的数据库"><a href="#检查已经存在的数据库" class="headerlink" title="检查已经存在的数据库"></a>检查已经存在的数据库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show databases;</span><br></pre></td></tr></table></figure></div><h2 id="创建新的数据库"><a href="#创建新的数据库" class="headerlink" title="创建新的数据库"></a>创建新的数据库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">create database <span class="built_in">test</span>;</span><br><span class="line"><span class="comment"># 查看已经存在的是为了避免重复创建</span></span><br></pre></td></tr></table></figure></div><h2 id="选择你所创建的数据库"><a href="#选择你所创建的数据库" class="headerlink" title="选择你所创建的数据库"></a>选择你所创建的数据库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use <span class="built_in">test</span>;</span><br></pre></td></tr></table></figure></div><h2 id="导入sql文件"><a href="#导入sql文件" class="headerlink" title="导入sql文件"></a>导入sql文件</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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="built_in">source</span> db-test.sql;</span><br><span class="line"><span class="comment">#注意sql文件的路径</span></span><br></pre></td></tr></table></figure></div><h2 id="查看导入结果"><a href="#查看导入结果" class="headerlink" title="查看导入结果"></a>查看导入结果</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show tables;</span><br></pre></td></tr></table></figure></div><h2 id="退出数据库"><a href="#退出数据库" class="headerlink" title="退出数据库"></a>退出数据库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">exit</span>;</span><br></pre></td></tr></table></figure></div><blockquote><p>方案二</p></blockquote><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">mysql -u root -p123 <span class="built_in">test</span> < test.sql</span><br><span class="line"><span class="comment"># mysql -u 用户名 -p 密码 数据库名 < 数据库名.sql</span></span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<p>记录一下数据库导入文件方法~</p>
</summary>
<category term="MySQL" scheme="https://blog.ihoey.com/categories/MySQL/"/>
<category term="Ubuntu" scheme="https://blog.ihoey.com/tags/Ubuntu/"/>
<category term="shell" scheme="https://blog.ihoey.com/tags/shell/"/>
<category term="NoSQL" scheme="https://blog.ihoey.com/tags/NoSQL/"/>
<category term="MySQL" scheme="https://blog.ihoey.com/tags/MySQL/"/>
</entry>
<entry>
<title>解决 ubuntu 服务器中文乱码</title>
<link href="https://blog.ihoey.com/posts/Linux/2018-03-15-ubuntu-zh-CN-UTF-8.html"/>
<id>https://blog.ihoey.com/posts/Linux/2018-03-15-ubuntu-zh-CN-UTF-8.html</id>
<published>2018-03-15T11:02:18.000Z</published>
<updated>2018-05-04T10:02:34.000Z</updated>
<content type="html"><![CDATA[<p>之前买了阿里云的服务器,后来在上面编辑中文字符的时候发现乱码,在网上找了下解决方案,发现比较乱,有的也不太好用,特此整理了一下可用的一个方案。</p><a id="more"></a><h2 id="检查"><a href="#检查" class="headerlink" title="检查"></a>检查</h2><p>检查是否已经安装了中文包支持。终端输入: <code>sudo dpkg -l</code> 查看是否安装了中文支持( <code>language-pack-zh</code>)的软件包。</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>没有安装,那就终端执行命令 : <code>apt-get install language-pack-zh</code></p><h2 id="配置语言环境变量"><a href="#配置语言环境变量" class="headerlink" title="配置语言环境变量"></a>配置语言环境变量</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/environment</span><br></pre></td></tr></table></figure></div><p>在下面添加如下两行:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">LANG=<span class="string">"zh_CN.UTF-8"</span></span><br><span class="line">LANGUAGE=<span class="string">"zh_CN:zh:en_US:en"</span></span><br></pre></td></tr></table></figure></div><p>打开文件:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /var/lib/locales/supported.d/<span class="built_in">local</span></span><br></pre></td></tr></table></figure></div><p>添加zh_CN.GB2312字符集,如下:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">en_US.UTF-8 UTF-8</span><br><span class="line">zh_CN.UTF-8 UTF-8</span><br><span class="line">zh_CN.GBK GBK</span><br><span class="line">zh_CN GB2312</span><br></pre></td></tr></table></figure></div><p>保存后,执行命令:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo locale-gen</span><br></pre></td></tr></table></figure></div><h2 id="设置系统默认语言"><a href="#设置系统默认语言" class="headerlink" title="设置系统默认语言"></a>设置系统默认语言</h2><p><code>vim</code> 编辑器编辑文档:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /etc/default/locale</span><br></pre></td></tr></table></figure></div><p>修改为:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">LANG=<span class="string">"zh_CN.UTF-8"</span></span><br><span class="line">LANGUAGE=<span class="string">"zh_CN:zh:en_US:en"</span></span><br><span class="line"></span><br><span class="line">sudo reboot</span><br></pre></td></tr></table></figure></div><p>重启 <code>Ubuntu</code> 下次登录就是中文界面的了。而且也解决了系统中文的乱码现象。</p>]]></content>
<summary type="html">
<p>之前买了阿里云的服务器,后来在上面编辑中文字符的时候发现乱码,在网上找了下解决方案,发现比较乱,有的也不太好用,特此整理了一下可用的一个方案。</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="Ubuntu" scheme="https://blog.ihoey.com/tags/Ubuntu/"/>
<category term="Linux" scheme="https://blog.ihoey.com/tags/Linux/"/>
<category term="shell" scheme="https://blog.ihoey.com/tags/shell/"/>
</entry>
<entry>
<title>面试分享:2018阿里巴巴前端面试总结(题目+答案)</title>
<link href="https://blog.ihoey.com/posts/Interview/2018-02-28-alibaba-interview.html"/>
<id>https://blog.ihoey.com/posts/Interview/2018-02-28-alibaba-interview.html</id>
<published>2018-02-28T09:37:18.000Z</published>
<updated>2018-05-04T10:01:47.000Z</updated>
<content type="html"><![CDATA[<p>脑子混了记得不多了,记得多少就记录多少吧。。。。</p><a id="more"></a><h2 id="使用css实现一个持续的动画效果"><a href="#使用css实现一个持续的动画效果" class="headerlink" title="使用css实现一个持续的动画效果"></a>使用css实现一个持续的动画效果</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="CSS"><figure class="iseeu 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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">animation</span><span class="selector-pseudo">:mymove</span> 5<span class="selector-tag">s</span> <span class="selector-tag">infinite</span>;</span><br><span class="line">@<span class="keyword">keyframes</span> mymove {</span><br><span class="line"><span class="selector-tag">from</span> {<span class="attribute">top</span>:<span class="number">0px</span>;}</span><br><span class="line"><span class="selector-tag">to</span> {<span class="attribute">top</span>:<span class="number">200px</span>;}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>主要考:<code>animation</code> 用法</p><table><thead><tr><th style="text-align:left">值</th><th style="text-align:left">描述</th></tr></thead><tbody><tr><td style="text-align:left"><code>animation-name</code></td><td style="text-align:left">规定需要绑定到选择器的 keyframe 名称。</td></tr><tr><td style="text-align:left"><code>animation-duration</code></td><td style="text-align:left">规定完成动画所花费的时间,以秒或毫秒计。</td></tr><tr><td style="text-align:left"><code>animation-timing-function</code></td><td style="text-align:left">规定动画的速度曲线。</td></tr><tr><td style="text-align:left"><code>animation-delay</code></td><td style="text-align:left">规定在动画开始之前的延迟。</td></tr><tr><td style="text-align:left"><code>animation-iteration-count</code></td><td style="text-align:left">规定动画应该播放的次数。</td></tr><tr><td style="text-align:left"><code>animation-direction</code></td><td style="text-align:left">规定是否应该轮流反向播放动画。</td></tr></tbody></table><h2 id="使用js实现一个持续的动画效果"><a href="#使用js实现一个持续的动画效果" class="headerlink" title="使用js实现一个持续的动画效果"></a>使用js实现一个持续的动画效果</h2><p>最开始的思路是用定时器实现,最后没有想的太完整,面试官给出的答案是用<code>requestAnimationFrame</code>。</p><ul><li>定时器思路</li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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">var</span> e = <span class="built_in">document</span>.getElementById(<span class="string">'e'</span>)</span><br><span class="line"><span class="keyword">var</span> flag = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">var</span> left = <span class="number">0</span>;</span><br><span class="line">setInterval(<span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> left == <span class="number">0</span> ? flag = <span class="literal">true</span> : left == <span class="number">100</span> ? flag = <span class="literal">false</span> : <span class="string">''</span></span><br><span class="line"> flag ? e.style.left = <span class="string">` <span class="subst">${left++}</span>px`</span> : e.style.left = <span class="string">` <span class="subst">${left--}</span>px`</span></span><br><span class="line">}, <span class="number">1000</span> / <span class="number">60</span>)</span><br></pre></td></tr></table></figure></div><ul><li><code>requestAnimationFrame</code><br>由于之前没有用过这个 <code>API</code> 所以是现学的。</li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//兼容性处理</span></span><br><span class="line"><span class="built_in">window</span>.requestAnimFrame = (<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">window</span>.requestAnimationFrame ||</span><br><span class="line"> <span class="built_in">window</span>.webkitRequestAnimationFrame ||</span><br><span class="line"> <span class="built_in">window</span>.mozRequestAnimationFrame ||</span><br><span class="line"> <span class="function"><span class="keyword">function</span>(<span class="params">callback</span>)</span>{</span><br><span class="line"> <span class="built_in">window</span>.setTimeout(callback, <span class="number">1000</span> / <span class="number">60</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> e = <span class="built_in">document</span>.getElementById(<span class="string">"e"</span>);</span><br><span class="line"><span class="keyword">var</span> flag = <span class="literal">true</span>;</span><br><span class="line"><span class="keyword">var</span> left = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">render</span>(<span class="params"></span>) </span>{</span><br><span class="line"> left == <span class="number">0</span> ? flag = <span class="literal">true</span> : left == <span class="number">100</span> ? flag = <span class="literal">false</span> : <span class="string">''</span>;</span><br><span class="line"> flag ? e.style.left = <span class="string">` <span class="subst">${left++}</span>px`</span> :</span><br><span class="line"> e.style.left = <span class="string">` <span class="subst">${left--}</span>px`</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">animloop</span>(<span class="params"></span>) </span>{</span><br><span class="line"> render();</span><br><span class="line"> requestAnimFrame(animloop);</span><br><span class="line">})();</span><br></pre></td></tr></table></figure></div><p>不足之处请指正(毕竟是现学的)顺便查了一下优势:</p><ul><li>浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果</li><li>解决毫秒的不精确性</li><li>避免过度渲染(渲染频率太高、<code>tab</code> 不可见暂停等等)<br>注:<code>requestAnimFrame</code> 和 定时器一样也头一个类似的清除方法 <code>cancelAnimationFrame</code>。</li></ul><h2 id="右边宽度固定,左边自适应"><a href="#右边宽度固定,左边自适应" class="headerlink" title="右边宽度固定,左边自适应"></a>右边宽度固定,左边自适应</h2><p>第一种:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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 class="tag"><<span class="name">style</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined">body{</span></span><br><span class="line"><span class="undefined"> display: flex;</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="css"><span class="selector-class">.left</span>{</span></span><br><span class="line"><span class="undefined"> background-color: rebeccapurple;</span></span><br><span class="line"><span class="undefined"> height: 200px;</span></span><br><span class="line"><span class="undefined"> flex: 1;</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="css"><span class="selector-class">.right</span>{</span></span><br><span class="line"><span class="undefined"> background-color: red;</span></span><br><span class="line"><span class="undefined"> height: 200px;</span></span><br><span class="line"><span class="undefined"> width: 100px;</span></span><br><span class="line"><span class="undefined">}</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">style</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"left"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"right"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br></pre></td></tr></table></figure></div><p>第二种</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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="tag"><<span class="name">style</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"> div {</span></span><br><span class="line"><span class="undefined"> height: 200px;</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="css"> <span class="selector-class">.left</span> {</span></span><br><span class="line"><span class="undefined"> float: right;</span></span><br><span class="line"><span class="undefined"> width: 200px;</span></span><br><span class="line"><span class="undefined"> background-color: rebeccapurple;</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="css"> <span class="selector-class">.right</span> {</span></span><br><span class="line"><span class="undefined"> margin-right: 200px;</span></span><br><span class="line"><span class="undefined"> background-color: red;</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">style</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"left"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"right"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br></pre></td></tr></table></figure></div><p>暂时想到了两种。</p><h2 id="水平垂直居中"><a href="#水平垂直居中" class="headerlink" title="水平垂直居中"></a>水平垂直居中</h2><p>第一种</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="CSS"><figure class="iseeu 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><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="selector-id">#container</span>{</span><br><span class="line"> <span class="attribute">position</span>:relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#center</span>{</span><br><span class="line"> <span class="attribute">width</span>:<span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">height</span>:<span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">position</span>:absolute;</span><br><span class="line"> <span class="attribute">top</span>:<span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">left</span>:<span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">transform</span>: <span class="built_in">translate</span>(-50%,-50%);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>第二种</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="CSS"><figure class="iseeu 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><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="selector-id">#container</span>{</span><br><span class="line"> <span class="attribute">position</span>:relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#center</span>{</span><br><span class="line"> <span class="attribute">width</span>:<span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">height</span>:<span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">position</span>:absolute;</span><br><span class="line"> <span class="attribute">top</span>:<span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">left</span>:<span class="number">50%</span>;</span><br><span class="line"> <span class="attribute">margin</span>:-<span class="number">50px</span> <span class="number">0</span> <span class="number">0</span> -<span class="number">50px</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>第三种</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="CSS"><figure class="iseeu 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><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="selector-id">#container</span>{</span><br><span class="line"> <span class="attribute">position</span>:relative;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="selector-id">#center</span>{</span><br><span class="line"> <span class="attribute">position</span>:absolute;</span><br><span class="line"> <span class="attribute">margin</span>:auto;</span><br><span class="line"> <span class="attribute">top</span>:<span class="number">0</span>;</span><br><span class="line"> <span class="attribute">bottom</span>:<span class="number">0</span>;</span><br><span class="line"> <span class="attribute">left</span>:<span class="number">0</span>;</span><br><span class="line"> <span class="attribute">right</span>:<span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>第四种 <code>flex</code></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="CSS"><figure class="iseeu 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><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-id">#container</span>{</span><br><span class="line"> <span class="attribute">display</span>:flex;</span><br><span class="line"> <span class="attribute">justify-content</span>:center;</span><br><span class="line"> <span class="attribute">align-items</span>: center;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="四种定位的区别"><a href="#四种定位的区别" class="headerlink" title="四种定位的区别"></a>四种定位的区别</h2><ul><li><code>static</code> 是默认值</li><li><code>relative</code> 相对定位 相对于自身原有位置进行偏移,仍处于标准文档流中</li><li><code>absolute</code> 绝对定位 相对于最近的已定位的祖先元素, 有已定位(指<code>position</code>不是<code>static</code>的元素)祖先元素, 以最近的祖先元素为参考标准。如果无已定位祖先元素, 以<code>body</code>元素为偏移参照基准, 完全脱离了标准文档流。</li><li><code>fixed</code> 固定定位的元素会相对于视窗来定位,这意味着即便页面滚动,它还是会停留在相同的位置。一个固定定位元素不会保留它原本在页面应有的空隙。</li></ul><h2 id="Flex布局用的多吗?"><a href="#Flex布局用的多吗?" class="headerlink" title="Flex布局用的多吗?"></a>Flex布局用的多吗?</h2><p>因为项目考虑兼容 <code>IE9</code> 所以直接说用的不多</p><h2 id="移动端适配怎么做的?"><a href="#移动端适配怎么做的?" class="headerlink" title="移动端适配怎么做的?"></a>移动端适配怎么做的?</h2><p>使用媒体查询做的响应式布局,根据不同屏幕宽度加载不同<code>css</code>.</p><h2 id="let与var的区别?"><a href="#let与var的区别?" class="headerlink" title="let与var的区别?"></a>let与var的区别?</h2><p><code>let</code> 为 <code>ES6</code> 新添加申明变量的命令,它类似于 <code>var</code>,但是有以下不同:</p><ul><li><code>var</code> 声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象</li><li><code>let</code> 声明的变量,其作用域为该语句所在的代码块内,不存在变量提升</li><li><code>let</code> 不允许重复声明.</li></ul><h2 id="为什么-var-可以重复声明?(这个就不知道了)"><a href="#为什么-var-可以重复声明?(这个就不知道了)" class="headerlink" title="为什么 var 可以重复声明?(这个就不知道了)"></a>为什么 var 可以重复声明?(这个就不知道了)</h2><p>当我们执行代码时,我们可以简单的理解为新变量分配一块儿内存,命名为<code>a</code>,并赋值为<code>2</code>,但在运行的时候编译器与引擎还会进行两项额外的操作:判断变量是否已经声明:</p><ul><li>首先编译器对代码进行分析拆解,从左至右遇见<code>var a</code>,则编译器会询问作用域是否已经存在叫 <code>a</code> 的变量了,如果不存在,则招呼作用域声明一个新的变量<code>a</code>,若已经存在,则忽略<code>var</code> 继续向下编译,这时<code>a = 2</code>被编译成可执行的代码供引擎使用。</li><li>引擎遇见<code>a=2</code>时同样会询问在当前的作用域下是否有变量<code>a</code>,若存在,则将<code>a</code>赋值为<code>2</code>(由于第一步编译器忽略了重复声明的<code>var</code>,且作用域中已经有<code>a</code>,所以重复声明会发生值得覆盖而并不会报错)。若不存在,则顺着作用域链向上查找,若最终找到了变量<code>a</code>则将其赋值<code>2</code>,若没有找到,则招呼作用域声明一个变量<code>a</code>并赋值为<code>2</code>。<br><a href="http://www.cnblogs.com/neil080320/p/6529679.html" target="_blank" rel="noopener">参考链接</a></li></ul><h2 id="封装一个函数,参数是定时器的时间,-then执行回调函数。"><a href="#封装一个函数,参数是定时器的时间,-then执行回调函数。" class="headerlink" title="封装一个函数,参数是定时器的时间,.then执行回调函数。"></a>封装一个函数,参数是定时器的时间,.then执行回调函数。</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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="function"><span class="keyword">function</span> <span class="title">sleep</span> (<span class="params">time</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, time));</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="一个关于-this-指向的问题"><a href="#一个关于-this-指向的问题" class="headerlink" title="一个关于 this 指向的问题"></a>一个关于 this 指向的问题</h2><p>差不多应该是这样,记不太清了<br><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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">obj = {</span><br><span class="line"> name: <span class="string">'a'</span>,</span><br><span class="line"> getName : <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><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> fn = obj.getName</span><br><span class="line">obj.getName()</span><br><span class="line"><span class="keyword">var</span> fn2 = obj.getName()</span><br><span class="line">fn()</span><br><span class="line">fn2()</span><br></pre></td></tr></table></figure></div></p><h2 id="CommonJS-中的-require-exports-和-ES6-中的-import-export-区别?"><a href="#CommonJS-中的-require-exports-和-ES6-中的-import-export-区别?" class="headerlink" title="CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?"></a>CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?</h2><ul><li><code>CommonJS</code> 模块的重要特性是加载时执行,即脚本代码在 <code>require</code> 的时候,就会全部执行。一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。</li><li><code>ES6</code> 模块是动态引用,如果使用 <code>import</code> 从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。</li><li><code>import/export</code> 最终都是编译为 <code>require/exports</code> 来执行的。</li><li><code>CommonJS</code> 规范规定,每个模块内部,<code>module</code> 变量代表当前模块。这个变量是一个对象,它的 <code>exports</code> 属性(即 <code>module.exports</code> )是对外的接口。加载某个模块,其实是加载该模块的 <code>module.exports</code> 属性。</li><li><code>export</code> 命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。</li></ul><h2 id="一行代码实现数组去重?"><a href="#一行代码实现数组去重?" class="headerlink" title="一行代码实现数组去重?"></a>一行代码实现数组去重?</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[...new <span class="built_in">Set</span>([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">1</span>,<span class="string">'a'</span>,<span class="number">1</span>,<span class="string">'a'</span>])]</span><br></pre></td></tr></table></figure></div><h2 id="使用addEventListener点击li弹出内容,并且动态添加li之后有效"><a href="#使用addEventListener点击li弹出内容,并且动态添加li之后有效" class="headerlink" title="使用addEventListener点击li弹出内容,并且动态添加li之后有效"></a>使用addEventListener点击li弹出内容,并且动态添加li之后有效</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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="tag"><<span class="name">ul</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>1<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>2<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>3<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span>4<span class="tag"></<span class="name">li</span>></span></span><br><span class="line"><span class="tag"></<span class="name">ul</span>></span></span><br></pre></td></tr></table></figure></div><p>这个题没答出来😨😨</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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">var</span> ulNode = <span class="built_in">document</span>.getElementById(<span class="string">"ul"</span>);</span><br><span class="line"> ulNode.addEventListener(<span class="string">'click'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (e.target && e.target.nodeName.toUpperCase() == <span class="string">"LI"</span>) {</span><br><span class="line"> alert(e.target.innerHTML);</span><br><span class="line"> }</span><br><span class="line"> }, <span class="literal">false</span>);</span><br></pre></td></tr></table></figure></div><h2 id="怎么判断两个对象相等?"><a href="#怎么判断两个对象相等?" class="headerlink" title="怎么判断两个对象相等?"></a>怎么判断两个对象相等?</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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">obj={</span><br><span class="line"> a:<span class="number">1</span>,</span><br><span class="line"> b:<span class="number">2</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">obj2={</span><br><span class="line"> a:<span class="number">1</span>,</span><br><span class="line"> b:<span class="number">2</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">obj3={</span><br><span class="line"> a:<span class="number">1</span>,</span><br><span class="line"> b:<span class="string">'2'</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>最开始的思路是遍历来判断,但是最后好像没有说清楚,查了下,好像可以转换为字符串来判断。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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="built_in">JSON</span>.stringify(obj)==<span class="built_in">JSON</span>.stringify(obj2);<span class="comment">//true</span></span><br><span class="line"><span class="built_in">JSON</span>.stringify(obj)==<span class="built_in">JSON</span>.stringify(obj3);<span class="comment">//false</span></span><br></pre></td></tr></table></figure></div><h2 id="项目做过哪些性能优化?"><a href="#项目做过哪些性能优化?" class="headerlink" title="项目做过哪些性能优化?"></a>项目做过哪些性能优化?</h2><ul><li>减少 <code>HTTP</code> 请求数</li><li>减少 <code>DNS</code> 查询</li><li>使用 <code>CDN</code></li><li>避免重定向</li><li>图片懒加载</li><li>减少 <code>DOM</code> 元素数量</li><li>减少 <code>DOM</code> 操作</li><li>使用外部 <code>JavaScript</code> 和 <code>CSS</code></li><li>压缩 <code>JavaScript</code> 、 <code>CSS</code> 、字体、图片等</li><li>优化 <code>CSS Sprite</code></li><li>使用 <code>iconfont</code></li><li>字体裁剪</li><li>多域名分发划分内容到不同域名</li><li>尽量减少 <code>iframe</code> 使用</li><li>避免图片 <code>src</code> 为空</li><li>把样式表放在 <head> 中</head></li><li>把脚本放在页面底部<br>欢迎补充。。。</li></ul><h2 id="模块化开发是怎么做的?"><a href="#模块化开发是怎么做的?" class="headerlink" title="模块化开发是怎么做的?"></a>模块化开发是怎么做的?</h2><p>使用命名空间。</p><h2 id="有没有使用过webpack?"><a href="#有没有使用过webpack?" class="headerlink" title="有没有使用过webpack?"></a>有没有使用过webpack?</h2><p>我说Vue项目中使用了,然后就没问了。</p><h2 id="gulp自己写过任务吗?还是都用的模块?"><a href="#gulp自己写过任务吗?还是都用的模块?" class="headerlink" title="gulp自己写过任务吗?还是都用的模块?"></a>gulp自己写过任务吗?还是都用的模块?</h2><p>不知道怎么怎么回答,不都是使用模块来写的么,然后就说是使用模块。</p><h2 id="Vue-router-除了-router-link-怎么实现跳转"><a href="#Vue-router-除了-router-link-怎么实现跳转" class="headerlink" title="Vue router 除了 router-link 怎么实现跳转?"></a>Vue router 除了 router-link 怎么实现跳转?</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JS"><figure class="iseeu highlight /js"><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">router.go(<span class="number">1</span>)</span><br><span class="line">router.push(<span class="string">'/'</span>)</span><br></pre></td></tr></table></figure></div><h2 id="Vue-router-跳转和-location-href-有什么区别?"><a href="#Vue-router-跳转和-location-href-有什么区别?" class="headerlink" title="Vue router 跳转和 location.href 有什么区别?"></a>Vue router 跳转和 location.href 有什么区别?</h2><p><code>router</code> 是 <code>hash</code> 改变<br><code>location.href</code> 是页面跳转,刷新页面</p><h2 id="Vue-双向绑定实现原理?"><a href="#Vue-双向绑定实现原理?" class="headerlink" title="Vue 双向绑定实现原理?"></a>Vue 双向绑定实现原理?</h2><p>通过 <code>Object.defineProperty</code> 实现的</p><h2 id="你能实现一下双向绑定吗?😰😰"><a href="#你能实现一下双向绑定吗?😰😰" class="headerlink" title="你能实现一下双向绑定吗?😰😰"></a>你能实现一下双向绑定吗?😰😰</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">id</span>=<span class="string">"txt"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">p</span> <span class="attr">id</span>=<span class="string">"show-txt"</span>></span><span class="tag"></<span class="name">p</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> obj = {}</span></span><br><span class="line"><span class="javascript"> <span class="built_in">Object</span>.defineProperty(obj, <span class="string">'txt'</span>, {</span></span><br><span class="line"><span class="javascript"> get: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="keyword">return</span> obj</span></span><br><span class="line"><span class="undefined"> },</span></span><br><span class="line"><span class="javascript"> set: <span class="function"><span class="keyword">function</span> (<span class="params">newValue</span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">'txt'</span>).value = newValue</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.getElementById(<span class="string">'show-txt'</span>).innerHTML = newValue</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="javascript"> <span class="built_in">document</span>.addEventListener(<span class="string">'keyup'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span></span><br><span class="line"><span class="undefined"> obj.txt = e.target.value</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br></pre></td></tr></table></figure></div><h2 id="React-和-Vue-有什么区别?"><a href="#React-和-Vue-有什么区别?" class="headerlink" title="React 和 Vue 有什么区别?"></a>React 和 Vue 有什么区别?</h2><h2 id="Set-和-Map-数据结构(😨😨)"><a href="#Set-和-Map-数据结构(😨😨)" class="headerlink" title="Set 和 Map 数据结构(😨😨)"></a>Set 和 Map 数据结构(😨😨)</h2><ul><li><code>ES6</code> 提供了新的数据结构 <code>Set</code> 它类似于数组,但是成员的值都是唯一的,没有重复的值。</li><li><code>ES6</code> 提供了 <code>Map</code> 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,<code>Object</code> 结构提供了“字符串—值”的对应,<code>Map</code> 结构提供了“值—值”的对应,是一种更完善的 <code>Hash</code> 结构实现。</li></ul><h2 id="WeakMap-和-Map-的区别"><a href="#WeakMap-和-Map-的区别" class="headerlink" title="WeakMap 和 Map 的区别?"></a>WeakMap 和 Map 的区别?</h2><ul><li><code>WeakMap</code> 结构与 <code>Map</code> 结构基本类似,唯一的区别是它只接受对象作为键名( <code>null</code> 除外),不接受其他类型的值作为键名,而且键名所指向的对象,不计入垃圾回收机制。</li><li><code>WeakMap</code> 最大的好处是可以避免内存泄漏。一个仅被 <code>WeakMap</code> 作为 <code>key</code> 而引用的对象,会被垃圾回收器回收掉。</li><li><code>WeakMap</code> 拥有和 <code>Map</code> 类似的 <code>set(key, value)</code> 、<code>get(key)、has(key)</code>、<code>delete(key)</code> ~~ 和 <code>clear()</code> ~~方法, 没有任何与迭代有关的属性和方法。<br><code>clear</code> 已经废弃了.</li></ul><h2 id="重排和重绘"><a href="#重排和重绘" class="headerlink" title="重排和重绘"></a>重排和重绘</h2><ul><li>部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算。这被称为重排。注意这里至少会有一次重排-初始化页面布局。</li><li>由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新。这样的更新被称为重绘。</li></ul><h2 id="什么情况会触发重排和重绘?"><a href="#什么情况会触发重排和重绘?" class="headerlink" title="什么情况会触发重排和重绘?"></a>什么情况会触发重排和重绘?</h2><ul><li>添加、删除、更新 <code>DOM</code> 节点</li><li>通过 <code>display: none</code> 隐藏一个 <code>DOM</code> 节点-触发重排和重绘</li><li>通过 <code>visibility: hidden</code> 隐藏一个 <code>DOM</code> 节点-只触发重绘,因为没有几何变化</li><li>移动或者给页面中的 <code>DOM</code> 节点添加动画</li><li>添加一个样式表,调整样式属性</li><li>用户行为,例如调整窗口大小,改变字号,或者滚动。</li></ul><h2 id="浏览器缓存"><a href="#浏览器缓存" class="headerlink" title="浏览器缓存"></a>浏览器缓存</h2><p>浏览器缓存分为强缓存和协商缓存。当客户端请求某个资源时,获取缓存的流程如下:</p><ul><li>先根据这个资源的一些 <code>http header</code> 判断它是否命中强缓存,如果命中,则直接从本地获取缓存资源,不会发请求到服务器;</li><li>当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些<code>request header</code>验证这个资源是否命中协商缓存,称为<code>http</code>再验证,如果命中,服务器将请求返回,但不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就会从缓存中获取资源;</li><li>强缓存和协商缓存共同之处在于,如果命中缓存,服务器都不会返回资源;</li><li>区别是,强缓存不对发送请求到服务器,但协商缓存会。</li><li>当协商缓存也没命中时,服务器就会将资源发送回客户端。</li><li>当 <code>ctrl+f5</code> 强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;</li><li>当 <code>f5</code> 刷新网页时,跳过强缓存,但是会检查协商缓存;</li></ul><h3 id="强缓存"><a href="#强缓存" class="headerlink" title="强缓存"></a>强缓存</h3><ul><li>Expires(该字段是 <code>http1.0</code> 时的规范,值为一个绝对时间的 <code>GMT</code> 格式的时间字符串,代表缓存资源的过期时间)</li><li>Cache-Control:max-age(该字段是 <code>http1.1</code> 的规范,强缓存利用其 <code>max-age</code> 值来判断缓存资源的最大生命周期,它的值单位为秒)</li></ul><h3 id="协商缓存"><a href="#协商缓存" class="headerlink" title="协商缓存"></a>协商缓存</h3><ul><li>Last-Modified(值为资源最后更新时间,随服务器response返回)</li><li>If-Modified-Since(通过比较两个时间来判断资源在两次请求期间是否有过修改,如果没有修改,则命中协商缓存)</li><li>ETag(表示资源内容的唯一标识,随服务器response返回)</li><li>If-None-Match(服务器通过比较请求头部的If-None-Match与当前资源的ETag是否一致来判断资源是否在两次请求之间有过修改,如果没有修改,则命中协商缓存)</li></ul><p><a href="https://juejin.im/entry/5a968ba56fb9a06340524128/detail" target="_blank" rel="noopener"><img src="https://badge.juejin.im/entry/5a968ba56fb9a06340524128/likes.svg?style=flat-square" alt=""></a></p>]]></content>
<summary type="html">
<p>脑子混了记得不多了,记得多少就记录多少吧。。。。</p>
</summary>
<category term="Interview" scheme="https://blog.ihoey.com/categories/Interview/"/>
<category term="面试" scheme="https://blog.ihoey.com/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>crontab 踩坑之绝对路径</title>
<link href="https://blog.ihoey.com/posts/Linux/2018-02-13-crontab-part1.html"/>
<id>https://blog.ihoey.com/posts/Linux/2018-02-13-crontab-part1.html</id>
<published>2018-02-13T02:09:26.000Z</published>
<updated>2018-05-10T08:48:38.533Z</updated>
<content type="html"><![CDATA[<p>由于放假后网络原因不方便使用电脑,需要创建一个 <code>crontab</code> 定时任务,用来在每天固定时间执行一个 <code>Shell</code> 脚本</p><a id="more"></a><h2 id="过程"><a href="#过程" class="headerlink" title="过程"></a>过程</h2><h3 id="添加计划任务"><a href="#添加计划任务" class="headerlink" title="添加计划任务"></a>添加计划任务</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">crontab -e</span><br><span class="line"></span><br><span class="line">* 10,19 * * * sh /root/home/cron.sh >> /root/home/temp.txt <span class="comment">#每天10点和19点执行一次,路径一定要是绝对路径</span></span><br><span class="line">30 9 * * * curl <span class="string">"https://sc.ftqq.com/SCU10625Td571049c53dd2e36148f134*****44ef59855df9df77c.send?text=-~"</span> <span class="comment"># 每天九点半执行一次</span></span><br></pre></td></tr></table></figure></div><h3 id="重启计划任务"><a href="#重启计划任务" class="headerlink" title="重启计划任务"></a>重启计划任务</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo service crond start</span><br></pre></td></tr></table></figure></div><p>到了时间以后发现第一个没有反应,第二个是有效的,后来一步步排查问题发现问题</p><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>在 <code>Shell</code> 脚本中,有对该脚本所在目录的相关文件进行操作的逻辑,在一开始实现时,对当前目录的文件操作时都是使用的相对目录,即 <code>./*</code> 。在终端直接 <code>sh</code> 执行时没有任何问题,正常结束,而一旦在 <code>crontab</code> 中定时执行时,就出现问题,如提示 <code>file not found</code> 或者没有任何输出等错误。</p><p>之前的脚本内容是</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">echo</span> <span class="string">"test"</span> >> temp.txt</span><br><span class="line">git add .</span><br><span class="line">git commit -m<span class="string">"更新"</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure></div><h2 id="解决问题"><a href="#解决问题" class="headerlink" title="解决问题"></a>解决问题</h2><p>出现问题后,我在脚本中试着打印出 <code>crontab</code> 执行时的当前目录,如 <code>curPath=$(pwd)</code> ,执行后发现,打印出的结果为 <code>$HOME</code> 的目录,而非脚本所在的原始目录,这就造成了在脚本中使用相对路径时出现找不到的情况。</p><p>找到问题后,解决方法有两个:</p><ul><li>将相对路径替换为绝对路径。(ps:如脚本中包含某些Shell命令,且命令的某些参数为默认当前目录的,都需要显式的给出绝对路径)</li><li>在操作相对路径之前,使用 <code>cd /....../</code> ,在执行脚本时强制进入到该目录。</li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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="built_in">cd</span> /root/home/</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">"test"</span> >> temp.txt</span><br><span class="line">git add .</span><br><span class="line">git commit -m<span class="string">"更新"</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure></div><h3 id="排查问题可以查看日志来看是否执行"><a href="#排查问题可以查看日志来看是否执行" class="headerlink" title="排查问题可以查看日志来看是否执行"></a>排查问题可以查看日志来看是否执行</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">#编辑rsyslog</span></span><br><span class="line">sudo vim /etc/rsyslog.d/50-default.conf</span><br><span class="line"><span class="comment">#找到rsyslog中cron一行将前面的注释符#去掉</span></span><br><span class="line">cron.* /var/<span class="built_in">log</span>/cron.log</span><br><span class="line"><span class="comment">#重启rsyslog</span></span><br><span class="line">sudo service rsyslog restart</span><br><span class="line"><span class="comment"># 然后查看日志,到指定时间看是否执行</span></span><br><span class="line">tail -f /var/<span class="built_in">log</span>/cron.log</span><br></pre></td></tr></table></figure></div><h2 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h2><p>系统在执行定时任务时,是不会加载任何环境变量的,所以当脚本需要环境变量时,可以通过在脚本中添加 <code>source /etc/profile</code> 命令来使配置生效。</p>]]></content>
<summary type="html">
<p>由于放假后网络原因不方便使用电脑,需要创建一个 <code>crontab</code> 定时任务,用来在每天固定时间执行一个 <code>Shell</code> 脚本</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="Ubuntu" scheme="https://blog.ihoey.com/tags/Ubuntu/"/>
<category term="Cron" scheme="https://blog.ihoey.com/tags/Cron/"/>
<category term="Linux" scheme="https://blog.ihoey.com/tags/Linux/"/>
<category term="shell" scheme="https://blog.ihoey.com/tags/shell/"/>
</entry>
<entry>
<title>SED 命令简明教程</title>
<link href="https://blog.ihoey.com/posts/Linux/2018-01-31-linux-sed-command.html"/>
<id>https://blog.ihoey.com/posts/Linux/2018-01-31-linux-sed-command.html</id>
<published>2018-01-31T11:03:52.000Z</published>
<updated>2018-05-04T10:02:19.000Z</updated>
<content type="html"><![CDATA[<p><code>awk</code>于1977年出生,今年36岁本命年,<code>sed</code>比<code>awk</code>大2-3岁,<code>awk</code>就像林妹妹,sed就是宝玉哥哥了。所以 林妹妹跳了个<code>Topless</code>,他的哥哥<code>sed</code>坐不住了,也一定要出来抖一抖。</p><p><code>sed</code>全名叫<code>stream editor</code>,流编辑器,用程序的方式来编辑文本,相当的<code>hacker</code>啊。<code>sed</code>基本上就是玩正则模式匹配,所以,玩<code>sed</code>的人,正则表达式一般都比较强。</p><a id="more"></a><p>同样,本篇文章不会说<code>sed</code>的全部东西,你可以参看 <a href="http://www.gnu.org/software/sed/manual/sed.html" target="_blank" rel="noopener"><code>sed</code>的手册</a> ,我这里主要还是想和大家竞争一下那些从手机指缝间或马桶里流走的时间,用这些时间来学习一些东西。当然,接下来的还是要靠大家自己双手。</p><h2 id="用s命令替换"><a href="#用s命令替换" class="headerlink" title="用s命令替换"></a>用s命令替换</h2><p>我使用下面的这段文本做演示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">cat pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is my dog</span><br><span class="line"> my dog's name is frank</span><br><span class="line">This is my fish</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>把其中的<code>my</code>字符串替换成<code>Hao Chen’s</code>,下面的语句应该很好理解(<code>s</code>表示替换命令,<code>/my/</code>表示匹配<code>my</code>,<code>/Hao Chen’s/</code>表示把匹配替换成<code>Hao Chen’s</code>,<code>/g</code> 表示一行上的替换所有的匹配):</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed "s/my/Hao Chen's/g" pets.txt</span><br><span class="line">"This is Hao Chen's cat</span><br><span class="line"> Hao Chen's cat's name is betty</span><br><span class="line">This is Hao Chen's dog</span><br><span class="line"> Hao Chen's dog's name is frank</span><br><span class="line">This is Hao Chen's fish</span><br><span class="line"> Hao Chen's fish's name is george</span><br><span class="line">This is Hao Chen's goat</span><br><span class="line"> Hao Chen's goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>注意:如果你要使用单引号,那么你没办法通过<code>\'</code>这样来转义,就有双引号就可以了,在双引号内可以用<code>\"</code>来转义。</p><p>再注意:上面的<code>sed</code>并没有对文件的内容改变,只是把处理过后的内容输出,如果你要写回文件,你可以使用重定向,如:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu highlight /shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sed "s/my/Hao Chen's/g" pets.txt > hao_pets.txt</span><br></pre></td></tr></table></figure></div><p>或使用 <code>-i</code> 参数直接修改文件内容:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu highlight /shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sed -i "s/my/Hao Chen's/g" pets.txt</span><br></pre></td></tr></table></figure></div><p>在每一行最前面加点东西:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/^/#/g' pets.txt</span><br><span class="line"><span class="meta">#</span><span class="bash">This is my cat</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my cat<span class="string">'s name is betty</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash">This is my dog</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my dog<span class="string">'s name is frank</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash">This is my fish</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my fish<span class="string">'s name is george</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash">This is my goat</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my goat<span class="string">'s name is adam</span></span></span><br></pre></td></tr></table></figure></div><p>在每一行最后面加点东西:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/$/ --- /g' pets.txt</span><br><span class="line">"This is my cat ---</span><br><span class="line"> my cat's name is betty ---</span><br><span class="line">This is my dog ---</span><br><span class="line"> my dog's name is frank ---</span><br><span class="line">This is my fish ---</span><br><span class="line"> my fish's name is george ---</span><br><span class="line">This is my goat ---</span><br><span class="line"> my goat's name is adam ---"</span><br></pre></td></tr></table></figure></div><p>顺手介绍一下正则表达式的一些最基本的东西:</p><ul><li><code>^</code> 表示一行的开头。如:<code>/^#/</code> 以<code>#</code>开头的匹配。</li><li><code>$</code> 表示一行的结尾。如:<code>/}$/</code> 以<code>}</code>结尾的匹配。</li><li><code>\<</code> 表示词首。 如:<code>\<abc</code> 表示以 <code>abc</code> 为首的詞。</li><li><code>\></code> 表示词尾。 如:<code>abc\></code> 表示以 <code>abc</code> 結尾的詞。</li><li><code>.</code> 表示任何单个字符。</li><li><code>*</code> 表示某个字符出现了0次或多次。</li><li><code>[ ]</code> 字符集合。 如:<code>[abc]</code> 表示匹配a或b或c,还有 <code>[a-zA-Z]</code> 表示匹配所有的<code>26</code>个字符。如果其中有<code>^</code>表示反,如 <code>[^a]</code> 表示非a的字符</li></ul><p>正规则表达式是一些很牛的事,比如我们要去掉某<code>html</code>中的<code>tags</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">b</span>></span>This<span class="tag"></<span class="name">b</span>></span> is what <span class="tag"><<span class="name">span</span> <span class="attr">style</span>=<span class="string">"text-decoration: underline;"</span>></span>I<span class="tag"></<span class="name">span</span>></span> meant. Understand?</span><br></pre></td></tr></table></figure></div><p>看看我们的<code>sed</code>命令</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 如果你这样搞的话,就会有问题</span></span><br><span class="line">sed 's/<.*>//g' html.txt</span><br><span class="line">" Understand?"</span><br><span class="line"></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="string">'[^>]'</span> 指定了除了>的字符重复0次或多次。</span></span><br><span class="line">sed 's/<[^>]*>//g' html.txt</span><br><span class="line">"This is what I meant. Understand?"</span><br></pre></td></tr></table></figure></div><p>我们再来看看指定需要替换的内容:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed "3s/my/your/g" pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is your dog</span><br><span class="line"> my dog's name is frank</span><br><span class="line">This is my fish</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>下面的命令只替换第<code>3</code>到第<code>6</code>行的文本。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed "3,6s/my/your/g" pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is your dog</span><br><span class="line"> your dog's name is frank</span><br><span class="line">This is your fish</span><br><span class="line"> your fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br></pre></td></tr></table></figure></div><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">cat my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>只替换每一行的第一个s:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/s/S/1' my.txt</span><br><span class="line">"ThiS is my cat, my cat's name is betty</span><br><span class="line">ThiS is my dog, my dog's name is frank</span><br><span class="line">ThiS is my fish, my fish's name is george</span><br><span class="line">ThiS is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>只替换每一行的第二个<code>s</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/s/S/2' my.txt</span><br><span class="line">"This iS my cat, my cat's name is betty</span><br><span class="line">This iS my dog, my dog's name is frank</span><br><span class="line">This iS my fish, my fish's name is george</span><br><span class="line">This iS my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>只替换第一行的第<code>3</code>个以后的<code>s</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/s/S/3g' my.txt</span><br><span class="line">"This is my cat, my cat'S name iS betty</span><br><span class="line">This is my dog, my dog'S name iS frank</span><br><span class="line">This is my fiSh, my fiSh'S name iS george</span><br><span class="line">This is my goat, my goat'S name iS adam"</span><br></pre></td></tr></table></figure></div><h2 id="多个匹配"><a href="#多个匹配" class="headerlink" title="多个匹配"></a>多个匹配</h2><p>如果我们需要一次替换多个模式,可参看下面的示例:(第一个模式把第一行到第三行的<code>my</code>替换成<code>your</code>,第二个则把第<code>3</code>行以后的<code>This</code>替换成了<code>That</code>)</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed '1,3s/my/your/g; 3,$s/This/That/g' my.txt</span><br><span class="line">"This is your cat, your cat's name is betty</span><br><span class="line">This is your dog, your dog's name is frank</span><br><span class="line">That is your fish, your fish's name is george</span><br><span class="line">That is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>上面的命令等价于:(注:下面使用的是<code>sed</code>的<code>-e</code>命令行参数)</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu highlight /shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sed -e '1,3s/my/your/g' -e '3,$s/This/That/g' my.txt</span><br></pre></td></tr></table></figure></div><p>我们可以使用&来当做被匹配的变量,然后可以在基本左右加点东西。如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/my/[&]/g' my.txt</span><br><span class="line">"This is [my] cat, [my] cat's name is betty</span><br><span class="line">This is [my] dog, [my] dog's name is frank</span><br><span class="line">This is [my] fish, [my] fish's name is george</span><br><span class="line">This is [my] goat, [my] goat's name is adam"</span><br></pre></td></tr></table></figure></div><h2 id="圆括号匹配"><a href="#圆括号匹配" class="headerlink" title="圆括号匹配"></a>圆括号匹配</h2><p>使用圆括号匹配的示例:(圆括号括起来的正则表达式所匹配的字符串会可以当成变量来使用,<code>sed</code>中使用的是<code>\1,\2…</code>)</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 's/This is my \([^,&]*\),.*is \(.*\)/\1:\2/g' my.txt</span><br><span class="line">"cat:betty</span><br><span class="line">dog:frank</span><br><span class="line">fish:george</span><br><span class="line">goat:adam"</span><br></pre></td></tr></table></figure></div><p>上面这个例子中的正则表达式有点复杂,解开如下(去掉转义字符):</p><ul><li>正则为:<code>This is my ([^,]*),.*is (.*)</code></li><li>匹配为:<code>This is my (cat),……….is (betty)</code></li></ul><p>然后:<code>\1</code>就是<code>cat</code>,<code>\2</code>就是<code>betty</code></p><h2 id="sed的命令"><a href="#sed的命令" class="headerlink" title="sed的命令"></a>sed的命令</h2><p>让我们回到最一开始的例子<code>pets.txt</code>,让我们来看几个命令:</p><h3 id="N命令"><a href="#N命令" class="headerlink" title="N命令"></a>N命令</h3><p>先来看<code>N</code>命令 —— 把下一行的内容纳入当成缓冲区做匹配。</p><p>下面的的示例会把原文本中的偶数行纳入奇数行匹配,而<code>s</code>只匹配并替换一次,所以,就成了下面的结果:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 'N;s/my/your/' pets.txt</span><br><span class="line">"This is your cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is your dog</span><br><span class="line"> my dog's name is frank</span><br><span class="line">This is your fish</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is your goat</span><br><span class="line"> my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>也就是说,原来的文件成了:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">This is my cat\n my cat's name is betty</span><br><span class="line">This is my dog\n my dog's name is frank</span><br><span class="line">This is my fish\n my fish's name is george</span><br><span class="line">This is my goat\n my goat's name is adam</span><br></pre></td></tr></table></figure></div><p>这样一来,下面的例子你就明白了,</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 'N;s/\n/,/' pets.txt</span><br><span class="line">This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam</span><br></pre></td></tr></table></figure></div><h3 id="a命令和i命令"><a href="#a命令和i命令" class="headerlink" title="a命令和i命令"></a>a命令和i命令</h3><p><code>a</code>命令就是<code>append</code>, <code>i</code>命令就是<code>insert</code>,它们是用来添加行的。如:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 其中的1i表明,其要在第1行前插入一行(insert)</span></span><br><span class="line">sed "1 i This is my monkey, my monkey's name is wukong" my.txt</span><br><span class="line">"This is my monkey, my monkey's name is wukong</span><br><span class="line">This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 其中的1a表明,其要在最后一行后追加一行(append)</span></span><br><span class="line">sed "1 a This is my monkey, my monkey's name is wukong" my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my monkey, my monkey's name is wukong</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>我们可以运用匹配来添加文本:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 注意其中的/fish/a,这意思是匹配到/fish/后就追加一行</span></span><br><span class="line">sed "/fish/a This is my monkey, my monkey's name is wukong" my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my monkey, my monkey's name is wukong</span><br><span class="line">This is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><p>下面这个例子是对每一行都挺插入:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed "/my/a ----" my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">----</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">----</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">----</span><br><span class="line">This is my goat, my goat's name is adam</span><br><span class="line">----"</span><br></pre></td></tr></table></figure></div><h3 id="c命令"><a href="#c命令" class="headerlink" title="c命令"></a>c命令</h3><p><code>c</code> 命令是替换匹配行</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed "2 c This is my monkey, my monkey's name is wukong" my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my monkey, my monkey's name is wukong</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br><span class="line"></span><br><span class="line">sed "/fish/c This is my monkey, my monkey's name is wukong" my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my monkey, my monkey's name is wukong</span><br><span class="line">This is my goat, my goat's name is adam"</span><br></pre></td></tr></table></figure></div><h3 id="d命令"><a href="#d命令" class="headerlink" title="d命令"></a>d命令</h3><p>删除匹配行</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed '/fish/d' my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my goat, my goat's name is adam"</span><br><span class="line"></span><br><span class="line">sed '2d' my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br><span class="line"></span><br><span class="line">sed '2,$d' my.txt</span><br><span class="line">"This is my cat, my cat's name is betty"</span><br></pre></td></tr></table></figure></div><h3 id="p命令"><a href="#p命令" class="headerlink" title="p命令"></a>p命令</h3><p>打印命令</p><p>你可以把这个命令当成<code>grep</code>式的命令</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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><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="meta">#</span><span class="bash"> 匹配fish并输出,可以看到fish的那一行被打了两遍,</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> 这是因为sed处理时会把处理的信息输出</span></span><br><span class="line">sed '/fish/p' my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my fish, my fish's name is george</span><br><span class="line">This is my goat, my goat's name is adam"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 使用n参数就好了</span></span><br><span class="line">sed -n '/fish/p' my.txt</span><br><span class="line">"This is my fish, my fish's name is george"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 从一个模式到另一个模式</span></span><br><span class="line">sed -n '/dog/,/fish/p' my.txt</span><br><span class="line">"This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash">从第一行打印到匹配fish成功的那一行</span></span><br><span class="line">sed -n '1,/fish/p' my.txt</span><br><span class="line">"This is my cat, my cat's name is betty</span><br><span class="line">This is my dog, my dog's name is frank</span><br><span class="line">This is my fish, my fish's name is george"</span><br></pre></td></tr></table></figure></div><h2 id="几个知识点"><a href="#几个知识点" class="headerlink" title="几个知识点"></a>几个知识点</h2><p>好了,下面我们要介绍四个<code>sed</code>的基本知识点:</p><h3 id="Pattern-Space"><a href="#Pattern-Space" class="headerlink" title="Pattern Space"></a>Pattern Space</h3><p>第零个是关于<code>-n</code>参数的,大家也许没看懂,没关系,我们来看一下<code>sed</code>处理文本的伪代码,并了解一下<code>Pattern Space</code>的概念:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">foreach line in file {</span><br><span class="line"> //放入把行Pattern_Space</span><br><span class="line"> Pattern_Space <= line;</span><br><span class="line"></span><br><span class="line"> // 对每个pattern space执行sed命令</span><br><span class="line"> Pattern_Space <= EXEC(sed_cmd, Pattern_Space);</span><br><span class="line"></span><br><span class="line"> // 如果没有指定 -n 则输出处理后的Pattern_Space</span><br><span class="line"> if (sed option hasn\'t "-n") {</span><br><span class="line"> print Pattern_Space</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h3 id="Address"><a href="#Address" class="headerlink" title="Address"></a>Address</h3><p>第一个是关于<code>address</code>,几乎上述所有的命令都是这样的(注:其中的<code>!</code>表示匹配成功后是否执行命令)</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu highlight /shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[address[,address]][!]{cmd}</span><br></pre></td></tr></table></figure></div><p><code>address</code>可以是一个数字,也可以是一个模式,你可以通过逗号要分隔两个<code>address</code> 表示两个<code>address</code>的区间,参执行命令<code>cmd</code>,伪代码如下:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">bool bexec = false</span><br><span class="line">foreach line in file {</span><br><span class="line"> if ( match(address1) ){</span><br><span class="line"> bexec = true;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if ( bexec == true) {</span><br><span class="line"> EXEC(sed_cmd);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if ( match (address2) ) {</span><br><span class="line"> bexec = false;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>关于<code>address</code>可以使用相对位置,如:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 其中的+3表示后面连续3行</span></span><br><span class="line">sed '/dog/,+3s/^/# /g' pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line"><span class="meta">#</span><span class="bash"> This is my dog</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my dog<span class="string">'s name is frank</span></span></span><br><span class="line"><span class="meta">#</span><span class="bash"> This is my fish</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> my fish<span class="string">'s name is george</span></span></span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br></pre></td></tr></table></figure></div><h3 id="命令打包"><a href="#命令打包" class="headerlink" title="命令打包"></a>命令打包</h3><p>第二个是<code>cmd</code>可以是多个,它们可以用分号分开,可以用大括号括起来作为嵌套命令。下面是几个例子:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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><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></pre></td><td class="code"><pre><span class="line">cat pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is my dog</span><br><span class="line"> my dog's name is frank</span><br><span class="line">This is my fish</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 对3行到第6行,执行命令/This/d</span></span><br><span class="line">sed '3,6 {/This/d}' pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line"> my dog's name is frank</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 对3行到第6行,匹配/This/成功后,再匹配/fish/,成功后执行d命令</span></span><br><span class="line">sed '3,6 {/This/{/fish/d}}' pets.txt</span><br><span class="line">"This is my cat</span><br><span class="line"> my cat's name is betty</span><br><span class="line">This is my dog</span><br><span class="line"> my dog's name is frank</span><br><span class="line"> my fish's name is george</span><br><span class="line">This is my goat</span><br><span class="line"> my goat's name is adam"</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 从第一行到最后一行,如果匹配到This,则删除之;如果前面有空格,则去除空格</span></span><br><span class="line">sed '1,${/This/d;s/^ *//g}' pets.txt</span><br><span class="line">"my cat's name is betty</span><br><span class="line">my dog's name is frank</span><br><span class="line">my fish's name is george</span><br><span class="line">my goat's name is adam"</span><br></pre></td></tr></table></figure></div><h3 id="Hold-Space"><a href="#Hold-Space" class="headerlink" title="Hold Space"></a>Hold Space</h3><p>第三个我们再来看一下 <code>Hold Space</code></p><p>接下来,我们需要了解一下<code>Hold Space</code>的概念,我们先来看几个命令:</p><ul><li><code>g</code>: 将<code>hold space</code>中的内容拷贝到<code>pattern space</code>中,原来<code>pattern space</code>里的内容清除</li><li><code>G</code>: 将<code>hold space</code>中的内容<code>append</code>到<code>pattern space\n</code>后</li><li><code>h</code>: 将<code>pattern space</code>中的内容拷贝到<code>hold space</code>中,原来的<code>hold space</code>里的内容被清除</li><li><code>H</code>: 将<code>pattern space</code>中的内容<code>append</code>到<code>hold space\n</code>后</li><li><code>x</code>: 交换<code>pattern space</code>和<code>hold space</code>的内容</li></ul><p>这些命令有什么用?我们来看两个示例吧,用到的示例文件是:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">cat t.txt</span><br><span class="line">one</span><br><span class="line">two</span><br><span class="line">three</span><br></pre></td></tr></table></figure></div><p>第一个示例:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed 'H;g' t.txt</span><br><span class="line">one</span><br><span class="line"></span><br><span class="line">one</span><br><span class="line">two</span><br><span class="line"></span><br><span class="line">one</span><br><span class="line">two</span><br><span class="line">three</span><br></pre></td></tr></table></figure></div><p>是不是有点没看懂,我作个图你就看懂了。</p><p><img src="https://cdn.dode.top/blog/sed_demo_00.jpg" alt=""></p><p>第二个示例,反序了一个文件的行:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">sed '1!G;h;$!d' t.txt</span><br><span class="line">three</span><br><span class="line">two</span><br><span class="line">one</span><br></pre></td></tr></table></figure></div><p>其中的 <code>'1!G;h;$!d'</code> 可拆解为三个命令</p><ul><li><code>1!G</code> —— 只有第一行不执行<code>G</code>命令,将<code>hold space</code>中的内容<code>append</code>回到<code>pattern space</code></li><li><code>h</code> —— 第一行都执行<code>h</code>命令,将<code>pattern space</code>中的内容拷贝到<code>hold space</code>中</li><li><code>$!d</code> —— 除了最后一行不执行<code>d</code>命令,其它行都执行<code>d</code>命令,删除当前行</li></ul><p>这个执行序列很难理解,做个图如下大家就明白了:</p><p><img src="https://cdn.dode.top/blog/sed_demo.jpg" alt=""></p><p>就先说这么多吧,希望对大家有用。</p>]]></content>
<summary type="html">
<p><code>awk</code>于1977年出生,今年36岁本命年,<code>sed</code>比<code>awk</code>大2-3岁,<code>awk</code>就像林妹妹,sed就是宝玉哥哥了。所以 林妹妹跳了个<code>Topless</code>,他的哥哥<code>sed</code>坐不住了,也一定要出来抖一抖。</p>
<p><code>sed</code>全名叫<code>stream editor</code>,流编辑器,用程序的方式来编辑文本,相当的<code>hacker</code>啊。<code>sed</code>基本上就是玩正则模式匹配,所以,玩<code>sed</code>的人,正则表达式一般都比较强。</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="Ubuntu" scheme="https://blog.ihoey.com/tags/Ubuntu/"/>
<category term="Linux" scheme="https://blog.ihoey.com/tags/Linux/"/>
<category term="shell" scheme="https://blog.ihoey.com/tags/shell/"/>
</entry>
<entry>
<title>在Hexo博客 NexT主题中部署Wildfire评论系统</title>
<link href="https://blog.ihoey.com/posts/Linux/2018-01-30-Hexo-NexT-Wildfire.html"/>
<id>https://blog.ihoey.com/posts/Linux/2018-01-30-Hexo-NexT-Wildfire.html</id>
<published>2018-01-30T04:14:00.000Z</published>
<updated>2018-05-04T10:01:55.000Z</updated>
<content type="html"><![CDATA[<p>前一段时间,发现了一个评论系统很好用,果断把这个评论系统换到自己的博客里了。</p><p>所以本文主要讲在 <code>Hexo</code> 的 <code>NexT</code> 主题中如何使用 <code>Wildfire</code> ,至于其他的博客以及其他的主题中如何使用的问题,我就不多说了。有需求的朋友可以去项目主页提问,或者在这里提问也可以。如果我懂得话一定会回答的。</p><a id="more"></a><h2 id="修改-NexT-评论模板"><a href="#修改-NexT-评论模板" class="headerlink" title="修改 NexT 评论模板"></a>修改 NexT 评论模板</h2><p>在你的博客项目中,打开./themes/next/layout/_partials/comments.swig 这个文件。<br>将文件尾部的内容:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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">{% if page.comments %}</span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"comments"</span> <span class="attr">id</span>=<span class="string">"comments"</span>></span></span><br><span class="line"> ...</span><br><span class="line"> ...</span><br><span class="line"> {% elseif theme.livere_uid %}</span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"lv-container"</span> <span class="attr">data-id</span>=<span class="string">"city"</span> <span class="attr">data-uid</span>=<span class="string">"{{ theme.livere_uid }}"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="comment"><!-- 添加内容的位置在这里 --></span></span><br><span class="line"> {% endif %}</span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line">{% endif %}</span><br></pre></td></tr></table></figure></div><p>修改为成下面的内容:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="HTML"><figure class="iseeu highlight /html"><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></pre></td><td class="code"><pre><span class="line">{% if page.comments %}</span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"comments"</span> <span class="attr">id</span>=<span class="string">"comments"</span>></span></span><br><span class="line"> ...</span><br><span class="line"> ...</span><br><span class="line"> {% elseif theme.livere_uid %}</span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"lv-container"</span> <span class="attr">data-id</span>=<span class="string">"city"</span> <span class="attr">data-uid</span>=<span class="string">"{{ theme.livere_uid }}"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> {% elseif theme.wildfire.enable %}</span><br><span class="line"> <span class="tag"><<span class="name">style</span> <span class="attr">type</span>=<span class="string">"text/css"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"> .wildfire_thread a {border-bottom: none}</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">style</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wildfire_thread"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">type</span>=<span class="string">"text/javascript"</span>></span><span class="undefined"></span></span><br><span class="line"><span class="undefined"> var wildfireConfig = () => ({</span></span><br><span class="line"><span class="undefined"> databaseProvider: '{{ theme.wildfire.database_provider }}',</span></span><br><span class="line"><span class="undefined"> databaseConfig: {</span></span><br><span class="line"><span class="undefined"> {% if (theme.wildfire.database_provider) === 'wilddog' %}</span></span><br><span class="line"><span class="undefined"> siteId: '{{ theme.wildfire.site_id }}'</span></span><br><span class="line"><span class="undefined"> {% elseif (theme.wildfire.database_provider) === 'firebase' %}</span></span><br><span class="line"><span class="undefined"> apiKey: '{{ theme.wildfire.api_key }}',</span></span><br><span class="line"><span class="undefined"> authDomain: '{{ theme.wildfire.auth_domain }}',</span></span><br><span class="line"><span class="undefined"> databaseURL: '{{ theme.wildfire.database_url }}',</span></span><br><span class="line"><span class="undefined"> projectId: '{{ theme.wildfire.project_id }}',</span></span><br><span class="line"><span class="undefined"> storageBucket: '{{theme.wildfire.storage_bucket}}',</span></span><br><span class="line"><span class="undefined"> messagingSenderId: '{{theme.wildfire.messaging_sender_id}}'</span></span><br><span class="line"><span class="undefined"> {% endif %}</span></span><br><span class="line"><span class="undefined"> },</span></span><br><span class="line"><span class="undefined"> theme: '{{theme.wildfire.theme}}',</span></span><br><span class="line"><span class="undefined"> locale: '{{theme.wildfire.locale}}'</span></span><br><span class="line"><span class="undefined"> })</span></span><br><span class="line"><span class="undefined"> </span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">'https://unpkg.com/wildfire/dist/wildfire.auto.js'</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> {% endif %}</span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line">{% endif %}</span><br></pre></td></tr></table></figure></div><p>然后保存。</p><h2 id="增加设置内容"><a href="#增加设置内容" class="headerlink" title="增加设置内容"></a>增加设置内容</h2><p>打开主题设置文件 <code>./themes/next/_config.yml</code>,注意:不是站点设置文件。<br>将下面的代码复制到合适的位置(包含全部注释):</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="YAML"><figure class="iseeu highlight /yaml"><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="comment"># Wildfire Support</span></span><br><span class="line"><span class="attr">wildfire:</span></span><br><span class="line"> <span class="comment">## 开启Wildfire支持</span></span><br><span class="line"><span class="attr"> enable:</span> <span class="literal">true</span></span><br><span class="line"> <span class="comment">## 主题颜色,目前可选值为light/dark两种,默认为light</span></span><br><span class="line"><span class="attr"> theme:</span> <span class="string">light</span></span><br><span class="line"> <span class="comment">## 系统语言,目前可选值为en/zh-CN两种,默认为en</span></span><br><span class="line"><span class="attr"> locale:</span> <span class="string">zh-CN</span></span><br><span class="line"> <span class="comment">## Wilddog配置</span></span><br><span class="line"><span class="attr"> database_provider:</span> <span class="string">wilddog</span></span><br><span class="line"><span class="attr"> site_id:</span> <span class="string">site_id</span></span><br><span class="line"><span class="attr"> avatarURL:</span> <span class="attr">https://image.flaticon.com/icons/svg/621/621863.svg</span></span><br><span class="line"> <span class="comment">## Firebase配置</span></span><br><span class="line"> <span class="comment"># database_provider: firebase</span></span><br><span class="line"> <span class="comment"># api_key: apiKey</span></span><br><span class="line"> <span class="comment"># auth_domain: authDomain</span></span><br><span class="line"> <span class="comment"># database_url: databaseURL</span></span><br><span class="line"> <span class="comment"># project_id: projectId</span></span><br><span class="line"> <span class="comment"># storage_bucket: storageBucket</span></span><br><span class="line"> <span class="comment"># messaging_sender_id: messagingSenderId</span></span><br></pre></td></tr></table></figure></div><p>需要注意的是,复制的时候不要修改这个配置的缩进关系。另外 <code>Wilddog</code> 和 <code>Firebase</code> 两者的配置只能选择其一。比如要使用 <code>Wilddog</code> 的话,配置内容就如下:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="YAML"><figure class="iseeu highlight /yaml"><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="attr">wildfire:</span></span><br><span class="line"><span class="attr"> enable:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr"> theme:</span> <span class="string">light</span></span><br><span class="line"><span class="attr"> locale:</span> <span class="string">zh-CN</span></span><br><span class="line"><span class="attr"> database_provider:</span> <span class="string">wilddog</span></span><br><span class="line"><span class="attr"> site_id:</span> <span class="string">wdg_my_site_id</span></span><br></pre></td></tr></table></figure></div><p>如果要使用 <code>Firebase</code> 则配置选择为如下:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="YAML"><figure class="iseeu highlight /yaml"><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="attr">wildfire:</span></span><br><span class="line"><span class="attr"> enable:</span> <span class="literal">true</span></span><br><span class="line"><span class="attr"> theme:</span> <span class="string">light</span></span><br><span class="line"><span class="attr"> locale:</span> <span class="string">zh-CN</span></span><br><span class="line"><span class="attr"> database_provider:</span> <span class="string">firebase</span></span><br><span class="line"><span class="attr"> api_key:</span> <span class="string">your_apiKey</span></span><br><span class="line"><span class="attr"> auth_domain:</span> <span class="string">your_authDomain</span></span><br><span class="line"><span class="attr"> database_url:</span> <span class="string">your_databaseURL</span></span><br><span class="line"><span class="attr"> project_id:</span> <span class="string">your_projectId</span></span><br><span class="line"><span class="attr"> storage_bucket:</span> <span class="string">your_storageBucket</span></span><br><span class="line"><span class="attr"> messaging_sender_id:</span> <span class="string">your_messagingSenderId</span></span><br></pre></td></tr></table></figure></div><p>上面的值呢,就需要大家从自己建好的 <code>APP</code> 应用中拷贝过来了。</p><h2 id="完成部署"><a href="#完成部署" class="headerlink" title="完成部署"></a>完成部署</h2><p>下面就可以直接 <code>hexo generate</code> 生成就可以了。很简单吧~<br>当然如果还有什么问题,欢迎在这里提问哦。</p>]]></content>
<summary type="html">
<p>前一段时间,发现了一个评论系统很好用,果断把这个评论系统换到自己的博客里了。</p>
<p>所以本文主要讲在 <code>Hexo</code> 的 <code>NexT</code> 主题中如何使用 <code>Wildfire</code> ,至于其他的博客以及其他的主题中如何使用的问题,我就不多说了。有需求的朋友可以去项目主页提问,或者在这里提问也可以。如果我懂得话一定会回答的。</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="comment" scheme="https://blog.ihoey.com/tags/comment/"/>
</entry>
<entry>
<title>使用 JavaScript 实现简单的拖拽</title>
<link href="https://blog.ihoey.com/posts/javascript/2018-01-29-use-javascript-to-achieve-simple-drag-and-drop.html"/>
<id>https://blog.ihoey.com/posts/javascript/2018-01-29-use-javascript-to-achieve-simple-drag-and-drop.html</id>
<published>2018-01-29T09:12:55.000Z</published>
<updated>2018-05-04T10:02:35.000Z</updated>
<content type="html"><![CDATA[<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><p>使用 <code>JavaScript</code> 实现拖拽的步骤:</p><ul><li>让元素捕获事件(<code>mousedown</code>, <code>mousemove</code> & <code>mouseup</code>)</li><li>单击并不释放,触发 <code>mousedown</code>,标记开始拖拽,并获取元素和鼠标的位置</li><li>拖动鼠标,触发 <code>mousemove</code>,不断的获取鼠标的位置,并通过计算重新确定元素的位置</li><li>释放师表,触发 <code>mouseup</code>,结束拖拽,确定元素位置并更新</li></ul><a id="more"></a><p><strong>被拖拽的元素必须是相对父元素定位,或者是绝对定位</strong></p><h2 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h2><p>绑定事件</p><p>首先,对拖拽的元素绑定 <code>mousedown</code> 时间,使其触发对应的函数,获取元素与鼠标的位置。在 <code>document</code> 对象上绑定 <code>mousemove</code> 和 <code>mouseup</code> 事件,不在拖拽的元素上绑定是因为当鼠标移动太快而超出元素的范围时会停止拖拽,而绑定在 <code>document</code> 上则可以避免这样的事情发生。拖拽再快都不会超出 <code>document</code> 的范围。</p><p><strong>绑定事件:</strong></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> box = <span class="built_in">document</span>.getElementById(<span class="string">'box'</span>);</span><br><span class="line"></span><br><span class="line">box.onmousedown = down;</span><br><span class="line"><span class="built_in">document</span>.onmousemove = move;</span><br><span class="line"><span class="built_in">document</span>.onmouseup = up;</span><br></pre></td></tr></table></figure></div><h2 id="获取鼠标位置"><a href="#获取鼠标位置" class="headerlink" title="获取鼠标位置"></a>获取鼠标位置</h2><p>鼠标位置可以在 <code>event</code> 对象中获得,常用的属性有:</p><ul><li><code>clientX / clientY</code> : 相对浏览器窗口坐标</li><li><code>offsetX / offsetY</code> : 相对事件目标对象坐标</li><li><code>pageX / pageY</code> : 相对 <code>document</code> 对象坐标</li></ul><p>一般鼠标的位置使用 <code>pageX / pageY</code> 获取,但是 IE 不支持这两个属性。所以在 IE 中使用 <code>event.clientX + document.body.scrollLeft - document.body.clientLeft;</code>获取鼠标的位置。</p><p><strong>获取鼠标位置的函数:</strong></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">getMouseXY</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> x = <span class="number">0</span>, y = <span class="number">0</span>;</span><br><span class="line"> e = e || <span class="built_in">window</span>.event;</span><br><span class="line"> <span class="keyword">if</span> (e.pageX) {</span><br><span class="line"> x = e.pageX;</span><br><span class="line"> y = e.pageY;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> x = e.clientX + <span class="built_in">document</span>.body.scrollLeft - <span class="built_in">document</span>.body.clientLeft;</span><br><span class="line"> y = e.clientY + <span class="built_in">document</span>.body.scrollTop - <span class="built_in">document</span>.body.clientTop;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> x: x,</span><br><span class="line"> y: y</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="事件触发函数"><a href="#事件触发函数" class="headerlink" title="事件触发函数"></a>事件触发函数</h2><p><code>mousedown</code><br>当鼠标移动到元素内并点击元素不放时,触发 <code>mousedown</code> 事件。按照上面的步骤,这一步是获取元素与鼠标的位置,用于触发 <code>mousemove</code> 时计算元素的位置。</p><p><strong><code>mousedown</code> 触发的函数:</strong></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">down</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> dragging = <span class="literal">true</span>;</span><br><span class="line"> boxX = box.offsetLeft;</span><br><span class="line"> boxY = box.offsetTop;</span><br><span class="line"> mouseX = <span class="built_in">parseInt</span>(getMouseXY(e).x);</span><br><span class="line"> mouseY = <span class="built_in">parseInt</span>(getMouseXY(e).y);</span><br><span class="line"> offsetX = mouseX - boxX;</span><br><span class="line"> offsetY = mouseY - boxY;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>boxX / boxY</code> 为元素左上角相对于已定位的父元素(相对或者绝对定位的父元素)的偏移的像素值,即元素左上角的坐标。<br><code>mouseX / mouseY</code> 是通过 <code>getMouseXY</code> 函数获得的鼠标的坐标。<br><code>offsetX/ offsetY</code> 是鼠标相对于元素坐标(左上角坐标)的坐标。<br><code>mousemove</code><br>当鼠标移动时,不断的获取鼠标的位置,并计算元素的新坐标修改元素的位置样式。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">move</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (dragging) {</span><br><span class="line"> <span class="keyword">var</span> x = getMouseXY(e).x - offsetX;</span><br><span class="line"> <span class="keyword">var</span> y = getMouseXY(e).y - offsetY;</span><br><span class="line"> <span class="keyword">var</span> width = <span class="built_in">document</span>.documentElement.clientWidth - box.offsetWidth;</span><br><span class="line"> <span class="keyword">var</span> height = <span class="built_in">document</span>.documentElement.clientHeight - box.offsetHeight;</span><br><span class="line"></span><br><span class="line"> x = <span class="built_in">Math</span>.min(<span class="built_in">Math</span>.max(<span class="number">0</span>, x), width);</span><br><span class="line"> y = <span class="built_in">Math</span>.min(<span class="built_in">Math</span>.max(<span class="number">0</span>, y), height);</span><br><span class="line"></span><br><span class="line"> box.style.left = x + <span class="string">'px'</span>;</span><br><span class="line"> box.style.top = y + <span class="string">'px'</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>变量 <code>width / height</code> 表示可移动的位置的大小,这里是 <code>document</code> 减去元素的大小(元素不会超出可移动的范围)。<br><code>Math.min</code> 使得元素不会超出可移动访问的右边界(元素 <code>x</code> 坐标不会超过 <code>width</code>),<code>Math.max</code> 使得元素不会超出可移动范围的左边界(元素的 x 坐标不小于 0)。<br>最后将改变后的元素 <code>left</code> 与 <code>top</code> 值应用当元素上,即修改元素的样式。<br><code>mouseup</code><br>拖拽结束,取消拖拽的标记。使其触发 <code>mousemove</code> 事件,但不做任何处理。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">up</span>(<span class="params">e</span>) </span>{</span><br><span class="line"> dragging = <span class="literal">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="在线演示"><a href="#在线演示" class="headerlink" title="在线演示"></a>在线演示</h2><iframe src="//fiddle.jshell.net/Lr73mn89/show/light/" frameborder="0" sandbox="allow-forms allow-scripts allow-same-origin allow-modals allow-popups" allow="midi; geolocation; microphone; camera" width="100%" height="200px"></iframe><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>上面使用的简单的 <code>JavaScript</code> 代码实现了元素的拖拽,但并没有对兼容性问题全面考虑,也没有对性能优化,有不必要的事件触发。</p>]]></content>
<summary type="html">
<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><p>使用 <code>JavaScript</code> 实现拖拽的步骤:</p>
<ul>
<li>让元素捕获事件(<code>mousedown</code>, <code>mousemove</code> &amp; <code>mouseup</code>)</li>
<li>单击并不释放,触发 <code>mousedown</code>,标记开始拖拽,并获取元素和鼠标的位置</li>
<li>拖动鼠标,触发 <code>mousemove</code>,不断的获取鼠标的位置,并通过计算重新确定元素的位置</li>
<li>释放师表,触发 <code>mouseup</code>,结束拖拽,确定元素位置并更新</li>
</ul>
</summary>
<category term="javascript" scheme="https://blog.ihoey.com/categories/javascript/"/>
<category term="javascript" scheme="https://blog.ihoey.com/tags/javascript/"/>
</entry>
<entry>
<title>Merry Christmas</title>
<link href="https://blog.ihoey.com/posts/Node/2017-12-25-Merry-Christmas.html"/>
<id>https://blog.ihoey.com/posts/Node/2017-12-25-Merry-Christmas.html</id>
<published>2017-12-25T00:05:52.000Z</published>
<updated>2018-05-04T10:02:22.000Z</updated>
<content type="html"><![CDATA[<p><code>npm</code> 没有写入文档的一个命令:<code>npm xmas</code></p><a id="more"></a><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu 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><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"> /\</span><br><span class="line"> / \</span><br><span class="line"> /i⁂i \</span><br><span class="line"> / \</span><br><span class="line"> /。 ⁂\</span><br><span class="line"> / ⸛ ⸮\</span><br><span class="line"> / i⁂ @ 。⸮\</span><br><span class="line"> /i&i ⸛。 i ⸮ 。\</span><br><span class="line"> / 。 @ @ \</span><br><span class="line"> / 。 。。& 。 i@@ & \</span><br><span class="line"> /& 。⸛ @ ⸛@ i ⸮ \</span><br><span class="line"> / ⸮ i ⸮@ @@⁂ ⁂@ ⸮⸛\</span><br><span class="line"> / & 。 i⁂⁂⸮\</span><br><span class="line"> /i 。 @ @ ⁂ ⸮ i& \</span><br><span class="line"> / ⸛ ⸛ ⸮ 。 && @ ⸛ ⸮\</span><br><span class="line"> / ⸛i ⁂。& ⁂ 。 ⸛。@ ⸮@ ⸮ \</span><br><span class="line"> / & ⸮ ⁂ @ ⸮ ⁂。 i⸮ ii ⸛&\</span><br><span class="line"> /。 @⸮ @& 。⸛⸛ i⸮ ⸮。。 ⸛ 。\</span><br><span class="line"> / ⸮ i 。 i ⸮ 。 i i ⸮ ⸛ 。 i \</span><br><span class="line">/。@ & i。⸮⁂。 i i i。 @ \</span><br><span class="line">^^^^^^^^^^^^^^^^^^^| |^^^^^^^^^^^^^^^^^^^</span><br><span class="line"> | |</span><br></pre></td></tr></table></figure></div><p>在终端是很漂亮的,因为是彩色的,大家可以自己试试,我这里就不贴图了,放个<a href="https://juejin.im/pin/5a3c77d06d6def0ae5017d84" target="_blank" rel="noopener">链接</a>吧</p><p>祝大家圣诞节快乐🎄</p>]]></content>
<summary type="html">
<p><code>npm</code> 没有写入文档的一个命令:<code>npm xmas</code></p>
</summary>
<category term="Node" scheme="https://blog.ihoey.com/categories/Node/"/>
<category term="日常水文" scheme="https://blog.ihoey.com/tags/%E6%97%A5%E5%B8%B8%E6%B0%B4%E6%96%87/"/>
</entry>
<entry>
<title>JAVASCRIPT生成图形验证码</title>
<link href="https://blog.ihoey.com/posts/javascript/2017-11-29-javascript-getGverify.html"/>
<id>https://blog.ihoey.com/posts/javascript/2017-11-29-javascript-getGverify.html</id>
<published>2017-11-29T11:49:01.000Z</published>
<updated>2018-05-04T10:01:57.000Z</updated>
<content type="html"><![CDATA[<p>本文实例为大家分享了js生成图形验证码的具体代码,供大家参考,具体内容如下</p><a id="more"></a><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br></pre></td><td class="code"><pre><span class="line">getGVerify: <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">GVerify</span>(<span class="params">options</span>) </span>{ <span class="comment">//创建一个图形验证码对象,接收options对象为参数</span></span><br><span class="line"> <span class="keyword">this</span>.options = { <span class="comment">//默认options参数值</span></span><br><span class="line"> id: <span class="string">""</span>, <span class="comment">//容器Id</span></span><br><span class="line"> canvasId: <span class="string">"verifyCanvas"</span>, <span class="comment">//canvas的ID</span></span><br><span class="line"> width: <span class="string">"100"</span>, <span class="comment">//默认canvas宽度</span></span><br><span class="line"> height: <span class="string">"30"</span>, <span class="comment">//默认canvas高度</span></span><br><span class="line"> type: <span class="string">"blend"</span>, <span class="comment">//图形验证码默认类型blend:数字字母混合类型、number:纯数字、letter:纯字母</span></span><br><span class="line"> code: <span class="string">""</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(options) == <span class="string">"[object Object]"</span>) { <span class="comment">//判断传入参数类型</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> options) { <span class="comment">//根据传入的参数,修改默认参数值</span></span><br><span class="line"> <span class="keyword">this</span>.options[i] = options[i];</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">this</span>.options.id = options;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>.options.numArr = <span class="string">"0,1,2,3,4,5,6,7,8,9"</span>.split(<span class="string">","</span>);</span><br><span class="line"> <span class="keyword">this</span>.options.letterArr = getAllLetter();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>._init();</span><br><span class="line"> <span class="keyword">this</span>.refresh();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> GVerify.prototype = {</span><br><span class="line"> <span class="comment">/**版本号**/</span></span><br><span class="line"> version: <span class="string">'1.0.0'</span>,</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**初始化方法**/</span></span><br><span class="line"> _init: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> con = <span class="built_in">document</span>.getElementById(<span class="keyword">this</span>.options.id);</span><br><span class="line"> <span class="keyword">var</span> canvas = <span class="built_in">document</span>.createElement(<span class="string">"canvas"</span>);</span><br><span class="line"> <span class="comment">/*this.options.width = con.offsetWidth > 0 ? con.offsetWidth : "100";</span></span><br><span class="line"><span class="comment"> this.options.height = con.offsetHeight > 0 ? con.offsetHeight : "30";*/</span></span><br><span class="line"> canvas.id = <span class="keyword">this</span>.options.canvasId;</span><br><span class="line"> canvas.width = <span class="keyword">this</span>.options.width;</span><br><span class="line"> canvas.height = <span class="keyword">this</span>.options.height;</span><br><span class="line"> canvas.style.cursor = <span class="string">"pointer"</span>;</span><br><span class="line"> canvas.innerHTML = <span class="string">"您的浏览器版本不支持canvas"</span>;</span><br><span class="line"> con.appendChild(canvas);</span><br><span class="line"> <span class="keyword">var</span> parent = <span class="keyword">this</span>;</span><br><span class="line"> canvas.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> parent.refresh();</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"> refresh: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.options.code = <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">var</span> canvas = <span class="built_in">document</span>.getElementById(<span class="keyword">this</span>.options.canvasId);</span><br><span class="line"> <span class="keyword">if</span> (canvas.getContext) {</span><br><span class="line"> <span class="keyword">var</span> ctx = canvas.getContext(<span class="string">'2d'</span>);</span><br><span class="line"> }</span><br><span class="line"> ctx.textBaseline = <span class="string">"middle"</span>;</span><br><span class="line"></span><br><span class="line"> ctx.fillStyle = randomColor(<span class="number">180</span>, <span class="number">240</span>);</span><br><span class="line"> ctx.fillRect(<span class="number">0</span>, <span class="number">0</span>, <span class="keyword">this</span>.options.width, <span class="keyword">this</span>.options.height);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.options.type == <span class="string">"blend"</span>) { <span class="comment">//判断验证码类型</span></span><br><span class="line"> <span class="keyword">var</span> txtArr = <span class="keyword">this</span>.options.numArr.concat(<span class="keyword">this</span>.options.letterArr);</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">this</span>.options.type == <span class="string">"number"</span>) {</span><br><span class="line"> <span class="keyword">var</span> txtArr = <span class="keyword">this</span>.options.numArr;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">var</span> txtArr = <span class="keyword">this</span>.options.letterArr;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">1</span>; i <= <span class="number">4</span>; i++) {</span><br><span class="line"> <span class="keyword">var</span> txt = txtArr[randomNum(<span class="number">0</span>, txtArr.length)];</span><br><span class="line"> <span class="keyword">this</span>.options.code += txt;</span><br><span class="line"> ctx.font = <span class="string">'20px SimHei'</span>;</span><br><span class="line"> <span class="comment">//ctx.font = randomNum(this.options.height/2, this.options.height) + 'px SimHei'; //随机生成字体大小</span></span><br><span class="line"> ctx.fillStyle = randomColor(<span class="number">50</span>, <span class="number">160</span>); <span class="comment">//随机生成字体颜色</span></span><br><span class="line"> <span class="comment">/* ctx.shadowOffsetX = randomNum(-3, 3);</span></span><br><span class="line"><span class="comment"> ctx.shadowOffsetY = randomNum(-3, 3);*/</span></span><br><span class="line"> ctx.shadowBlur = randomNum(<span class="number">-3</span>, <span class="number">3</span>);</span><br><span class="line"> ctx.shadowColor = <span class="string">"rgba(0, 0, 0, 0.3)"</span>;</span><br><span class="line"> <span class="keyword">var</span> x = <span class="keyword">this</span>.options.width / <span class="number">5</span> * i;</span><br><span class="line"> <span class="keyword">var</span> y = <span class="keyword">this</span>.options.height / <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">var</span> deg = randomNum(<span class="number">-30</span>, <span class="number">30</span>);</span><br><span class="line"> <span class="comment">/**设置旋转角度和坐标原点**/</span></span><br><span class="line"> ctx.translate(x, y);</span><br><span class="line"> ctx.rotate(deg * <span class="built_in">Math</span>.PI / <span class="number">180</span>);</span><br><span class="line"> ctx.fillText(txt, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="comment">/**恢复旋转角度和坐标原点**/</span></span><br><span class="line"> ctx.rotate(-deg * <span class="built_in">Math</span>.PI / <span class="number">180</span>);</span><br><span class="line"> ctx.translate(-x, -y);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**绘制干扰线**/</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">4</span>; i++) {</span><br><span class="line"> ctx.strokeStyle = randomColor(<span class="number">40</span>, <span class="number">180</span>);</span><br><span class="line"> ctx.beginPath();</span><br><span class="line"> ctx.moveTo(randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.width / <span class="number">2</span>), randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.height / <span class="number">2</span>));</span><br><span class="line"> ctx.lineTo(randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.width / <span class="number">2</span>), randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.height));</span><br><span class="line"> ctx.stroke();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**绘制干扰点**/</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="keyword">this</span>.options.width / <span class="number">4</span>; i++) {</span><br><span class="line"> ctx.fillStyle = randomColor(<span class="number">0</span>, <span class="number">255</span>);</span><br><span class="line"> ctx.beginPath();</span><br><span class="line"> ctx.arc(randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.width), randomNum(<span class="number">0</span>, <span class="keyword">this</span>.options.height), <span class="number">1</span>, <span class="number">0</span>, <span class="number">2</span> * <span class="built_in">Math</span>.PI);</span><br><span class="line"> ctx.fill();</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"> validate: <span class="function"><span class="keyword">function</span>(<span class="params">code</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> verifyCode = code.toLowerCase();</span><br><span class="line"> <span class="keyword">var</span> v_code = <span class="keyword">this</span>.options.code.toLowerCase();</span><br><span class="line"> <span class="keyword">if</span> (verifyCode == v_code) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</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="comment">/**生成字母数组**/</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">getAllLetter</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> letterStr = <span class="string">"a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z"</span>;</span><br><span class="line"> <span class="keyword">return</span> letterStr.split(<span class="string">","</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**生成一个随机数**/</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">randomNum</span>(<span class="params">min, max</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * (max - min) + min);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**生成一个随机色**/</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">randomColor</span>(<span class="params">min, max</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> r = randomNum(min, max);</span><br><span class="line"> <span class="keyword">var</span> g = randomNum(min, max);</span><br><span class="line"> <span class="keyword">var</span> b = randomNum(min, max);</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"rgb("</span> + r + <span class="string">","</span> + g + <span class="string">","</span> + b + <span class="string">")"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> GVerify(id);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="调用方法"><a href="#调用方法" class="headerlink" title="调用方法"></a>调用方法</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> verifyCode = <span class="keyword">new</span> GVerify(id);</span><br></pre></td></tr></table></figure></div><h2 id="验证方法"><a href="#验证方法" class="headerlink" title="验证方法"></a>验证方法</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">if</span> (verifyCode.validate(inputCode)) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line">esle {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<p>本文实例为大家分享了js生成图形验证码的具体代码,供大家参考,具体内容如下</p>
</summary>
<category term="javascript" scheme="https://blog.ihoey.com/categories/javascript/"/>
<category term="javascript" scheme="https://blog.ihoey.com/tags/javascript/"/>
<category term="原生Js" scheme="https://blog.ihoey.com/tags/%E5%8E%9F%E7%94%9FJs/"/>
<category term="tools" scheme="https://blog.ihoey.com/tags/tools/"/>
</entry>
<entry>
<title>笔记:NPM版本号自增,自动化发布NPM包</title>
<link href="https://blog.ihoey.com/posts/Node/2017-11-24-npm-version.html"/>
<id>https://blog.ihoey.com/posts/Node/2017-11-24-npm-version.html</id>
<published>2017-11-24T11:08:43.000Z</published>
<updated>2018-05-04T10:02:27.000Z</updated>
<content type="html"><![CDATA[<h1 id="提升一个包的版本号"><a href="#提升一个包的版本号" class="headerlink" title="提升一个包的版本号"></a>提升一个包的版本号</h1><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="SHELL"><figure class="iseeu highlight /shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]</span><br></pre></td></tr></table></figure></div><p><code>Description</code> 在一个包的目录下执行此命令,会提升版本号,并把这个新的版本号写进<code>package.json</code>文件,如果存在<code>npm-shrinkwrap.json</code>,也会写进去。</p><a id="more"></a><p>参数 <code>newversion</code> 应该是一个有效的semver字符串, 或者是<code>pathch</code>, <code>minor</code>, <code>major</code>等,<code>semver.inc</code>中定义的任意一个有效的。<br><code>major</code>: 版本号中第一段数字自增1 <code>minor</code>: 版本号中第一段数字自增1 <code>patch</code>: 版本号中第三段数字自增1<br>如果<code>package.json</code>中的<code>scripts</code>包含<code>version</code>,<code>preversion</code>,<code>postversion</code>,他们将作为<code>npm version</code>的一部分被执行。</p><p>可以将此放入到npm script流中,自动化构建!</p><h2 id="npm-不常用的命令"><a href="#npm-不常用的命令" class="headerlink" title="npm 不常用的命令"></a>npm 不常用的命令</h2><p><code>npm view</code> 包名 <code>version</code> 相看某个包的最新版本号<br><code>npm ls</code> 列出当前安装的所有包<br><code>npm root</code> 查看当前包的安装路径<br><code>npm root -g</code> 查看全局包的安装路径<br><code>npm config ls</code> 查看 <code>npm</code> 当前配置</p>]]></content>
<summary type="html">
<h1 id="提升一个包的版本号"><a href="#提升一个包的版本号" class="headerlink" title="提升一个包的版本号"></a>提升一个包的版本号</h1><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm version [&lt;newversion&gt; | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]</span><br></pre></td></tr></table></figure>
<p><code>Description</code> 在一个包的目录下执行此命令,会提升版本号,并把这个新的版本号写进<code>package.json</code>文件,如果存在<code>npm-shrinkwrap.json</code>,也会写进去。</p>
</summary>
<category term="Node" scheme="https://blog.ihoey.com/categories/Node/"/>
<category term="Node" scheme="https://blog.ihoey.com/tags/Node/"/>
<category term="NodeJs" scheme="https://blog.ihoey.com/tags/NodeJs/"/>
<category term="npm" scheme="https://blog.ihoey.com/tags/npm/"/>
</entry>
<entry>
<title>不可不知的Mac OS X专用命令行工具(持续更新中)</title>
<link href="https://blog.ihoey.com/posts/Mac/2017-11-21-Mac-OS-X-command-line-tool.html"/>
<id>https://blog.ihoey.com/posts/Mac/2017-11-21-Mac-OS-X-command-line-tool.html</id>
<published>2017-11-21T05:45:05.000Z</published>
<updated>2018-05-04T10:02:21.000Z</updated>
<content type="html"><![CDATA[<p><code>OS X</code> 的终端下通用很多 <code>Unix</code> 的工具和脚本。如果从 <code>Linux</code> 迁移到 <code>OS X</code> 会发现很多熟悉的命令和脚本工具,其实并没有任何区别。</p><p>但是 <code>OS X</code> 也提供了很多其他系统所没有的特别的命令行工具。我们推荐 <code>8</code> 个这类的工具,希望有助于提高在 <code>Mac</code> 的命令行环境下的效率。</p><a id="more"></a><h2 id="open"><a href="#open" class="headerlink" title="open"></a>open</h2><p><code>open</code> 命令用于打开文件、目录或执行程序。就等同于在命令行模式下,重复图形界面“双击”的动作。例如这个命令与在 <code>Finder</code> 中双击 <code>Safari</code> 是一样的:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`open /Applications/Safari.app/`</span><br></pre></td></tr></table></figure></div><p>如果 <code>open</code> 一个文件,则会使用关联的程序打开之。例如 <code>open screenshot.png</code> 会在 <code>Preview</code> 中查看图片。</p><p>可以使用 <code>-a</code> 选项要求自行选择打开的程序,或使用 <code>-e</code> 强制在 <code>TextEdit</code> 中编辑此文件。</p><p><code>open</code> 一个目录会在 <code>Finder</code> 窗口中打开此目录。一个很有用的技巧是 <code>open .</code> 打开当前目录。</p><p><code>Finder</code> 和终端的交互是双向的——把文件从 <code>Finder</code> 中拖入终端,就等同于把文件的完整路径粘贴到命令行中。</p><h2 id="pbcopy-和-pbpaste"><a href="#pbcopy-和-pbpaste" class="headerlink" title="pbcopy 和 pbpaste"></a>pbcopy 和 pbpaste</h2><p>这两个工具可以打通命令行和剪贴板。当然用鼠标操作复制粘贴也可以——但这两个工具的真正威力,发挥在将其用作Unix工具的时候。意思就是说:可以将这两个工具用作管道、IO重定向以及和其他命令的整合。例如:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls ~ | pbcopy</span><br></pre></td></tr></table></figure></div><p>可以将主目录的文件列表复制到剪贴板。</p><p>也可以把任意文件的内容读入剪贴板:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pbcopy < blogpost.txt</span><br></pre></td></tr></table></figure></div><p>做点更疯狂的尝试:获取最新 Google 纪念徽标(doodle)的 URL 并复制到剪贴板:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl http://www.google.com/doodles<span class="comment">#oodles/archive | grep -A5 'latest-doodle on' | grep 'img src' | sed s/.*'<img src="\/\/'/''/ | sed s/'" alt=".*'/''/ | pbcopy</span></span><br></pre></td></tr></table></figure></div><p>使用管道语法配合 <code>pbcopy</code> 工具可以简单的抓取命令的输出,而不必向上滚动翻阅终端窗口。可以用于和他人分享命令行的标准和错误输出。 <code>pbcopy</code> 和 <code>pbpaste</code> 也可以用于自动化或加速执行一些事情。例如把一些邮件的主题存为任务列表,就可以先从 <code>Mail.app</code> 中复制主题,再运行:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pbpaste >> tasklist.txt</span><br></pre></td></tr></table></figure></div><h2 id="mdfind"><a href="#mdfind" class="headerlink" title="mdfind"></a>mdfind</h2><p>许多 <code>Linux</code> 用户都发现 <code>Linux</code> 下查找文件的方法在 <code>OS X</code> 上不好用。当然经典的 <code>Unix find</code> 命令总是可以,但既然 <code>OS X</code> 有杀手级搜索工具 <code>Spotlight</code> ,为什么不在命令行上也使用一下呢?</p><p>这就是mdfind命令了。 <code>Spotlight</code> 能做的查找, <code>mdfind</code> 也能做。包括搜索文件的内容和元数据(<code>metadata</code>)。</p><p><code>mdfind</code>还提供更多的搜索选项。例如<code>-onlyin</code>选项可以约束搜索范围为一个目录:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mdfind -onlyin ~/Documents essay</span><br></pre></td></tr></table></figure></div><p><code>mdfind</code> 的索引数据库在后台自动更新,不过你也可以使用 <code>mdutil</code> 工具诊断数据库的问题,诊断 <code>mdfind</code> 的问题也等同于诊断 <code>Spotlight</code> 。如果 <code>Spotlight</code> 的工作不正确,<code>mdutil -E</code>命令可以强制重建索引数据库。也可以用 <code>mdutil -i</code> 彻底关闭文件索引。</p><h2 id="screencapture"><a href="#screencapture" class="headerlink" title="screencapture"></a>screencapture</h2><p><code>screencapture</code> 命令可以截图。和 <code>Grab.app</code> 与 <code>cmd + shift + 3</code> 或 <code>cmd + shift + 4</code> 热键相似,但更加的灵活。</p><p>抓取包含鼠标光标的全屏幕,并以 <code>image.png</code> 插入到新邮件的附件中:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">screencapture -C -M image.png</span><br></pre></td></tr></table></figure></div><p>用鼠标选择抓取窗口(及阴影)并复制到剪贴板:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">screencapture -c -W</span><br></pre></td></tr></table></figure></div><p>延时10秒后抓屏,并在Preview中打开之:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">screencapture -T 10 -P image.png</span><br></pre></td></tr></table></figure></div><p>用鼠标截取一个矩形区域,抓取后存为pdf文件:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">screencapture -s -t pdf image.pdf</span><br></pre></td></tr></table></figure></div><p>更多用法请参阅 <code>screencapture --help</code> 。</p><h2 id="launchctl"><a href="#launchctl" class="headerlink" title="launchctl"></a>launchctl</h2><p><code>launchctl</code> 管理 <code>OS X</code> 的启动脚本,控制启动计算机时需要开启的服务。也可以设置定时执行特定任务的脚本,就像 <code>Linux cron</code> 一样。</p><p>例如,开机时自动启动 <code>Apache</code> 服务器:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist</span><br></pre></td></tr></table></figure></div><p>运行 <code>launchctl list</code> 显示当前的启动脚本。 <code>sudo launchctl unload [path/to/script]</code> 停止正在运行的启动脚本,再加上 <code>-w</code> 选项即可去除开机启动。用这个方法可以一次去除 <code>Adobe</code> 或 <code>Microsoft Office</code> 所附带的所有“自动更新”后台程序。</p><p><code>Launchd</code> 脚本存储在以下位置:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">~/Library/LaunchAgents</span><br><span class="line">/Library/LaunchAgents</span><br><span class="line">/Library/LaunchDaemons</span><br><span class="line">/System/Library/LaunchAgents</span><br><span class="line">/System/Library/LaunchDaemons</span><br></pre></td></tr></table></figure></div><!-- 启动脚本的格式可以参考这篇blog,或苹果开发者中心的文章。你也可以使用Lingon应用来完全取代命令行。 --><h2 id="say"><a href="#say" class="headerlink" title="say"></a>say</h2><p><code>say</code> 是一个文本转语音(<code>TTS</code>)的有趣的工具,引擎和 <code>OS X</code> 使用的一样也是 <code>VoiceOver</code> 。如果不加其他选项,则会简单的语音朗读你给定的字符串:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">say <span class="string">"Never trust a computer you can't lift."</span></span><br><span class="line">用-f选项朗读特定文本文件,-o选项将朗读结果存为音频文件而不是播放:</span><br></pre></td></tr></table></figure></div><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">say -f mynovel.txt -o myaudiobook.aiff</span><br></pre></td></tr></table></figure></div><p><code>say</code> 命令可以用于在脚本中播放警告或提示。例如你可以设置 <code>Automator</code> 或 <code>Hazel</code> 脚本处理文件,并在任务完成时用 <code>say</code> 命令语音提示。</p><p>最好玩(不过也负罪感十足)的用法是:通过 <code>SSH</code> 连接到朋友或同事的计算机,然后用 <code>say</code> 命令给他们一个大大大惊喜……</p><p>可以在系统设置 <code>(System Preferences)</code> 的字典和语音 <code>(Dictation & Speech)</code> 选项中调整系统的语音选项甚至是语音的语言。</p><h2 id="diskutil"><a href="#diskutil" class="headerlink" title="diskutil"></a>diskutil</h2><p><code>diskutil</code> 是 <code>OS X</code> 磁盘工具应用的命令行版。既可以完成图形界面应用的所有任务,也可以做一些全盘填0、全盘填随机数等额外的任务。先使用 <code>diskutil list</code> 查看所有磁盘的列表和所在路径,然后对特定的磁盘执行命令。</p><p>警告:不正确使用 <code>diskutil</code> 可能意外的破坏磁盘数据。请小心。</p><h2 id="brew"><a href="#brew" class="headerlink" title="brew"></a>brew</h2><p><code>Homebrew</code> 程序提供的 <code>brew</code> ,严格来讲不是一个 <code>OS X</code> 的原生命令,但任何一个 <code>OS X</code> 的专业用户都不会错过它。“ <code>OS X</code> 缺少的包管理器”这个评价是恰如其分的。如果你曾经在 <code>Linux</code> 上使用过 <code>apt-get</code> (或其他包管理器——译者注),你就会发现 <code>Homebrew</code> 基本上是一样的。</p><p>使用 <code>brew</code> 可以简单的获取数千种开源工具和函数库。例如 <code>brew install imagemagick</code> 就可以安装 <code>ImageMagick</code> (几乎可以处理任何图像问题,转换任何格式的图像工具), <code>brew install node</code> 可以安装 <code>Node.js</code> (当前大热的服务器端 <code>JavaScript</code> 编程工具)。</p><p>也可以通过 <code>Homebrew</code> 做有趣的事情: <code>brew install archey</code> 会安装 <code>Archey</code> (在启动命令行时显示苹果 <code>LOGO</code> 和计算机硬件参数的小工具)。</p><p><img src="https://cdn.dode.top/item2.png" alt="item2"></p><p><code>Homebrew</code> 能安装的工具数量庞大,并且一直保持更新。<code>Homebrew</code> 最棒的一点是:所有的文件都被约束在 <code>/usr/local/</code> 一个位置之下。也就是说可以通过 <code>Homebrew</code> 安装新版软件的同时,保持系统内置的依赖库或其他软件不变。同时如果想彻底删除 <code>Homebrew</code> ,也变得非常简单。</p><p>(注:删除 <code>Homebrew</code> 最好还是不要直接删除 <code>/usr/local/</code> 。应当用这个卸载脚本点击预览。)</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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="meta">#!/bin/sh</span></span><br><span class="line"><span class="comment"># Just copy and paste the lines below (all at once, it won't work line by line!)</span></span><br><span class="line"><span class="comment"># MAKE SURE YOU ARE HAPPY WITH WHAT IT DOES FIRST! THERE IS NO WARRANTY!</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> abort {</span><br><span class="line"> <span class="built_in">echo</span> <span class="string">"<span class="variable">$1</span>"</span></span><br><span class="line"> <span class="built_in">exit</span> 1</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> -e</span><br><span class="line"></span><br><span class="line">/usr/bin/<span class="built_in">which</span> -s git || abort <span class="string">"brew install git first!"</span></span><br><span class="line"><span class="built_in">test</span> -d /usr/<span class="built_in">local</span>/.git || abort <span class="string">"brew update first!"</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> `brew --prefix`</span><br><span class="line">git checkout master</span><br><span class="line">git ls-files -z | pbcopy</span><br><span class="line">rm -rf Cellar</span><br><span class="line">bin/brew prune</span><br><span class="line">pbpaste | xargs -0 rm</span><br><span class="line">rm -r Library/Homebrew Library/Aliases Library/Formula Library/Contributions</span><br><span class="line"><span class="built_in">test</span> -d Library/LinkedKegs && rm -r Library/LinkedKegs</span><br><span class="line">rmdir -p bin Library share/man/man1 2> /dev/null</span><br><span class="line">rm -rf .git</span><br><span class="line">rm -rf ~/Library/Caches/Homebrew</span><br><span class="line">rm -rf ~/Library/Logs/Homebrew</span><br><span class="line">rm -rf /Library/Caches/Homebrew</span><br></pre></td></tr></table></figure></div><h2 id="在-访达-中预览-webp-格式图片"><a href="#在-访达-中预览-webp-格式图片" class="headerlink" title="在 访达 中预览 webp 格式图片"></a>在 访达 中预览 webp 格式图片</h2><p><code>WebP</code>文件的快速查看插件</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -L https://raw.github.com/emin/WebPQuickLook/master/install.sh | sh</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<p><code>OS X</code> 的终端下通用很多 <code>Unix</code> 的工具和脚本。如果从 <code>Linux</code> 迁移到 <code>OS X</code> 会发现很多熟悉的命令和脚本工具,其实并没有任何区别。</p>
<p>但是 <code>OS X</code> 也提供了很多其他系统所没有的特别的命令行工具。我们推荐 <code>8</code> 个这类的工具,希望有助于提高在 <code>Mac</code> 的命令行环境下的效率。</p>
</summary>
<category term="Mac" scheme="https://blog.ihoey.com/categories/Mac/"/>
<category term="Mac" scheme="https://blog.ihoey.com/tags/Mac/"/>
<category term="Mac OS" scheme="https://blog.ihoey.com/tags/Mac-OS/"/>
</entry>
<entry>
<title>继多说、网易关停之后该何去何从(网易云跟帖宣布2017年8月1日停止服务)</title>
<link href="https://blog.ihoey.com/posts/Linux/2017-07-06-comment_ru_he_xuan_ze.html"/>
<id>https://blog.ihoey.com/posts/Linux/2017-07-06-comment_ru_he_xuan_ze.html</id>
<published>2017-07-06T10:51:21.000Z</published>
<updated>2018-05-04T10:01:50.000Z</updated>
<content type="html"><![CDATA[<p><img src="https://cdn.dode.top/IHOEY_20170706_184907.png" alt="comment_ihoey"><br>继多说(多说关闭想必大家都已经知道了)关闭之后,很多人包括我,都转移到了网易云跟帖,现在网易云跟帖也正式发出公告宣布于2017年8月1日停止服务。</p><a id="more"></a><p>在多说关闭之后,使用网易云跟帖的站点非常多,昨日宣布停止服务,小编也感到很意外。官方在QQ群内通知并没有说明具体原因,或许还是评论服务的老话题——盈利!</p><p>并且QQ群管理称涉及网易自身评论,开源几乎不大!</p><p>这是提前在官方群得到的通知!<br><img src="https://cdn.dode.top/IHOEY_20170706_171445.png" alt="comment_ihoey"></p><p>多说刚挂了两个月,跟帖也跟着去了,刚做的提醒小功能都还没怎么用,好伤心,不知道小伙伴下一步都选择什么呢?有好用的推荐一下啊!<br><img src="https://cdn.dode.top/IHOEY_20170706_171444.png" alt="comment_ihoey"></p>]]></content>
<summary type="html">
<p><img src="https://cdn.dode.top/IHOEY_20170706_184907.png" alt="comment_ihoey"><br>继多说(多说关闭想必大家都已经知道了)关闭之后,很多人包括我,都转移到了网易云跟帖,现在网易云跟帖也正式发出公告宣布于2017年8月1日停止服务。</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="comment" scheme="https://blog.ihoey.com/tags/comment/"/>
</entry>
<entry>
<title>重新介绍 JavaScript(JS全面系列教程)</title>
<link href="https://blog.ihoey.com/posts/javascript/2017-07-03-A_re-introduction_to_JavaScript.html"/>
<id>https://blog.ihoey.com/posts/javascript/2017-07-03-A_re-introduction_to_JavaScript.html</id>
<published>2017-07-03T10:51:21.000Z</published>
<updated>2018-05-04T10:01:43.000Z</updated>
<content type="html"><![CDATA[<h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>为什么会有这一篇“重新介绍”呢?因为 <code>JavaScript</code> 堪称世界上被人误解最深的编程语言。虽然常被嘲为“玩具语言”,但在它看似简洁的外衣下,还隐藏着强大的语言特性。 <code>JavaScript</code> 目前广泛应用于众多知名应用中,对于网页和移动开发者来说,深入理解 <code>JavaScript</code> 就尤有必要。</p><a id="more"></a><p>先从这门语言的历史谈起是有必要的。在<code>1995</code> 年 <code>Netscape</code> 一位名为 Brendan Eich 的工程师创造了 <code>JavaScript</code>,随后在 <code>1996</code> 年初,<code>JavaScript</code> 首先被应用于 <code>Netscape</code> 2 浏览器上。最初的 <code>JavaScript</code> 名为 <code>LiveScript</code>,后来因为 <code>Sun Microsystem</code> 的 <code>Java</code> 语言的兴起和广泛使用,<code>Netscape</code> 出于宣传和推广的考虑,将它的名字从最初的 LiveScript 更改为 <code>JavaScript</code>——尽管两者之间并没有什么共同点。这便是之后混淆产生的根源。</p><p>几个月后,<code>Microsoft</code> 随着 <code>IE 3</code> 推出了一个与之基本兼容的语言 <code>JScript</code>。又几个月后,<code>Netscape</code> 将 <code>JavaScript</code> 提交至 <code>Ecma International</code>(一个欧洲标准化组织), <code>ECMAScript</code> 标准第一版便在 <code>1997</code> 年诞生了,随后在 <code>1999</code> 年以 <code>ECMAScript</code> 第三版的形式进行了更新,从那之后这个标准没有发生过大的改动。由于委员会在语言特性的讨论上发生分歧,<code>ECMAScript</code> 第四版尚未推出便被废除,但随后于 <code>2009</code> 年 <code>12</code> 月发布的 <code>ECMAScript</code> 第五版引入了第四版草案加入的许多特性。第六版标准已经于<code>2015</code>年六月发布。</p><p>注意: 为熟悉起见,从这里开始我们将用 “<code>JavaScript</code>” 替代 <code>ECMAScript</code> 。<br>与大多数编程语言不同,<code>JavaScript</code> 没有输入或输出的概念。它是一个在宿主环境(<code>host environment</code>)下运行的脚本语言,任何与外界沟通的机制都是由宿主环境提供的。浏览器是最常见的宿主环境,但在非常多的其他程序中也包含 <code>JavaScript</code> 解释器,如 <code>Adobe Acrobat</code>、<code>Photoshop</code>、<code>SVG</code> 图像、<code>Yahoo!</code> 的 <code>Widget</code> 引擎,以及 <code>Node.js</code> 之类的服务器端环境。<code>JavaScript</code> 的实际应用远不止这些,除此之外还有 <code>NoSQL</code> 数据库(如开源的 <code>Apache CouchDB</code>)、嵌入式计算机,以及包括 <code>GNOME</code> (注:<code>GNU/Linux</code> 上最流行的 <code>GUI</code> 之一)在内的桌面环境等等。</p><h2 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h2><p><code>JavaScript</code> 是一种面向对象的动态语言,它包含类型、运算符、标准内置( <code>built-in</code>)对象和方法。它的语法来源于 <code>Java</code> 和 <code>C</code>,所以这两种语言的许多语法特性同样适用于 <code>JavaScript</code>。需要注意的一个主要区别是 <code>JavaScript</code> 不支持类,类这一概念在 <code>JavaScript</code> 通过对象原型(<code>object prototype</code>)得到延续(有关 <code>ES6</code> 类的内容参考这里<code>Classes</code>)。另一个主要区别是 <code>JavaScript</code> 中的函数也是对象,<code>JavaScript</code> 允许函数在包含可执行代码的同时,能像其他对象一样被传递。</p><p>先从任何编程语言都不可缺少的组成部分——“类型”开始。<code>JavaScript</code> 程序可以修改值(<code>value</code>),这些值都有各自的类型。<code>JavaScript</code> 中的类型包括:</p><ul><li><code>Number</code>(数字)</li><li><code>String</code>(字符串)</li><li><code>Boolean</code>(布尔)</li><li><code>Function</code>(函数)</li><li><code>Object</code>(对象)</li><li><code>Symbol</code> (第六版新增)</li></ul><p>…哦,还有看上去有些…奇怪的 <code>undefined</code>(未定义)类型和 <code>null</code>(空)类型。此外还有<code>Array</code>(数组)类型,以及分别用于表示日期和正则表达式的 <code>Date</code>(日期)和 <code>RegExp</code>(正则表达式),这三种类型都是特殊的对象。严格意义上说,<code>Function</code>(函数)也是一种特殊的对象。所以准确来说,<code>JavaScript</code> 中的类型应该包括这些:</p><ul><li><code>Number</code>(数字)</li><li><code>String</code>(字符串)</li><li><code>Boolean</code>(布尔)</li><li><code>Symbol</code>(符号)(第六版新增)</li><li><code>Object</code>(对象)</li><li><code>Function</code>(函数)</li><li><code>Array</code>(数组)</li><li><code>Date</code>(日期)</li><li><code>RegExp</code>(正则表达式)</li><li><code>Null</code>(空)</li><li><code>Undefined</code>(未定义)</li><li><code>JavaScript</code> 还有一种内置<code>Error</code>(错误)类型,这个会在之后的介绍中提到;现在我们先讨论下上面这些类型。</li></ul><h2 id="数字"><a href="#数字" class="headerlink" title="数字"></a>数字</h2><p>根据语言规范,<code>JavaScript</code> 采用“<code>IEEE 754</code> 标准定义的双精度<code>64</code>位格式”(”<code>double-precision 64-bit format IEEE 754 values</code>“)表示数字。据此我们能得到一个有趣的结论,和其他编程语言(如 <code>C</code> 和 <code>Java</code>)不同,<code>JavaScript</code> 不区分整数值和浮点数值,所有数字在 <code>JavaScript</code> 中均用浮点数值表示,所以在进行数字运算的时候要特别注意。看看下面的例子:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="number">0.1</span> + <span class="number">0.2</span> = <span class="number">0.30000000000000004</span></span><br></pre></td></tr></table></figure></div><p>在具体实现时,整数值通常被视为<code>32</code>位整型变量,在个别实现(如某些浏览器)中也以<code>32</code>位整型变量的形式进行存储,直到它被用于执行某些<code>32</code>位整型不支持的操作,这是为了便于进行位操作。</p><p><code>JavaScript</code> 支持标准的算术运算符,包括加法、减法、取模(或取余)等等。还有一个之前没有提及的内置对象 <code>Math</code>(数学对象),用以处理更多的高级数学函数和常数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="built_in">Math</span>.sin(<span class="number">3.5</span>);</span><br><span class="line"><span class="keyword">var</span> d = <span class="built_in">Math</span>.PI * (r + r);</span><br></pre></td></tr></table></figure></div><p>你可以使用内置函数 <code>parseInt()</code> 将字符串转换为整型。该函数的第二个参数表示字符串所表示数字的基(进制):</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="built_in">parseInt</span>(<span class="string">"123"</span>, <span class="number">10</span>); <span class="comment">// 123</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">"010"</span>, <span class="number">10</span>); <span class="comment">//10</span></span><br></pre></td></tr></table></figure></div><p>如果调用时没有提供第二个参数(字符串所表示数字的基),<code>2013</code> 年以前的 <code>JavaScript</code> 实现会返回一个意外的结果:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="built_in">parseInt</span>(<span class="string">"010"</span>); <span class="comment">// 8</span></span><br><span class="line"><span class="built_in">parseInt</span>(<span class="string">"0x10"</span>); <span class="comment">// 16</span></span><br></pre></td></tr></table></figure></div><p>这是因为字符串以数字 <code>0</code> 开头,<code>parseInt()</code>函数会把这样的字符串视作八进制数字;同理,<code>0x</code>开头的字符串则视为十六进制数字。</p><p>如果想把一个二进制数字字符串转换成整数值,只要把第二个参数设置为 <code>2</code> 就可以了:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">parseInt</span>(<span class="string">"11"</span>, <span class="number">2</span>); <span class="comment">// 3</span></span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 还有一个类似的内置函数 <code>parseFloat()</code>,用以解析浮点数字符串,与 <code>parseInt()</code> 不同的地方是,<code>parseFloat()</code>只应用于解析十进制数字。</p><p>单元运算符 + 也可以把数字字符串转换成数值:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"42"</span>; <span class="comment">// 42</span></span><br><span class="line">+ <span class="string">"010"</span>; <span class="comment">// 10</span></span><br><span class="line">+ <span class="string">"0x10"</span>; <span class="comment">// 16</span></span><br></pre></td></tr></table></figure></div><p>如果给定的字符串不存在数值形式,函数会返回一个特殊的值 <code>NaN</code>(<code>Not a Number</code> 的缩写):</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">parseInt</span>(<span class="string">"hello"</span>, <span class="number">10</span>); <span class="comment">// NaN</span></span><br></pre></td></tr></table></figure></div><p>要小心<code>NaN</code>:如果把 <code>NaN</code> 作为参数进行任何数学运算,结果也会是 <code>NaN</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="literal">NaN</span> + <span class="number">5</span>; <span class="comment">//NaN</span></span><br></pre></td></tr></table></figure></div><p>可以使用内置函数 <code>isNaN()</code> 来判断一个变量是否为 <code>NaN</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">isNaN</span>(<span class="literal">NaN</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 还有两个特殊值:<code>Infinity</code>(正无穷)和 <code>-Infinity</code>(负无穷):</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="number">1</span> / <span class="number">0</span>; <span class="comment">// Infinity</span></span><br><span class="line"><span class="number">-1</span> / <span class="number">0</span>; <span class="comment">// -Infinity</span></span><br></pre></td></tr></table></figure></div><p>可以使用内置函数 <code>isFinite()</code> 来判断一个变量是否是一个有穷数, 如果类型为 <code>Infinity</code>, <code>-Infinity</code> 或 <code>NaN</code>则返回<code>false</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="built_in">isFinite</span>(<span class="number">1</span>/<span class="number">0</span>); <span class="comment">// false</span></span><br><span class="line"><span class="built_in">isFinite</span>(<span class="literal">Infinity</span>); <span class="comment">// false</span></span><br><span class="line"><span class="built_in">isFinite</span>(<span class="literal">NaN</span>); <span class="comment">// false</span></span><br><span class="line"><span class="built_in">isFinite</span>(-<span class="literal">Infinity</span>); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">isFinite</span>(<span class="number">0</span>); <span class="comment">// true</span></span><br><span class="line"><span class="built_in">isFinite</span>(<span class="number">2e64</span>); <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">isFinite</span>(<span class="string">"0"</span>); <span class="comment">// true,如果是纯数值类型的检测,则返回false:Number.isFinite("0");</span></span><br></pre></td></tr></table></figure></div><p>备注: <code>parseInt()</code> 和 <code>parseFloat()</code> 函数会尝试逐个解析字符串中的字符,直到遇上一个无法被解析成数字的字符,然后返回该字符前所有数字字符组成的数字。使用运算符 “<code>+</code>“ 将字符串转换成数字,只要字符串中含有无法被解析成数字的字符,该字符串都将被转换成 <code>NaN</code>。请你用这两种方法分别解析“<code>10.2abc</code>”这一字符串,比较得到的结果,理解这两种方法的区别。</p><h2 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h2><p><code>JavaScript</code> 中的字符串是一串<code>Unicode</code> 字符序列。这对于那些需要和多语种网页打交道的开发者来说是个好消息。更准确地说,它们是一串<code>UTF-16</code>编码单元的序列,每一个编码单元由一个 <code>16</code> 位二进制数表示。每一个<code>Unicode</code>字符由一个或两个编码单元来表示。</p><p>如果想表示一个单独的字符,只需使用长度为 <code>1</code> 的字符串。</p><p>通过访问字符串的长度(编码单元的个数)属性可以得到它的长度。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"hello"</span>.length; <span class="comment">// 5</span></span><br></pre></td></tr></table></figure></div><p>这是我们第一次碰到 <code>JavaScript</code> 对象。我们有没有提过你可以像 <code>objects</code> 一样使用字符串?是的,字符串也有 <code>methods</code>(方法)能让你操作字符串和获取字符串的信息。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"hello"</span>.charAt(<span class="number">0</span>); <span class="comment">// "h"</span></span><br><span class="line"><span class="string">"hello, world"</span>.replace(<span class="string">"hello"</span>, <span class="string">"goodbye"</span>); <span class="comment">// "goodbye, world"</span></span><br><span class="line"><span class="string">"hello"</span>.toUpperCase(); <span class="comment">// "HELLO"</span></span><br></pre></td></tr></table></figure></div><h2 id="其他类型"><a href="#其他类型" class="headerlink" title="其他类型"></a>其他类型</h2><p><code>JavaScript</code> 中 <code>null</code> 和 <code>undefined</code> 是不同的,前者表示一个空值(<code>non-value</code>),必须使用<code>null</code>关键字才能访问,后者是“<code>undefined</code>(未定义)”类型的对象,表示一个未初始化的值,也就是还没有被分配的值。我们之后再具体讨论变量,但有一点可以先简单说明一下,<code>JavaScript</code> 允许声明变量但不对其赋值,一个未被赋值的变量就是 <code>undefined</code> 类型。还有一点需要说明的是,<code>undefined</code> 实际上是一个不允许修改的常量。</p><p><code>JavaScript</code> 包含布尔类型,这个类型的变量有两个可能的值,分别是 <code>true</code> 和 <code>false</code>(两者都是关键字)。根据具体需要,<code>JavaScript</code> 按照如下规则将变量转换成布尔类型:</p><p><code>false</code>、<code>0</code>、空字符串(“”)、<code>NaN</code>、<code>null</code> 和 <code>undefined</code> 被转换为 <code>false</code><br>所有其他值被转换为 <code>true</code><br>也可以使用 <code>Boolean()</code> 函数进行显式转换:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="built_in">Boolean</span>(<span class="string">""</span>); <span class="comment">// false</span></span><br><span class="line"><span class="built_in">Boolean</span>(<span class="number">234</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure></div><p>不过一般没必要这么做,因为 <code>JavaScript</code> 会在需要一个布尔变量时隐式完成这个转换操作(比如在 <code>if</code> 条件语句中)。所以,有时我们可以把转换成布尔值后的变量分别称为 真值(<code>true values</code>)——即值为 <code>true</code> 和 假值(<code>false values</code>)——即值为 <code>false</code>;也可以分别称为“真的”(<code>truthy</code>)和“假的”(<code>falsy</code>)。</p><p><code>JavaScript</code> 支持包括 <code>&&</code>(逻辑与)、<code>||</code> (逻辑或)和 <code>!</code>(逻辑非)在内的逻辑运算符。下面会有所提到。</p><h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><p>在 <code>JavaScript</code> 中声明一个新变量的方法是使用关键字 <code>var</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> a;</span><br><span class="line"><span class="keyword">var</span> name = <span class="string">"simon"</span>;</span><br></pre></td></tr></table></figure></div><p>如果声明了一个变量却没有对其赋值,那么这个变量的类型就是 <code>undefined</code>。</p><p><code>JavaScript</code> 与其他语言的(如 <code>Java</code>)的重要区别是在 <code>JavaScript</code> 中语句块(<code>blocks</code>)是没有作用域的,只有函数有作用域。因此如果在一个复合语句中(如 <code>if</code> 控制结构中)使用 <code>var</code> 声明一个变量,那么它的作用域是整个函数(复合语句在函数中)。 但是从 <code>ECMAScript</code> <code>Edition 6</code> 开始将有所不同的, <code>let</code> 和 <code>const</code> 关键字允许你创建块作用域的变量。</p><h2 id="运算符"><a href="#运算符" class="headerlink" title="运算符"></a>运算符</h2><p><code>JavaScript</code>的算术操作符包括 <code>+</code>、<code>-</code>、<code>*</code>、<code>/</code> 和 <code>%</code> ——求余(与模运算不同)。赋值使用 <code>=</code> 运算符,此外还有一些复合运算符,如 <code>+=</code> 和 <code>-=</code>,它们等价于 <code>x = x op y</code>。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu highlight /javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">x += <span class="number">5</span>; <span class="comment">// 等价于 x = x + 5;</span></span><br></pre></td></tr></table></figure></div><p>可以使用 <code>++</code> 和 <code>--</code> 分别实现变量的自增和自减。两者都可以作为前缀或后缀操作符使用。</p><ul><li>操作符还可以用来连接字符串:</li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"hello"</span> + <span class="string">" world"</span>; <span class="comment">// hello world</span></span><br></pre></td></tr></table></figure></div><p>如果你用一个字符串加上一个数字(或其他值),那么操作数都会被首先转换为字符串。如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"3"</span> + <span class="number">4</span> + <span class="number">5</span>; <span class="comment">// 345</span></span><br><span class="line"><span class="number">3</span> + <span class="number">4</span> + <span class="string">"5"</span>; <span class="comment">// 75</span></span><br></pre></td></tr></table></figure></div><p>这里不难看出一个实用的技巧——通过与空字符串相加,可以将某个变量快速转换成字符串类型。</p><p><code>JavaScript</code> 中的比较操作使用 <code><</code>、<code>></code>、<code><=</code> 和 <code>>=</code>,这些运算符对于数字和字符串都通用。相等的比较稍微复杂一些。由两个“<code>=</code>(等号)”组成的相等运算符有类型自适应的功能,具体例子如下:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="number">123</span> == <span class="string">"123"</span> <span class="comment">// true</span></span><br><span class="line"><span class="number">1</span> == <span class="literal">true</span>; <span class="comment">// true</span></span><br></pre></td></tr></table></figure></div><p>如果在比较前不需要自动类型转换,应该使用由三个“<code>=</code>(等号)”组成的相等运算符:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="number">1</span> === <span class="literal">true</span>; <span class="comment">//false</span></span><br><span class="line"><span class="number">123</span> === <span class="string">"123"</span>; <span class="comment">// false</span></span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 还支持 <code>!=</code> 和 <code>!==</code> 两种不等运算符,具体区别与两种相等运算符的区别类似。</p><p><code>JavaScript</code> 还提供了 位操作符。</p><h2 id="控制结构"><a href="#控制结构" class="headerlink" title="控制结构"></a>控制结构</h2><p><code>JavaScript</code> 的控制结构与其他类 <code>C</code> 语言类似。可以使用 <code>if</code> 和 <code>else</code> 来定义条件语句,还可以连起来使用:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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> name = <span class="string">"kittens"</span>;</span><br><span class="line"><span class="keyword">if</span> (name == <span class="string">"puppies"</span>) {</span><br><span class="line"> name += <span class="string">"!"</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (name == <span class="string">"kittens"</span>) {</span><br><span class="line"> name += <span class="string">"!!"</span>;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> name = <span class="string">"!"</span> + name;</span><br><span class="line">}</span><br><span class="line">name == <span class="string">"kittens!!"</span>; <span class="comment">// true</span></span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 支持 <code>while</code> 循环和 <code>do-while</code>循环。前者适合常见的基本循环操作,如果需要循环体至少被执行一次则可以使用 <code>do-while</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">while</span> (<span class="literal">true</span>) {</span><br><span class="line"> <span class="comment">// 一个无限循环!</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> input;</span><br><span class="line"><span class="keyword">do</span> {</span><br><span class="line"> input = get_input();</span><br><span class="line">} <span class="keyword">while</span> (inputIsNotValid(input))</span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 的 <code>for</code> 循环与 <code>C</code> 和 <code>Java</code> 中的相同,使用时可以在一行代码中提供控制信息。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">5</span>; i++) {</span><br><span class="line"> <span class="comment">// 将会执行五次</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>&&</code> 和 <code>||</code> 运算符使用短路逻辑(<code>short-circuit logic</code>),是否会执行第二个语句(操作数)取决于第一个操作数的结果。在需要访问某个对象的属性时,使用这个特性可以事先检测该对象是否为空:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> name = o && o.getName();</span><br></pre></td></tr></table></figure></div><p>或运算可以用来设置默认值:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> name = otherName || <span class="string">"default"</span>;</span><br></pre></td></tr></table></figure></div><p>类似地,<code>JavaScript</code> 也有一个用于条件表达式的三元操作符:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> allowed = (age > <span class="number">18</span>) ? <span class="string">"yes"</span> : <span class="string">"no"</span>;</span><br></pre></td></tr></table></figure></div><p>在需要多重分支时可以使用 基于一个数字或字符串的 <code>switch</code> 语句:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">switch</span>(action) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'draw'</span>:</span><br><span class="line"> drawIt();</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'eat'</span>:</span><br><span class="line"> eatIt();</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"> doNothing();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>如果你不使用 <code>break</code> 语句,<code>JavaScript</code> 解释器将会执行之后 <code>case</code> 中的代码。除非是为了调试,一般你并不需要这个特性,所以大多数时候不要忘了加上 <code>break</code>。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">switch</span>(a) {</span><br><span class="line"> <span class="keyword">case</span> <span class="number">1</span>: <span class="comment">// 继续向下</span></span><br><span class="line"> <span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line"> eatIt();</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"> doNothing();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>default</code> 语句是可选的。<code>switch</code> 和 <code>case</code> 都可以使用需要运算才能得到结果的表达式;在 <code>switch</code> 的表达式和 <code>case</code> 的表达式是使用 <code>===</code> 严格相等运算符进行比较的:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">switch</span>(<span class="number">1</span> + <span class="number">3</span>){</span><br><span class="line"> <span class="keyword">case</span> <span class="number">2</span> + <span class="number">2</span>:</span><br><span class="line"> yay();</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"> neverhappens();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h2><p><code>JavaScript</code> 中的对象可以简单理解成“名称-值”对,不难联想 <code>JavaScript</code> 中的对象与下面这些概念类似:</p><ul><li><code>Python</code> 中的字典</li><li><code>Perl</code> 和 <code>Ruby</code> 中的散列(哈希)</li><li><code>C/C++</code> 中的散列表</li><li><code>Java</code> 中的 <code>HashMap</code></li><li><code>PHP</code> 中的关联数组<br>这样的数据结构设计合理,能应付各类复杂需求,所以被各类编程语言广泛采用。正因为 <code>JavaScript</code> 中的一切(除了核心类型,<code>core object</code>)都是对象,所以 <code>JavaScript</code> 程序必然与大量的散列表查找操作有着千丝万缕的联系,而散列表擅长的正是高速查找。</li></ul><p>“名称”部分是一个 <code>JavaScript</code> 字符串,“值”部分可以是任何 <code>JavaScript</code> 的数据类型——包括对象。这使用户可以根据具体需求,创建出相当复杂的数据结构。</p><p>有两种简单方法可以创建一个空对象:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> obj = <span class="keyword">new</span> <span class="built_in">Object</span>();</span><br></pre></td></tr></table></figure></div><p>和:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> obj = {};</span><br></pre></td></tr></table></figure></div><p>这两种方法在语义上是相同的。第二种更方便的方法叫作“对象字面量(<code>object literal</code>)”法。这种也是 <code>JSON</code> 格式的核心语法,一般我们优先选择第二种方法。</p><p>“对象字面量”也可以用来在对象实例中定义一个对象:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">var</span> obj = {</span><br><span class="line"> name: <span class="string">"Carrot"</span>,</span><br><span class="line"> <span class="string">"for"</span>: <span class="string">"Max"</span>,</span><br><span class="line"> details: {</span><br><span class="line"> color: <span class="string">"orange"</span>,</span><br><span class="line"> size: <span class="number">12</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>对象的属性可以通过链式(<code>chain</code>)表示方法进行访问:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">obj.details.color; <span class="comment">// orange</span></span><br><span class="line">obj[<span class="string">"details"</span>][<span class="string">"size"</span>]; <span class="comment">// 12</span></span><br></pre></td></tr></table></figure></div><p>下面的例子创建了一个对象原型,<code>Person</code>,和这个原型的实例,<code>You</code>。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name;</span><br><span class="line"> <span class="keyword">this</span>.age = age;</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">var</span> You = <span class="keyword">new</span> Person(<span class="string">"You"</span>, <span class="number">24</span>);</span><br><span class="line"><span class="comment">// 我们创建了一个新的 Person,名称是 "You"</span></span><br><span class="line"><span class="comment">// ("You" 是第一个参数, 24 是第二个参数..)</span></span><br></pre></td></tr></table></figure></div><p>完成创建后,对象属性可以通过如下两种方式进行赋值和访问:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">obj.name = <span class="string">"Simon"</span></span><br><span class="line"><span class="keyword">var</span> name = obj.name;</span><br></pre></td></tr></table></figure></div><p>和:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">obj[<span class="string">"name"</span>] = <span class="string">"Simon"</span>;</span><br><span class="line"><span class="keyword">var</span> name = obj[<span class="string">"name"</span>];</span><br></pre></td></tr></table></figure></div><p>这两种方法在语义上也是相同的。第二种方法的优点在于属性的名称被看作一个字符串,这就意味着它可以在运行时被计算,缺点在于这样的代码有可能无法在后期被解释器优化。它也可以被用来访问某些以预留关键字作为名称的属性的值:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">obj.for = <span class="string">"Simon"</span>; <span class="comment">// 语法错误,因为 for 是一个预留关键字</span></span><br><span class="line">obj[<span class="string">"for"</span>] = <span class="string">"Simon"</span>; <span class="comment">// 工作正常</span></span><br></pre></td></tr></table></figure></div><p>注意:从 <code>EcmaScript 5</code>开始,预留关键字可以作为对象的属性名(<code>reserved words may be used as object property names "in the buff"</code>)。 这意味着当定义对象字面量时不需要用双引号了。参见 <code>ES5 Spec</code>.<br>关于对象和原型的详情参见: <code>Object.prototype</code>.</p><h2 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h2><p><code>JavaScript</code> 中的数组是一种特殊的对象。它的工作原理与普通对象类似(以数字为属性名,但只能通过<code>[]</code> 来访问),但数组还有一个特殊的属性——<code>length</code>(长度)属性。这个属性的值通常比数组最大索引大 <code>1</code>。</p><p>创建数组的传统方法是:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> a = <span class="keyword">new</span> <span class="string">`Array`</span>();</span><br><span class="line">a[<span class="number">0</span>] = <span class="string">"dog"</span>;</span><br><span class="line">a[<span class="number">1</span>] = <span class="string">"cat"</span>;</span><br><span class="line">a[<span class="number">2</span>] = <span class="string">"hen"</span>;</span><br><span class="line">a.length; <span class="comment">// 3</span></span><br></pre></td></tr></table></figure></div><p>使用数组字面量(<code>array literal</code>)法更加方便:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> a = [<span class="string">"dog"</span>, <span class="string">"cat"</span>, <span class="string">"hen"</span>];</span><br><span class="line">a.length; <span class="comment">// 3</span></span><br></pre></td></tr></table></figure></div><p>注意,<code>Array.length</code> 并不总是等于数组中元素的个数,如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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> a = [<span class="string">"dog"</span>, <span class="string">"cat"</span>, <span class="string">"hen"</span>];</span><br><span class="line">a[<span class="number">100</span>] = <span class="string">"fox"</span>;</span><br><span class="line">a.length; <span class="comment">// 101</span></span><br></pre></td></tr></table></figure></div><p>记住:数组的长度是比数组最大索引值多一的数。</p><p>如果试图访问一个不存在的数组索引,会得到 <code>undefined</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">typeof</span>(a[<span class="number">90</span>]); <span class="comment">// `undefined`</span></span><br></pre></td></tr></table></figure></div><p>可以通过如下方式遍历一个数组:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < a.length; i++) {</span><br><span class="line"> <span class="comment">// Do something with a[i]</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>遍历数组的另一种方法是使用 <code>for...in</code> 循环。注意,如果有人向 <code>Array.prototype</code> 添加了新的属性,使用这样的循环这些属性也同样会被遍历。所以并不推荐这种方法:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">for</span> (<span class="keyword">var</span> i <span class="keyword">in</span> a) {</span><br><span class="line"> <span class="comment">// Do something with a[i]</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>ECMAScript 5</code> 增加了遍历数组的另一个方法 <code>forEach()</code>:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"dog"</span>, <span class="string">"cat"</span>, <span class="string">"hen"</span>].forEach(<span class="function"><span class="keyword">function</span>(<span class="params">currentValue, index, array</span>) </span>{</span><br><span class="line"> <span class="comment">// Do something with currentValue or array[index]</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure></div><p>如果想在数组后追加元素,只需要:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu highlight /javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a.push(item);</span><br></pre></td></tr></table></figure></div><p><code>Array</code>(数组)类自带了许多方法。查看 <code>array</code> 方法的完整文档。</p><table><thead><tr><th style="text-align:left">方法名称</th><th style="text-align:left">描述</th></tr></thead><tbody><tr><td style="text-align:left">a.toString()</td><td style="text-align:left">返回一个包含数组中所有元素的字符串,每个元素通过逗号分隔。</td></tr><tr><td style="text-align:left">a.toLocaleString()</td><td style="text-align:left">根据宿主环境的区域设置,返回一个包含数组中所有元素的字符串,每个元素通过逗号分隔。</td></tr><tr><td style="text-align:left">a.concat(item1[, item2[, …[, itemN]]])</td><td style="text-align:left">返回一个数组,这个数组包含原先 a 和 item1、item2、……、itemN 中的所有元素。</td></tr><tr><td style="text-align:left">a.join(sep)</td><td style="text-align:left">返回一个包含数组中所有元素的字符串,每个元素通过指定的 sep 分隔。</td></tr><tr><td style="text-align:left">a.pop()</td><td style="text-align:left">删除并返回数组中的最后一个元素。</td></tr><tr><td style="text-align:left">a.push(item1, …, itemN)</td><td style="text-align:left">将 item1、item2、……、itemN 追加至数组 a。</td></tr><tr><td style="text-align:left">a.reverse()</td><td style="text-align:left">数组逆序(会更改原数组 a)。</td></tr><tr><td style="text-align:left">a.shift()</td><td style="text-align:left">删除并返回数组中第一个元素。</td></tr><tr><td style="text-align:left">a.slice(start, end)</td><td style="text-align:left">返回子数组,以 a[start] 开头,以 a[end] 前一个元素结尾。</td></tr><tr><td style="text-align:left">a.sort([cmpfn])</td><td style="text-align:left">依据 cmpfn 返回的结果进行排序,如果未指定比较函数则按字符顺序比较(即使元素是数字)。</td></tr><tr><td style="text-align:left">a.splice(start, delcount[, item1[, …[, itemN]]])</td><td style="text-align:left">从 start 开始,删除delcount个元素,然后插入所有的</td></tr><tr><td style="text-align:left">a.unshift([item])</td><td style="text-align:left">将 item 插入数组头部,返回数组新长度(考虑 undefined)。</td></tr></tbody></table><h2 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h2><p>学习 <code>JavaScript</code> 最重要的就是要理解对象和函数两个部分。最简单的函数就像下面这个这么简单:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params">x, y</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> total = x + y;</span><br><span class="line"> <span class="keyword">return</span> total;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这个例子包括你需要了解的关于基本函数的所有部分。一个 <code>JavaScript</code> 函数可以包含 <code>0</code> 个或多个已命名的变量。函数体中的表达式数量也没有限制。你可以声明函数自己的局部变量。<code>return</code>语句在返回一个值并结束函数。如果没有使用 <code>return</code> 语句,或者一个没有值的 <code>return</code> 语句,<code>JavaScript</code> 会返回 <code>undefined</code>。</p><p>已命名的参数更像是一个指示而没有其他作用。如果调用函数时没有提供足够的参数,缺少的参数会被 <code>undefined</code> 替代。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">add(); <span class="comment">// NaN</span></span><br><span class="line"><span class="comment">// 不能在 `undefined` 对象上进行加法操作</span></span><br></pre></td></tr></table></figure></div><p>你还可以传入多于函数本身需要参数个数的参数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">add(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>); <span class="comment">// 5</span></span><br><span class="line"> <span class="comment">// 将前两个值相加,4被忽略了</span></span><br></pre></td></tr></table></figure></div><p>这看上去有点蠢。函数实际上是访问了函数体中一个名为 <code>arguments</code> 的内部对象,这个对象就如同一个类似于数组的对象一样,包括了所有被传入的参数。让我们重写一下上面的函数,使它可以接收任意个数的参数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">add</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, j = <span class="built_in">arguments</span>.length; i < j; i++) {</span><br><span class="line"> sum += <span class="built_in">arguments</span>[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> sum;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">add(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>); <span class="comment">// 14</span></span><br></pre></td></tr></table></figure></div><p>这跟直接写成 <code>2 + 3 + 4 + 5</code> 也没什么区别。接下来创建一个求平均数的函数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">avg</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, j = <span class="built_in">arguments</span>.length; i < j; i++) {</span><br><span class="line"> sum += <span class="built_in">arguments</span>[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> sum / <span class="built_in">arguments</span>.length;</span><br><span class="line">}</span><br><span class="line">avg(<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>); <span class="comment">// 3.5</span></span><br></pre></td></tr></table></figure></div><p>这个很有用,但是却带来了新的问题。<code>avg()</code> 函数处理一个由逗号连接的变量串,但如果想得到一个数组的平均值该怎么办呢?可以这么修改函数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">avg</span>`<span class="title">Array</span>`(<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, j = arr.length; i < j; i++) {</span><br><span class="line"> sum += arr[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> sum / arr.length;</span><br><span class="line">}</span><br><span class="line">avg<span class="string">`Array`</span>([<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]); <span class="comment">// 3.5</span></span><br></pre></td></tr></table></figure></div><p>但如果能重用我们已经创建的那个函数不是更好吗?幸运的是 <code>JavaScript</code> 允许使用任意函数对象的<code>apply()</code>方法来调用该函数,并传递给它一个包含了参数的数组。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu highlight /javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">avg.apply(<span class="string">`null`</span>, [<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]); <span class="comment">// 3.5</span></span><br></pre></td></tr></table></figure></div><p>传给 <code>apply()</code> 的第二个参数是一个数组,它将被当作 <code>avg()</code> 的参数使用,至于第一个参数 <code>null</code>,我们将在后面讨论。这也正说明一个事实——函数也是对象。</p><p><code>JavaScript</code> 允许你创建匿名函数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">var</span> avg = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> sum = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, j = <span class="built_in">arguments</span>.length; i < j; i++) {</span><br><span class="line"> sum += <span class="built_in">arguments</span>[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> sum / <span class="built_in">arguments</span>.length;</span><br><span class="line">};</span><br></pre></td></tr></table></figure></div><p>这个函数在语义上与 <code>function avg()</code> 相同。你可以在代码中的任何地方定义这个函数,就像写普通的表达式一样。基于这个特性,有人发明出一些有趣的技巧。与 <code>C</code> 中的块级作用域类似,下面这个例子隐藏了局部变量:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">var</span> b = <span class="number">2</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">var</span> b = <span class="number">3</span>;</span><br><span class="line"> a += b;</span><br><span class="line">})();</span><br><span class="line"></span><br><span class="line">a; <span class="comment">// 4</span></span><br><span class="line">b; <span class="comment">// 2</span></span><br></pre></td></tr></table></figure></div><p><code>JavaScript</code> 允许以递归方式调用函数。递归在处理树形结构(比如浏览器 <code>DOM</code>)时非常有用。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">countChars</span>(<span class="params">elm</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (elm.nodeType == <span class="number">3</span>) { <span class="comment">// 文本节点</span></span><br><span class="line"> <span class="keyword">return</span> elm.nodeValue.length;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> count = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, child; child = elm.childNodes[i]; i++) {</span><br><span class="line"> count += countChars(child);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> count;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这里需要说明一个潜在问题——既然匿名函数没有名字,那该怎么递归调用它呢?在这一点上,<code>JavaScript</code> 允许你命名这个函数表达式。你可以命名立即调用的函数表达式(<code>IIFES——Immediately Invoked Function Expressions</code>),如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">var</span> charsInBody = (<span class="function"><span class="keyword">function</span> <span class="title">counter</span>(<span class="params">elm</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (elm.nodeType == <span class="number">3</span>) { <span class="comment">// 文本节点</span></span><br><span class="line"> <span class="keyword">return</span> elm.nodeValue.length;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> count = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>, child; child = elm.childNodes[i]; i++) {</span><br><span class="line"> count += counter(child);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> count;</span><br><span class="line">})(<span class="built_in">document</span>.body);</span><br></pre></td></tr></table></figure></div><p>如上所提供的函数表达式的名称的作用域仅仅是该函数自身。这允许引擎去做更多的优化,并且这种实现更可读、友好。该名称也显示在调试器和一些堆栈跟踪中,节省了调试时的时间。</p><p>需要注意的是 <code>JavaScript</code> 函数是它们本身的对象——就和 <code>JavaScript</code> 其他一切一样——你可以给它们添加属性或者更改它们的属性,这与前面的对象部分一样。</p><h2 id="自定义对象"><a href="#自定义对象" class="headerlink" title="自定义对象"></a>自定义对象</h2><p>备注:关于 <code>JavaScript</code> 中面向对象编程更详细的信息,请参考 <code>JavaScript</code> 面向对象简介。<br>在经典的面向对象语言中,对象是指数据和在这些数据上进行的操作的集合。与 <code>C++</code> 和 <code>Java</code> 不同,<code>JavaScript</code> 是一种基于原型的编程语言,并没有 <code>class</code> 语句,而是把函数用作类。那么让我们来定义一个人名对象,这个对象包括人的姓和名两个域(<code>field</code>)。名字的表示有两种方法:“名 姓(<code>First Last</code>)”或“姓, 名(<code>Last</code>, <code>First</code>)”。使用我们前面讨论过的函数和对象概念,可以像这样完成定义:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">makePerson</span>(<span class="params">first, last</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> first: first,</span><br><span class="line"> last: last</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">personFullName</span>(<span class="params">person</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> person.first + <span class="string">' '</span> + person.last;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">personFullNameReversed</span>(<span class="params">person</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> person.last + <span class="string">', '</span> + person.first</span><br><span class="line">}</span><br><span class="line">s = makePerson(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line">personFullName(s); <span class="comment">// Simon Willison</span></span><br><span class="line">personFullNameReversed(s); <span class="comment">// Willison, Simon</span></span><br></pre></td></tr></table></figure></div><p>上面的写法虽然可以满足要求,但是看起来很麻烦,因为需要在全局命名空间中写很多函数。既然函数本身就是对象,如果需要使一个函数隶属于一个对象,那么不难得到:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">makePerson</span>(<span class="params">first, last</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> first: first,</span><br><span class="line"> last: last,</span><br><span class="line"> fullName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.first + <span class="string">' '</span> + <span class="keyword">this</span>.last;</span><br><span class="line"> },</span><br><span class="line"> fullNameReversed: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.last + <span class="string">', '</span> + <span class="keyword">this</span>.first;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">s = makePerson(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line">s.fullName(); <span class="comment">// Simon Willison</span></span><br><span class="line">s.fullNameReversed(); <span class="comment">// Willison, Simon</span></span><br></pre></td></tr></table></figure></div><p>上面的代码里有一些我们之前没有见过的东西:关键字 <code>this</code>。当使用在函数中时,<code>this</code> 指代当前的对象,也就是调用了函数的对象。如果在一个对象上使用点或者方括号来访问属性或方法,这个对象就成了 <code>this</code>。如果并没有使用“点”运算符调用某个对象,那么 <code>this</code> 将指向全局对象(<code>global object</code>)。这是一个经常出错的地方。例如:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">s = makePerson(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line"><span class="keyword">var</span> fullName = s.fullName;</span><br><span class="line">fullName(); <span class="comment">// `undefined` `undefined`</span></span><br></pre></td></tr></table></figure></div><p>当我们调用 <code>fullName()</code> 时,<code>this</code> 实际上是指向全局对象的,并没有名为 <code>first</code> 或 <code>last</code> 的全局变量,所以它们两个的返回值都会是 <code>undefined</code>。</p><p>下面使用关键字 <code>this</code> 改进已有的 <code>makePerson</code>函数:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">first, last</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.first = first;</span><br><span class="line"> <span class="keyword">this</span>.last = last;</span><br><span class="line"> <span class="keyword">this</span>.fullName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.first + <span class="string">' '</span> + <span class="keyword">this</span>.last;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">this</span>.fullNameReversed = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.last + <span class="string">', '</span> + <span class="keyword">this</span>.first;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> Person(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);\</span><br></pre></td></tr></table></figure></div><p>我们引入了另外一个关键字:<code>new</code>,它和 <code>this</code> 密切相关。它的作用是创建一个崭新的空对象,然后使用指向那个对象的 <code>this</code> 调用特定的函数。注意,含有 <code>this</code> 的特定函数不会返回任何值,只会修改 <code>this</code> 对象本身。<code>new</code> 关键字将生成的 <code>this</code> 对象返回给调用方,而被 <code>new</code> 调用的函数成为构造函数。习惯的做法是将这些函数的首字母大写,这样用 <code>new</code> 调用他们的时候就容易识别了。</p><p>不过这个改进的函数还是和上一个例子一样,单独调用<code>fullName()</code> 时会产生相同的问题。</p><p>我们的 <code>Person</code> 对象现在已经相当完善了,但还有一些不太好的地方。每次我们创建一个 <code>Person</code> 对象的时候,我们都在其中创建了两个新的函数对象——如果这个代码可以共享不是更好吗?</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">personFullName</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.first + <span class="string">' '</span> + <span class="keyword">this</span>.last;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">personFullNameReversed</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.last + <span class="string">', '</span> + <span class="keyword">this</span>.first;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">first, last</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.first = first;</span><br><span class="line"> <span class="keyword">this</span>.last = last;</span><br><span class="line"> <span class="keyword">this</span>.fullName = personFullName;</span><br><span class="line"> <span class="keyword">this</span>.fullNameReversed = personFullNameReversed;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这种写法的好处是,我们只需要创建一次方法函数,在构造函数中引用它们。那是否还有更好的方法呢?答案是肯定的。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">first, last</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.first = first;</span><br><span class="line"> <span class="keyword">this</span>.last = last;</span><br><span class="line">}</span><br><span class="line">Person.prototype.fullName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.first + <span class="string">' '</span> + <span class="keyword">this</span>.last;</span><br><span class="line">}</span><br><span class="line">Person.prototype.fullNameReversed = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.last + <span class="string">', '</span> + <span class="keyword">this</span>.first;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>Person.prototype</code>是一个可以被<code>Person</code>的所有实例共享的对象。它是一个名叫原型链(<code>prototype chain</code>)的查询链的一部分:当你试图访问一个 <code>Person</code>没有定义的属性时,解释器会首先检查这个<code>Person.prototype</code>来判断是否存在这样一个属性。所以,任何分配给 <code>Person.prototype</code> 的东西对通过 <code>this</code> 对象构造的实例都是可用的。</p><p>这个特性功能十分强大,<code>JavaScript</code> 允许你在程序中的任何时候修改原型(<code>prototype</code>)中的一些东西,也就是说你可以在运行时(<code>runtime</code>)给已存在的对象添加额外的方法:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">s = <span class="keyword">new</span> Person(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line">s.firstNameCaps(); <span class="comment">// TypeError on line 1: s.firstNameCaps is not a function</span></span><br><span class="line"></span><br><span class="line">Person.prototype.firstNameCaps = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.first.toUpperCase()</span><br><span class="line">}</span><br><span class="line">s.firstNameCaps(); <span class="comment">// SIMON</span></span><br></pre></td></tr></table></figure></div><p>有趣的是,你还可以给 <code>JavaScript</code> 的内置函数原型(<code>prototype</code>)添加东西。让我们给 <code>String</code> 添加一个方法用来返回逆序的字符串:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> s = <span class="string">"Simon"</span>;</span><br><span class="line">s.reversed(); <span class="comment">// TypeError on line 1: s.reversed is not a function</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">String</span>.prototype.reversed = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> r = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="keyword">this</span>.length - <span class="number">1</span>; i >= <span class="number">0</span>; i--) {</span><br><span class="line"> r += <span class="keyword">this</span>[i];</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> r;</span><br><span class="line">}</span><br><span class="line">s.reversed(); <span class="comment">// nomiS</span></span><br></pre></td></tr></table></figure></div><p>定义新方法也可以在字符串字面量上用(<code>string literal</code>)。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"This can now be reversed"</span>.reversed(); <span class="comment">// desrever eb won nac sihT</span></span><br></pre></td></tr></table></figure></div><p>正如我前面提到的,原型组成链的一部分。那条链的根节点是 <code>Object.prototype</code>,它包括 <code>toString()</code>方法——将对象转换成字符串时调用的方法。这对于调试我们的 <code>Person</code> 对象很有用:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="keyword">var</span> s = <span class="keyword">new</span> Person(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line">s; <span class="comment">// [object Object]</span></span><br><span class="line"></span><br><span class="line">Person.prototype.toString = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'<Person: '</span> + <span class="keyword">this</span>.fullName() + <span class="string">'>'</span>;</span><br><span class="line">}</span><br><span class="line">s.toString(); <span class="comment">// <Person: Simon Willison></span></span><br></pre></td></tr></table></figure></div><p>你是否还记得之前我们说的 <code>avg.apply()</code> 中的第一个参数 <code>null</code>?现在我们可以回头看看这个东西了。<code>apply()</code> 的第一个参数应该是一个被当作 <code>this</code> 来看待的对象。下面是一个 <code>new</code> 方法的简单实现:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">trivialNew</span>(<span class="params">constructor, ...args</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> o = {}; <span class="comment">// 创建一个对象</span></span><br><span class="line"> <span class="keyword">constructor</span>.apply(o, args);</span><br><span class="line"> return o;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这并不是 <code>new</code> 的完整实现,因为它没有创建原型(<code>prototype</code>)链。想举例说明 <code>new</code> 的实现有些困难,因为你不会经常用到这个,但是适当了解一下还是很有用的。在这一小段代码里,<code>...args</code>(包括省略号)叫作剩余参数(<code>rest arguments</code>)。如名所示,这个东西包含了剩下的参数。</p><p>因此调用</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> bill = trivialNew(Person, <span class="string">"William"</span>, <span class="string">"Orange"</span>);</span><br></pre></td></tr></table></figure></div><p>可认为和调用如下语句是等效的</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> bill = <span class="keyword">new</span> Person(<span class="string">"William"</span>, <span class="string">"Orange"</span>);</span><br></pre></td></tr></table></figure></div><p><code>apply()</code> 有一个姐妹函数,名叫 <code>call</code>,它也可以允许你设置 <code>this</code>,但它带有一个扩展的参数列表而不是一个数组。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">lastNameCaps</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.last.toUpperCase();</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> Person(<span class="string">"Simon"</span>, <span class="string">"Willison"</span>);</span><br><span class="line">lastNameCaps.call(s);</span><br><span class="line"><span class="comment">// 和以下方式等价</span></span><br><span class="line">s.lastNameCaps = lastNameCaps;</span><br><span class="line">s.lastNameCaps();</span><br></pre></td></tr></table></figure></div><h2 id="内部函数"><a href="#内部函数" class="headerlink" title="内部函数"></a>内部函数</h2><p><code>JavaScript</code> 允许在一个函数内部定义函数,这一点我们在之前的 <code>makePerson()</code> 例子中也见过。关于 <code>JavaScript</code> 中的嵌套函数,一个很重要的细节是它们可以访问父函数作用域中的变量:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">betterExampleNeeded</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> a = <span class="number">1</span>;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">oneMoreThanA</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> a + <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> oneMoreThanA();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>如果某个函数依赖于其他的一两个函数,而这一两个函数对你其余的代码没有用处,你可以将它们嵌套在会被调用的那个函数内部,这样做可以减少全局作用域下的函数的数量,这有利于编写易于维护的代码。</p><p>这也是一个减少使用全局变量的好方法。当编写复杂代码时,程序员往往试图使用全局变量,将值共享给多个函数,但这样做会使代码很难维护。内部函数可以共享父函数的变量,所以你可以使用这个特性把一些函数捆绑在一起,这样可以有效地防止“污染”你的全局命名空间——你可以称它为“局部全局(<code>local global</code>)”。虽然这种方法应该谨慎使用,但它确实很有用,应该掌握。</p><h2 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h2><p>下面我们将看到的是 <code>JavaScript</code> 中必须提到的功能最强大的抽象概念之一:闭包。但它可能也会带来一些潜在的困惑。那它究竟是做什么的呢?</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">makeAdder</span>(<span class="params">a</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params">b</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> a + b;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> x = makeAdder(<span class="number">5</span>);</span><br><span class="line"><span class="keyword">var</span> y = makeAdder(<span class="number">20</span>);</span><br><span class="line">x(<span class="number">6</span>); <span class="comment">// ?</span></span><br><span class="line">y(<span class="number">7</span>); <span class="comment">// ?</span></span><br></pre></td></tr></table></figure></div><p><code>makeAdder</code> 这个名字本身应该能说明函数是用来做什么的:它创建了一个新的 <code>adder</code> 函数,这个函数自身带有一个参数,它被调用的时候这个参数会被加在外层函数传进来的参数上。</p><p>这里发生的事情和前面介绍过的内嵌函数十分相似:一个函数被定义在了另外一个函数的内部,内部函数可以访问外部函数的变量。唯一的不同是,外部函数被返回了,那么常识告诉我们局部变量“应该”不再存在。但是它们却仍然存在——否则 <code>adder</code> 函数将不能工作。也就是说,这里存在 <code>makeAdder</code> 的局部变量的两个不同的“副本”——一个是 <code>a</code> 等于<code>5</code>,另一个是 <code>a</code> 等于<code>20</code>。那些函数的运行结果就如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">x(<span class="number">6</span>); <span class="comment">// 返回 11</span></span><br><span class="line">y(<span class="number">7</span>); <span class="comment">// 返回 27</span></span><br></pre></td></tr></table></figure></div><p>下面来说说到底发生了什么。每当 <code>JavaScript</code> 执行一个函数时,都会创建一个作用域对象(<code>scope object</code>),用来保存在这个函数中创建的局部变量。它和被传入函数的变量一起被初始化。这与那些保存的所有全局变量和函数的全局对象(<code>global object</code>)类似,但仍有一些很重要的区别,第一,每次函数被执行的时候,就会创建一个新的,特定的作用域对象;第二,与全局对象(在浏览器里面是当做 window 对象来访问的)不同的是,你不能从 <code>JavaScript</code> 代码中直接访问作用域对象,也没有可以遍历当前的作用域对象里面属性的方法。</p><p>所以当调用 <code>makeAdder</code>时,解释器创建了一个作用域对象,它带有一个属性:<code>a</code>,这个属性被当作参数传入 <code>makeAdder</code> 函数。然后 <code>makeAdder</code> 返回一个新创建的函数。通常 <code>JavaScript</code> 的垃圾回收器会在这时回收 <code>makeAdder</code> 创建的作用域对象,但是返回的函数却保留一个指向那个作用域对象的引用。结果是这个作用域对象不会被垃圾回收器回收,直到指向 <code>makeAdder</code> 返回的那个函数对象的引用计数为零。</p><p>作用域对象组成了一个名为作用域链(<code>scope chain</code>)的链。它类似于原形(<code>prototype</code>)链一样,被 <code>JavaScript</code> 的对象系统使用。</p><p>一个闭包就是一个函数和被创建的函数中的作用域对象的组合。</p><p>闭包允许你保存状态——所以它们通常可以代替对象来使用。这里有一些关于闭包的详细介绍。</p><h3 id="内存泄露"><a href="#内存泄露" class="headerlink" title="内存泄露"></a>内存泄露</h3><p>使用闭包的一个坏处是,在 <code>IE</code> 浏览器中它会很容易导致内存泄露。<code>JavaScript</code> 是一种具有垃圾回收机制的语言——对象在被创建的时候分配内存,然后当指向这个对象的引用计数为零时,浏览器会回收内存。宿主环境提供的对象都是按照这种方法被处理的。</p><p>浏览器主机需要处理大量的对象来描绘一个正在被展现的 <code>HTML</code> 页面——<code>DOM</code> 对象。浏览器负责管理它们的内存分配和回收。</p><p><code>IE</code> 浏览器有自己的一套垃圾回收机制,这套机制与 <code>JavaScript</code> 提供的垃圾回收机制进行交互时,可能会发生内存泄露。</p><p>在 <code>IE</code> 中,每当在一个 <code>JavaScript</code> 对象和一个本地对象之间形成循环引用时,就会发生内存泄露。如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">leakMemory</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> el = <span class="built_in">document</span>.getElementById(<span class="string">'el'</span>);</span><br><span class="line"> <span class="keyword">var</span> o = { <span class="string">'el'</span>: el };</span><br><span class="line"> el.o = o;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这段代码的循环引用会导致内存泄露:<code>IE</code> 不会释放被 <code>el</code> 和 <code>o</code> 使用的内存,直到浏览器被彻底关闭并重启后。</p><p>这个例子往往无法引起人们的重视:一般只会在长时间运行的应用程序中,或者因为巨大的数据量和循环中导致内存泄露发生时,内存泄露才会引起注意。</p><p>不过一般也很少发生如此明显的内存泄露现象——通常泄露的数据结构有多层的引用(<code>references</code>),往往掩盖了循环引用的情况。</p><p>闭包很容易发生无意识的内存泄露。如下所示:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">addHandler</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> el = <span class="built_in">document</span>.getElementById(<span class="string">'el'</span>);</span><br><span class="line"> el.onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> el.style.backgroundColor = <span class="string">'red'</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这段代码创建了一个元素,当它被点击的时候变红,但同时它也会发生内存泄露。为什么?因为对 <code>el</code> 的引用不小心被放在一个匿名内部函数中。这就在 <code>JavaScript</code> 对象(这个内部函数)和本地对象之间(<code>el</code>)创建了一个循环引用。</p><p>这个问题有很多种解决方法,最简单的一种是不要使用 <code>el</code> 变量:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">addHandler</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="built_in">document</span>.getElementById(<span class="string">'el'</span>).onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">this</span>.style.backgroundColor = <span class="string">'red'</span>;</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>有趣的是,有一种窍门解决因闭包而引入的循环引用,是添加另外一个闭包:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="function"><span class="keyword">function</span> <span class="title">addHandler</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> clickHandler = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.style.backgroundColor = <span class="string">'red'</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="keyword">var</span> el = <span class="built_in">document</span>.getElementById(<span class="string">'el'</span>);</span><br><span class="line"> el.onclick = clickHandler;</span><br><span class="line"> })();</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>内部函数被直接执行,并在 <code>clickHandler</code> 创建的闭包中隐藏了它的内容。</p><p>另外一种避免闭包的好方法是在 <code>window.onunload</code> 事件发生期间破坏循环引用。很多事件库都能完成这项工作。注意这样做将使 <code>Firefox</code> 中的 <code>bfcache</code> 无法工作。所以除非有其他必要的原因,最好不要在 <code>Firefox</code> 中注册一个 <code>onunload</code> 的监听器。</p><p>原文来自:<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/A_re-introduction_to_JavaScript" target="_blank" rel="noopener">重新介绍 JavaScript(JS 教程)</a></p><p><a href="https://juejin.im/entry/595a40785188250d92086765/detail" target="_blank" rel="noopener"><img src="https://badge.juejin.im/entry/595a40785188250d92086765/likes.svg?style=flat-square" alt=""></a></p>]]></content>
<summary type="html">
<h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>为什么会有这一篇“重新介绍”呢?因为 <code>JavaScript</code> 堪称世界上被人误解最深的编程语言。虽然常被嘲为“玩具语言”,但在它看似简洁的外衣下,还隐藏着强大的语言特性。 <code>JavaScript</code> 目前广泛应用于众多知名应用中,对于网页和移动开发者来说,深入理解 <code>JavaScript</code> 就尤有必要。</p>
</summary>
<category term="javascript" scheme="https://blog.ihoey.com/categories/javascript/"/>
<category term="javascript" scheme="https://blog.ihoey.com/tags/javascript/"/>
<category term="Function" scheme="https://blog.ihoey.com/tags/Function/"/>
</entry>
<entry>
<title>博客评论网易云跟帖评论提醒功能</title>
<link href="https://blog.ihoey.com/posts/Linux/2017-06-22-blog-comment-gentie-remind.html"/>
<id>https://blog.ihoey.com/posts/Linux/2017-06-22-blog-comment-gentie-remind.html</id>
<published>2017-06-22T11:00:21.000Z</published>
<updated>2018-05-04T10:01:48.000Z</updated>
<content type="html"><![CDATA[<p><img src="https://cdn.dode.top/comment_ihoey.png" alt="comment_ihoey"><br>多说官方宣布17年6月1号停止维护,一个优秀的评论系统从此倒下了,令人唏嘘不已,还是要感谢多说团队多年的付出。眼下留给博主们的选择也就畅言和网易云跟帖了。经过综合考虑选择了网易跟帖,由于网易云跟帖没有提醒功能,所以今天就做了一个邮件提醒的功能。</p><a id="more"></a><ul><li><p>网易云跟帖的安装这里就不多说了,照着网上的教程走一遍或者按官方的文档基本上就可以了,不过提醒一下,网易云跟帖不能在本地测试,必须部署完成才会显示!</p></li><li><p>接下来才是本篇文章的重点。也是云跟帖不足的一个地方。之前多说收到评论会在博客的右上角提示,云跟帖就没有这个功能,而且也不会收到邮件,这样就不能即时的处理评论。好在提供了收到评论的回调功能,所以我们自己来实现发送邮件的功能。</p></li></ul><h2 id="数据回推"><a href="#数据回推" class="headerlink" title="数据回推"></a>数据回推</h2><p>在获取代码里面有个优化设置功能,需要我们自己设置接口来接受评论推送。以下邮件评论提示由php来实现。php模拟邮箱登录发送邮件采用如下库:<a href="http://download.csdn.net/download/zhong960725/9755214" target="_blank" rel="noopener">http://download.csdn.net/download/zhong960725/9755214</a><br>,亲测能正常使用,需要配置smtp服务区,端口,帐号和密码等。 网易通过结果返回的数据如下:</p><figure class="highlight"><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></pre></td><td class="code"><pre><span class="line">[</span><br><span class="line"> {</span><br><span class="line"> "title" : "xxx",//文章标题</span><br><span class="line"> "url" : "http://localhost/1.htm",//文章url</span><br><span class="line"> "sourceId" : "xxx",//文章唯一id</span><br><span class="line"> "ctime" : 11111,//文章创建时间</span><br><span class="line"> "comments" : [{</span><br><span class="line"> "cid" : "xxx",//跟贴id</span><br><span class="line"> "content" : "xxxx",//内容</span><br><span class="line"> "ctime" : 11111,//创建时间</span><br><span class="line"> "pid" : "xxxx",//父贴id</span><br><span class="line"> "ip" : "127.0.0.1",//发贴ip</span><br><span class="line"> "source" : "web",//来源 app,web,wap</span><br><span class="line"> "anonymous" : false,//是否匿名跟贴 false:非匿名 true:匿名</span><br><span class="line"> "attachment" : {</span><br><span class="line"> "type" : 0,//0没有附件 1为图片 2为语音 3为视频</span><br><span class="line"> "desc" : "xxx",//描述</span><br><span class="line"> "info" : "http://localhost/1.jpg"//附件地址</span><br><span class="line"> },</span><br><span class="line"> "user" : {</span><br><span class="line"> "userId" : "xxx",//第三方用户id</span><br><span class="line"> "nickname" : "xxx",//昵称</span><br><span class="line"> "avatar" : "http://localhost/2.png"//头像地址</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><h2 id="服务器配置"><a href="#服务器配置" class="headerlink" title="服务器配置"></a>服务器配置</h2><ul><li>搭建<code>web</code>服务器,博客前面有提到,可以<a href="https://blog.ihoey.com/posts/Linux/2017-05-26-liunx-shell.html">Linux常用命令笔记</a></li><li>搭建<code>PHP</code>环境,由于我的服务器是<code>Ubuntu 16.04</code>的,所以貌似不能安装<code>php5</code>了,所以这里是<code>php7</code>。<ul><li>安装<code>PHP</code> : <code>sudo apt-get install -y php7.0 php7.0-fpm php7.0-cli php7.0-common php7.0-mbstring php7.0-gd php7.0-intl php7.0-xml php7.0-mysql php7.0-mcrypt php7.0-zip</code>.</li></ul></li><li><p>配置<code>nginx</code>,</p><figure class="highlight"><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></pre></td><td class="code"><pre><span class="line">server {</span><br><span class="line"> listen 80;</span><br><span class="line"> server_name xxxx.xxx.xxx;</span><br><span class="line"></span><br><span class="line"> root /var/www/comment;</span><br><span class="line"> index index.php index.html index.htm;</span><br><span class="line"></span><br><span class="line"> location ~ \.php$ {</span><br><span class="line"> try_files $uri =404;</span><br><span class="line"> fastcgi_split_path_info ^(.+\.php)(/.+)$;</span><br><span class="line"> fastcgi_pass unix:/run/php/php7.0-fpm.sock;</span><br><span class="line"> fastcgi_index index.php;</span><br><span class="line"> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</span><br><span class="line"> include fastcgi_params;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>然后我这里将下载的<code>php</code>库文件放到<code>/var/www/comment</code>目录下。</p></li></ul><h2 id="代码实现"><a href="#代码实现" class="headerlink" title="代码实现"></a>代码实现</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PHP"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line">header(<span class="string">"Content-type: text/html; charset=utf-8"</span>);</span><br><span class="line">date_default_timezone_set(<span class="string">"Asia/Shanghai"</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Created by Ihoey</span></span><br><span class="line"><span class="comment"> * User: Ihoey</span></span><br><span class="line"><span class="comment"> * Date: 17/6/22</span></span><br><span class="line"><span class="comment"> * Time: 15:00</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line">$receiver = $_REQUEST;</span><br><span class="line"><span class="keyword">if</span>(count($receiver) > <span class="number">0</span>) {</span><br><span class="line"> $content = implode(<span class="string">','</span>, $receiver);</span><br><span class="line"> $json = json_decode($content);</span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">isset</span>($json) && count($json) > <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">require_once</span>(<span class="string">"./functions.php"</span>);</span><br><span class="line"> $title = $json[<span class="number">0</span>]->title;</span><br><span class="line"> $url = $json[<span class="number">0</span>]->url;</span><br><span class="line"> $ctime = $json[<span class="number">0</span>]->ctime;</span><br><span class="line"> $date = date(<span class="string">'Y-m-d H:i:s'</span>, $ctime/<span class="number">1000</span>);</span><br><span class="line"> $name = $json[<span class="number">0</span>]->comments[<span class="number">0</span>]->user->nickname;</span><br><span class="line"> $userId = $json[<span class="number">0</span>]->comments[<span class="number">0</span>]->user->userId;</span><br><span class="line"> $comment = $json[<span class="number">0</span>]->comments[<span class="number">0</span>]->content;</span><br><span class="line"> $flag = sendMail(<span class="string">'123456.qq.com'</span>,<span class="string">"您的博客收到一条来自{$name}({$userId})的新评论"</span>,</span><br><span class="line"> <span class="string">"文章标题:<br/><a target='_blank' href='{$url}'>{$title}</a><br/><br/>评论内容:<br/>{$name}({$userId}): {$comment}<br/><br/>评论时间:<br/>{$date}<br/><br/><br/>{$content}"</span>);</span><br><span class="line"> file_put_contents(<span class="string">'./comment.txt'</span>, $flag ? <span class="string">"success!"</span> : <span class="string">"failure!"</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="meta">?></span></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * comment.php</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure></div><h2 id="设置回推"><a href="#设置回推" class="headerlink" title="设置回推"></a>设置回推</h2><p>优化设置里面的回推结果设置如下就好<code>http://yourDomain/comment.php</code>;</p>]]></content>
<summary type="html">
<p><img src="https://cdn.dode.top/comment_ihoey.png" alt="comment_ihoey"><br>多说官方宣布17年6月1号停止维护,一个优秀的评论系统从此倒下了,令人唏嘘不已,还是要感谢多说团队多年的付出。眼下留给博主们的选择也就畅言和网易云跟帖了。经过综合考虑选择了网易跟帖,由于网易云跟帖没有提醒功能,所以今天就做了一个邮件提醒的功能。</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="comment" scheme="https://blog.ihoey.com/tags/comment/"/>
</entry>
<entry>
<title>Linux常用命令笔记</title>
<link href="https://blog.ihoey.com/posts/Linux/2017-05-26-liunx-shell.html"/>
<id>https://blog.ihoey.com/posts/Linux/2017-05-26-liunx-shell.html</id>
<published>2017-05-26T13:49:04.000Z</published>
<updated>2018-05-04T10:02:19.000Z</updated>
<content type="html"><![CDATA[<p>记录使用到的 <code>Linux</code> 命令!</p><a id="more"></a><h2 id="安装-Git"><a href="#安装-Git" class="headerlink" title="安装 Git"></a>安装 Git</h2><ul><li>安装: <code>sudo apt-get install git</code> , <code>git</code> 配置请查看<a href=""></a>。</li></ul><h2 id="安装-Nginx"><a href="#安装-Nginx" class="headerlink" title="安装 Nginx"></a>安装 Nginx</h2><ul><li>安装: <code>sudo apt-get install nginx</code></li><li>启动: <code>sudo /etc/init.d/nginx start</code></li><li>停止: <code>sudo /etc/init.d/nginx stop</code></li><li>重启: <code>sudo /etc/init.d/nginx restart</code></li><li>检查配置文件: <code>sudo service nginx configtest</code></li><li>重载配置文件: <code>sudo service nginx reload</code></li><li>查询nginx进程: <code>ps -ef | grep nginx</code></li></ul><h2 id="Nginx-配置"><a href="#Nginx-配置" class="headerlink" title="Nginx 配置"></a>Nginx 配置</h2><p><code>sudo vim /etc/nginx/sites-available/default</code></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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></pre></td><td class="code"><pre><span class="line">server {</span><br><span class="line"> listen 80 default_server;</span><br><span class="line"> listen [::]:80 default_server ipv6only=on;</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 如果要支持HTTPS,修改这里</span></span><br><span class="line"> <span class="comment"># 可以使用 https://letsencrypt.org 的免费SSL证书</span></span><br><span class="line"> <span class="comment">#listen 443 ssl;</span></span><br><span class="line"> <span class="comment">#ssl_certificate www.example.com.crt;</span></span><br><span class="line"> <span class="comment">#ssl_certificate_key www.example.com.key;</span></span><br><span class="line"> <span class="comment">#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;</span></span><br><span class="line"> <span class="comment">#ssl_ciphers HIGH:!aNULL:!MD5;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 重定向所有HTTP到HTTPS</span></span><br><span class="line"> <span class="comment"># rewrite ^(.*)$ https://$host$1 permanent;</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># 网站根目录,根据需要修改</span></span><br><span class="line"> root /usr/share/nginx/html;</span><br><span class="line"> <span class="comment"># 增加index.php</span></span><br><span class="line"> index index.php index.html index.htm;</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 假设域名是 ssl.mcxiaoke.com</span></span><br><span class="line"> server_name ssl.mcxiaoke.com; <span class="comment">#绑定域名</span></span><br><span class="line"></span><br><span class="line"> location / {</span><br><span class="line"> try_files <span class="variable">$uri</span> <span class="variable">$uri</span>/ =404;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> error_page 404 /404.html;</span><br><span class="line"> error_page 500 502 503 504 /50x.html;</span><br><span class="line"> location = /50x.html {</span><br><span class="line"> root /usr/share/nginx/html;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">#支持php-fpm的配置</span></span><br><span class="line"> location ~ \.php$ {</span><br><span class="line"> try_files <span class="variable">$uri</span> =404;</span><br><span class="line"> fastcgi_split_path_info ^(.+\.php)(/.+)$;</span><br><span class="line"> fastcgi_pass unix:/var/run/php5-fpm.sock;</span><br><span class="line"> fastcgi_index index.php;</span><br><span class="line"> fastcgi_param SCRIPT_FILENAME <span class="variable">$document_root</span><span class="variable">$fastcgi_script_name</span>;</span><br><span class="line"> include fastcgi_params;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="安装-MySQL"><a href="#安装-MySQL" class="headerlink" title="安装 MySQL"></a>安装 MySQL</h2><ul><li>安装: <code>sudo apt-get install mysql-server</code></li></ul><h2 id="安装-php-fpm"><a href="#安装-php-fpm" class="headerlink" title="安装 php-fpm"></a>安装 php-fpm</h2><ul><li>安装: <code>sudo apt-get install php5-fpm</code></li><li>重启: <code>sudo service php5-fpm restart</code></li><li>安装PHP常用扩展: <code>sudo apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl php5-xcache</code></li></ul><h2 id="常用linux命令说明"><a href="#常用linux命令说明" class="headerlink" title="常用linux命令说明"></a>常用linux命令说明</h2><ul><li>查看端口占用: <code>lsof -i:80</code></li><li>杀死进程: <code>kill -9 3274</code></li><li><code>tar</code><ul><li>z- 用<code>gzip</code>对存档压缩或解压</li><li>x-从存档展开文件</li><li>v-详细显示处理的文件</li><li>f-指定存档或设备</li></ul></li><li><p><code>chmod</code><br> +</p></li><li><p>更新源: <code>sudo apt-get update</code></p></li><li>更新已安装的包<code>sudo apt-get upgrade</code></li></ul><h2 id="账号和密码文件"><a href="#账号和密码文件" class="headerlink" title="账号和密码文件"></a>账号和密码文件</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">ls -al /etc/passwd /etc/shadow</span><br><span class="line">-rw-r–r– 1 root root 1611 2011-12-16 05:30 /etc/passwd <span class="comment"># 保存的是账号</span></span><br><span class="line">-rw-r—– 1 root shadow 947 2011-12-16 05:30 /etc/shadow <span class="comment"># 账号的密码等信息</span></span><br></pre></td></tr></table></figure></div><h3 id="etc-passwd"><a href="#etc-passwd" class="headerlink" title="/etc/passwd"></a>/etc/passwd</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">root:x:0:0:root:/root:/bin/bash</span><br><span class="line">daemon:x:1:1:daemon:/usr/sbin:/bin/sh</span><br><span class="line">bin:x:2:2:bin:/bin:/bin/sh</span><br><span class="line">sys:x:3:3:sys:/dev:/bin/sh</span><br></pre></td></tr></table></figure></div><ol><li>账号名称</li><li>原先用来保存密码的,现在密码都放在/etc/shadow中,所以这里显示x</li><li>UID,也就是使用者ID。默认的系统管理员的UID为0,我们添加用户的时候最好使用1000以上的UID,1-1000范围的UID最好保留给系统用。</li><li>GID,也就是群组ID</li><li>关于账号的一些说明信息(暂时可以忽略)</li><li>账号的家目录,家目录就是你登陆系统后默认的那个目录</li><li>账号使用的shell</li></ol><h3 id="etc-shadow"><a href="#etc-shadow" class="headerlink" title="/etc/shadow"></a>/etc/shadow</h3><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">root:!:15324:0:99999:7:::</span><br><span class="line">daemon:*:15259:0:99999:7:::</span><br><span class="line">bin:*:15259:0:99999:7:::</span><br><span class="line">letuknowit:<span class="variable">$1</span><span class="variable">$cPf</span>/cIvr<span class="variable">$sCws95uSip2ljTK052DDB</span>.:15400:5:60:7:2:15490:</span><br></pre></td></tr></table></figure></div><ol><li>账户名称(密码需要与账户对应的嘛)</li><li>加密后的密码(总不能学CSDN放明文密码,是吧),如果这一栏的第一个字符为!或者*的话,说明这是一个不能登录的账户,从上面可以看出,ubuntu默认的就不启用root账户。</li><li>最近改动密码的日期(不是日期吗,咋是一堆数字,别急,这个是从1970年1月1日算起的总的天数)。那怎么才能知道今天距1970年1月1日有多少天呢?很简单,你改下密码,然后看下这个栏目中的数字是多少就可以了!</li><li>密码不可被变更的天数:设置了这个值,则表示从变更密码的日期算起,多少天内无法再次修改密码,如果是0的话,则没有限制</li><li>密码需要重新变更的天数:密码经常更换才能保证安全,为了提醒某些经常不更换密码的用户,可以设置一个天数,强制让用户更换密码,也就是说该用户的密码会在多少天后过期,如果为99999则没有限制</li><li>密码过期预警天数:如果在5中设置了密码需要重新变更的天数,则会在密码过期的前多少天进行提醒,提示用户其密码将在多少天后过期</li><li>密码过期的宽恕时间:如果在5中设置的日期过后,用户仍然没有修改密码,则该用户还可以继续使用的天数</li><li>账号失效日期,过了这个日期账号就不能用了</li><li>保留的</li></ol><p>以上面最后用户letuknowit为例(15400对应的日期为2012年3月1日),其保护如下信息:</p><ol start="3"><li>用户letuknowit最近一次修改密码的日期是2012年3月1日,</li><li>在2012年3月6日之前不能再改动密码了,</li><li>在2012-3-1到2012-4-29期间letuknowit需要更改密码,</li><li>在2012-4-29之前的7天,letuknowit登陆系统的时候,系统会提示letuknowit其密码即将过期,</li><li>如果letuknowit一直到2012-4-29都没有修改密码,则其仍然可以继续使用该账户2天,2天后该账户将不可用</li><li>无论如何,到了2012年5月29日,该账号都将失效</li></ol><h2 id="主机名"><a href="#主机名" class="headerlink" title="主机名"></a>主机名</h2><ul><li>查看主机名: <code>hostname</code> 或<code>uname –n</code>,均可以查看到当前主机的主机名。</li><li>临时修改主机名: <code>hostname 新主机名</code></li><li>永久修改主机名: <code>/etc/hostname</code>文件中修改</li><li><code>host</code> 文件: <code>/etc/hosts</code> 存放的是域名与ip的对应关系, 添加一个新主机名到<code>127.0.0.1</code>.</li></ul><p>待续中…</p>]]></content>
<summary type="html">
<p>记录使用到的 <code>Linux</code> 命令!</p>
</summary>
<category term="Linux" scheme="https://blog.ihoey.com/categories/Linux/"/>
<category term="Linux" scheme="https://blog.ihoey.com/tags/Linux/"/>
<category term="shell" scheme="https://blog.ihoey.com/tags/shell/"/>
</entry>
<entry>
<title>NPM 学习笔记整理</title>
<link href="https://blog.ihoey.com/posts/Node/2017-05-10-npm.html"/>
<id>https://blog.ihoey.com/posts/Node/2017-05-10-npm.html</id>
<published>2017-05-09T19:25:24.000Z</published>
<updated>2018-05-04T10:02:31.000Z</updated>
<content type="html"><![CDATA[<h1 id="什么是-NPM"><a href="#什么是-NPM" class="headerlink" title="什么是 NPM"></a>什么是 NPM</h1><p><code>npm</code> 之于 <code>Node</code> ,就像 <code>pip</code> 之于 <code>Python</code> , <code>gem</code> 之于 <code>Ruby</code> , <code>composer</code> 之于 <code>PHP</code> 。</p><p><code>npm</code> 是 <code>Node</code> 官方提供的包管理工具,他已经成了 <code>Node</code> 包的标准发布平台,用于 <code>Node</code> 包的发布、传播、依赖控制。<br><code>npm</code> 提供了命令行工具,使你可以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。</p><a id="more"></a><h1 id="为什么要使用-NPM"><a href="#为什么要使用-NPM" class="headerlink" title="为什么要使用 NPM"></a>为什么要使用 NPM</h1><p><code>npm</code> 是随同 <code>Node</code> 一起安装的包管理工具,能解决 <code>Node</code> 代码部署上的很多问题,常见的场景有以下几种:</p><ul><li>允许用户从 <code>npm</code> 服务器下载别人编写的第三方包到本地使用。</li><li>允许用户从 <code>npm</code> 服务器下载并安装别人编写的命令行程序到本地使用。</li><li>允许用户将自己编写的包或命令行程序上传到 <code>npm</code> 服务器供别人使用。</li></ul><p><code>npm</code> 的背后,是基于 <code>CouchDB</code> 的一个数据库,详细记录了每个包的信息,包括作者、版本、依赖、授权信息等。它的一个很重要的作用就是:将开发者从繁琐的包管理工作(版本、依赖等)中解放出来,更加专注于功能的开发。</p><h1 id="如何使用-NPM"><a href="#如何使用-NPM" class="headerlink" title="如何使用 NPM"></a>如何使用 NPM</h1><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p><code>npm</code> 不需要单独安装。在安装 <code>Node</code> 的时候,会连带一起安装 <code>npm</code> 。但是,<code>Node</code> 附带的 <code>npm</code> 可能不是最新版本,最后用下面的命令,更新到最新版本。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo npm install npm@latest -g</span><br></pre></td></tr></table></figure></div><p>如果是 Window 系统使用以下命令即可:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install npm -g</span><br></pre></td></tr></table></figure></div><p>也就是使用 <code>npm</code> 安装自己。之所以可以这样,是因为 <code>npm</code> 本身与 <code>Node</code> 的其他模块没有区别。</p><p>然后,运行下面的命令,查看各种信息。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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"># 查看 npm 命令列表</span></span><br><span class="line">$ npm <span class="built_in">help</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看各个命令的简单用法</span></span><br><span class="line">$ npm -l</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 npm 的版本</span></span><br><span class="line">$ npm -v</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看 npm 的配置</span></span><br><span class="line">$ npm config list -l</span><br></pre></td></tr></table></figure></div><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><h3 id="npm-init"><a href="#npm-init" class="headerlink" title="npm init"></a>npm init</h3><p><code>npm init</code> 用来初始化生成一个新的 <code>package.json</code> 文件。它会向用户提问一系列问题,如果你觉得不用修改默认配置,一路回车就可以了。<br>如果使用了 <code>-f</code>(代表<code>force</code>)、<code>-y</code>(代表<code>yes</code>),则跳过提问阶段,直接生成一个新的 <code>package.json</code> 文件。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm init -y</span><br></pre></td></tr></table></figure></div><h3 id="npm-set"><a href="#npm-set" class="headerlink" title="npm set"></a>npm set</h3><p><code>npm set</code> 用来设置环境变量</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm <span class="built_in">set</span> init-author-name <span class="string">'Your name'</span></span><br><span class="line">$ npm <span class="built_in">set</span> init-author-email <span class="string">'Your email'</span></span><br><span class="line">$ npm <span class="built_in">set</span> init-author-url <span class="string">'http://yourdomain.com'</span></span><br><span class="line">$ npm <span class="built_in">set</span> init-license <span class="string">'MIT'</span></span><br></pre></td></tr></table></figure></div><p>上面命令等于为 <code>npm init</code> 设置了默认值,以后执行 <code>npm init</code> 的时候,<code>package.json</code>的作者姓名、邮件、主页、许可证字段就会自动写入预设的值。这些信息会存放在用户主目录的 <code>~/.npmrc</code>文件,使得用户不用每个项目都输入。如果某个项目有不同的设置,可以针对该项目运行 <code>npm config</code>。</p><h3 id="npm-info"><a href="#npm-info" class="headerlink" title="npm info"></a>npm info</h3><p><code>npm info</code> 命令可以查看每个模块的具体信息。比如,查看 <code>underscore</code> 模块的信息。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm info underscore</span><br></pre></td></tr></table></figure></div><p>上面命令返回一个 <code>JavaScript</code> 对象,包含了 <code>underscore</code> 模块的详细信息。这个对象的每个成员,都可以直接从 <code>info</code> 命令查询。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm info underscore description</span><br><span class="line"></span><br><span class="line">$ npm info underscore homepage</span><br><span class="line"></span><br><span class="line">$ npm info underscore version</span><br></pre></td></tr></table></figure></div><h3 id="npm-search"><a href="#npm-search" class="headerlink" title="npm search"></a>npm search</h3><p><code>npm search</code> 命令用于搜索 <code>npm</code> 仓库,它后面可以跟字符串,也可以跟正则表达式。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm search <搜索词></span><br></pre></td></tr></table></figure></div><h3 id="npm-list"><a href="#npm-list" class="headerlink" title="npm list"></a>npm list</h3><p><code>npm list</code> 命令以树形结构列出当前项目安装的所有模块,以及它们依赖的模块。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm list</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加上 global 参数,会列出全局安装的模块</span></span><br><span class="line">$ npm list -global</span><br><span class="line"></span><br><span class="line"><span class="comment"># npm list 命令也可以列出单个模块</span></span><br><span class="line">$ npm list underscore</span><br></pre></td></tr></table></figure></div><h3 id="npm-install"><a href="#npm-install" class="headerlink" title="npm install"></a>npm install</h3><p>使用 <code>npm</code> 安装包的命令格式为:<code>npm [install/i] [package_name]</code></p><h4 id="本地模式和全局模式"><a href="#本地模式和全局模式" class="headerlink" title="本地模式和全局模式"></a>本地模式和全局模式</h4><p><code>npm</code> 在默认情况下会从 <a href="http://npmjs.org" target="_blank" rel="noopener">NPM</a> 搜索或下载包,将包安装到当前目录的 <code>node_modules</code> 子目录下。</p><p>如果你熟悉 <code>Ruby</code> 的 <code>gem</code> 或者 <code>Python</code> 的 <code>pip</code> ,你会发现 <code>npm</code> 与它们的行为不同, <code>gem</code> 或 <code>pip</code> 总是以全局模式安装,使包可以供所有的程序使用,而 <code>npm</code> 默认会把包安装到当前目录下。这反映了 <code>npm</code> 不同的设计哲学。如果把包安装到全局,可以提供程序的重复利用程度,避免同样的内容的多分副本,但坏处是难以处理不同的版本依赖。如果把包安装到当前目录,或者说本地,则不会有不同程序依赖不同版本的包的冲突问题,同时还减轻了包作者的 <code>API</code> 兼容性压力,但缺陷则是同一个包可能会被安装许多次。</p><p>我们在使用 <code>supervisor</code> 的时候使用了 <code>npm install -g supervisor</code> 命令,就是以全局模式安装 <code>supervisor</code> 。</p><p>这里注意一点的就是, <code>supervisor</code> 必须安装到全局,如果你不安装到全局,错误命令会提示你安装到全局。如果不想安装到默认的全局,也可以自己修改全局路径到当前路径 <code>npm config set prefix "路径"</code> 安装完以后就可以用 <code>supervisor</code> 来启动服务了。<br><code>supervisor</code> 可以帮助你实现这个功能,它会监视你对代码的驱动,并自动重启 <code>Node</code> 。</p><p>一般来说,全局安装只适用于工具模块,比如 <code>eslint</code> 和 <code>gulp</code> 。关于使用全局模式,多数时候并不是因为许多程序都有可能用到了它,为了减少多重副本而使用全局模式,而是因为 <strong>本地模式不会注册 <code>PATH</code> 环境变量</strong>。<br>“本地安装”指的是将一个模块下载到当前项目的 <code>node_modules</code> 子目录,然后只有在项目目录之中,才能调用这个模块。</p><p>本地模式和全局模式的特点如下:</p><table><thead><tr><th style="text-align:center">模式</th><th style="text-align:center">可通过 require 使用</th><th style="text-align:center">注册 PATH</th></tr></thead><tbody><tr><td style="text-align:center">本地模式</td><td style="text-align:center">是</td><td style="text-align:center">否</td></tr><tr><td style="text-align:center">全局模式</td><td style="text-align:center">否</td><td style="text-align:center">是</td></tr></tbody></table><p><br></p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm install <package name></span><br><span class="line"></span><br><span class="line"><span class="comment"># 全局安装</span></span><br><span class="line">$ sudo npm install -global <package name></span><br><span class="line">$ sudo npm install -g <package name></span><br></pre></td></tr></table></figure></div><p><code>npm install</code> 也支持直接输入 <code>Github</code> 代码库地址。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm install git://github.com/package/path.git</span><br><span class="line">$ npm install git://github.com/package/path.git<span class="comment">#0.1.0</span></span><br></pre></td></tr></table></figure></div><p>安装之前,<code>npm install</code> 会先检查,<code>node_modules</code> 目录之中是否已经存在指定模块。如果存在,就不再重新安装了,即使远程仓库已经有了一个新版本,也是如此。</p><p>如果你希望,一个模块不管是否安装过, <code>npm</code> 都要强制重新安装,可以使用 <code>-f</code> 或 <code>--force</code> 参数。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm install <packageName> --force</span><br></pre></td></tr></table></figure></div><h4 id="安装不同版本"><a href="#安装不同版本" class="headerlink" title="安装不同版本"></a>安装不同版本</h4><p><code>install</code> 命令总是安装模块的最新版本,如果要安装模块的特定版本,可以在模块名后面加上 <code>@</code> 和版本号。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm install sax@latest</span><br><span class="line">$ npm install [email protected]</span><br><span class="line">$ npm install sax@<span class="string">">=0.1.0 <0.2.0"</span></span><br></pre></td></tr></table></figure></div><p><code>install</code> 命令可以使用不同参数,指定所安装的模块属于哪一种性质的依赖关系,即出现在 <code>packages.json</code> 文件的哪一项中。</p><blockquote><p>–save:模块名将被添加到 dependencies,可以简化为参数-S。<br>–save-dev:模块名将被添加到 devDependencies,可以简化为参数-D。</p></blockquote><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm install sax --save</span><br><span class="line">$ npm install node-tap --save-dev</span><br><span class="line"><span class="comment"># 或者</span></span><br><span class="line">$ npm install sax -S</span><br><span class="line">$ npm install node-tap -D</span><br></pre></td></tr></table></figure></div><h5 id="dependencies-依赖"><a href="#dependencies-依赖" class="headerlink" title="dependencies 依赖"></a>dependencies 依赖</h5><p>这个可以说是我们 <code>npm</code> 核心一项内容,依赖管理,这个对象里面的内容就是我们这个项目所依赖的 <code>js</code> 模块包。下面这段代码表示我们依赖了 <code>markdown-it</code> 这个包,版本是 <code>^8.1.0</code> ,代表最小依赖版本是 <code>8.1.0</code> ,如果这个包有更新,那么当我们使用 <code>npm install</code> 命令的时候, <code>npm</code> 会帮我们下载最新的包。当别人引用我们这个包的时候,包内的依赖包也会被下载下来。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"dependencies"</span>: {</span><br><span class="line"> <span class="string">"markdown-it"</span>: <span class="string">"^8.1.0"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h5 id="devDependencies-开发依赖"><a href="#devDependencies-开发依赖" class="headerlink" title="devDependencies 开发依赖"></a>devDependencies 开发依赖</h5><p>在我们开发的时候会用到的一些包,只是在开发环境中需要用到,但是在别人引用我们包的时候,不会用到这些内容,放在 <code>devDependencies</code> 的包,在别人引用的时候不会被 <code>npm</code> 下载。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line"><span class="string">"devDependencies"</span>: {</span><br><span class="line"> <span class="string">"autoprefixer"</span>: <span class="string">"^6.4.0"</span>,</span><br><span class="line"> <span class="string">"babel-preset-es2015"</span>: <span class="string">"^6.0.0"</span>,</span><br><span class="line"> <span class="string">"babel-preset-stage-2"</span>: <span class="string">"^6.0.0"</span>,</span><br><span class="line"> <span class="string">"babel-register"</span>: <span class="string">"^6.0.0"</span>,</span><br><span class="line"> <span class="string">"webpack"</span>: <span class="string">"^1.13.2"</span>,</span><br><span class="line"> <span class="string">"webpack-dev-middleware"</span>: <span class="string">"^1.8.3"</span>,</span><br><span class="line"> <span class="string">"webpack-hot-middleware"</span>: <span class="string">"^2.12.2"</span>,</span><br><span class="line"> <span class="string">"webpack-merge"</span>: <span class="string">"^0.14.1"</span>,</span><br><span class="line"> <span class="string">"highlightjs"</span>: <span class="string">"^9.8.0"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>当你有了一个完整的 <code>package.json</code>文件的时候,就可以让人一眼看出来,这个模块的基本信息,和这个模块所需要依赖的包。我们可以通过 <code>npm install</code> 就可以很方便的下载好这个模块所需要的包。</p><p><code>npm install</code> 默认会安装 <code>dependencies</code> 字段和 <code>devDependencies</code> 字段中的所有模块,如果使用 <code>--production</code> 参数,可以只安装 <code>dependencies</code> 字段的模块。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">$ npm install --production</span><br><span class="line"><span class="comment"># 或者</span></span><br><span class="line">$ NODE_ENV=production npm install</span><br></pre></td></tr></table></figure></div><p>一旦安装了某个模块,就可以在代码中用 <code>require</code> 命令加载这个模块。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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">var</span> backbone = <span class="built_in">require</span>(<span class="string">'backbone'</span>)</span><br><span class="line"><span class="built_in">console</span>.log(backbone.VERSION)</span><br></pre></td></tr></table></figure></div><h3 id="npm-run"><a href="#npm-run" class="headerlink" title="npm run"></a>npm run</h3><p><code>npm</code> 不仅可以用于模块管理,还可以用于执行脚本。<code>package.json</code> 文件有一个 <code>scripts</code> 字段,可以用于指定脚本命令,供 <code>npm</code> 直接调用。<br><code>package.json</code> 文件内容:</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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><br><span class="line"> <span class="string">"name"</span>: <span class="string">"myproject"</span>,</span><br><span class="line"> <span class="string">"devDependencies"</span>: {</span><br><span class="line"> <span class="string">"jshint"</span>: <span class="string">"latest"</span>,</span><br><span class="line"> <span class="string">"browserify"</span>: <span class="string">"latest"</span>,</span><br><span class="line"> <span class="string">"mocha"</span>: <span class="string">"latest"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"lint"</span>: <span class="string">"jshint **.js"</span>,</span><br><span class="line"> <span class="string">"test"</span>: <span class="string">"mocha test/"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h4 id="scripts-脚本"><a href="#scripts-脚本" class="headerlink" title="scripts 脚本"></a>scripts 脚本</h4><p>顾名思义,就是一些脚本代码,可以通过 <code>npm run script-key</code> 来调用,例如在这个 <code>package.json</code> 的文件夹下使用 <code>npm run dev</code> 就相当于运行了 <code>node build/dev-server.js</code> 这一段代码。使用 <code>scripts</code> 的目的就是为了把一些要执行的代码合并到一起,使用 npm run 来快速的运行,方便省事。<br><code>npm run</code> 是 <code>npm run-script</code> 的缩写,一般都使用前者,但是后者可以更好的反应这个命令的本质。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"dev"</span>: <span class="string">"node build/dev-server.js"</span>,</span><br><span class="line"> <span class="string">"build"</span>: <span class="string">"node build/build.js"</span>,</span><br><span class="line"> <span class="string">"docs"</span>: <span class="string">"node build/docs.js"</span>,</span><br><span class="line"> <span class="string">"build-docs"</span>: <span class="string">"npm run docs & git checkout gh-pages & xcopy /sy dist\\* . & git add . & git commit -m 'auto-pages' & git push & git checkout master"</span>,</span><br><span class="line"> <span class="string">"build-publish"</span>: <span class="string">"rmdir /S /Q lib & npm run build &git add . & git commit -m auto-build & npm version patch & npm publish & git push"</span>,</span><br><span class="line"> <span class="string">"lint"</span>: <span class="string">"eslint --ext .js,.vue src"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><code>npm run</code> 如果不加任何参数,直接运行,会列出 <code>package.json</code> 里面所有可以执行的脚本命令。<br><code>npm</code> 内置了两个命令简写, <code>npm test</code> 等同于执行 <code>npm run test</code> ,<code>npm start</code> 等同于执行 <code>npm run start</code>。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"build"</span>: <span class="string">"npm run build-js && npm run build-css"</span></span><br></pre></td></tr></table></figure></div><p>上面的写法是先运行 <code>npm run build-js</code> ,然后再运行 <code>npm run build-css</code> ,两个命令中间用 <code>&&</code> 连接。如果希望两个命令同时平行执行,它们中间可以用 <code>&</code> 连接。</p><p>写在 <code>scripts</code> 属性中的命令,也可以在 <code>node_modules/.bin</code> 目录中直接写成 <code>bash</code> 脚本。下面是一个 <code>bash</code> 脚本。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">cd</span> site/main</span><br><span class="line">browserify browser/main.js | uglifyjs -mc > static/bundle.js</span><br></pre></td></tr></table></figure></div><p>假定上面的脚本文件名为 <code>build.sh</code> ,并且权限为可执行,就可以在 <code>scripts</code> 属性中引用该文件。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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="string">"build-js"</span>: <span class="string">"bin/build.sh"</span></span><br></pre></td></tr></table></figure></div><h3 id="pre-和-post-脚本"><a href="#pre-和-post-脚本" class="headerlink" title="pre- 和 post- 脚本"></a>pre- 和 post- 脚本</h3><p><code>npm run</code> 为每条命令提供了 <code>pre-</code> 和 <code>post-</code> 两个钩子( <code>hook</code> )。以 <code>npm run lint</code> 为例,执行这条命令之前, <code>npm</code> 会先查看有没有定义 <code>prelint</code> 和 <code>postlint</code> 两个钩子,如果有的话,就会先执行 <code>npm run prelint</code> ,然后执行 <code>npm run lint</code> ,最后执行 <code>npm run postlint</code> 。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="JAVASCRIPT"><figure class="iseeu 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></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"myproject"</span>,</span><br><span class="line"> <span class="string">"devDependencies"</span>: {</span><br><span class="line"> <span class="string">"eslint"</span>: <span class="string">"latest"</span></span><br><span class="line"> <span class="string">"karma"</span>: <span class="string">"latest"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"lint"</span>: <span class="string">"eslint --cache --ext .js --ext .jsx src"</span>,</span><br><span class="line"> <span class="string">"test"</span>: <span class="string">"karma start --log-leve=error karma.config.js --single-run=true"</span>,</span><br><span class="line"> <span class="string">"pretest"</span>: <span class="string">"npm run lint"</span>,</span><br><span class="line"> <span class="string">"posttest"</span>: <span class="string">"echo 'Finished running tests'"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>上面代码是一个 <code>package.json</code> 文件的例子。如果执行 <code>npm test</code>,会按下面的顺序执行相应的命令。</p><ol><li><code>pretest</code></li><li><code>test</code></li><li><code>posttest</code></li></ol><p>如果执行过程出错,就不会执行排在后面的脚本,即如果 <code>prelint</code> 脚本执行出错,就不会接着执行 <code>lint</code> 和 <code>postlint</code> 脚本。</p><h3 id="npm-bin"><a href="#npm-bin" class="headerlink" title="npm bin"></a>npm bin</h3><p><code>npm bin</code> 命令显示相对于当前目录的,<code>Node</code> 模块的可执行脚本所在的目录(即 <code>.bin</code> 目录)。</p><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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="comment"># 项目根目录下执行</span></span><br><span class="line">$ npm bin</span><br><span class="line">./node_modules/.bin</span><br></pre></td></tr></table></figure></div><h1 id="创建全局链接"><a href="#创建全局链接" class="headerlink" title="创建全局链接"></a>创建全局链接</h1><p><code>npm</code> 提供了一个有趣的命令 <code>npm link</code>,它的功能是在本地包和全局包之间创建符号链接。我们说过使用全局模式安装的包不能直接通过 <code>require</code> 使用。但通过 <code>npm link</code> 命令可以打破这一限制。举个例子,我们已经通过 <code>npm install -g express</code> 安装了 <code>express</code> ,这时在工程的目录下运行命令:<code>npm link express ./node_modules/express -> /user/local/lib/node_modules/express</code><br>我们可以在 <code>node_modules</code> 子目录中发现一个指向安装到全局的包的符号链接。通过这种方法,我们就可以把全局包当做本地包来使用了。<br>除了将全局的包链接到本地以外,使用 <code>npm link</code> 命令还可以将本地的包链接到全局。使用方法是在包目录(<code>package.json</code> 所在目录)中运行 <code>npm link</code> 命令。如果我们要开发一个包,利用这种方法可以非常方便地在不同的工程间进行测试。</p><h1 id="创建包"><a href="#创建包" class="headerlink" title="创建包"></a>创建包</h1><p>包是在模块基础上更深一步的抽象,<code>Node</code> 的包类似于 <code>C/C++</code> 的函数库或者 <code>Java</code> 、<code>.Net</code> 的类库。它将某个独立的功能封装起来,用于发布、更新、依赖管理和版本控制。<code>Node</code> 根据 <code>CommonJS</code> 规范实现了包机制,开发了 <code>npm</code> 来解决包的发布和获取需求。<br><code>Node</code> 的包是一个目录,其中包含了一个 <code>JSON</code> 格式的包说明文件 <code>package.json</code>。严格符合 <code>CommonJS</code> 规范的包应该具备以下特征:</p><ul><li><code>package.json</code> 必须在包的顶层目录下;</li><li>二进制文件应该在 <code>bin</code> 目录下;</li><li><code>JavaScript</code> 代码应该在 <code>lib</code> 目录下;</li><li>文档应该在 <code>doc</code> 目录下;</li><li>单元测试应该在 <code>test</code> 目录下。</li></ul><p><code>Node</code> 对包的要求并没有这么严格,只要顶层目录下有 <code>package.json</code>,并符合一些规范即可。当然为了提高兼容性,我们还是建议你在制作包的时候,严格遵守 <code>CommonJS</code> 规范。</p><p>我们也可以把文件夹封装为一个模块,即所谓的包。包通常是一些模块的集合,在模块的基础上提供了更高层的抽象,相当于提供了一些固定接口的函数库。通过定制 <code>package.json</code>,我们可以创建更复杂,更完善,更符合规范的包用于发布。</p><p><code>Node</code> 在调用某个包时,会首先检查包中 <code>packgage.json</code> 文件的 <code>main</code> 字段,将其作为包的接口模块,如果 <code>package.json</code> 或 <code>main</code> 字段不存在,会尝试寻找 index.js 或 index.node 作为包的接口。</p><p><code>package.json</code> 是 <code>CommonJS</code> 规定的用来描述包的文件,完全符合规范的 <code>package.json</code> 文件应该含有以下字段:<br><span id="inline-yellow">name</span>: 包的名字,必须是唯一的,由小写英文字母、数字和下划线组成,不能包含空格。<br><span id="inline-blue">description</span>: 包的简要说明。<br><span id="inline-green">version</span>: 符合语义化版本识别规范的版本字符串。<br><span id="inline-red">keywords</span>: 关键字数组,通常用于搜索。<br><span id="inline-purple">maintainers</span>: 维护者数组,每个元素要包含 <code>name</code> 、 <code>email</code>(可选)、 <code>web</code>(可选)字段。<br><span id="inline-yellow">contributors</span>: 贡献者数组,格式与 <code>maintainers</code> 相同。包的作者应该是贡献者数组的第一个元素。<br><span id="inline-blue">bugs</span>: 提交 <code>bug</code> 的地址,可以是网址或者电子邮件地址。<br><span id="inline-green">licenses</span>: 许可证数组,每个元素要包含 <code>type</code> (许可证的名称)和 url(链接到许可证文本的地址)字段。<br><span id="inline-red">repositories</span>: 仓库托管地址数组,每个元素要包含 <code>type</code> (仓库的类型,如 git)、URL(仓库的地址)和 path(相对于仓库的路径,可选)字段。<br><span id="inline-purple">dependencies</span>: 包的依赖,一个关联数组,由包名称和版本号组成。</p><h1 id="包的发布"><a href="#包的发布" class="headerlink" title="包的发布"></a>包的发布</h1><p>通过使用 <code>npm init</code> 可以根据交互式回答产生一个符合标准的 <code>package.json</code>。创建一个 <code>index.js</code> 作为包的接口,一个简单的包就制作完成了。<br>在发布前,我们还需要获得一个账号用于今后维护自己的包,使用 <code>npm adduser</code> 根据提示完成账号的创建<br>完成后可以使用 <code>npm whoami</code> 检测是否已经取得了账号。<br>接下来,在 <code>package.json</code> 所在目录下运行 <code>npm publish</code>,稍等片刻就可以完成发布了,打开浏览器,访问 <a href="http://search.npmjs.org/" target="_blank" rel="noopener">NPM搜索</a> 就可以找到自己刚刚发布的包了。现在我们可以在世界的任意一台计算机上使用 <code>npm install neveryumodule</code> 命令来安装它。<br>如果你的包将来有更新,只需要在 <code>package.json</code> 文件中修改 <code>version</code> 字段,然后重新使用 <code>npm publish</code>命令就行了。<br>如果你对已发布的包不满意,可以使用 <code>npm unpublish</code> 命令来取消发布。</p><p id="div-border-top-yellow"><em>需要说明的是: <code>json</code> 文件不能有注释</em><br></p><h1 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h1><p><a href="http://javascript.ruanyifeng.com/nodejs/npm.html" target="_blank" rel="noopener">http://javascript.ruanyifeng.com/nodejs/npm.html</a></p>]]></content>
<summary type="html">
<h1 id="什么是-NPM"><a href="#什么是-NPM" class="headerlink" title="什么是 NPM"></a>什么是 NPM</h1><p><code>npm</code> 之于 <code>Node</code> ,就像 <code>pip</code> 之于 <code>Python</code> , <code>gem</code> 之于 <code>Ruby</code> , <code>composer</code> 之于 <code>PHP</code> 。</p>
<p><code>npm</code> 是 <code>Node</code> 官方提供的包管理工具,他已经成了 <code>Node</code> 包的标准发布平台,用于 <code>Node</code> 包的发布、传播、依赖控制。<br><code>npm</code> 提供了命令行工具,使你可以方便地下载、安装、升级、删除包,也可以让你作为开发者发布并维护包。</p>
</summary>
<category term="Node" scheme="https://blog.ihoey.com/categories/Node/"/>
<category term="Node" scheme="https://blog.ihoey.com/tags/Node/"/>
<category term="npm" scheme="https://blog.ihoey.com/tags/npm/"/>
</entry>
<entry>
<title>重新认识伪类和伪元素</title>
<link href="https://blog.ihoey.com/posts/CSS3/2017-04-28-pseudo-elements-and-pseudo-classes.html"/>
<id>https://blog.ihoey.com/posts/CSS3/2017-04-28-pseudo-elements-and-pseudo-classes.html</id>
<published>2017-04-28T08:35:10.000Z</published>
<updated>2018-05-04T10:02:32.000Z</updated>
<content type="html"><![CDATA[<p>熟悉前端的人都会听过<code>css</code>的伪类与伪元素,然而大多数的人都会将这两者混淆(包括我)。那今天就让我们来看看伪类和伪元素的区别吧!</p><a id="more"></a><h2 id="伪类与伪元素"><a href="#伪类与伪元素" class="headerlink" title="伪类与伪元素"></a>伪类与伪元素</h2><p>先说一说为什么<code>css</code>要引入伪元素和伪类,以下是<code>css2.1 Selectors</code>章节中对伪类与伪元素的描述:</p><p><code>CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.</code></p><ul><li>直译过来就是:<code>css</code>引入伪类和伪元素概念是为了格式化文档树以外的信息。也就是说,伪类和伪元素是用来修饰不在文档树中的部分,比如,一句话中的第一个字母,或者是列表中的第一个元素。下面分别对伪类和伪元素进行解释:<ul><li>伪类用于当已有元素处于的某个状态时,为其添加对应的样式,这个状态是根据用户行为而动态变化的。比如说,当用户悬停在指定的元素时,我们可以通过<code>:hover</code>来描述这个元素的状态。虽然它和普通的<code>css</code>类相似,可以为已有的元素添加样式,但是它只有处于<code>dom</code>树无法描述的状态下才能为元素添加样式,所以将其称为伪类。</li><li>伪元素用于创建一些不在文档树中的元素,并为其添加样式。比如说,我们可以通过<code>:before</code>来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。</li></ul></li></ul><h2 id="伪类"><a href="#伪类" class="headerlink" title="伪类"></a>伪类</h2><ul><li>伪类前面是一个冒号,<code>E:first-child</code> 伪类,会对现有的元素进行筛选<ul><li><code>:link</code></li><li><code>:visited</code></li><li><code>:hover</code></li><li><code>:active</code></li><li><code>:focus</code></li><li><code>:not()</code></li><li><code>:first-child</code></li><li><code>:last-child</code></li><li><code>:nth-child</code></li><li><code>:nth-last-child</code> 从后面计数</li><li><code>:only-child</code> 只满足一个子元素</li><li><code>:target</code> 当URL带有锚名称,指向文档内某个具体的元素时,<code>:target</code>匹配该元素。</li><li><code>:checked</code> 被选中的input元素</li><li><code>:empty</code> 匹配没有子元素的元素</li><li><code>:valid</code> 匹配条件验证正确的表单元素。</li></ul></li></ul><h2 id="伪元素"><a href="#伪元素" class="headerlink" title="伪元素"></a>伪元素</h2><ul><li>伪元素前面是两个冒号,<code>E::first-line</code> 伪元素。会创造出不存在的新元素,由于 <code>css</code> 对单冒号的伪元素也支持,所以这样很容易让新学者混淆。但实际上现在 <code>css3</code> 已经明确规定了伪类单冒号,伪元素双冒号的规则。<ul><li><code>::before/:before</code> 在被选元素前插入内容</li><li><code>::after/:after</code> 在被元素后插入内容,其用法和特性与<code>:before</code>相似。</li><li><code>::first-letter/:first-letter</code> 匹配元素中文本的首字母。被修饰的首字母不在文档树中</li><li><code>::first-line/:first-line</code> 匹配元素中第一行的文本。这个伪元素只能用在块元素中,不能用在内联元素中。</li><li><code>::selection</code> 匹配用户被用户选中或者处于高亮状态的部分。在火狐浏览器使用时需要添加<code>-moz</code>前缀。该伪元素只支持双冒号的形式。</li><li><code>::placeholder</code> 匹配占位符的文本,只有元素设置了<code>placeholder</code>属性时,该伪元素才能生效。</li></ul></li><li>该伪元素不是<code>CSS</code>的标准,它的实现可能在将来会有所改变,所以要决定使用时必须谨慎。<br>在一些浏览器中(<code>IE10</code>和<code>Firefox18</code>及其以下版本)会使用单冒号的形式。</li><li>对于伪元素 <code>:before</code> 和 <code>:after</code> 而言,属性 <code>content</code> 是必须设置的,我们知道属性的值可以为字符串,也可以有其它形式,比如指向一张图片的 <code>URL:</code></li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu highlight /plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">content: url('img/icon.png')</span><br></pre></td></tr></table></figure></div><ul><li>配合伪类使用<ul><li>伪元素 <code>:before</code> 还可以配合伪类使用,这里举经常与 <code>:before</code> 配合使用的伪类 <code>:hover</code> 为例:</li></ul></li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu 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">.before:hover:before{content:'you before'; color:red;}</span><br><span class="line"><div class="before"> me</div></span><br></pre></td></tr></table></figure></div><ul><li>配合取值函数 <code>attr()</code> 使用</li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="PLAIN"><figure class="iseeu 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><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">a::before{content: attr(title)}</span><br><span class="line"><a href="https://blog.ihoey.com" title="梦魇小栈"></a></span><br><span class="line"></span><br><span class="line">效果</span><br><span class="line"><a href="https://blog.ihoey.com" title="梦魇小栈">梦魇小栈</a></span><br></pre></td></tr></table></figure></div><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>伪元素和伪类之所以这么容易混淆,是因为他们的效果类似而且写法相仿,但实际上 <code>css3</code> 为了区分两者,已经明确规定了伪类用一个冒号来表示,而伪元素则用两个冒号来表示。</li><li>伪类的效果可以通过添加一个实际的类来达到,而伪元素的效果则需要通过添加一个实际的元素才能达到,这也是为什么他们一个称为伪类,一个称为伪元素的原因。</li></ul>]]></content>
<summary type="html">
<p>熟悉前端的人都会听过<code>css</code>的伪类与伪元素,然而大多数的人都会将这两者混淆(包括我)。那今天就让我们来看看伪类和伪元素的区别吧!</p>
</summary>
<category term="CSS3" scheme="https://blog.ihoey.com/categories/CSS3/"/>
<category term="伪类" scheme="https://blog.ihoey.com/tags/%E4%BC%AA%E7%B1%BB/"/>
<category term="伪元素" scheme="https://blog.ihoey.com/tags/%E4%BC%AA%E5%85%83%E7%B4%A0/"/>
</entry>
<entry>
<title>Git 常用命令学习及整理</title>
<link href="https://blog.ihoey.com/posts/Git/2017-04-23-git.html"/>
<id>https://blog.ihoey.com/posts/Git/2017-04-23-git.html</id>
<published>2017-04-23T02:23:21.000Z</published>
<updated>2018-05-04T10:01:53.000Z</updated>
<content type="html"><![CDATA[<p>最近用Git比较多,所以大概整理下 <strong>Git是目前世界上最先进的分布式版本控制系统。</strong></p><a id="more"></a><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>安装软件就不多说了,这个肯定都会了</p><ul><li>下载地址:<a class="active" href="https://git-scm.com/downloads" rel="noopener" target="_blank">Downloads</a></li></ul><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git config --global user.name <span class="string">"ihoey"</span> <span class="comment"># 设置git用户名</span></span><br><span class="line">git config --global user.email <span class="string">"[email protected]"</span> <span class="comment"># 设置git邮箱</span></span><br><span class="line">git config --global color.ui <span class="literal">true</span> <span class="comment"># 为true是终端着色</span></span><br><span class="line">git config --global alias.co checkout <span class="comment"># 配置checkout的别名</span></span><br><span class="line">git config --global alias.ci commit <span class="comment"># 配置commit的别名</span></span><br><span class="line">git config --global alias.st status <span class="comment"># 配置status的别名</span></span><br><span class="line">git config --global alias.br branch <span class="comment"># 配置branch的别名</span></span><br><span class="line">git config --global core.editor <span class="string">"mate -w"</span> <span class="comment"># 设置Editor使用textmate</span></span><br><span class="line">git config -l <span class="comment"># 列举所有配置</span></span><br><span class="line"><span class="comment">#用户的git配置文件~/.gitconfig</span></span><br></pre></td></tr></table></figure></div><h2 id="SSH-秘钥"><a href="#SSH-秘钥" class="headerlink" title="SSH 秘钥"></a>SSH 秘钥</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">ssh-keygen -t rsa -C <span class="string">"[email protected]"</span></span><br><span class="line"><span class="comment"># 连续3个回车。如果不需要密码的话。</span></span><br><span class="line"><span class="comment"># 最后得到了两个文件:id_rsa和id_rsa.pub,在~/.ssh/文件夹下面</span></span><br><span class="line"><span class="comment"># id_rsa为你的私钥,不可以告诉别人</span></span><br><span class="line"><span class="comment"># id_rsa.pub为你的公钥,一般会放在你的服务器做ssh登录,或者放在github上面</span></span><br></pre></td></tr></table></figure></div><h2 id="GitHub-测试"><a href="#GitHub-测试" class="headerlink" title="GitHub 测试"></a>GitHub 测试</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">ssh -T [email protected]</span><br><span class="line"><span class="comment"># 将公钥放在 github 测试是否验证通过命令,选择 yes 如果看到 Hi 后面是你的用户名,就说明成功了。</span></span><br></pre></td></tr></table></figure></div><h2 id="基本命令"><a href="#基本命令" class="headerlink" title="基本命令"></a>基本命令</h2><ul><li>创建<code>git</code>仓库 <code>git init</code></li><li>添加文件到暂存区 <code>git add fileName</code> / <code>git add .</code></li><li>提交文件到仓库 <code>git commit -m "版本提交信息"</code></li><li>查看文件提交状态 <code>git status</code></li><li>查看文件修改的信息 <code>git diff readme.txt</code></li></ul><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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></pre></td><td class="code"><pre><span class="line">git <span class="built_in">help</span> <<span class="built_in">command</span>> <span class="comment"># 显示command的help</span></span><br><span class="line">git show <span class="comment"># 显示某次提交的内容</span></span><br><span class="line">git show <span class="variable">$id</span></span><br><span class="line"></span><br><span class="line">git checkout -- <file> <span class="comment"># 抛弃工作区修改</span></span><br><span class="line">git checkout . <span class="comment"># 抛弃工作区修改</span></span><br><span class="line"></span><br><span class="line">git add <file> <span class="comment"># 将工作文件修改提交到本地暂存区</span></span><br><span class="line">git add . <span class="comment"># 将所有修改过的工作文件提交暂存区</span></span><br><span class="line"></span><br><span class="line">git rm <file> <span class="comment"># 从版本库中删除文件</span></span><br><span class="line">git rm <file> --cached <span class="comment"># 从版本库中删除文件,但不删除文件</span></span><br><span class="line"></span><br><span class="line">git reset <file> <span class="comment"># 从暂存区恢复到工作文件</span></span><br><span class="line">git reset -- . <span class="comment"># 从暂存区恢复到工作文件</span></span><br><span class="line">git reset --hard <span class="comment"># 恢复最近一次提交过的状态,即放弃上次提交后的所有本次修改</span></span><br><span class="line"></span><br><span class="line">git commit -m <span class="string">"some comments"</span></span><br><span class="line"></span><br><span class="line">git revert <<span class="variable">$id</span>> <span class="comment"># 恢复某次提交的状态,恢复动作本身也创建了一次提交对象</span></span><br><span class="line">git revert HEAD <span class="comment"># 恢复最后一次提交的状态</span></span><br></pre></td></tr></table></figure></div><h2 id="查看文件"><a href="#查看文件" class="headerlink" title="查看文件"></a>查看文件</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git diff <file> <span class="comment"># 比较当前文件和暂存区文件差异</span></span><br><span class="line">git diff</span><br><span class="line">git diff <<span class="variable">$id1</span>> <<span class="variable">$id2</span>> <span class="comment"># 比较两次提交之间的差异</span></span><br><span class="line">git diff <branch1>..<branch2> <span class="comment"># 在两个分支之间比较</span></span><br><span class="line">git diff --staged <span class="comment"># 比较暂存区和版本库差异</span></span><br><span class="line">git diff --cached <span class="comment"># 比较暂存区和版本库差异</span></span><br><span class="line">git diff --<span class="built_in">stat</span> <span class="comment"># 仅仅比较统计信息</span></span><br></pre></td></tr></table></figure></div><h2 id="查看提交记录"><a href="#查看提交记录" class="headerlink" title="查看提交记录"></a>查看提交记录</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git <span class="built_in">log</span></span><br><span class="line">git <span class="built_in">log</span> <file> <span class="comment"># 查看该文件每次提交记录</span></span><br><span class="line">git <span class="built_in">log</span> -p <file> <span class="comment"># 查看每次详细修改内容的diff</span></span><br><span class="line">git <span class="built_in">log</span> -p -2 <span class="comment"># 查看最近两次详细修改内容的diff</span></span><br><span class="line">git <span class="built_in">log</span> --<span class="built_in">stat</span> <span class="comment"># 查看提交统计信息</span></span><br></pre></td></tr></table></figure></div><h2 id="分支管理"><a href="#分支管理" class="headerlink" title="分支管理"></a>分支管理</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git branch -r <span class="comment"># 查看远程分支</span></span><br><span class="line">git branch <new_branch> <span class="comment"># 创建新的分支</span></span><br><span class="line">git branch -v <span class="comment"># 查看各个分支最后提交信息</span></span><br><span class="line">git branch --merged <span class="comment"># 查看已经被合并到当前分支的分支</span></span><br><span class="line">git branch --no-merged <span class="comment"># 查看尚未被合并到当前分支的分支</span></span><br><span class="line"></span><br><span class="line">git checkout <branch> <span class="comment"># 切换到某个分支</span></span><br><span class="line">git checkout -b <new_branch> <span class="comment"># 创建新的分支,并且切换过去</span></span><br><span class="line">git checkout -b <new_branch> <branch> <span class="comment"># 基于branch创建新的new_branch</span></span><br><span class="line">git checkout <span class="variable">$id</span> <span class="comment"># 把某次历史提交记录checkout出来,但无分支信息,切换到其他分支会自动删除</span></span><br><span class="line">git checkout <span class="variable">$id</span> -b <new_branch> <span class="comment"># 把某次历史提交记录checkout出来,创建成一个分支</span></span><br><span class="line">git branch -d <branch> <span class="comment"># 删除某个分支</span></span><br><span class="line">git branch -D <branch> <span class="comment"># 强制删除某个分支 (未被合并的分支被删除的时候需要强制)</span></span><br></pre></td></tr></table></figure></div><h2 id="分支合并和rebase"><a href="#分支合并和rebase" class="headerlink" title="分支合并和rebase"></a>分支合并和rebase</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git merge <branch> <span class="comment"># 将branch分支合并到当前分支</span></span><br><span class="line">git merge --no-ff <branch> <span class="comment"># 不要Fast-Foward合并,这样可以生成merge提交</span></span><br><span class="line">git rebase master <branch> <span class="comment"># 将master rebase到branch,相当于:</span></span><br><span class="line">git checkout <branch> && git rebase master && git checkout master && git merge <branch></span><br></pre></td></tr></table></figure></div><ul><li>在我们操作过程中。<code>merge</code>操作遇到冲突的时候,当前<code>merge</code>不能继续进行下去。手动修改冲突内容后,<code>add</code> 修改,<code>commit</code> 就可以了。</li><li>而<code>rebase</code> 操作的话,会中断<code>rebase</code>,同时会提示去解决冲突。解决冲突后,将修改<code>add</code>后执行<code>git rebase –continue</code>继续操作,或者<code>git rebase –skip</code>忽略冲突。</li></ul><h2 id="Git暂存管理"><a href="#Git暂存管理" class="headerlink" title="Git暂存管理"></a>Git暂存管理</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git stash <span class="comment"># 暂存</span></span><br><span class="line">git stash list <span class="comment"># 列所有stash</span></span><br><span class="line">git stash apply <span class="comment"># 恢复暂存的内容</span></span><br><span class="line">git stash drop <span class="comment"># 删除暂存区</span></span><br></pre></td></tr></table></figure></div><h2 id="远程分支管理"><a href="#远程分支管理" class="headerlink" title="远程分支管理"></a>远程分支管理</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git pull <span class="comment"># 抓取远程仓库所有分支更新并合并到本地</span></span><br><span class="line">git pull --no-ff <span class="comment"># 抓取远程仓库所有分支更新并合并到本地,不要快进合并</span></span><br><span class="line">git fetch origin <span class="comment"># 抓取远程仓库更新</span></span><br><span class="line">git merge origin/master <span class="comment"># 将远程主分支合并到本地当前分支</span></span><br><span class="line">git checkout --track origin/branch <span class="comment"># 跟踪某个远程分支创建相应的本地分支</span></span><br><span class="line">git checkout -b <local_branch> origin/<remote_branch> <span class="comment"># 基于远程分支创建本地分支,功能同上</span></span><br><span class="line">git push <span class="comment"># push所有分支</span></span><br><span class="line">git push origin master <span class="comment"># 将本地主分支推到远程主分支</span></span><br><span class="line">git push -u origin master <span class="comment"># 将本地主分支推到远程(如无远程主分支则创建,用于初始化远程仓库)</span></span><br><span class="line">git push origin <local_branch> <span class="comment"># 创建远程分支, origin是远程仓库名</span></span><br><span class="line">git push origin <local_branch>:<remote_branch> <span class="comment"># 创建远程分支</span></span><br><span class="line">git push origin :<remote_branch> <span class="comment">#先删除本地分支(git br -d <branch>),然后再push删除远程分支</span></span><br></pre></td></tr></table></figure></div><h2 id="Git远程仓库管理"><a href="#Git远程仓库管理" class="headerlink" title="Git远程仓库管理"></a>Git远程仓库管理</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git remote -v <span class="comment"># 查看远程服务器地址和仓库名称</span></span><br><span class="line">git remote show origin <span class="comment"># 查看远程服务器仓库状态</span></span><br><span class="line">git remote add origin [email protected]:ihoey/blog.git <span class="comment"># 添加远程仓库地址</span></span><br><span class="line">git remote <span class="built_in">set</span>-url origin [email protected]:ihoey/blog.git <span class="comment"># 设置远程仓库地址(用于修改远程仓库地址)</span></span><br><span class="line">git remote rm <repository> <span class="comment"># 删除远程仓库</span></span><br></pre></td></tr></table></figure></div><h2 id="创建远程仓库"><a href="#创建远程仓库" class="headerlink" title="创建远程仓库"></a>创建远程仓库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git <span class="built_in">clone</span> --bare ihoey.com blog.git <span class="comment"># 用带版本的项目创建纯版本仓库</span></span><br><span class="line">scp -r my_blog.git [email protected]:~ <span class="comment"># 将纯仓库上传到服务器上</span></span><br><span class="line">mkdir blog.git && <span class="built_in">cd</span> blog.git && git --bare init <span class="comment"># 在服务器创建纯仓库</span></span><br><span class="line"></span><br><span class="line">git push -u origin master <span class="comment"># 客户端首次提交</span></span><br><span class="line">git push -u origin develop <span class="comment"># 首次将本地develop分支提交到远程develop分支,并且track</span></span><br><span class="line"></span><br><span class="line">git remote <span class="built_in">set</span>-head origin master <span class="comment"># 设置远程仓库的HEAD指向master分支</span></span><br></pre></td></tr></table></figure></div><h2 id="设置跟踪远程库和本地库"><a href="#设置跟踪远程库和本地库" class="headerlink" title="设置跟踪远程库和本地库"></a>设置跟踪远程库和本地库</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">git branch --<span class="built_in">set</span>-upstream master origin/master <span class="comment">#master</span></span><br><span class="line">git branch --<span class="built_in">set</span>-upstream develop origin/develop <span class="comment">#develop</span></span><br></pre></td></tr></table></figure></div><h2 id="其他命令"><a href="#其他命令" class="headerlink" title="其他命令"></a>其他命令</h2><div class="highlight-wrap"autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" contenteditable="true"data-rel="BASH"><figure class="iseeu highlight /bash"><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">mkdir XX <span class="comment">#(创建一个空目录 XX指目录名)</span></span><br><span class="line"><span class="built_in">pwd</span> <span class="comment">#显示当前目录的路径。</span></span><br><span class="line">cat XX <span class="comment">#查看XX文件内容</span></span><br><span class="line">rm XX <span class="comment">#删除文件</span></span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<p>最近用Git比较多,所以大概整理下 <strong>Git是目前世界上最先进的分布式版本控制系统。</strong></p>
</summary>
<category term="Git" scheme="https://blog.ihoey.com/categories/Git/"/>
<category term="Git" scheme="https://blog.ihoey.com/tags/Git/"/>
</entry>
</feed>