-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
1163 lines (917 loc) · 153 KB
/
index.html
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
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TuTu</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description" content="IF YOU REALLY WANT IT">
<meta property="og:type" content="website">
<meta property="og:title" content="TuTu">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="TuTu">
<meta property="og:description" content="IF YOU REALLY WANT IT">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="TuTu">
<meta name="twitter:description" content="IF YOU REALLY WANT IT">
<link rel="alternative" href="/atom.xml" title="TuTu" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="/css/style.css">
</head>
<body>
<div id="container">
<div id="wrap">
<header id="header">
<div id="banner"></div>
<div id="header-outer" class="outer">
<div id="header-title" class="inner">
<h1 id="logo-wrap">
<a href="/" id="logo">TuTu</a>
</h1>
<h2 id="subtitle-wrap">
<a href="/" id="subtitle">IF YOU REALLY WANT IT</a>
</h2>
</div>
<div id="header-inner" class="inner">
<nav id="main-nav">
<a id="main-nav-toggle" class="nav-icon"></a>
<a class="main-nav-link" href="/">Home</a>
<a class="main-nav-link" href="/archives">Archives</a>
</nav>
<nav id="sub-nav">
<a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
<a id="nav-search-btn" class="nav-icon" title="Search"></a>
</nav>
<div id="search-form-wrap">
<form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" results="0" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit"></button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
</div>
</div>
</div>
</header>
<div class="outer">
<section id="main">
<article id="post-Git指南" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/10/08/Git指南/" class="article-date">
<time datetime="2016-10-08T15:54:36.000Z" itemprop="datePublished">2016-10-08</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/版本控制/">版本控制</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/10/08/Git指南/">Git指南</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="Git是什么?"><a href="#Git是什么?" class="headerlink" title="Git是什么?"></a>Git是什么?</h1><p>Git是目前世界上最先进的分布式版本控制系统(没有之一)。</p>
<h1 id="为什么不是svn?"><a href="#为什么不是svn?" class="headerlink" title="为什么不是svn?"></a>为什么不是svn?</h1><ol>
<li>Git极其强大的分支管理</li>
<li>Git本地仓库包含代码库还有历史库,在本地的环境开发就可以记录历史,而SVN的历史库存在于中央仓库,每次对比与提交代码都必须连接到中央仓库才能进行<br> 这样的好处在于:<ul>
<li>自己可以在脱机环境查看开发的版本历史</li>
<li>多人开发时如果充当中央仓库的Git仓库挂了,任何一个开发者的仓库都可以作为中央仓库进行服务</li>
</ul>
</li>
</ol>
<h1 id="安装Git"><a href="#安装Git" class="headerlink" title="安装Git"></a>安装Git</h1><ol>
<li><p>不同环境下的安装方法请自行google,安装完成后需要配置git账号:</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git config --global user<span class="selector-class">.name</span> <span class="string">"Your Name"</span></div><div class="line">git config --global user<span class="selector-class">.email</span> <span class="string">"email@example.com"</span></div></pre></td></tr></table></figure>
</li>
<li><p>因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。注意git config命令的–global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。</p>
</li>
</ol>
<h1 id="创建版本库"><a href="#创建版本库" class="headerlink" title="创建版本库"></a>创建版本库</h1><p>版本库既仓库既repository,可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。</p>
<ol>
<li><p>创建空目录</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">mkdir</span> myrepo</div><div class="line"><span class="keyword">cd</span> myrepo</div><div class="line"><span class="keyword">pwd</span> <span class="comment">//查看当前路径</span></div></pre></td></tr></table></figure>
</li>
<li><p>初始化git仓库,把新建的文件夹变成git可管理的仓库</p>
<figure class="highlight ebnf"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="attribute">git init</span></div></pre></td></tr></table></figure>
<p> 初始化完成后会发现根目录下多了.git文件夹,这就是GIt用来跟踪管理版本库的文件,如果你看不到该文件夹,说明是被隐藏了,用<code>ls -ah</code>命令即可查看。</p>
</li>
<li><p>添加文件到仓库<br> 现有的版本控制工具都只能跟踪文本文件的改动,对于word、图片、视频等二进二进制文件,版本控制工具只能知道文件大小的变化,无法跟踪到具体的内容变化。</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">touch readme<span class="selector-class">.txt</span></div><div class="line">git add readme<span class="selector-class">.txt</span> <span class="comment">//添加准备提交的文件,git add .可添加所有文件,git add file1 file2可添加两个文件</span></div></pre></td></tr></table></figure>
</li>
</ol>
<ol>
<li>提交文件到仓库 <figure class="highlight 1c"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git commit -m <span class="string">"wrote a readme file"</span> <span class="comment">//提交已添加到仓库的文件,-m为对提交文件的说明</span></div></pre></td></tr></table></figure>
</li>
</ol>
<h1 id="操作版本库"><a href="#操作版本库" class="headerlink" title="操作版本库"></a>操作版本库</h1><ol>
<li><p>查看仓库状态及文件变化</p>
<figure class="highlight maxima"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">status</span> //查看仓库当前的状态</div><div class="line">git <span class="built_in">diff</span> readme.txt//如果git <span class="built_in">status</span>告诉你有文件被修改过,可用git <span class="built_in">diff</span>查看当前文件相比上次提交的版本修改了什么内容,既查看工作区和版本库中最新版本的区别</div></pre></td></tr></table></figure>
</li>
<li><p>版本切换</p>
<ul>
<li><p>每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,查看历史commit,可用命令:</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">log</span><span class="comment">//查看详细的历史commit</span></div><div class="line">git <span class="built_in">log</span> --pretty=oneline<span class="comment">//更改log的输出格式(版本号:SHA1计算出来的一个非常大的数字,用十六进制表示,因为是分布式,防止每个人提交时的id冲突)和提交说明</span></div></pre></td></tr></table></figure>
</li>
<li><p>在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。HEAD^也可以用commit id,命令中的commitid也可以用它的前几位来代替。</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">reset</span> <span class="comment">--hard HEAD^</span></div></pre></td></tr></table></figure>
</li>
<li><p>此时用<code>git log</code>查看历史,发现只有之前的版本了,如果要想回到最新版本(未来)</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">reset</span> <span class="comment">--hard 最新版本的commit id</span></div></pre></td></tr></table></figure>
</li>
<li><p>如果你回退后不记得最新版本的commitid了,可用<code>git reflog</code>查看你使用过的所有命令,找到你提交最新版本的哪一行命令,即可看到最新版的commitid,这样就可以回到未来了。</p>
</li>
<li>git内部有个指向当前版本的head指针,版本切换实际是改变head指针的指向。</li>
</ul>
</li>
<li><p>工作区和暂存区<br> 工作区:已经初始化过的工作文件夹<br> 版本库:工作区中的隐藏目录.git,版本库中包括叫Stage的暂存区和git自动创建的第一个分支master,及指向master分支的指针。<br> 一次完整的版本添加包括以下两步:<br> 第一步是用git add把文件修改添加到暂存区,暂存区用来保存文件的修改(并不是文件,因为修改一次,然后git add,再修改一次,然后git commit后,用git stauts查看发现依然有未提交的更改,所以提交的其实是第一次修改后的结果,第二次修改并没放入暂存区,所以不会被提交 );<br> 第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支<br> 可以理解为:需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。</p>
</li>
<li><p>撤销修改</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git checkout -- <span class="selector-tag">a</span>.txt<span class="comment">//丢弃工作区中的修改,必须有--,如果没有就变成了切换分支</span></div></pre></td></tr></table></figure>
<p> 要撤销的修改有以下几种情况:</p>
<ul>
<li>如果你只是修改了文件而没添加到暂存区,使用撤销修改命令会将文件修改恢复原状,既丢弃工作区修改。</li>
<li>如果已经添加到暂存区后,又作了修改,使用撤销修改就回到添加到暂存区后的状态。</li>
<li><p>如果要撤销暂存区中的修改,可以使用:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">reset</span> <span class="keyword">HEAD</span> <span class="keyword">file</span>//git <span class="keyword">reset</span>命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用<span class="keyword">HEAD</span>时,表示最新的版本。</div></pre></td></tr></table></figure>
<p>然后用<code>git status</code>发现暂存区是干净的,再使用<code>git checkout -- file</code>丢弃工作区中的修改。</p>
</li>
<li>已经提交了不合适的修改到版本库时,想要撤销本次提交,参考[2.版本切换],不过前提是没有推送到远程库。</li>
</ul>
</li>
<li><p>删除文件</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">touch <span class="keyword">test</span>.txt</div><div class="line">git add <span class="keyword">test</span>.txt</div><div class="line">git commit -<span class="keyword">m</span> 'add <span class="keyword">file</span>'</div><div class="line"><span class="keyword">rm</span> <span class="keyword">test</span>.txt<span class="comment">//工作区中删除test.txt</span></div></pre></td></tr></table></figure>
<p> 工作区中删除一个已经提交的文件后,你有两个选择:</p>
<ul>
<li><p>确实要在版本库中删除这个文件</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">rm</span> <span class="keyword">test</span>.txt</div><div class="line">git commit -<span class="keyword">m</span> 'remove <span class="keyword">test</span>.txt'</div></pre></td></tr></table></figure>
</li>
<li><p>删错文件了,撤销修改即可</p>
<figure class="highlight ada"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git checkout <span class="comment">-- test.txt</span></div></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>远程仓库<br> Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。怎么分布呢?最早,肯定只有一台机器有一个原始版本库,此后,别的机器可以“克隆”这个原始版本库,而且每台机器的版本库其实都是一样的,并没有主次之分。<br> 实际情况往往是这样,找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。<br> 完全可以自己搭建一台运行Git的服务器,不过现阶段,为了学Git先搭个服务器绝对是小题大作。好在这个世界上有个叫GitHub的神奇的网站,从名字就可以看出,这个网站就是提供Git仓库托管服务的,所以,只要注册一个GitHub账号,就可以免费获得Git远程仓库。<br> 这样就可以使这两个仓库进行远程同步,远程仓库既可以作为备份,又可以让其他人通过该仓库来协作。</p>
<ul>
<li><p>准备git远程仓库<br>由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置:<br>第1步:创建SSH Key。在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:</p>
<figure class="highlight elixir"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="variable">$ </span>ssh-keygen -t rsa -C <span class="string">"youremail@example.com"</span></div></pre></td></tr></table></figure>
<p>你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。<br>如果一切顺利的话,可以在用户主目录(当前用户的根目录)里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。<br>第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面:<br>然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容:点“Add Key”,你就应该看到已经添加的Key:<br>为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。<br>当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。<br>最后友情提示,在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。<br>如果你不想让别人看到Git库,有两个办法,一个是交点保护费,让GitHub把公开的仓库变成私有的,这样别人就看不见了(不可读更不可写)。另一个办法是自己动手,搭一个Git服务器,因为是你自己的Git服务器,所以别人也是看不见的。这个方法我们后面会讲到的,相当简单,公司内部开发必备。</p>
</li>
<li><p>添加远程库</p>
<ul>
<li>登陆GitHub》Create a new repo》填入Repository name》Create repository》创建成功</li>
<li>本地仓库下运行:<code>git remote add origin git@github.com:michaelliao/learngit.git</code> ,将本地仓库与远程仓库关联,origin为远程仓库的名字。</li>
<li><code>git push -u origin master</code>将本地库的master分支推送到远程仓库,由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。</li>
<li>从现在起,只要本地作了提交,就可以通过命令:<code>git push origin master</code>,把本地master分支的最新修改推送至GitHub,现在,你就拥有了真正的分布式版本库!</li>
<li>SSH警告<br> 当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:<br> 这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。<br> Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:<br> 这个警告只会出现一次,后面的操作就不会有任何警告了。<br> 如果你实在担心有人冒充GitHub服务器,输入yes前可以对照GitHub的RSA Key的指纹信息是否与SSH连接给出的一致。</li>
</ul>
</li>
<li><p>从远程库克隆<br>假设我们从零开发,那么最好的方式是先创建远程库,然后,从远程库克隆。</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">clone</span> <span class="title">git</span>@github.com:michaelliao/gitskills.git</div></pre></td></tr></table></figure>
<p>GitHub给出的地址不止一个,还可以用<a href="https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。" target="_blank" rel="external">https://github.com/michaelliao/gitskills.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。使用https除了速度慢以外,还有个最大的麻烦是每次推送都必须输入口令,但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。</a></p>
</li>
</ul>
</li>
<li><p>分支管理<br> 分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。<br> 现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。<br> 其他版本控制系统如SVN等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。<br> 但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件。</p>
<ul>
<li><p>创建与合并分支<br>目前的实例中只有一个分支叫主分支,即master分支,之前说的HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。<br>当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:<br>不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:<br>假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并<br>合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:<br>实战:</p>
<ul>
<li><p>创建并切换分支</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="symbol">git</span> checkout -<span class="keyword">b </span>dev //-<span class="keyword">b参数表示创建并替换,相当于`git </span><span class="keyword">branch </span>dev git checkout dev`</div></pre></td></tr></table></figure>
</li>
<li><p>用<code>git branch</code>命令查看当前分支:</p>
<figure class="highlight asciidoc"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="bullet">* </span>dev</div><div class="line"><span class="code"> master</span></div></pre></td></tr></table></figure>
</li>
<li><p>修改工作区后提交修改</p>
<figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git add readme<span class="selector-class">.txt</span> </div><div class="line">git commit -m <span class="string">"branch test"</span></div></pre></td></tr></table></figure>
</li>
<li><p>切换到master分支后,会发现并没有刚才的修改,这是因为刚才的提交是在dev分支上。</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git checkout <span class="literal">master</span></div></pre></td></tr></table></figure>
</li>
<li><p>将dev分支合并到当前的master分支</p>
<figure class="highlight gams"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="symbol">$</span> git merge dev</div><div class="line"><span class="function"><span class="title">Updating</span></span> d17efd8..fec145a</div><div class="line">Fast-forward <span class="comment">//表示这次合并是快进模式,也就是直接把master指向dev的当前提交</span></div><div class="line"> readme.txt | <span class="number">1</span> +</div><div class="line"> <span class="number">1</span> <span class="keyword">file</span> changed, <span class="number">1</span> insertion(+)</div></pre></td></tr></table></figure>
</li>
<li><p>合并完成后,删除dev分支</p>
<figure class="highlight armasm"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="symbol">git</span> <span class="keyword">branch </span>-d dev</div></pre></td></tr></table></figure>
</li>
</ul>
</li>
</ul>
</li>
<li><p>解决冲突<br> 如果两个分支在同一个文件同一个地方做了修改,比如a文件在分支1中是:A and B,分支2中是 A or B,那么在合并的时候就会发生冲突,此时需要手动解决冲突后合并:</p>
<ul>
<li><code>git status</code>可以看到发生冲突的文件</li>
<li>打开冲突的文件,git会在发生冲突的位置用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,修改后提交即可。</li>
<li>合并分支,<code>git log --graph --pretty=oneline --abbrev-commit</code>该命令可以看到分支合并图,并删除不用的分支。</li>
</ul>
</li>
<li><p>分支管理策略<br> 通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。<br> 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="keyword">merge</span> --<span class="keyword">no</span>-ff -<span class="keyword">m</span> <span class="string">"merge with no-ff"</span> dev<span class="comment">//因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。</span></div></pre></td></tr></table></figure>
<p> 首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;<br> 那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;<br> 你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了,再把本地的dev合并到本地的master,最后把本地的master推到远程master。</p>
</li>
<li><p>bug分支<br>在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。<br>当我们正在dev版本上开发新功能时,突然收到要在1小时内解决bug的需求,而自己的新功能又只开发了一半不想提交,这时就要用到Git的<code>stash</code>功能先把当前的工作现场隐藏起来。</p>
<figure class="highlight lsl"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">git status<span class="comment">//...发现当前工作区有未提交或未添加到暂存区的修改</span></div><div class="line">git stash<span class="comment">//隐藏当前的修改</span></div><div class="line">git status<span class="comment">//...发现工作区是干净的</span></div><div class="line">git checkout master<span class="comment">//切换到要修复bug的分支</span></div><div class="line">git checkout -b issue<span class="number">-1</span><span class="comment">//从要修复bug的master分支创建临时bug分支并切换到bug分支</span></div><div class="line">.......fixing bug</div><div class="line">git add file<span class="comment">//添加修改到暂存区</span></div><div class="line">git commit -m <span class="string">"fix bug 101"</span><span class="comment">//提交更改</span></div><div class="line">git checkout master<span class="comment">//切回master分支准备合并</span></div><div class="line">git merge --no-ff -m <span class="string">"merged bug fix issue1"</span> issue<span class="number">-1</span><span class="comment">//合并分支并添加备注</span></div><div class="line">git branch -d issue<span class="number">-1</span><span class="comment">//删除分支</span></div><div class="line">git checkout dev<span class="comment">//回dev分支继续干活</span></div><div class="line">git status<span class="comment">//发现工作区是干净的</span></div><div class="line">git stash <span class="type">list</span><span class="comment">//查看刚才隐藏的工作现场</span></div><div class="line">git stash apply/pop <span class="comment">//恢复隐藏的工作现场,apply和pop的区别在于恢复工作现场后后者删除了stash内容</span></div><div class="line">git stash <span class="type">list</span><span class="comment">//如果上一步用了`git stash pop`,此时看不到任何stash内容。</span></div><div class="line">git stash apply stash@{<span class="number">0</span>}<span class="comment">//可以多次stash,恢复的时候,先用`git stash list`查看,然后恢复指定的stash</span></div></pre></td></tr></table></figure>
</li>
<li><p>Feature分支<br>添加一个新功能时,你肯定不希望因为一些实验性质的代码,把主分支搞乱了,所以,每添加一个新功能,最好新建一个feature分支,在上面开发,完成后,合并,最后,删除该feature分支。</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">git checkout -b feature <span class="comment"> //新建并切换到feature分支</span></div><div class="line">git <span class="built_in">add</span> <span class="built_in">file</span> <span class="comment"> //开发完成后添加到暂存区</span></div><div class="line">git commit -m <span class="string">"add feature"</span> <span class="comment"> //提交更改</span></div><div class="line">git checkout dev <span class="comment"> //切换到dev分支准备合并</span></div><div class="line">git branch -D feature <span class="comment"> //此时收到通知丢弃feature功能,用-D删除未合并的分支</span></div></pre></td></tr></table></figure>
</li>
<li><p>多人协作<br>当从远程克隆仓库时,Git会自动把本地master分支和远程master分支对应起来,查看远程库的信息用<code>git remote</code>,<code>git remote -v</code>可显示抓取和推送的origin地址,如果没有推送权限,就看不到push的地址。</p>
<ul>
<li>推送分支<br>就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:<figure class="highlight maxima"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">push</span> <span class="built_in">origin</span> master</div></pre></td></tr></table></figure>
</li>
</ul>
<p>但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?</p>
<pre><code>master分支是主分支,因此要时刻与远程同步;
dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
</code></pre><ul>
<li>抓取分支<br>当你使用<code>git clone</code>命令克隆一个仓库时,你克隆的只是仓库的master分支,此时若要在dev分支上开发,需要先创建远程origin的dev分支到本地,然后再时不时把dev分支push到远程。<figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">git checkout -<span class="keyword">b </span>dev <span class="keyword">origin/dev</span></div><div class="line">git <span class="keyword">add </span>file</div><div class="line">git commit -m <span class="string">'xxx'</span></div><div class="line">git push <span class="keyword">origin </span>dev</div></pre></td></tr></table></figure>
</li>
</ul>
<p>如果你和同事对项目做了同样的修改,在push时会推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull把最新的提交从origin/dev抓下来,然后,在本地合并,解决冲突,再推送:</p>
<figure class="highlight maxima"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">git pull//git pull也失败了,原因是没有指定本地dev分支与远程<span class="built_in">origin</span>/dev分支的链接,根据提示,设置dev和<span class="built_in">origin</span>/dev的链接:</div><div class="line">git branch --set-upstream dev <span class="built_in">origin</span>/dev</div><div class="line">git pull//再pull,pull成功但是合并有冲突,参考之前的冲突解决方法解决冲突后提交再<span class="built_in">push</span></div><div class="line">git commit -m <span class="string">"xxx"</span></div><div class="line">git <span class="built_in">push</span> <span class="built_in">origin</span> dev</div></pre></td></tr></table></figure>
<p>因此,多人协作的工作模式通常是这样:<br>首先,可以试图用git push origin branch-name推送自己的修改;<br>如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;<br>如果合并有冲突,则解决冲突,并在本地提交;<br>没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!<br>如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。<br>这就是多人协作的工作模式,一旦熟悉了,就非常简单。</p>
</li>
<li><p>标签管理<br>发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签也是版本库的一个快照。</p>
<ul>
<li>创建标签<br> 切换到要打标签的分支<br> git tag v1.0 //标签名为v1.0,打在最新提交的commit处<br> git tag //查看所有标签<br> 如果要打到历史提交的commit处,需要先找到历史提交的commit id<pre><code>git log --pretty=oneline --abbrev-commit
git tag v0.9 6224937 //git tag tagname commitid
</code></pre> git show tagname//查看标签信息<br> git tag -a v0.1 -m “version 0.1 released” 3628164//创建带说明的标签,-a指定标签名,-m指定tag说明</li>
<li>操作标签<br> git tag -d v1.0//删除标签<br> git push origin tagname//推送某个标签到远程<br> git push origin –tags//推送所有标签到远程<br> 删除远程标签 <figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git tag -d v1.<span class="number">0</span><span class="comment">//先在本地删除标签</span></div><div class="line">git <span class="keyword">push</span> origin :refs<span class="regexp">/tags/</span>v1.<span class="number">0</span><span class="comment">//远程删除标签,是否真正删除可登录github查看</span></div></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>如何参与开源项目<br>1.fork你想参与的项目,相当于在自己的账号下克隆了该项目的仓库<br>2.从自己的账号下clone项目到本地,一定要从自己的账号下克隆,否则将会没有权限推送<br>3.修改后推送到自己的仓库,然后在github上发起pull request,对方如果认可你的修改,便会接受。</p>
</li>
<li><p>自定义git<br>除了在安装git一节中介绍的user.name和user.email,git还有很多配置<br>如:<code>git config --global color.ui true</code>可以让git显示颜色</p>
<ul>
<li><p>忽略特殊文件<br> 有的文件涉及密码、ip等配置文件,github中不能上传隐私信息,解决方法是只需在工作区的根目录下添加名为.gitignore的文件,这个文件不需要重头写,可参考<a href="https://github.com/github/gitignore" target="_blank" rel="external">.gitignore大全</a>。<br> 配置完忽略文件后将其提交到git就完成了。<br> 有时候当你想添加一个文件却发现添加不了,原因是这个文件被.gitignore忽略了,如果你确实想添加该文件,可以用-f强制添加到Git:</p>
<figure class="highlight livecodeserver"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git <span class="built_in">add</span> -f <span class="built_in">file</span></div></pre></td></tr></table></figure>
<p> 或者你发现,可能是.gitignore写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:</p>
<figure class="highlight smali"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">$ git<span class="built_in"> check-ignore </span>-v App.class</div><div class="line"><span class="keyword">.gitignore</span>:3:*.class App.class</div></pre></td></tr></table></figure>
<p> Git会告诉我们,.gitignore的第3行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。</p>
</li>
</ul>
</li>
</ol>
<h1 id="Git使用流程"><a href="#Git使用流程" class="headerlink" title="Git使用流程"></a>Git使用流程</h1><p>克隆代码 git clone 远程代码<br>创建分支 git checkout -b branch_name<br>在分支中开发 无<br>review代码 无<br>第一轮测试 无<br>添加代码到分支的暂存区 git add somefile<br>提交代码到分支 git commit -m “本次提交的注释”<br>切换到主版本 git checkout master<br>获取远程最新代码 git pull origin master<br>合并某分支到master分支 git merge branch_name<br>解决合并时产生的冲突 无<br>第二轮测试 无<br>准备上线文档 无<br>获取远程最新代码 git pull origin master<br>推送master分支 git push origin master<br>通知上线 无<br>没有问题了删除本地分支 git branch -d branch_name</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/10/08/Git指南/" data-id="ciz5et7w800068vfy6v3owtyg" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Git/">Git</a></li></ul>
</footer>
</div>
</article>
<article id="post-ES6笔记" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/10/08/ES6笔记/" class="article-date">
<time datetime="2016-10-08T15:54:36.000Z" itemprop="datePublished">2016-10-08</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/ES6/">ES6</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/10/08/ES6笔记/">ES6笔记</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。</p>
<p>babel是常用的es6转换器,这儿提供一个学习使用的es6在线编辑工具:<a href="http://www.es6fiddle.net/" target="_blank" rel="external">ES6在线编辑器</a>。</p>
<ol>
<li><p>let, const</p>
<figure class="highlight sqf"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">var <span class="built_in">name</span> = <span class="string">'zach'</span></div><div class="line"><span class="keyword">while</span> (<span class="literal">true</span>) {</div><div class="line"> var <span class="built_in">name</span> = <span class="string">'obama'</span></div><div class="line"> console.<span class="built_in">log</span>(<span class="built_in">name</span>) <span class="comment">//obama</span></div><div class="line"> break</div><div class="line">}</div><div class="line">console.<span class="built_in">log</span>(<span class="built_in">name</span>) <span class="comment">//obama</span></div></pre></td></tr></table></figure>
</li>
</ol>
<p>由于ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。第一种场景就是你现在看到的内层变量覆盖外层变量。而let则实际上为JavaScript新增了块级作用域。用它所声明的变量,只在let命令所在的代码块内有效。<br> <figure class="highlight sqf"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">let <span class="built_in">name</span> = <span class="string">'zach'</span></div><div class="line"></div><div class="line"><span class="keyword">while</span> (<span class="literal">true</span>) {</div><div class="line"> let <span class="built_in">name</span> = <span class="string">'obama'</span></div><div class="line"> console.<span class="built_in">log</span>(<span class="built_in">name</span>) <span class="comment">//obama</span></div><div class="line"> break</div><div class="line">}</div><div class="line"></div><div class="line">console.<span class="built_in">log</span>(<span class="built_in">name</span>) <span class="comment">//zach</span></div></pre></td></tr></table></figure></p>
<p>另外一个var带来的不合理场景就是用来计数的循环变量泄露为全局变量,看下面的例子:<br> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a = [];</div><div class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < <span class="number">10</span>; i++) {</div><div class="line"> a[i] = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(i);</div><div class="line"> };</div><div class="line">}</div><div class="line">a[<span class="number">6</span>](); <span class="comment">// 10</span></div></pre></td></tr></table></figure></p>
<p>上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。而使用let则不会出现这个问题。<br> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> a = [];</div><div class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < <span class="number">10</span>; i++) {</div><div class="line"> a[i] = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(i);</div><div class="line"> };</div><div class="line">}</div><div class="line">a[<span class="number">6</span>](); <span class="comment">// 6</span></div></pre></td></tr></table></figure></p>
<p>再来看一个更常见的例子,了解下如果不用ES6,而用闭包如何解决这个问题。<br> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> clickBoxs = <span class="built_in">document</span>.querySelectorAll(<span class="string">'.clickBox'</span>)</div><div class="line"><span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < clickBoxs.length; i++){</div><div class="line"> clickBoxs[i].onclick = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(i)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>我们本来希望的是点击不同的clickBox,显示不同的i,但事实是无论我们点击哪个clickBox,输出的都是5。下面我们来看下,如何用闭包搞定它。<br> <figure class="highlight matlab"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">iteratorFactory</span><span class="params">(i)</span>{</span></div><div class="line"> var onclick = <span class="function"><span class="keyword">function</span><span class="params">(e)</span>{</span></div><div class="line"> console.<span class="built_in">log</span>(<span class="built_in">i</span>)</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> onclick;</div><div class="line">}</div><div class="line">var clickBoxs = document.querySelectorAll(<span class="string">'.clickBox'</span>)</div><div class="line"><span class="keyword">for</span> (var <span class="built_in">i</span> = <span class="number">0</span>; <span class="built_in">i</span> < clickBoxs.<span class="built_in">length</span>; <span class="built_in">i</span>++){</div><div class="line"> clickBoxs[i].onclick = iteratorFactory(i)</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>const也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。<br> <figure class="highlight monkey"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> <span class="built_in">PI</span> = Math.<span class="built_in">PI</span></div><div class="line"></div><div class="line"><span class="built_in">PI</span> = <span class="number">23</span> //<span class="keyword">Module</span> build failed: SyntaxError: /es6/app.js: <span class="string">"PI"</span> is read-only</div></pre></td></tr></table></figure></p>
<p>当我们尝试去改变用const声明的常量时,浏览器就会报错。const有一个很好的应用场景,就是当我们引用第三方库的时声明的变量,用const来声明可以避免未来不小心重命名而导致出现bug:<br> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> monent = <span class="built_in">require</span>(<span class="string">'moment'</span>)</div></pre></td></tr></table></figure></p>
<ol>
<li>class, extends, super</li>
</ol>
<p>这三个特性涉及了ES5中最令人头疼的的几个部分:原型、构造函数,继承…你还在为它们复杂难懂的语法而烦恼吗?你还在为指针到底指向哪里而纠结万分吗?</p>
<p>有了ES6我们不再烦恼!</p>
<p>ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>{</div><div class="line"> <span class="keyword">constructor</span>(){</div><div class="line"> <span class="keyword">this</span>.type = <span class="string">'animal'</span></div><div class="line"> }</div><div class="line"> says(say){</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.type + <span class="string">' says '</span> + say)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight scala"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">let animal = <span class="keyword">new</span> <span class="type">Animal</span>()</div><div class="line">animal.says(<span class="symbol">'hell</span>o') <span class="comment">//animal says hello</span></div><div class="line"></div><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Cat</span> <span class="keyword">extends</span> <span class="title">Animal</span> </span>{</div><div class="line"> constructor(){</div><div class="line"> <span class="keyword">super</span>()</div><div class="line"> <span class="keyword">this</span>.<span class="keyword">type</span> = <span class="symbol">'ca</span>t'</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">let cat = <span class="keyword">new</span> <span class="type">Cat</span>()</div><div class="line">cat.says(<span class="symbol">'hell</span>o') <span class="comment">//cat says hello</span></div></pre></td></tr></table></figure>
</code></pre><p>上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实例对象可以共享的。</p>
<p>Class之间可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。上面定义了一个Cat类,该类通过extends关键字,继承了Animal类的所有属性和方法。</p>
<p>super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。</p>
<p>ES6的继承机制,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。</p>
<ol>
<li>arrow function</li>
</ol>
<p>这个恐怕是ES6最最常用的一个新特性了,用它来写function比原来的写法要简洁清晰很多:</p>
<pre><code><figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span><span class="params">(i)</span></span>{ <span class="keyword">return</span> i + <span class="number">1</span>; } <span class="comment">//ES5</span></div><div class="line">(i) => i + <span class="number">1</span> <span class="comment">//ES6</span></div></pre></td></tr></table></figure>
</code></pre><p>简直是简单的不像话对吧…<br>如果方程比较复杂,则需要用{}把代码包起来:</p>
<pre><code><figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span><span class="params">(x, y)</span></span> { </div><div class="line"> x++;</div><div class="line"> y<span class="comment">--;</span></div><div class="line"> <span class="keyword">return</span> x + y;</div><div class="line">}</div><div class="line">(x, y) => {x++; y<span class="comment">--; return x+y}</span></div></pre></td></tr></table></figure>
</code></pre><p>除了看上去更简洁以外,arrow function还有一项超级无敌的功能!<br>长期以来,JavaScript语言的this对象一直是一个令人头痛的问题,在对象方法中使用this,必须非常小心。例如:</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>{</div><div class="line"> <span class="keyword">constructor</span>(){</div><div class="line"> <span class="keyword">this</span>.type = <span class="string">'animal'</span></div><div class="line"> }</div><div class="line"> says(say){</div><div class="line"> setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.type + <span class="string">' says '</span> + say)</div><div class="line"> }, <span class="number">1000</span>)</div><div class="line"> }</div><div class="line">}</div><div class="line"> <span class="keyword">var</span> animal = <span class="keyword">new</span> Animal()</div><div class="line"> animal.says(<span class="string">'hi'</span>) <span class="comment">//undefined says hi</span></div></pre></td></tr></table></figure>
</code></pre><p>运行上面的代码会报错,这是因为setTimeout中的this指向的是全局对象。所以为了让它能够正确的运行,传统的解决方法有两种:</p>
<pre><code>第一种是将this传给self,再用self来指代this
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">says(say){</div><div class="line"> <span class="keyword">var</span> self = <span class="keyword">this</span>;</div><div class="line"> setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(self.type + <span class="string">' says '</span> + say)</div><div class="line"> }, <span class="number">1000</span>)</div></pre></td></tr></table></figure>
2.第二种方法是用bind(this),即
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">says(say){</div><div class="line"> setTimeout(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.type + <span class="string">' says '</span> + say)</div><div class="line"> }.bind(<span class="keyword">this</span>), <span class="number">1000</span>)</div></pre></td></tr></table></figure>
但现在我们有了箭头函数,就不需要这么麻烦了:
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span> </span>{</div><div class="line"> <span class="keyword">constructor</span>(){</div><div class="line"> <span class="keyword">this</span>.type = <span class="string">'animal'</span></div><div class="line"> }</div><div class="line"> says(say){</div><div class="line"> setTimeout( () => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.type + <span class="string">' says '</span> + say)</div><div class="line"> }, <span class="number">1000</span>)</div><div class="line"> }</div><div class="line">}</div><div class="line"> <span class="keyword">var</span> animal = <span class="keyword">new</span> Animal()</div><div class="line"> animal.says(<span class="string">'hi'</span>) <span class="comment">//animal says hi</span></div></pre></td></tr></table></figure>
</code></pre><p>当我们使用箭头函数时,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。</p>
<ol>
<li>template string</li>
</ol>
<p>这个东西也是非常有用,当我们要插入大段的html内容到文档中时,传统的写法非常麻烦,所以之前我们通常会引用一些模板工具库,比如mustache等等。</p>
<p>大家可以先看下面一段代码:</p>
<pre><code><figure class="highlight smalltalk"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="string">$(</span><span class="comment">"#result"</span>).append(</div><div class="line"> <span class="comment">"There are <b>"</span> + basket.count + <span class="comment">"</b> "</span> +</div><div class="line"> <span class="comment">"items in your basket, "</span> +</div><div class="line"> <span class="comment">"<em>"</span> + basket.onSale +</div><div class="line"> <span class="comment">"</em> are on sale!"</span></div><div class="line">);</div></pre></td></tr></table></figure>
</code></pre><p>我们要用一堆的’+’号来连接文本与变量,而使用ES6的新特性模板字符串后,我们可以直接这么来写:</p>
<pre><code><figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">$(<span class="string">"#result"</span>).<span class="keyword">append</span>(`</div><div class="line"> There are <b><span class="variable">${basket</span>.<span class="keyword">count</span>}</b> items</div><div class="line"> <span class="keyword">in</span> your basket, <em><span class="variable">${basket</span>.onSale}</em></div><div class="line"> are <span class="keyword">on</span> sale!</div><div class="line">`);</div></pre></td></tr></table></figure>
</code></pre><p>用反引号(\)来标识起始,用${}`来引用变量,而且所有的空格和缩进都会被保留在输出之中,是不是非常爽?!</p>
<ol>
<li>destructuring</li>
</ol>
<p>ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。</p>
<p>看下面的例子:</p>
<pre><code><figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> <span class="keyword">cat</span> = <span class="string">'ken'</span></div><div class="line"><span class="keyword">let</span> dog = <span class="string">'lili'</span></div><div class="line"><span class="keyword">let</span> zoo = {<span class="keyword">ca</span><span class="variable">t:</span> <span class="keyword">cat</span>, <span class="keyword">do</span><span class="variable">g:</span> dog}</div><div class="line">console.<span class="built_in">log</span>(zoo) //Object {<span class="keyword">ca</span><span class="variable">t:</span> <span class="string">"ken"</span>, <span class="keyword">do</span><span class="variable">g:</span> <span class="string">"lili"</span>}</div></pre></td></tr></table></figure>
</code></pre><p>用ES6完全可以像下面这么写:</p>
<pre><code><figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> <span class="keyword">cat</span> = <span class="string">'ken'</span></div><div class="line"><span class="keyword">let</span> dog = <span class="string">'lili'</span></div><div class="line"><span class="keyword">let</span> zoo = {<span class="keyword">cat</span>, dog}</div><div class="line">console.<span class="built_in">log</span>(zoo) //Object {<span class="keyword">ca</span><span class="variable">t:</span> <span class="string">"ken"</span>, <span class="keyword">do</span><span class="variable">g:</span> <span class="string">"lili"</span>}</div></pre></td></tr></table></figure>
</code></pre><p>反过来可以这么写:</p>
<pre><code><figure class="highlight fsharp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> dog = {<span class="class"><span class="keyword">type</span>: '<span class="title">animal</span>', <span class="title">many</span>: 2}</span></div><div class="line"><span class="keyword">let</span> { <span class="class"><span class="keyword">type</span>, <span class="title">many</span>} </span>= dog</div><div class="line">console.log(<span class="class"><span class="keyword">type</span>, <span class="title">many</span>) //<span class="title">animal</span> 2</span></div></pre></td></tr></table></figure>
</code></pre><ol>
<li>default, rest</li>
</ol>
<p>default很简单,意思就是默认值。大家可以看下面的例子,调用animal()方法时忘了传参数,传统的做法就是加上这一句type = type || ‘cat’ 来指定默认值。</p>
<pre><code><figure class="highlight fsharp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">function</span> animal(<span class="class"><span class="keyword">type</span>){</span></div><div class="line"> <span class="class"><span class="keyword">type</span> </span>= <span class="class"><span class="keyword">type</span> || '<span class="title">cat</span>' </span></div><div class="line"> console.log(<span class="class"><span class="keyword">type</span>)</span></div><div class="line">}</div><div class="line">animal()</div></pre></td></tr></table></figure>
</code></pre><p>如果用ES6我们而已直接这么写:</p>
<pre><code><figure class="highlight delphi"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">animal</span><span class="params">(<span class="keyword">type</span> = <span class="string">'cat'</span>)</span><span class="comment">{</span></span></div><div class="line"> console.log(type)</div><div class="line">}</div><div class="line"><span class="title">animal</span><span class="params">()</span></div></pre></td></tr></table></figure>
</code></pre><p>最后一个rest语法也很简单,直接看例子:</p>
<pre><code><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">animals</span><span class="params">(<span class="rest_arg">...types</span>)</span></span>{</div><div class="line"> console.log(types)</div><div class="line">}</div><div class="line">animals(<span class="string">'cat'</span>, <span class="string">'dog'</span>, <span class="string">'fish'</span>) <span class="comment">//["cat", "dog", "fish"]</span></div></pre></td></tr></table></figure>
</code></pre><p>而如果不用ES6的话,我们则得使用ES5的arguments。</p>
<ol>
<li>import export</li>
</ol>
<p>这两个家伙对应的就是es6自己的module功能。</p>
<p>我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小工程,再用一种简单的方法把这些小工程连接在一起。</p>
<p>这有可能导致两个问题:</p>
<pre><code>一方面js代码变得很臃肿,难以维护
另一方面我们常常得很注意每个script标签在html中的位置,因为它们通常有依赖关系,顺序错了可能就会出bug
</code></pre><p>在es6之前为解决上面提到的问题,我们得利用第三方提供的一些方案,主要有两种CommonJS(服务器端)和AMD(浏览器端,如require.js)。</p>
<p>而现在我们有了es6的module功能,它实现非常简单,可以成为服务器和浏览器通用的模块解决方案。</p>
<pre><code>ES6模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时确定这些东西。
</code></pre><p>上面的设计思想看不懂也没关系,咱先学会怎么用,等以后用多了、熟练了再去研究它背后的设计思想也不迟!好,那我们就上代码…<br>传统的写法</p>
<p>首先我们回顾下require.js的写法。假设我们有两个js文件: index.js和content.js,现在我们想要在index.js中使用content.js返回的结果,我们要怎么做呢?</p>
<p>首先定义:</p>
<pre><code><figure class="highlight actionscript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//content.js</span></div><div class="line">define(<span class="string">'content.js'</span>, <span class="function"><span class="keyword">function</span><span class="params">()</span></span>{</div><div class="line"> <span class="keyword">return</span> <span class="string">'A cat'</span>;</div><div class="line">})</div></pre></td></tr></table></figure>
</code></pre><p>然后require:</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="built_in">require</span>([<span class="string">'./content.js'</span>], <span class="function"><span class="keyword">function</span>(<span class="params">animal</span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(animal); <span class="comment">//A cat</span></div><div class="line">})</div></pre></td></tr></table></figure>
</code></pre><p>那CommonJS是怎么写的呢?</p>
<pre><code><figure class="highlight stylus"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="selector-tag">var</span> animal = require(<span class="string">'./content.js'</span>)</div><div class="line"></div><div class="line"><span class="comment">//content.js</span></div><div class="line">module<span class="selector-class">.exports</span> = <span class="string">'A cat'</span></div></pre></td></tr></table></figure>
</code></pre><p>ES6的写法</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="keyword">import</span> animal <span class="keyword">from</span> <span class="string">'./content'</span></div><div class="line"></div><div class="line"><span class="comment">//content.js</span></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="string">'A cat'</span></div></pre></td></tr></table></figure>
</code></pre><p>以上我把三者都列出来了,妈妈再也不用担心我写混淆了…<br>ES6 module的其他高级用法</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//content.js</span></div><div class="line"></div><div class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="string">'A cat'</span> </div><div class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">say</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">return</span> <span class="string">'Hello!'</span></div><div class="line">} </div><div class="line"><span class="keyword">export</span> <span class="keyword">const</span> type = <span class="string">'dog'</span></div></pre></td></tr></table></figure>
</code></pre><p>上面可以看出,export命令除了输出变量,还可以输出函数,甚至是类</p>
<pre><code><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//index.js</span></div><div class="line"><span class="keyword">import</span> { say, type } <span class="keyword">from</span> <span class="string">'./content'</span> </div><div class="line"><span class="keyword">let</span> says = say()</div><div class="line"><span class="built_in">console</span>.log(<span class="string">`The <span class="subst">${type}</span> says <span class="subst">${says}</span>`</span>) <span class="comment">//The dog says Hello</span></div></pre></td></tr></table></figure>
</code></pre><p>这里输入的时候要注意:大括号里面的变量名,必须与被导入模块(content.js)对外接口的名称相同。</p>
<p>如果还希望输入content.js中输出的默认值(default), 可以写在大括号外面。</p>
<pre><code>//index.js
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> animal, { say, type } <span class="keyword">from</span> <span class="string">'./content'</span> </div><div class="line"><span class="keyword">let</span> says = say()</div><div class="line"><span class="built_in">console</span>.log(<span class="string">`The <span class="subst">${type}</span> says <span class="subst">${says}</span> to <span class="subst">${animal}</span>`</span>) </div><div class="line"><span class="comment">//The dog says Hello to A cat</span></div></pre></td></tr></table></figure>
</code></pre><p>修改变量名</p>
<p>此时我们不喜欢type这个变量名,因为它有可能重名,所以我们需要修改一下它的变量名。在es6中可以用as实现一键换名。</p>
<pre><code>//index.js
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> animal, { say, type <span class="keyword">as</span> animalType } <span class="keyword">from</span> <span class="string">'./content'</span> </div><div class="line"><span class="keyword">let</span> says = say()</div><div class="line"><span class="built_in">console</span>.log(<span class="string">`The <span class="subst">${animalType}</span> says <span class="subst">${says}</span> to <span class="subst">${animal}</span>`</span>) </div><div class="line"><span class="comment">//The dog says Hello to A cat</span></div></pre></td></tr></table></figure>
</code></pre><p>模块的整体加载</p>
<p>除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。</p>
<pre><code>//index.js
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> animal, * <span class="keyword">as</span> content <span class="keyword">from</span> <span class="string">'./content'</span> </div><div class="line"><span class="keyword">let</span> says = content.say()</div><div class="line"><span class="built_in">console</span>.log(<span class="string">`The <span class="subst">${content.type}</span> says <span class="subst">${says}</span> to <span class="subst">${animal}</span>`</span>) </div><div class="line"><span class="comment">//The dog says Hello to A cat</span></div></pre></td></tr></table></figure>
</code></pre><p>通常星号*结合as一起使用比较合适。<br>终极秘籍</p>
<p>考虑下面的场景:上面的content.js一共输出了三个变量(default, say, type),假如我们的实际项目当中只需要用到type这一个变量,其余两个我们暂时不需要。我们可以只输入一个变量:</p>
<pre><code><figure class="highlight moonscript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> { <span class="built_in">type</span> } <span class="keyword">from</span> <span class="string">'./content'</span></div></pre></td></tr></table></figure>
</code></pre><p>由于其他两个变量没有被使用,我们希望代码打包的时候也忽略它们,抛弃它们,这样在大项目中可以显著减少文件的体积。</p>
<p>ES6帮我们实现了!s</p>
<p>不过,目前无论是webpack还是browserify都还不支持这一功能…</p>
<p>如果你现在就想实现这一功能的话,可以尝试使用rollup.js</p>
<p>他们把这个功能叫做Tree-shaking,哈哈哈,意思就是打包前让整个文档树抖一抖,把那些并未被依赖或使用的东西统统抖落下去。。。</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/10/08/ES6笔记/" data-id="ciz5et7w000028vfyzqbljzj8" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/ES6/">ES6</a></li></ul>
</footer>
</div>
</article>
<article id="post-js作用域与闭包" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/09/08/js作用域与闭包/" class="article-date">
<time datetime="2016-09-08T11:54:36.000Z" itemprop="datePublished">2016-09-08</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/JavaScript/">JavaScript</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/09/08/js作用域与闭包/">js作用域与闭包</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<ul>
<li><p>JavaScript 中,变量的局部作用域是函数级别的。不同于C语言,在C语言中,作用域是块级别的。 JavaScript中没有块级作用域。js 中,函数中声明的变量在整个函数中都有定义,比如for循环中定义的i,函数内都可使用</p>
<figure class="highlight qml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">var</span> <span class="built_in">parent</span> = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">var</span> name = <span class="string">"parent_name"</span>;</div><div class="line"> <span class="built_in">var</span> age = <span class="number">13</span>;</div><div class="line"></div><div class="line"> <span class="built_in">var</span> child = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">var</span> name = <span class="string">"child_name"</span>;</div><div class="line"> <span class="built_in">var</span> childAge = <span class="number">0.3</span>;</div><div class="line"></div><div class="line"> <span class="comment">// => child_name 13 0.3</span></div><div class="line"> <span class="built_in">console</span>.log(name, age, childAge);</div><div class="line"> };</div><div class="line"></div><div class="line"> child();</div><div class="line"></div><div class="line"> <span class="comment">// will throw Error</span></div><div class="line"> <span class="comment">// ReferenceError: childAge is not defined</span></div><div class="line"> <span class="built_in">console</span>.log(name, age, childAge);</div><div class="line">};</div><div class="line"></div><div class="line"><span class="built_in">parent</span>();</div></pre></td></tr></table></figure>
</li>
<li><p>闭包这个概念,在函数式编程里很常见,简单的说,就是使内部函数可以访问定义在外部函数中的变量。每次调用 adder 时,adder 都会返回一个函数给我们。我们传给 adder 的值,会保存在一个名为 base 的变量中。由于返回的函数在其中引用了 base 的值,于是 base 的引用计数被 +1。当返回函数不被垃圾回收时,则 base 也会一直存在。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> adder = <span class="function"><span class="keyword">function</span> (<span class="params">x</span>) </span>{</div><div class="line"> <span class="keyword">var</span> base = x;</div><div class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params">n</span>) </span>{</div><div class="line"> <span class="keyword">return</span> n + base;</div><div class="line"> };</div><div class="line">};</div><div class="line"><span class="keyword">var</span> add10 = adder(<span class="number">10</span>);</div><div class="line"><span class="built_in">console</span>.log(add10(<span class="number">5</span>));</div><div class="line"><span class="keyword">var</span> add20 = adder(<span class="number">20</span>);</div><div class="line"><span class="built_in">console</span>.log(add20(<span class="number">5</span>));</div><div 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++) {</div><div class="line"> setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(i);</div><div class="line"> }, <span class="number">5</span>);</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>上面这个代码块会打印五个 5 出来,而我们预想的结果是打印 0 1 2 3 4。<br>之所以会这样,是因为 setTimeout 中的 i 是对外层 i 的引用。当 setTimeout 的代码被解释的时候,运行时只是记录了 i 的引用,而不是值。而当 setTimeout 被触发时,五个 setTimeout 中的 i 同时被取值,由于它们都指向了外层的同一个 i,而那个 i 的值在迭代完成时为 5,所以打印了五次 5为了得到我们预想的结果,我们可以把 i 赋值成一个局部的变量,从而摆脱外层迭代的影响。</p>
<pre><code><figure class="highlight lisp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">for (<span class="name">var</span> i = <span class="number">0</span><span class="comment">; i < 5; i++) {</span></div><div class="line"> (<span class="name">function</span> (<span class="name">idx</span>) {</div><div class="line"> setTimeout(<span class="name">function</span> () {</div><div class="line"> console.log(<span class="name">idx</span>)<span class="comment">;</span></div><div class="line"> }, <span class="number">1000</span>)<span class="comment">;</span></div><div class="line"> })(<span class="name">i</span>)<span class="comment">;</span></div><div class="line">}</div></pre></td></tr></table></figure>
</code></pre><ul>
<li>在函数执行时,this 总是指向调用该函数的对象。要判断 this 的指向,其实就是判断 this 所在的函数属于谁。</li>
</ul>
<ol>
<li><p>函数有所属对象时:指向所属对象</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> myObject = {value: <span class="number">100</span>};</div><div class="line">myObject.getValue = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.value); <span class="comment">// 输出 100</span></div><div class="line"></div><div class="line"> <span class="comment">// 输出 { value: 100, getValue: [Function] },</span></div><div class="line"> <span class="comment">// 其实就是 myObject 对象本身</span></div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.value;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(myObject.getValue()); <span class="comment">// => 100</span></div></pre></td></tr></table></figure>
</li>
<li><p>函数没有所属对象:指向全局对象</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> myObject = {value: <span class="number">100</span>};</div><div class="line">myObje.getValue = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">var</span> foo = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.value) <span class="comment">// => undefined</span></div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>);<span class="comment">// 输出全局对象 global</span></div><div class="line"> };</div><div class="line"></div><div class="line"> foo();</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.value;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(myObject.getValue()); <span class="comment">// => 100</span></div></pre></td></tr></table></figure>
</li>
<li><p>构造器中的 this:指向新对象<br>在 js 中,构造函数、普通函数、对象方法、闭包,这四者没有明确界线</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> SomeClass = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="keyword">this</span>.value = <span class="number">100</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> myCreate = <span class="keyword">new</span> SomeClass();</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(myCreate.value); <span class="comment">// 输出100</span></div></pre></td></tr></table></figure>
</li>
<li><p>apply 和 call 调用以及 bind 绑定:指向绑定的对象.<br>apply() 方法接受两个参数第一个是函数运行的作用域,另外一个是一个参数数组(arguments)。<br>call() 方法第一个参数的意义与 apply() 方法相同,只是其他的参数需要一个个列举出来。<br>简单来说,call 的方式更接近我们平时调用函数,而 apply 需要我们传递 Array 形式的数组给它。它们是可以互相转换的。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> myObject = {value: <span class="number">100</span>};</div><div class="line"></div><div class="line"><span class="keyword">var</span> foo = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>);</div><div class="line">};</div><div class="line"></div><div class="line">foo(); <span class="comment">// 全局变量 global</span></div><div class="line">foo.apply(myObject); <span class="comment">// { value: 100 }</span></div><div class="line">foo.call(myObject); <span class="comment">// { value: 100 }</span></div><div class="line"></div><div class="line"><span class="keyword">var</span> newFoo = foo.bind(myObject);</div><div class="line">newFoo(); <span class="comment">// { value: 100 }</span></div></pre></td></tr></table></figure>
</li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/09/08/js作用域与闭包/" data-id="ciz5et7wk000i8vfyunq0u1v4" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/作用域/">作用域</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/闭包/">闭包</a></li></ul>
</footer>
</div>
</article>
<article id="post-Git在本地及远程仓库中实现版本回退" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/09/01/Git在本地及远程仓库中实现版本回退/" class="article-date">
<time datetime="2016-09-01T11:54:36.000Z" itemprop="datePublished">2016-09-01</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/版本控制/">版本控制</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/09/01/Git在本地及远程仓库中实现版本回退/">Git在本地及远程仓库中实现版本回退</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>通过使用GIT版本恢复命令reset,可以回退版本。</p>
<p>reset命令有3种方式:</p>
<p>git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,回退commit和index信息 </p>
<p>git reset –soft:回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可 </p>
<p>git reset –hard:彻底回退到某个版本,本地的源码也会变为上一个版本的内容 </p>
<p>以下是一些reset的示例:</p>
<p>#回退所有内容到上一个版本 </p>
<p>git reset HEAD^ </p>
<p>#回退a.py这个文件的版本到上一个版本 </p>
<p>git reset HEAD^ a.py </p>
<p>#向前回退到第3个版本 </p>
<p>git reset –soft HEAD~3 </p>
<p>#将本地的状态回退到和远程的一样 </p>
<p>git reset –hard origin/master </p>
<p>#回退到某个版本 </p>
<p>git reset 057d </p>
<p>#回退到上一次提交的状态,按照某一次的commit完全反向的进行一次commit </p>
<p>git revert HEAD </p>
<p>如果我们某次修改了某些内容,并且已经commit到本地仓库,而且已经push到远程仓库了</p>
<p>这种情况下,我们想把本地和远程仓库都回退到某个版本,该怎么做呢?</p>
<p>前面讲到的git reset只是在本地仓库中回退版本,而远程仓库的版本不会变化</p>
<p>这样,即时本地reset了,但如果再git pull,那么,远程仓库的内容又会和本地之前版本的内容进行merge</p>
<p>这并不是我们想要的东西,这时可以有2种办法来解决这个问题:</p>
<p>直接在远程server的仓库目录下,执行git reset –soft 10efa来回退。注意:在远程不能使用mixed或hard参数</p>
<p>在本地直接把远程的master分支给删除,然后再把reset后的分支内容给push上去,如下:</p>
<p>#新建old_master分支做备份 </p>
<p>git branch old_master </p>
<p>#push到远程 </p>
<p>git push origin old_master:old_master </p>
<p>#本地仓库回退到某个版本 </p>
<p>git reset –hard bae168 </p>
<p>#删除远程的master分支</p>
<p>#如果使用的是bitbucket,先要在项目的设置里面将主分支改为其他,才可删除master分支</p>
<p>git push origin :master </p>
<p>#重新创建master分支 </p>
<p>git push origin master</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/09/01/Git在本地及远程仓库中实现版本回退/" data-id="ciz5et7vu00008vfy2c2brriy" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Git/">Git</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/版本回退/">版本回退</a></li></ul>
</footer>
</div>
</article>
<article id="post-正则表达式学习" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/09/01/正则表达式学习/" class="article-date">
<time datetime="2016-09-01T11:54:36.000Z" itemprop="datePublished">2016-09-01</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/正则表达式/">正则表达式</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/09/01/正则表达式学习/">正则表达式学习</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>###什么是正则表达式?</p>
<p>正则表达式用来查找字符串中符合某些规则的字符串,相当于记录文本规则的代码。</p>
<p>###使用</p>
<ol>
<li><p>元字符</p>
<ul>
<li>. 匹配除换行符以外的任意字符</li>
<li><ul>
<li>表示前边的内容可以连续重复使用任意次以使整个表达式得到匹配</li>
</ul>
</li>
<li>\w 匹配字母或数字或下划线或汉字</li>
<li>\s 匹配任意的空白符</li>
<li>\b 匹配单词的开始或结束</li>
<li>\d 匹配数字</li>
<li>^ 匹配字符串的开始</li>
<li>$ 匹配字符串的结束</li>
</ul>
</li>
</ol>
<pre><code>示例:
hi 匹配字符串中所有的字符串hi
\bhi\b 匹配完整的单词hi
\bhi\b.*\bLucy\b 匹配完整单词hi后跟着Lucy的字符串
0\d\d-\d\d\d\d\d\d\d\d 或 0\d{2}-\d{8} 匹配区号为三位的中国电话号码
\ba\w*\b 匹配以字母a开头的单词
\d+ 匹配1个或更多连续的数字
\b\w{6}\b 匹配刚好6个字符的单词
^\d{5,12}$ 匹配5-12位数字
</code></pre><ol>
<li><p>字符转义<br> 用来查找元字符本身<br> 通过使用\来取消这些字符的特殊意义</p>
<p> 示例:<br> deerchao.net 匹配deerchao.net<br> C:\Windows 匹配C:\Windows</p>
</li>
<li><p>重复</p>
<ul>
<li><ul>
<li>重复零次或更多次</li>
</ul>
</li>
<li><ul>
<li>重复一次或更多次</li>
</ul>
</li>
<li>? 重复零次或一次</li>
<li>{n} 重复n次</li>
<li>{n,} 重复n次或更多次</li>
<li><p>{n,m} 重复n到m次</p>
<p>示例:<br>Windows\d+ 匹配Windows后面跟1个或更多数字<br>^\w+ 匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个意思得看选项设置)</p>
</li>
</ul>
</li>
<li><p>字符类</p>
<p> 要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u)</p>
<p> 示例:<br> [aeiou] 匹配任何一个英文元音字母<br> [.?!] 匹配标点符号(.或?或!)<br> [0-9] 代表的含意与\d就是完全一致的:一位数字<br> [a-z0-9A-Z_] 也完全等同于\w(如果只考虑英文的话)<br> (?0\d{2}[) -]?\d{8} 可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。首先是一个转义字符(,它能出现0次或1次(?),然后是一个0,后面跟着2个数字(\d{2}),然后是)或-或空格中的一个,它出现1次或不出现(?),最后是8个数字(\d{8}</p>
</li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/09/01/正则表达式学习/" data-id="ciz5et7wv000u8vfy099zsrck" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/正则表达式/">正则表达式</a></li></ul>
</footer>
</div>
</article>
<article id="post-Mac下使用siege做系统压力测试" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/31/Mac下使用siege做系统压力测试/" class="article-date">
<time datetime="2016-08-31T11:54:36.000Z" itemprop="datePublished">2016-08-31</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/系统测试/">系统测试</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/31/Mac下使用siege做系统压力测试/">Mac下使用siege做系统压力测试</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>Siege是一款开源的压力测试工具,设计用于评估WEB应用在压力下的承受能力。可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。siege可以从您选择的预置列表中请求随机的URL。所以siege可用于仿真用户请求负载,而ab则不能。但不要使用siege来执行最高性能基准调校测试,这方面ab就准确很多。</p>
<ol>
<li>安装<a href="https://www.macports.org/install.php" target="_blank" rel="external">macports</a>,用dmg方式:</li>
<li><p>将/opt/local/bin和/opt/local/sbin添加到$PATH搜索路径中,编辑/etc/profile文件中,加上:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">export</span> PATH=/opt/<span class="built_in">local</span>/bin:<span class="variable">$PATH</span></div><div class="line"><span class="built_in">export</span> PATH=/opt/<span class="built_in">local</span>/sbin:<span class="variable">$PATH</span></div></pre></td></tr></table></figure>
</li>
<li><p>安装siege</p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo port <span class="keyword">install</span> siege</div></pre></td></tr></table></figure>
</li>
<li><p>并发测试</p>
<ul>
<li><p>参数说明</p>
<figure class="highlight applescript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line">siege <span class="comment">--help</span></div><div class="line">Usage: siege [options]</div><div class="line"> siege [options] URL</div><div class="line"> siege -g URL</div><div class="line">Options:</div><div class="line"> -V, <span class="comment">--version VERSION, prints the version number.</span></div><div class="line"> -h, <span class="comment">--help HELP, prints this section.</span></div><div class="line"> -C, <span class="comment">--config CONFIGURATION, show the current config.</span></div><div class="line"> <span class="comment">#在屏幕上打印显示出当前的配置,配置是包括在他的配置文件$HOME/.siegerc中,</span></div><div class="line"> <span class="comment">#可以编辑里面的参数,这样每次siege 都会按照它运行.</span></div><div class="line"> -v, <span class="comment">--verbose VERBOSE, prints notification to screen.</span></div><div class="line"> <span class="comment">#运行时能看到详细的运行信息</span></div><div class="line"> -q, <span class="comment">--quiet QUIET turns verbose off and suppresses output.</span></div><div class="line"> -g, <span class="comment">--get GET, pull down HTTP headers and display the</span></div><div class="line"> <span class="keyword">transaction</span>. Great <span class="keyword">for</span> <span class="built_in">application</span> debugging.</div><div class="line"> -c, <span class="comment">--concurrent=NUM CONCURRENT users, default is 10</span></div><div class="line"> <span class="comment">#模拟有n个用户在同时访问,n不要设得太大,因为越大,siege 消耗本地机器的资源越多</span></div><div class="line"> -i, <span class="comment">--internet INTERNET user simulation, hits URLs randomly.</span></div><div class="line"> <span class="comment">#随机访问urls.txt中的url列表项,以此模拟真实的访问情况(随机性)</span></div><div class="line"> -b, <span class="comment">--benchmark BENCHMARK: no delays between requests.</span></div><div class="line"> -t, <span class="comment">--time=NUMm TIMED testing where "m" is modifier S, M, or H</span></div><div class="line"> ex: <span class="comment">--time=1H, one hour test.</span></div><div class="line"> <span class="comment">#持续运行siege ‘n’秒(如10S),分钟(10M),小时(10H)</span></div><div class="line"> -r, <span class="comment">--reps=NUM REPS, number of times to run the test.</span></div><div class="line"> <span class="comment">#重复运行测试n次,不能与 -t同时存在</span></div><div class="line"> -f, <span class="comment">--file=FILE FILE, select a specific URLS FILE.</span></div><div class="line"> <span class="comment">#指定用urls文件,默认为siege安装目录下的etc/urls.txt</span></div><div class="line"> <span class="comment">#urls.txt文件:是很多行待测试URL的列表以换行符断开,格式为:</span></div><div class="line"> <span class="comment">#[protocol://]host.domain.com[:port][path/to/file]</span></div><div class="line"> -R, <span class="comment">--rc=FILE RC, specify an siegerc file</span></div><div class="line"> <span class="comment">#指定用特定的siege配置文件来运行,默认的为$HOME/.siegerc</span></div><div class="line"> -l, <span class="comment">--log[=FILE] LOG to FILE. If FILE is not specified, the</span></div><div class="line"> default <span class="keyword">is</span> used: PREFIX/var/siege.<span class="built_in">log</span></div><div class="line"> <span class="comment">#运行结束,将统计数据保存到日志文件siege.log中,可在.siegerc中自定义日志文件</span></div><div class="line"> -m, <span class="comment">--mark="text" MARK, mark the log file with a string.</span></div><div class="line"> -d, <span class="comment">--delay=NUM Time DELAY, random delay before each requst</span></div><div class="line"> <span class="keyword">between</span> <span class="number">1</span> <span class="keyword">and</span> NUM. (NOT COUNTED IN STATS)</div><div class="line"> <span class="comment">#hit每个url之间的延迟,在0-n之间</span></div><div class="line"> -H, <span class="comment">--header="text" Add a header to request (can be many)</span></div><div class="line"> -A, <span class="comment">--user-agent="text" Sets User-Agent in request</span></div><div class="line"> -T, <span class="comment">--content-type="text" Sets Content-Type in request</span></div></pre></td></tr></table></figure>
</li>
<li><p>使用方法</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//以1000并发量重复执行100次</span></div><div class="line">siege -c <span class="number">1000</span> -r <span class="number">100</span> <span class="string">http:</span><span class="comment">//www.baidu.com</span></div></pre></td></tr></table></figure>
</li>
<li><p>结果说明</p>
<figure class="highlight avrasm"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="symbol">Transactions:</span> <span class="number">30000</span> hits <span class="meta">#完成30000次处理</span></div><div class="line"><span class="symbol">Availability:</span> <span class="number">100.00</span> % <span class="meta">#成功率</span></div><div class="line">Elapsed time: <span class="number">68.59</span> secs <span class="meta">#总共使用时间</span></div><div class="line">Data transferred: <span class="number">817.76</span> MB <span class="meta">#共数据传输 817.76 MB</span></div><div class="line">Response time: <span class="number">0.04</span> secs <span class="meta">#响应时间,显示网络连接的速度</span></div><div class="line">Transaction rate: <span class="number">437.38</span> trans/<span class="keyword">sec</span> <span class="meta">#平均每秒完成 437.38 次处理</span></div><div class="line"><span class="symbol">Throughput:</span> <span class="number">11.92</span> MB/<span class="keyword">sec</span> <span class="meta">#平均每秒传送数据</span></div><div class="line"><span class="symbol">Concurrency:</span> <span class="number">17.53</span> <span class="meta">#实际最高并发连接数</span></div><div class="line">Successful transactions: <span class="number">30000</span> <span class="meta">#成功处理次数</span></div><div class="line">Failed transactions: <span class="number">0</span> <span class="meta">#失败处理次数</span></div><div class="line">Longest transaction: <span class="number">3.12</span> <span class="meta">#每次传输所花最长时间</span></div><div class="line">Shortest transaction: <span class="number">0.00</span> <span class="meta">#每次传输所花最短时间</span></div></pre></td></tr></table></figure>
</li>
<li><p>注意事项</p>
<ul>
<li>发送post请求时,url格式为:<a href="http://www.xxxx.com/" target="_blank" rel="external">http://www.xxxx.com/</a> POST p1=v1&p2=v2</li>
<li>如果url中含有空格和中文,要先进行url编码,否则siege发送的请求url不准确</li>
</ul>
</li>
</ul>
</li>
</ol>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/08/31/Mac下使用siege做系统压力测试/" data-id="ciz5et7wa00088vfye15tlno2" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/macports/">macports</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/系统测试/">系统测试</a></li></ul>
</footer>
</div>
</article>
<article id="post-webpack中使用ol3-layerswitcher" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/25/webpack中使用ol3-layerswitcher/" class="article-date">
<time datetime="2016-08-25T11:17:52.000Z" itemprop="datePublished">2016-08-25</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/Openlayers/">Openlayers</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/25/webpack中使用ol3-layerswitcher/">webpack中使用ol3-layerswitcher</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<ul>
<li><p>在webpack中用如下代码模块化引入ol3-layerswitcher时报错:ol is not defined;</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> ol <span class="keyword">from</span> <span class="string">'openlayers'</span>;</div><div class="line"><span class="keyword">import</span> <span class="string">'ol3-layerswitcher/src/ol3-layerswitcher'</span>;</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p>原因:因为webpack在模块化引入时每个文件的作用域是封闭的,导致加载ol3-layerswitcher时引用不到openlayers模块中的ol。所以需要把ol声明成全局变量:</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">module.exports = {</div><div class="line"><span class="attr"> resolve:</span> {</div><div class="line"><span class="attr"> root:</span> [],</div><div class="line"><span class="attr"> alias:</span> {</div><div class="line"><span class="attr"> openlayers:</span> path.resolve(__dirname, <span class="string">'../node_modules/openlayers/dist/ol.js'</span>)</div><div class="line"> }</div><div class="line"> },</div><div class="line"><span class="attr"> plugins:</span> [</div><div class="line"> new webpack.ProvidePlugin({</div><div class="line"><span class="attr"> ol:</span> <span class="string">'openlayers'</span></div><div class="line"> })</div><div class="line"> ]</div><div class="line">};</div></pre></td></tr></table></figure>
</li>
</ul>
<p>这个插件将ol暴露给所有模块,其它模块不用再显式引入openlayers了;只要模块的代码中出现了ol,webpack就会自动将openlayers注入。</p>
<ul>
<li><p>然后在vue文件中引入即可:</p>
<figure class="highlight gradle"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">import</span> ol <span class="keyword">from</span> <span class="string">'openlayers'</span>;</div><div class="line"><span class="keyword">import</span> <span class="string">'ol3-layerswitcher/src/ol3-layerswitcher'</span>;</div></pre></td></tr></table></figure>
</li>
</ul>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/08/25/webpack中使用ol3-layerswitcher/" data-id="ciz5et7wp000o8vfyzm1yib73" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Openlayers/">Openlayers</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Webpack/">Webpack</a></li></ul>
</footer>
</div>
</article>
<article id="post-NPM安装OL时readECONNRESET的解决方法" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/24/NPM安装OL时readECONNRESET的解决方法/" class="article-date">
<time datetime="2016-08-24T11:17:52.000Z" itemprop="datePublished">2016-08-24</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/NPM/">NPM</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/24/NPM安装OL时readECONNRESET的解决方法/">NPM安装OL时readECONNRESET的解决方法</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<ul>
<li><p>最近在通过NPM安装openlayers的时候遇到问题,报错如下:</p>
<figure class="highlight stata"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">ERR</span>! closure-util <span class="keyword">read</span> ECONNRESET</div></pre></td></tr></table></figure>
</li>
<li><p>解决方法:</p>
<figure class="highlight tcl"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">//将包地址从https切换到<span class="keyword">http</span></div><div class="line">npm config <span class="keyword">set</span> <span class="keyword">registry</span> <span class="keyword">http</span>://<span class="keyword">registry</span>.npmjs.org/</div></pre></td></tr></table></figure>
</li>
<li><p>然后:</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm <span class="keyword">install</span> openlayers <span class="comment">--save</span></div></pre></td></tr></table></figure>
</li>
</ul>
<p>轻松搞定!</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/08/24/NPM安装OL时readECONNRESET的解决方法/" data-id="ciz5et7wf000e8vfykf7bhsq1" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/NPM/">NPM</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Openlayers/">Openlayers</a></li></ul>
</footer>
</div>
</article>
<article id="post-Webpack使用指南" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/18/Webpack使用指南/" class="article-date">
<time datetime="2016-08-18T08:53:16.000Z" itemprop="datePublished">2016-08-18</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/前端构建/">前端构建</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/18/Webpack使用指南/">Webpack使用指南</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>。。。。</p>
</div>
<footer class="article-footer">
<a data-url="http://yoursite.com/2016/08/18/Webpack使用指南/" data-id="ciz5et7wm000k8vfy5bud4wf1" class="article-share-link">Share</a>
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/Webpack/">Webpack</a></li></ul>
</footer>
</div>
</article>
<article id="post-是时候学学前端自动化测试了" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/16/是时候学学前端自动化测试了/" class="article-date">
<time datetime="2016-08-16T09:12:59.000Z" itemprop="datePublished">2016-08-16</time>
</a>
<div class="article-category">
<a class="article-category-link" href="/categories/前端测试/">前端测试</a>
</div>
</div>
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/16/是时候学学前端自动化测试了/">是时候学学前端自动化测试了</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>测试是项目研发中不可或缺的一环,也是前端中最容易被忽视的环节。虽然现在有很多前端自动化测试工具,但是应用并不广泛,大多公司依旧以手工测试为主。</p>
<h2 id="为什么需要自动化测试?"><a href="#为什么需要自动化测试?" class="headerlink" title="为什么需要自动化测试?"></a>为什么需要自动化测试?</h2><hr>
<p>项目在快速迭代中不可避免的要进行一遍又一遍测试,费时又费力,而且极有可能因人工失误忽略某些环节。再者,怎么能容忍一次搞定的事非要多次重复呢?不能忍啊。。。那么,自动化测试的收益总结如下:</p>
<p><code>自动化的收益 = 迭代次数 * 全手动执行成本 - 首次自动化成本 - 维护次数 * 维护成本</code></p>
<h2 id="前端测试的方式及方向"><a href="#前端测试的方式及方向" class="headerlink" title="前端测试的方式及方向"></a>前端测试的方式及方向</h2><hr>
<p>测试方式主要有<code>单元测试</code>和<code>端到端测试(e2e)</code>。单元测试的工具体系虽然已经很完善,但是单元测试维护成本很高,而且不能满足前端测试的所有需求。故将前端测试的重点放到e2e测试,端到端测试将试着尽可能从用户的视角,对真实系统的访问行为进行仿真。对Web应用来说,这意味着需要打开浏览器、加载页面、运行JavaScript,以及进行与DOM交互等操作。。</p>
<p>前端需要测试的方向无非就以下几个方面:</p>
<ul>
<li>界面测试:测试不同浏览器下界面是否正常。<ul>
<li>像素对比<ul>
<li>像素对比:PhantomCSS,PhantomCSS结合了Casperjs截图和ResembleJs图像对比分析</li>
<li>多浏览器:selenium、<a href="http://dalekjs.com" target="_blank" rel="external">dalekjs</a>、<a href="http://triflejs.org" target="_blank" rel="external">triflejs</a></li>
<li>响应式页面测:通过PhantomJS、capserJS等工具在不同尺寸下截图然后根据resemberJS进行像素比对判断是否正常</li>
</ul>
</li>
<li>dom结构对比:<a href="https://github.com/fouber/page-monitor" target="_blank" rel="external">page-monitor</a></li>
<li>两者结合:<a href="http://pagediff.baidu.com" target="_blank" rel="external">pagediff</a></li>
</ul>
</li>
<li>UI测试:测试交互是否正常。<ul>
<li>Phantomjs:Phantom JS是一个服务器端的 JavaScript API 的 WebKit。其支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG。对于web测试、界面、网络捕获、页面自动化访问等等方面可以说是信手拈来。</li>
<li>CasperJS:casperjs是对PhantomJS的封装,提供了更加易用的API, 增强了测试等方面的支持。casperjs能用简单的API、从真实用户操作的角度来快速测试网站的功能是否正常,并且可以保留每一步测试的截图最终实现操作流可视化。</li>
</ul>
</li>
<li>性能测试:测试网页性能。<ul>
<li>Phantomas:它能运行测试页面获取很多性能指标,加载时间、页面请求数、资源大小、是否开启缓存和Gzip、选择器性能、dom结构等等。性能监控推荐这篇大神的文章:<a href="http://fex.baidu.com/blog/2014/05/build-performance-monitor-in-7-days/" target="_blank" rel="external">7天打造前端性能监控系统</a></li>
</ul>
</li>
</ul>
<h2 id="使用Selenium和Nightwatch搭建自动化测试环境"><a href="#使用Selenium和Nightwatch搭建自动化测试环境" class="headerlink" title="使用Selenium和Nightwatch搭建自动化测试环境"></a>使用Selenium和Nightwatch搭建自动化测试环境</h2><hr>
<p><code>Selenium</code>是ThoughtWorks专门为Web应用程序编写的一个验收测试工具。它包含了测试的录制(Selenium IDE)、编写及运行(Selenium Remote Control)和测试的并行处理(Selenium Grid)。Selenium的核心Selenium Core基于JsUnit,完全由JavaScript编写,因此可运行于任何支持JavaScript的浏览器上。与WatiN相同,Selenium也是一款同样使用Apache License 2.0协议发布的开源框架。</p>
<p><code>Nightwatch</code>是一套新近问世的基于Node.js的验收测试框架,使用Selenium WebDriver API以将Web应用测试自动化。它提供了简单的语法,支持使用JavaScript和CSS选择器,来编写运行在Selenium服务器上的端到端测试。</p>
<h3 id="开始动手啦!!"><a href="#开始动手啦!!" class="headerlink" title="开始动手啦!!"></a>开始动手啦!!</h3><ol>
<li><p>安装 Selenium 与 Nightwatch</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">npm <span class="keyword">install</span> nightwatch selenium-<span class="keyword">standalone</span> <span class="comment">--save-dev</span></div></pre></td></tr></table></figure>
</li>
<li><p>配置工具</p>
<ul>
<li><p>配置Nightwatch</p>
<ul>
<li><p>根目录创建nightwatch.json,写入以下内容:</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> <span class="attr">"src_folders"</span>: [<span class="string">"tests"</span>],</div><div class="line"> <span class="attr">"output_folder"</span>: <span class="string">"reports"</span>,</div><div class="line"> <span class="attr">"custom_commands_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"custom_assertions_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"page_objects_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"globals_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"selenium"</span>: {</div><div class="line"> <span class="attr">"start_process"</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">"server_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"log_path"</span>: <span class="string">""</span>,</div><div class="line"> <span class="attr">"host"</span>: <span class="string">"127.0.0.1"</span>,</div><div class="line"> <span class="attr">"port"</span>: <span class="number">4444</span>,</div><div class="line"> <span class="attr">"cli_args"</span>: {</div><div class="line"> <span class="attr">"webdriver.chrome.driver"</span>: <span class="string">""</span></div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">"test_settings"</span>: {</div><div class="line"> <span class="attr">"default"</span>: {</div><div class="line"> <span class="attr">"launch_url"</span>: <span class="string">"http://localhost"</span>,</div><div class="line"> <span class="attr">"selenium_port"</span>: <span class="number">4444</span>,</div><div class="line"> <span class="attr">"selenium_host"</span>: <span class="string">"localhost"</span>,</div><div class="line"> <span class="attr">"silent"</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">"screenshots"</span>: {</div><div class="line"> <span class="attr">"enabled"</span>: <span class="literal">false</span>,</div><div class="line"> <span class="attr">"path"</span>: <span class="string">""</span></div><div class="line"> },</div><div class="line"> <span class="attr">"desiredCapabilities"</span>: {</div><div class="line"> <span class="attr">"browserName"</span>: <span class="string">"firefox"</span>,</div><div class="line"> <span class="attr">"javascriptEnabled"</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">"acceptSslCerts"</span>: <span class="literal">true</span></div><div class="line"> }</div><div class="line"> },</div><div class="line"> <span class="attr">"chrome"</span> : {</div><div class="line"> <span class="attr">"desiredCapabilities"</span>: {</div><div class="line"> <span class="attr">"browserName"</span>: <span class="string">"chrome"</span>,</div><div class="line"> <span class="attr">"javascriptEnabled"</span>: <span class="literal">true</span>,</div><div class="line"> <span class="attr">"acceptSslCerts"</span>: <span class="literal">true</span></div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure>
<p>注意:test_settings.desiredCapabilities.browserName默认是firefox,如果需要用chrome、internet explorer、phantomjs的话,要安装相应的driver才能使用,并要把test_settings.desiredCapabilities.browserName改为‘chrome’。</p>
</li>
<li><p>根目录下创建文件nightwatch.conf.js,写入:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>)</div><div class="line"><span class="built_in">module</span>.exports = (<span class="function"><span class="keyword">function</span> (<span class="params">settings</span>) </span>{</div><div class="line"> <span class="keyword">return</span> settings;</div><div class="line">})(<span class="built_in">require</span>(<span class="string">'./nightwatch.json'</span>))</div><div class="line"><span class="comment">//Nightwatch 会从 nightwatch.json 中读取配置。</span></div><div class="line"><span class="comment">// 不过如果存在 nightwatch.conf.js,将会变为首先从后者中读取配置。</span></div><div class="line"><span class="comment">// nightwatch.conf.js 存在的意义是使用 JavaScript 动态生成配置信息。</span></div><div class="line"><span class="comment">// 如果配置信息是不需要代码修改的,直接使用 nightwatch.json 就可以啦。</span></div></pre></td></tr></table></figure>