-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
2029 lines (1356 loc) · 227 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">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge" >
<link rel="dns-prefetch" href="https://lizheguang.github.io">
<title>前端圈</title>
<meta name="generator" content="hexo-theme-yilia-plus">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<!-- <meta name="keywords" content="">
<meta name="description" content=""> -->
<meta property="og:type" content="website">
<meta property="og:title" content="前端圈">
<meta property="og:url" content="https://lizheguang.github.io/index.html">
<meta property="og:site_name" content="前端圈">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="前端圈">
<meta name="twitter:card" content="summary">
<link rel="alternative" href="/zhaiGuang/atom.xml" title="前端圈" type="application/atom+xml">
<link rel="icon" href="/zhaiGuang/favicon.ico">
<link rel="apple-touch-icon" href="/zhaiGuang/apple-touch-icon-180x180.png">
<link rel="stylesheet" type="text/css" href="/zhaiGuang/./main.a5fda8.css">
<style type="text/css">
#container.show {
background: linear-gradient(200deg,#a0cfe4,#e8c37e);
}
</style>
<script src="/zhaiGuang/lib/clickLove.js"></script>
</head>
<body>
<div id="container" q-class="show:isCtnShow">
<canvas id="anm-canvas" class="anm-canvas"></canvas>
<div class="left-col" q-class="show:isShow">
<div class="overlay" style="background: #4d4d4d;"></div>
<div class="intrude-less">
<header id="header" class="inner">
<a href="/zhaiGuang/" class="profilepic">
<img src="/zhaiGuang/img/Head.jpeg" class="js-avatar">
</a>
<hgroup>
<h1 class="header-author"><a href="/zhaiGuang/">前端圈</a></h1>
</hgroup>
<nav class="header-menu">
<ul>
<li><a href="/zhaiGuang/" target="_blank">主页</a></li>
<li><a href="https://www.toutiao.com/c/user/51181806849/#mid=1571432089459714" target="_blank">技术笔记</a></li>
<li><a href="/zhaiGuang/tags/%E9%9A%8F%E7%AC%94/" target="_blank">随笔</a></li>
</ul>
</nav>
<nav class="header-smart-menu">
<a q-on="click: openSlider(e, 'innerArchive')" href="javascript:void(0)">所有文章</a>
<a q-on="click: openSlider(e, 'friends')" href="javascript:void(0)">友链</a>
<a q-on="click: openSlider(e, 'aboutme')" href="javascript:void(0)">关于我</a>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" href="#" title="GitHub" target="_blank"><i class="icon-github"></i></a>
<a class="gitee" href="#" title="gitee" target="_blank"><i class="icon-gitee"></i></a>
<a class="jianshu" href="#" title="jianshu" target="_blank"><i class="icon-jianshu"></i></a>
<a class="cnblog" href="#" title="cnblog" target="_blank"><i class="icon-cnblog"></i></a>
</div>
</nav>
</header>
</div>
</div>
<div class="mid-col" q-class="show:isShow,hide:isShow|isFalse">
<nav id="mobile-nav">
<div class="overlay js-overlay" style="background: #4d4d4d"></div>
<div class="btnctn js-mobile-btnctn">
<div class="slider-trigger list" q-on="click: openSlider(e)"><i class="icon icon-sort"></i></div>
</div>
<div class="intrude-less">
<header id="header" class="inner">
<div class="profilepic">
<a href="/zhaiGuang/">
<img src="/zhaiGuang/img/Head.jpeg" class="js-avatar">
</a>
</div>
<hgroup>
<h1 class="header-author js-header-author">前端圈</h1>
</hgroup>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="#" title="GitHub"><i class="icon-github"></i></a>
<a class="gitee" target="_blank" href="#" title="gitee"><i class="icon-gitee"></i></a>
<a class="jianshu" target="_blank" href="#" title="jianshu"><i class="icon-jianshu"></i></a>
<a class="cnblog" target="_blank" href="#" title="cnblog"><i class="icon-cnblog"></i></a>
</div>
</nav>
<nav class="header-menu js-header-menu">
<ul style="width: 70%">
<li style="width: 33.333333333333336%"><a href="/zhaiGuang/">主页</a></li>
<li style="width: 33.333333333333336%"><a href="https://www.toutiao.com/c/user/51181806849/#mid=1571432089459714" target="_blank" rel="noopener">技术笔记</a></li>
<li style="width: 33.333333333333336%"><a href="/zhaiGuang/tags/%E9%9A%8F%E7%AC%94/">随笔</a></li>
</ul>
</nav>
</header>
</div>
<div class="mobile-mask" style="display:none" q-show="isShow"></div>
</nav>
<div id="wrapper" class="body-wrap">
<div class="menu-l">
<div class="canvas-wrap">
<canvas data-colors="#eaeaea" data-sectionHeight="100" data-contentId="js-content" id="myCanvas1"
class="anm-canvas"></canvas>
</div>
<div id="js-content" class="content-ll">
<article id="post-gitwebp" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2020/10/10/gitwebp/" target="_blank">apng、webp适用性调研与兼容性方案</a>
</h1>
<a href="/zhaiGuang/2020/10/10/gitwebp/" class="archive-article-date">
<time datetime="2020-10-10T09:27:46.646Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-10-10</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="apng、webp适用性调研与兼容性方案"><a href="#apng、webp适用性调研与兼容性方案" class="headerlink" title="apng、webp适用性调研与兼容性方案"></a>apng、webp适用性调研与兼容性方案</h2><h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><p>业务中大量使用gif动态图,动画不细腻,体积大,占用不必要的带宽,根据这几点,寻找能替代gif图的方案(动画流程,体积小)</p>
<h3 id="动态图类型"><a href="#动态图类型" class="headerlink" title="动态图类型"></a>动态图类型</h3><h4 id="GIF"><a href="#GIF" class="headerlink" title="GIF"></a>GIF</h4><p>GIF 是一个非常古老的格式,1987 年诞生,最后一个版本是 1989 年。(这就是为什么 GIF 文件头的 magic number 是 GIF89a)</p>
<p><strong>颜色</strong></p>
<p>GIF 每个像素只有 8 bit,也就是说只有 256 种颜色,于是很多人误以为 GIF 不支持 24 bit RGB,但实际上,GIF 的限制是每一帧最多只能有 256 种颜色,但是每种颜色可以是 24 bit 的。不过即使是这样,256 种颜色还是太少了,这就导致了 GIF 的画质都比较差。</p>
<p>而 APNG 和 WebP 则完全没有这方面的限制。</p>
<p><strong>透明</strong></p>
<p>GIF 虽然也支持透明,但不支持半透明,只支持完全透明或者完全不透明。如果把一个边缘是半透明的图片转换成 GIF,就会出现杂边问题。</p>
<p><strong>兼容性</strong></p>
<p>是唯一GIF的优势了,几乎所有浏览器都支持GIF</p>
<hr>
<h4 id="APNG"><a href="#APNG" class="headerlink" title="APNG"></a>APNG</h4><p><strong>APNG是什么</strong></p>
<p>APNG 是什么?相对于 GIF 有哪些优势?APNG 是一个基于 PNG 格式的位图动画格式图片,因为对于一直以来的特点就是以动态显示为主的 GIF,为了更好地在网络上传播,它需要牺牲质量来降低体积,图像信息比较多的情况下,颗粒感很明显。APNG 是普通 png 图片的升级版,它的后缀依然是.png,包含动态的情况下体积会比普通静态 png 打出数倍,可以做到无损的情况展示动态。其诞生的目的是为了替代老旧的 GIF 格式,但它目前并没有获得 PNG 组织官方的认可。</p>
<p><strong>APNG应用场景</strong></p>
<p><img src="/zhaiGuang/2020/10/10/gitwebp/1601351760565.png" alt="Alt text"></p>
<p><a href="http://littlesvr.ca/apng/gif_vs_apng.html" target="_blank" rel="noopener">GIF VS APNG</a></p>
<p><strong>兼容性</strong><br><img src="/zhaiGuang/2020/10/10/gitwebp/1601351344820.png" alt="Alt text"></p>
<p><a href="https://caniuse.com/?search=APNG" target="_blank" rel="noopener">详情兼容情况</a><br>对于 APNG 而言,支持的浏览器只有 Firefox 和 Safari,同时 Chrome 59 也将支持 APNG,</p>
<p><strong>对比</strong></p>
<p>GIF:</p>
<p>最多支持 8 位 256 色,色阶过渡糟糕,图片具有颗粒感<br>不支持 Alpha 透明通道,边缘有杂边<br>APNG:</p>
<p>支持 24 位真彩色图片<br>支持 8 位 Alpha 透明通道<br>向下兼容 PNG</p>
<p><strong>缺点</strong></p>
<ul>
<li>很难被标准化</li>
<li>生成比较繁琐(特殊处理才能比原有GIF图体积大,在压缩上并没有webp效果好,参考动效输出:用APNG代替GIF完美输出动态效果)</li>
</ul>
<hr>
<h5 id="WEBP"><a href="#WEBP" class="headerlink" title="WEBP"></a>WEBP</h5><p>先放一个 WebP 转换的示例链接,可以直观感受 WebP 在图片大小上的优势。</p>
<p><a href="https://www.upyun.com/webp" target="_blank" rel="noopener">DEMO地址</a></p>
<p>WebP,是一种同时提供了有损压缩与无损压缩的图片文件格式,派生自视频编码格式 VP8。WebP 最初在2010年发布,目标是减少文件大小,但达到 和 JEPG 格式相同的图片质量,希望能够减少图片档在网络上的发送时间</p>
<p><strong>同等质量但是图片更小</strong></p>
<p><a href="https://res.cloudinary.com/demo/image/upload/bored_animation.gif" target="_blank" rel="noopener">GIF图</a></p>
<p><a href="https://res.cloudinary.com/demo/image/upload/fl_awebp/bored_animation.webp" target="_blank" rel="noopener">webp</a></p>
<p>从动画GIF切换到动画WebP的结果令人印象深刻-在上面显示的示例中,图像大小和带宽减少了65-90%,并且具有相同的视觉效果。尽管WebP仅由少数浏览器使用,但是最新版本的Chrome变得越来越流行,因此WebP的重要性正在上升。</p>
<p>此外,如果将原始的高质量视频转换为WebP(而不仅仅是像我们在上面的示例中那样从GIF转换为WebP),则与WebP格式的全彩色支持相比,您将获得更好的视觉效果动画(GIF中最多只能显示256种颜色。)</p>
<p><strong>压缩之后质量无明显变化</strong><br>JPEG 格式的图片在质量较低时会有明显的缺陷,尤其是当图片包含微小的细节或文本时,但 WebP 格式则没有明显的缺陷,但也会在低质量设置时产生稍微模糊的图像</p>
<p><strong>完美支持无损图像</strong><br>WebP 同样支持一如 PNG 格式的无损模式,想要生成无损的 WebP 文件,只需将「quality」变量设置为 100</p>
<p><strong>支持动态图(Animated WebP)</strong></p>
<p>兼容性不是很乐观</p>
<p>苹果的Safari浏览器及其iOS Safari浏览器将在Safari 14和iOS 14(预计于2020年9月发布)中都具有WebP支持</p>
<p><strong>缺点:浏览器兼容性</strong></p>
<p>在洋葱学院APP中存在了兼容问题:<br>1.安卓暂时未发现不兼容问题<br>2.ios 系统存在版本兼容问题(12.x系统上就存在了不兼容情况)</p>
<p><strong>兼容场景:</strong></p>
<p><a href="https://caniuse.com/?search=Webp" target="_blank" rel="noopener">WEBP兼容地址</a><br><a href="https://caniuse.com/?search=picture" target="_blank" rel="noopener">picture兼容地址</a></p>
<ul>
<li>解决兼容:</li>
<li>七牛提供了高级图像处理的功能</li>
<li>通过URL后拼接参数,能把gif图处理成webp</li>
<li>1.安卓下七牛CDN借用高级图像处理功能form成webp(IOS维持GIF图原样)</li>
<li>2.JS判断是否支持webp如果支持,把gif图通过七牛处理成webp动态图,不支持维持原样。</li>
<li>HTML5标签 picture,是一套精简的兼容方案,浏览器兼容可通过此标签来展示对应的图片</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><picture></span><br><span class="line"> <source srcset="https://dn-odum9helk.qbox.me/test.gif?imageMogr2/thumbnail/100x|imageMogr2/format/webp" type="image/webp" /></span><br><span class="line"> <img src="https://dn-odum9helk.qbox.me/test.gif?imageMogr2/thumbnail/100x" alt="MDN" /></span><br><span class="line"></picture></span><br></pre></td></tr></table></figure>
<p><strong>应该用webp嘛?</strong></p>
<p>由于WebP在全球范围内的支持率徘徊在80%左右,因此使用此图像格式替代PNG和JPEG在很大程度上很有意义。需要特别注意的是,无论如何实现WebP,您都只是向支持WebP的浏览器提供WebP图像,然后将默认格式(如PNG和JPEG)提供给其他浏览器。使用WebP不会破坏图像。可以将其视为增加而不是更改。与PNG和JPEG相比,还需要考虑其他一些因素,例如浏览器市场份额,当前流量和WebP文件大小。</p>
<hr>
<p><strong>参考文章:</strong></p>
<p><a href="https://dreampiggy.com/2017/03/06/%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%B8%8A%E5%8A%A8%E6%80%81%E5%9B%BE%E6%A0%BC%E5%BC%8F%E5%AF%B9%E6%AF%94%E5%92%8C%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88/" target="_blank" rel="noopener">客户端上动态图格式对比</a></p>
<p><a href="https://cloudinary.com/blog/animated_webp_how_to_convert_animated_gif_to_webp_and_save_up_to_90_bandwidth" target="_blank" rel="noopener">Animated WebP - how to convert animated GIF to WebP and save up to 90% bandwidth</a></p>
<p><a href="https://www.zcool.com.cn/work/ZMjgyNjA2NjQ=.html" target="_blank" rel="noopener">动效输出:用APNG代替GIF完美输出动态效果</a></p>
<p><a href="https://aotu.io/notes/2016/11/07/apng/index.html" target="_blank" rel="noopener">APNG的那些事</a></p>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2020/10/10/gitwebp/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="post-whyJiaoShoujia" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2020/08/07/whyJiaoShoujia/" target="_blank">什么是前端脚手架?</a>
</h1>
<a href="/zhaiGuang/2020/08/07/whyJiaoShoujia/" class="archive-article-date">
<time datetime="2020-08-07T08:03:49.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-08-07</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h3 id="先查查百度百科里对“脚手架”的定义吧"><a href="#先查查百度百科里对“脚手架”的定义吧" class="headerlink" title="先查查百度百科里对“脚手架”的定义吧"></a>先查查百度百科里对“脚手架”的定义吧</h3><p>脚手架是为了保证各施工过程顺利进行而搭设的工作平台,生活中也就是我们要借用折叠梯去完成一些生活所需,这个折叠梯就给我带来很大的方便,并且搭建方便,可以称之为脚手架!</p>
<p>个人觉得“脚手架”只是一个宽泛的概念,只是一个或者一套“搭建工具”的总称,这些工具能够帮助你更好的去完成前端代码构建。</p>
<p>传统中我们写前端代码并不需要所谓的脚手架,一个 html 加上 css 和 js,再搭配编辑器就可以开始撸代码了。</p>
<p>但是随着 web2.0 的发展,页面越来越丰富,尤其是一些大型的、页面数据交互比较复杂的网站,为了优化前端工作,诞生了很多工具。比如让你写 css 更方便的 less,比如当下流行的用将 html 模板直接用 js 来写的 React,以及实现 js 模块化以及前端代码打包的工具 webpack。</p>
<p>总结的话就是</p>
<p>脚手架是帮你减少「为减少重复性工作而做的重复性工作」的工具</p>
<h3 id="比较稳定且出彩的前端脚手架有以下几种"><a href="#比较稳定且出彩的前端脚手架有以下几种" class="headerlink" title="比较稳定且出彩的前端脚手架有以下几种"></a>比较稳定且出彩的前端脚手架有以下几种</h3><ul>
<li><p>Vue/React 脚手架</p>
</li>
<li><p>使用 Node、yeoman 打造自己的脚手架</p>
</li>
<li><p>从零搭建 webpack 脚手架</p>
</li>
</ul>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2020/08/07/whyJiaoShoujia/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="post-git-cz" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2020/07/29/git-cz/" target="_blank">git-cz</a>
</h1>
<a href="/zhaiGuang/2020/07/29/git-cz/" class="archive-article-date">
<time datetime="2020-07-29T08:30:54.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2020-07-29</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h2 id="git-cz-一款git-commit-规范统一工具"><a href="#git-cz-一款git-commit-规范统一工具" class="headerlink" title="git-cz 一款git commit 规范统一工具"></a>git-cz 一款git commit 规范统一工具</h2><p><img src="/zhaiGuang/2020/07/29/git-cz/git-cz.png" alt="git-cz"></p>
<p> 简而言之,git commit 就是你在做一次修改后类似于写一个备注,现在安装了commitizen后,你可以使用git cz取代git commit,每次提交的时候可以选择本次commit的类型,这样commit的文本会更具有可读性。</p>
<h4 id="全局安装"><a href="#全局安装" class="headerlink" title="全局安装"></a>全局安装</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g git-cz</span><br><span class="line">git-cz</span><br></pre></td></tr></table></figure>
<h4 id="与Commitizen在本地安装"><a href="#与Commitizen在本地安装" class="headerlink" title="与Commitizen在本地安装"></a>与Commitizen在本地安装</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm install -g commitizen</span><br><span class="line">npm install --save-dev git-cz</span><br></pre></td></tr></table></figure>
<blockquote>
<p>package.json:</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> "config": {</span><br><span class="line"> "commitizen": {</span><br><span class="line"> "path": "git-cz"</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><strong>run</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cz</span><br></pre></td></tr></table></figure>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<i class="icon-price-tags icon"></i>
<ul class="article-tag-list">
<li class="article-tag-list-item">
<a href="javascript:void(0)" class="js-tag article-tag-list-link color5">github git-cz 命令行工具</a>
</li>
</ul>
</div>
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2020/07/29/git-cz/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="post-类数组对象" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2019/02/15/%E7%B1%BB%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1/" target="_blank">类数组对象</a>
</h1>
<a href="/zhaiGuang/2019/02/15/%E7%B1%BB%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1/" class="archive-article-date">
<time datetime="2019-02-15T04:17:08.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2019-02-15</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="类数组对象"><a href="#类数组对象" class="headerlink" title="类数组对象"></a>类数组对象</h1><p><strong>故事要从一行代码说起</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">arr[0]</span><br><span class="line">// 'tom'</span><br></pre></td></tr></table></figure>
<p>请问这里的 arr 一定是一个数组吗?非也,它也可能是一个对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">let arr = {</span><br><span class="line"> 0: 'tom'</span><br><span class="line">}</span><br><span class="line">arr[0]</span><br><span class="line">// 'tom'</span><br></pre></td></tr></table></figure>
<p>前面我们讲过 <strong>arguments</strong> 这个对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let say = function (){</span><br><span class="line"> console.log(arguments)</span><br><span class="line">}</span><br><span class="line">say(1,2)</span><br></pre></td></tr></table></figure>
<p>其大致结构如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0: 1</span><br><span class="line">1: 2</span><br><span class="line">length: 2</span><br></pre></td></tr></table></figure>
<p>我们称 arguments 为类数组对象,正是因为它有这个 length 属性,虽然不能用数组的方法,但是可以通过索引来访问,而且还可以将其转换成数组。</p>
<p>如果一个普通的对象加上一个 length 属性就可以变成一个类数组对象。</p>
<p>之所以今天要讲这个类数组对象,是因为 JavaScirpt 中有很多方法和处理跟类数组对象有关系,所以我们有必要搞清楚这个概念。</p>
<h3 id="转换"><a href="#转换" class="headerlink" title="转换"></a>转换</h3><p>ES6 的 Array.from() 可以将一个类数组对象转成数组</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">let say = function () {</span><br><span class="line"> console.log(Array.from(arguments))</span><br><span class="line">}</span><br><span class="line">say(1, 2)</span><br><span class="line">// [1, 2]</span><br></pre></td></tr></table></figure>
<p>当然也可以用 ES5 的 slice</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Array.prototype.slice.call(arguments)</span><br></pre></td></tr></table></figure>
<p>接下来我们自己起来创建一个类数组对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom", "lucy"]</span><br></pre></td></tr></table></figure>
<p>如果 length 值和实际元素不相等呢?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom", undefined]</span><br></pre></td></tr></table></figure>
<p>可以看到,如果 length 值大于实际元素的数量,不足的将用 undefined 填充,那么反过来呢?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 1</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom"]</span><br></pre></td></tr></table></figure>
<p>可见,length 值是决定最终生成数组的长度的,多余的去掉,不足的用 undefined 补齐。好奇心驱使我们继续探索,0 和 1 这两个索引真的有用吗?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mans = {</span><br><span class="line"> 3: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// [undefined, "lucy"]</span><br></pre></td></tr></table></figure>
<p>所以,这个值是真的有用的,决定了最终的填充索引。细心的同学可能会记得,还有另外一个转换 arguments 的方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[...arguments]</span><br></pre></td></tr></table></figure>
<p>那么这个展开运算符可以用到普通的类数组对象上吗?还是亲自测试一下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">};</span><br><span class="line">[...mans]</span><br><span class="line">// Uncaught TypeError: mans is not iterable</span><br></pre></td></tr></table></figure>
<p>可以看到报错了,mans 不是可迭代的,也就证实了 arguments 除了是类数组对象,还是一个可迭代对象,而我们自定义的对象并不具备可迭代功能,所以不能使用展开运算符。</p>
<h3 id="遍历"><a href="#遍历" class="headerlink" title="遍历"></a>遍历</h3><p>因为有 length 属性,所以我们可以用 for 循环进行遍历</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">};</span><br><span class="line">for (let i = 0; i < mans.length; i++) {</span><br><span class="line"> console.log(i)</span><br><span class="line">}</span><br><span class="line">// 0</span><br><span class="line">// 1</span><br></pre></td></tr></table></figure>
<p>除了传统的 for 循环,其它遍历方法可以使用吗?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mans.forEach(item => {</span><br><span class="line"> console.log(item)</span><br><span class="line">})</span><br><span class="line">// mans.forEach is not a function</span><br></pre></td></tr></table></figure>
<p>因为 forEach 是数组的一个方法,只能用于数组,自然就不能用在类数组对象身上了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for (let man of mans) {</span><br><span class="line"> console.log(man)</span><br><span class="line">}</span><br><span class="line">// mans is not iterable</span><br></pre></td></tr></table></figure>
<p>因为 for…of 也是需要应用到可迭代对象上的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">for (let index in mans) {</span><br><span class="line"> console.log(index)</span><br><span class="line">}</span><br><span class="line">// 0</span><br><span class="line">// 1</span><br></pre></td></tr></table></figure>
<p>所以只有 for 和 for…in 可以用来遍历类数组对象。</p>
<p>检测</p>
<p>除了 arguments,DOM 元素节点集合也是一个类数组对象,打开任意一个网页,F12 输入下面的代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">document.getElementsByTagName('div')</span><br></pre></td></tr></table></figure>
<p>可以看到里面有 length 属性,的确是类数组的结构,Array 也有 length 属性,难道这就不会是一个真的数组吗?</p>
<p>倒也是,这个时候就需要利用我们前面讲过的检测数组的方法了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object.prototype.toString.call(document.getElementsByTagName('div'))</span><br><span class="line">// [object HTMLCollection]</span><br></pre></td></tr></table></figure>
<p>可以看到这确实不是一个数组。</p>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2019/02/15/%E7%B1%BB%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="post-TCP三次握手与四次握手" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2019/02/15/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E4%B8%8E%E5%9B%9B%E6%AC%A1%E6%8F%A1%E6%89%8B/" target="_blank">TCP三次握手与四次握手</a>
</h1>
<a href="/zhaiGuang/2019/02/15/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E4%B8%8E%E5%9B%9B%E6%AC%A1%E6%8F%A1%E6%89%8B/" class="archive-article-date">
<time datetime="2019-02-15T04:17:08.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2019-02-15</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<!-- toc -->
<h2 id="TCP三次握手与四次握手"><a href="#TCP三次握手与四次握手" class="headerlink" title="TCP三次握手与四次握手"></a>TCP三次握手与四次握手</h2><h3 id="什么是三次握手?"><a href="#什么是三次握手?" class="headerlink" title="什么是三次握手?"></a>什么是三次握手?</h3><p>所谓三次握手,是指建立一个TCP连接时,需要客户端和服务器总共发送3个包</p>
<p>三次握手的目的是建立可靠的通信信道,简单来说就是数据的发送与接收。</p>
<h4 id="为什么要三次握手?"><a href="#为什么要三次握手?" class="headerlink" title="为什么要三次握手?"></a>为什么要三次握手?</h4><p>三次握手最主要的目的就是双方确认自己与对方的发送与接收机能正常</p>
<p><strong>三次握手的过程</strong></p>
<ol>
<li>第一次握手:client什么都不能确认;server确认了对方发送正常</li>
<li>第二次握手:client确认了:自己发送,接收正常,对方发送,接收正常;server确认了:自己接收正常,对方发送正常</li>
<li>第三次握手:client确认了:自己发送,接收正常,对方发送,接收正常;server确认了:自己发送,接收正常,对方发送接收正常。</li>
</ol>
<p>所以三次握手,就能确认双方,收发功能都正常。</p>
<p>整个三次握手,其实就是为了验证彼此是否接收都正常</p>
<hr>
<h3 id="什么是四次挥手?"><a href="#什么是四次挥手?" class="headerlink" title="什么是四次挥手?"></a>什么是四次挥手?</h3><p>假设Client端发起中断连接请求,也就是发送FIN报文。</p>
<p>Server端接到FIN报文后,意思是说”我Client端没有数据要发给你了”,但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。</p>
<p>所以你先发送ACK,”告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。</p>
<p>这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,”告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。</p>
<p>Client端收到FIN报文后,”就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,”就知道可以断开连接了”。</p>
<p>Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!</p>
<h4 id="为什么要四次挥手?"><a href="#为什么要四次挥手?" class="headerlink" title="为什么要四次挥手?"></a>为什么要四次挥手?</h4><p>一方发送FIN只表示自己发完了所有要发的数据,但还允许对方继续把没发完的数据发过来。</p>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2019/02/15/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B%E4%B8%8E%E5%9B%9B%E6%AC%A1%E6%8F%A1%E6%89%8B/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="post-hello-world" class="article article-type-post article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2019/02/15/hello-world/" target="_blank">类数组对象</a>
</h1>
<a href="/zhaiGuang/2019/02/15/hello-world/" class="archive-article-date">
<time datetime="2019-02-15T04:17:08.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2019-02-15</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="类数组对象"><a href="#类数组对象" class="headerlink" title="类数组对象"></a>类数组对象</h1><p><strong>故事要从一行代码说起</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">arr[0]</span><br><span class="line">// 'tom'</span><br></pre></td></tr></table></figure>
<p>请问这里的 arr 一定是一个数组吗?非也,它也可能是一个对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">let arr = {</span><br><span class="line"> 0: 'tom'</span><br><span class="line">}</span><br><span class="line">arr[0]</span><br><span class="line">// 'tom'</span><br></pre></td></tr></table></figure>
<p>前面我们讲过 <strong>arguments</strong> 这个对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">let say = function (){</span><br><span class="line"> console.log(arguments)</span><br><span class="line">}</span><br><span class="line">say(1,2)</span><br></pre></td></tr></table></figure>
<p>其大致结构如下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">0: 1</span><br><span class="line">1: 2</span><br><span class="line">length: 2</span><br></pre></td></tr></table></figure>
<p>我们称 arguments 为类数组对象,正是因为它有这个 length 属性,虽然不能用数组的方法,但是可以通过索引来访问,而且还可以将其转换成数组。</p>
<p>如果一个普通的对象加上一个 length 属性就可以变成一个类数组对象。</p>
<p>之所以今天要讲这个类数组对象,是因为 JavaScirpt 中有很多方法和处理跟类数组对象有关系,所以我们有必要搞清楚这个概念。</p>
<h3 id="转换"><a href="#转换" class="headerlink" title="转换"></a>转换</h3><p>ES6 的 Array.from() 可以将一个类数组对象转成数组</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">let say = function () {</span><br><span class="line"> console.log(Array.from(arguments))</span><br><span class="line">}</span><br><span class="line">say(1, 2)</span><br><span class="line">// [1, 2]</span><br></pre></td></tr></table></figure>
<p>当然也可以用 ES5 的 slice</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Array.prototype.slice.call(arguments)</span><br></pre></td></tr></table></figure>
<p>接下来我们自己起来创建一个类数组对象</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom", "lucy"]</span><br></pre></td></tr></table></figure>
<p>如果 length 值和实际元素不相等呢?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom", undefined]</span><br></pre></td></tr></table></figure>
<p>可以看到,如果 length 值大于实际元素的数量,不足的将用 undefined 填充,那么反过来呢?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 1</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// ["tom"]</span><br></pre></td></tr></table></figure>
<p>可见,length 值是决定最终生成数组的长度的,多余的去掉,不足的用 undefined 补齐。好奇心驱使我们继续探索,0 和 1 这两个索引真的有用吗?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mans = {</span><br><span class="line"> 3: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">}</span><br><span class="line">Array.from(mans)</span><br><span class="line">// [undefined, "lucy"]</span><br></pre></td></tr></table></figure>
<p>所以,这个值是真的有用的,决定了最终的填充索引。细心的同学可能会记得,还有另外一个转换 arguments 的方法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[...arguments]</span><br></pre></td></tr></table></figure>
<p>那么这个展开运算符可以用到普通的类数组对象上吗?还是亲自测试一下</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">};</span><br><span class="line">[...mans]</span><br><span class="line">// Uncaught TypeError: mans is not iterable</span><br></pre></td></tr></table></figure>
<p>可以看到报错了,mans 不是可迭代的,也就证实了 arguments 除了是类数组对象,还是一个可迭代对象,而我们自定义的对象并不具备可迭代功能,所以不能使用展开运算符。</p>
<h3 id="遍历"><a href="#遍历" class="headerlink" title="遍历"></a>遍历</h3><p>因为有 length 属性,所以我们可以用 for 循环进行遍历</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">let mans = {</span><br><span class="line"> 0: 'tom',</span><br><span class="line"> 1: 'lucy',</span><br><span class="line"> length: 2</span><br><span class="line">};</span><br><span class="line">for (let i = 0; i < mans.length; i++) {</span><br><span class="line"> console.log(i)</span><br><span class="line">}</span><br><span class="line">// 0</span><br><span class="line">// 1</span><br></pre></td></tr></table></figure>
<p>除了传统的 for 循环,其它遍历方法可以使用吗?</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mans.forEach(item => {</span><br><span class="line"> console.log(item)</span><br><span class="line">})</span><br><span class="line">// mans.forEach is not a function</span><br></pre></td></tr></table></figure>
<p>因为 forEach 是数组的一个方法,只能用于数组,自然就不能用在类数组对象身上了。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for (let man of mans) {</span><br><span class="line"> console.log(man)</span><br><span class="line">}</span><br><span class="line">// mans is not iterable</span><br></pre></td></tr></table></figure>
<p>因为 for…of 也是需要应用到可迭代对象上的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">for (let index in mans) {</span><br><span class="line"> console.log(index)</span><br><span class="line">}</span><br><span class="line">// 0</span><br><span class="line">// 1</span><br></pre></td></tr></table></figure>
<p>所以只有 for 和 for…in 可以用来遍历类数组对象。</p>
<p>检测</p>
<p>除了 arguments,DOM 元素节点集合也是一个类数组对象,打开任意一个网页,F12 输入下面的代码</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">document.getElementsByTagName('div')</span><br></pre></td></tr></table></figure>
<p>可以看到里面有 length 属性,的确是类数组的结构,Array 也有 length 属性,难道这就不会是一个真的数组吗?</p>
<p>倒也是,这个时候就需要利用我们前面讲过的检测数组的方法了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Object.prototype.toString.call(document.getElementsByTagName('div'))</span><br><span class="line">// [object HTMLCollection]</span><br></pre></td></tr></table></figure>
<p>可以看到这确实不是一个数组。</p>
</div>
<div class="article-info article-info-index">
<p class="article-more-link">
<a class="article-more-a" href="/zhaiGuang/2019/02/15/hello-world/">展开全文 >></a>
</p>
<div class="clearfix"></div>
</div>
</div>
</article>
<aside class="wrap-side-operation">
<div class="mod-side-operation">
<div class="jump-container" id="js-jump-container" style="display:none;">
<a href="javascript:void(0)" class="mod-side-operation__jump-to-top">
<i class="icon-font icon-back"></i>
</a>
<div id="js-jump-plan-container" class="jump-plan-container" style="top: -11px;">
<i class="icon-font icon-plane jump-plane"></i>
</div>
</div>
</div>
</aside>
<article id="[layout]-node面试" class="article article-type-[layout] article-index" itemscope itemprop="blogPost">
<div class="article-inner">
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/zhaiGuang/2018/12/17/node%E9%9D%A2%E8%AF%95/" target="_blank">node面试</a>
</h1>
<a href="/zhaiGuang/2018/12/17/node%E9%9D%A2%E8%AF%95/" class="archive-article-date">
<time datetime="2018-12-17T06:29:12.000Z" itemprop="datePublished"><i class="icon-calendar icon"></i>2018-12-17</time>
</a>
</header>
<div class="article-entry" itemprop="articleBody">
<h3 id="nodeJS常见问题"><a href="#nodeJS常见问题" class="headerlink" title="nodeJS常见问题"></a>nodeJS常见问题</h3><!-- toc -->
<ul>
<li>node的特点<ul>
<li>异步IO</li>
<li>单线程</li>
<li>跨平台</li>
<li>前后端编程语言的统一</li>
<li>工具类应用</li>
</ul>
</li>
<li>单线程的缺点<ul>
<li>无法利用多核CPU</li>
<li>错误会引起整个应用的退出</li>
<li>大量计算占用CPU无法继续调用异步IO</li>
<li>解决方案:<ul>
<li>node提供了子进程的概念</li>
</ul>
</li>
</ul>
</li>
<li>对于javascript自身而言,它的规范依然包若,还有以下的缺陷<ul>
<li>没有模块系统</li>
<li>标准库较少</li>
<li>没有标准接口</li>
<li>缺乏包管理系统</li>
</ul>
</li>
</ul>
<hr>
<h3 id="为什么javaScript是单线程"><a href="#为什么javaScript是单线程" class="headerlink" title="为什么javaScript是单线程"></a>为什么javaScript是单线程</h3><blockquote>
<p>js语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。<br>javascript的单线程,与他的用途有关,作为浏览器脚本语言,js的主要用途是用于交互,以及操作DOM元素。<br>这决定了他只能是单线程,否则,会带来很复杂的同步问题!<br>所以为了避免复杂性,js从一诞生,就是单线程,已经成了这门语言的核心特征。</p>
</blockquote>
<h3 id="EventLoop"><a href="#EventLoop" class="headerlink" title="EventLoop"></a>EventLoop</h3><p>主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。</p>
<h3 id="Libuv"><a href="#Libuv" class="headerlink" title="Libuv"></a>Libuv</h3><p>什么是Libuv?Libuv是一个高性能的,事件驱动的I/O库,并且提供了 跨平台(如windows, nix)的API。简单的来说:<br><strong>Node.js的异步、非阻塞I/O,底层实际上是Libuv实现的</strong>。</p>
<h3 id="Node-的模块实现"><a href="#Node-的模块实现" class="headerlink" title="Node 的模块实现"></a>Node 的模块实现</h3><pre><code>Node在实现中并非完全按照实现,尽管规范中 exports,require和module 听起来十分简单,但是node在实现他们的过程中经历了。</code></pre><ul>
<li>在node中引入模块,需要经历如下3个步骤<ul>
<li>路径分析</li>
<li>文件定位</li>
<li>编译执行</li>
</ul>
</li>
<li>在node中,模块分为两类:一类是node提供的模块,称为核心模块;</li>
<li>另一类是用户编写的模块,称为文件模块</li>
<li>简洁以下 以上的问题<ul>
<li>核心模块(node自身的)</li>
<li>文件模块</li>
</ul>
</li>
</ul>
<p><strong>node 的模块会优先从缓存加载</strong></p>
<h4 id="NODE-js的运行机制"><a href="#NODE-js的运行机制" class="headerlink" title="NODE.js的运行机制"></a>NODE.js的运行机制</h4><ul>
<li>V8引擎解析Javascript脚本</li>
<li>解析后的代码,调用NODE API</li>
<li>libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。</li>
<li>V8引擎再将结果返回</li>
</ul>
<hr>
<h3 id="模块编译过程总结"><a href="#模块编译过程总结" class="headerlink" title="模块编译过程总结"></a>模块编译过程总结</h3><p><strong>核心模块编译过程中经过了头尾包装的过程</strong><br>有些模块是C++来编写,有些则是由C++完成核心部分,其他部分择优javascript实现包装或向外导出。</p>
<h4 id="内建模块的优势"><a href="#内建模块的优势" class="headerlink" title="内建模块的优势"></a>内建模块的优势</h4><ul>
<li>本身是由C/C++编写,性能上高于脚本语言</li>
<li>在文件被编译时,它被编译成二进制文件,一旦node执行,在直接被加载进内存中。</li>
</ul>
<h4 id="前后端模块的侧重点"><a href="#前后端模块的侧重点" class="headerlink" title="前后端模块的侧重点"></a>前后端模块的侧重点</h4><p><img src="evernotecid://EBC06249-D6A1-4732-BCC4-49915E428FC6/appyinxiangcom/12846741/ENResource/p188" alt="12078c89e5b5ad49eced67b3452b58fe.png"></p>
<p>前后端javascript分别搁置在HTTP的两端,它们扮演的角色并不同。浏览器端的Javascript需要经历从同一个服务器端分发到多个客户端执行,而服务端的javascript则是相同的代码多次执行,前者的瓶颈在于带宽,后者的瓶颈在于CPU和内存等资源。<br>前者需要通过网络加载代码,后者从磁盘中加载,两者的加载不在一个数量级上。</p>
<h3 id="异步IO小结"><a href="#异步IO小结" class="headerlink" title="异步IO小结"></a>异步IO小结</h3><p>从前面实现的异步IO过程描述中,我们可以提取出几个异步IO的关键字</p>
<ul>
<li>单线程</li>
<li>事件循环</li>
<li>观察者</li>
<li>IO线程池</li>
</ul>
<blockquote>
<p>在node中,除了JavaScript是单线程外,node自身其实是多线程<br>除了用户的代码无法并行执行外,所有的IO操作则是可以并行起来的</p>
</blockquote>
<h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p> 时间循环是异步实现的核心,它与浏览器中的执行模型基本保持了一致。</p>
<h3 id="NODE与v8"><a href="#NODE与v8" class="headerlink" title="NODE与v8"></a>NODE与v8</h3><p><img src="evernotecid://EBC06249-D6A1-4732-BCC4-49915E428FC6/appyinxiangcom/12846741/ENResource/p191" alt="5fcce6df68995159091d4b840a6c6d6b.png"></p>
<h4 id="v8的内存限制"><a href="#v8的内存限制" class="headerlink" title="v8的内存限制"></a>v8的内存限制</h4><ul>
<li>在node中通过javascript使用内存时,只能使用部分内存</li>
<li>64位操作系统 1.4GB</li>
<li>32位操作系统0.7gb</li>
<li>这导致node无法直接操作大内存对象</li>
<li>node在启动时,可以打开内存限制</li>
</ul>
<h3 id="网络编程"><a href="#网络编程" class="headerlink" title="网络编程"></a>网络编程</h3><blockquote>
<p>NODE提供了net,dgram,http,https 着4个模块,分别用于处理TCP,UDP,HTTP,HTTPS适用于服务端和客户端</p>
</blockquote>
<h4 id="TCP"><a href="#TCP" class="headerlink" title="TCP"></a>TCP</h4><p>TCP名为<strong>传输控制协议</strong>,在OSI模型(由七层组成,物理层,数据链结层,网络层,传输层,会话层,表示层,应用层)</p>
<p><img src="evernotecid://EBC06249-D6A1-4732-BCC4-49915E428FC6/appyinxiangcom/12846741/ENResource/p192" alt="58ef920c8d2d629beb347082b2913158.png"></p>
<p>TCP是面向连接的协议,最显著地特征就是需要<strong>三次握手</strong>形成会话,只有会话形成后,服务端与客户端才能进行互相的发送数据</p>
<h3 id="内存泄漏"><a href="#内存泄漏" class="headerlink" title="内存泄漏"></a>内存泄漏</h3><ul>
<li>用户服务异常</li>
<li>进程异常</li>
<li>服务器性能异常</li>
</ul>
<h3 id="事物(ACID)"><a href="#事物(ACID)" class="headerlink" title="事物(ACID)"></a>事物(ACID)</h3><h4 id="数据库事物的四大特性"><a href="#数据库事物的四大特性" class="headerlink" title="数据库事物的四大特性"></a>数据库事物的四大特性</h4><ul>
<li>原子性 atomicity<ul>
<li>原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。</li>