-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
3725 lines (3325 loc) · 791 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>散列表(哈希表)的实现</title>
<url>/2019/11/09/alorigam/hash-js/</url>
<content><![CDATA[<h2 id="HashMap"><a href="#HashMap" class="headerlink" title="HashMap"></a>HashMap</h2><p>在真实世界中,我们描述一个事物最常用的方式是使用属性-值(key-value)这样的键值对数据,面向对象编程中对象的定义和js中的对象都是这种模式。比如我们描述一个人是这样的:</p>
<p><img src="http://note.youdao.com/yws/res/16157/C4787981899847E4A1F742927AD7D3DD" alt="image"></p>
<h3 id="那在计算机中怎么保存这样的数据呢?"><a href="#那在计算机中怎么保存这样的数据呢?" class="headerlink" title="那在计算机中怎么保存这样的数据呢?"></a>那在计算机中怎么保存这样的数据呢?</h3><p>开数组存储,并把键名和数组下标按一定程度联系起来,以用特定的码表(如ASCII)进行转换。变换下面这样</p>
<p><img src="http://note.youdao.com/yws/res/16170/F9F56E8A0D5E4CE18DDB60DA27257614" alt="image"></p>
<p>若依照上图,开一个10010长度的数组,全部容纳此对象,则就可以实现查找一遍得出值的目的。</p>
<p>但由于键名长度不一,所以转换后的下标的值也相差巨大,个数不确定,也就意味着下标的个数也有很大的范围,甚至无穷多,就有了下面的问题:</p>
<ul>
<li>怎么将一组值相差范围巨大,个数波动范围很大的下标放入特定的数组空间呢?</li>
<li>如何处理下标冲突呢?</li>
</ul>
<h3 id="怎么将一组值相差范围巨大,个数波动范围很大的下标放入特定的数组空间呢?"><a href="#怎么将一组值相差范围巨大,个数波动范围很大的下标放入特定的数组空间呢?" class="headerlink" title="怎么将一组值相差范围巨大,个数波动范围很大的下标放入特定的数组空间呢?"></a>怎么将一组值相差范围巨大,个数波动范围很大的下标放入特定的数组空间呢?</h3><p>若直接取键名的所有字母 Ascii 码来构建数组长度,则是一个极大的浪费,必须针对此数据进行处理,有三种方式</p>
<p>1,除法散列法。</p>
<p>最直观的一种,公式:index = key % 16。这样取得的下标参见下面的图</p>
<p><img src="http://note.youdao.com/yws/res/16201/D225FE8428D24DDC86049D574C9D35FF" alt="image"></p>
<p>2,平方散列法。</p>
<p>因为乘法的运算要比除法来得省时,所以我们考虑把除法换成乘法和一个位移操作。公式:index = (key * key) >> 28。</p>
<p>如果数值分配比较均匀的话这种方法能得到不错的结果,另外key如果很大,key * key会发生溢出。但我们这个乘法不关心溢出,因为我们根本不是为了获取相乘结果,而是为了获取index。</p>
<p>3,斐波那契(Fibonacci)散列法</p>
<p>平方散列法的缺点是显而易见的,所以我们能不能找出一个理想的乘数,而不是拿value本身当作乘数呢?答案是肯定的。</p>
<p>对于16位整数而言,这个乘数是40503,对于32位整数(JS中的Number是64位的,但在位操作时,会转化为32位整数处理,最后结果再转化位64位浮点数)而言,这个乘数是2654435769,对于64位整数而言,这个乘数是11400714819323198485</p>
<p>这几个“理想乘数”是如何得出来的呢?这跟一个法则有关,叫黄金分割法则,而描述黄金分割法则的最经典表达式无疑就是著名的斐波那契数列,即如此形式的序列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946,…。</p>
<p>对我们常见的32位整数而言,公式(>>>是JS的无符号右移操作,得到的都是整数):index = (key* 2654435769) >>> 28。32位移动28位,剩下只有4位,数值也就在0~15之间。</p>
<h3 id="如何处理冲突的下标"><a href="#如何处理冲突的下标" class="headerlink" title="如何处理冲突的下标"></a>如何处理冲突的下标</h3><p>还是上面这个例子,29和69发生了冲突,但是我们可以将他们组成一个链表,链表的头部放在数组中,得到。链表结构中,每个元素(除单向链表的尾部)都包含了相连元素的内存地址和本身的值,上文中的冲突放入一个链表中,可以得到这样的结构:</p>
<p><img src="http://note.youdao.com/yws/res/16207/8D1F626E65BE407B84413287BE6D2B4D" alt="image"></p>
<p>最终得到的这个数据结构,也就是我们常说哈希表了。这种将数组与链表结合生成哈希表的方法,叫拉链法。</p>
<p>此外还有其他策略如下</p>
<p>1)拉链法变种。由于链表的查找需要遍历,如果我们将链表换成树或者哈希表结构,那么就能大幅提高冲突元素的查找效率。不过这样做则会加大哈希表构造的复杂度,也就是构建哈希表时的效率会变差。</p>
<p>2)开放寻址: 当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi,将相应元素存入其中。这种方法有一个通用的函数形式:</p>
<p>Hi=(H(key)+di)% m i=1,2,…,n</p>
<p>根据di的不同,又可以分为线性的、平方的、随机数之类的。。。这里不再展开。</p>
<p>开发寻址的好处是存储空间更加紧凑,利用率高。但是这种方式让冲突元素之间产生了联系,在删除元素的时候,不能直接删除,否则就打乱了冲突元素的寻址链。</p>
<p>3)再哈希法</p>
<p>这种方法会预先定义一组哈希算法,发生冲突的时候,调用下一个哈希算法计算一直计算到不发生冲突的时候则插入元素,这种方法跟开放寻址的方法优缺点类似。函数表达式:</p>
<p>index=Hi(key) , i=1,2,…,n</p>
<h2 id="哈希表数据的查找"><a href="#哈希表数据的查找" class="headerlink" title="哈希表数据的查找"></a>哈希表数据的查找</h2><p>比如想知道小明的name属性,即小明.name。流程是这样的:</p>
<ol>
<li>根据字符映射关系(若使用简单除法散列)得到映射值为69</li>
<li>使用哈希算法得到下标 index=hash(69)=9</li>
<li>遍历数组中下标为9的链表,链表的第一个元素的key刚好就是我们要找的name,所以返回value值小明</li>
</ol>
<p>哈希表中增删一个元素并不会影响到其他的元素,不像数组一样需要改变后面所有的元素下标。在拉链式的哈希表中,属性的增删就是链表的增删,非常方便。而在纯数组形式的哈希表中,对属性的删并不是真的删除,而是做一个空标志而已,所以不影响其他元素。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 链表</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">LinkedList</span>(<span class="params"></span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> Node = <span class="function"><span class="keyword">function</span>(<span class="params">element</span>)</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>.element = element;</span><br><span class="line"> <span class="keyword">this</span>.next = <span class="literal">null</span>;</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> length = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">var</span> head = <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>.append = <span class="function"><span class="keyword">function</span>(<span class="params">element</span>)</span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> node = <span class="keyword">new</span> Node(element),</span><br><span class="line"> current;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (head === <span class="literal">null</span>){ <span class="comment">//first node on list</span></span><br><span class="line"> head = node;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"></span><br><span class="line"> current = head;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//loop the list until find last item</span></span><br><span class="line"> <span class="keyword">while</span>(current.next){</span><br><span class="line"> current = current.next;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//get last item and assign next to added item to make the link</span></span><br><span class="line"> current.next = node;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> length++; <span class="comment">//update size of list</span></span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">this</span>.insert = <span class="function"><span class="keyword">function</span>(<span class="params">position, element</span>)</span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">//check for out-of-bounds values</span></span><br><span class="line"> <span class="keyword">if</span> (position >= <span class="number">0</span> && position <= length){</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> node = <span class="keyword">new</span> Node(element),</span><br><span class="line"> current = head,</span><br><span class="line"> previous,</span><br><span class="line"> index = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (position === <span class="number">0</span>){ <span class="comment">//add on first position</span></span><br><span class="line"></span><br><span class="line"> node.next = current;</span><br><span class="line"> head = node;</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">while</span> (index++ <span class="xml"><span class="tag">< <span class="attr">position</span>){</span></span></span><br><span class="line"><span class="xml"> previous = current;</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> node.next = current;</span></span><br><span class="line"><span class="xml"> previous.next = node;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> length++; //update size of list</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> return true;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> } else {</span></span><br><span class="line"><span class="xml"> return false;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.removeAt = function(position){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //check for out-of-bounds values</span></span><br><span class="line"><span class="xml"> if (position > -1 && position <span class="tag">< <span class="attr">length</span>){</span></span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var current = head,</span></span><br><span class="line"><span class="xml"> previous,</span></span><br><span class="line"><span class="xml"> index = 0;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //removing first item</span></span><br><span class="line"><span class="xml"> if (position === 0){</span></span><br><span class="line"><span class="xml"> head = current.next;</span></span><br><span class="line"><span class="xml"> } else {</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> while (index++ <span class="tag">< <span class="attr">position</span>){</span></span></span><br><span class="line"></span><br><span class="line"><span class="xml"> previous = current;</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //link previous with current's next - skip it to remove</span></span><br><span class="line"><span class="xml"> previous.next = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> length--;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> return current.element;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> } else {</span></span><br><span class="line"><span class="xml"> return null;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.remove = function(element){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var index = this.indexOf(element);</span></span><br><span class="line"><span class="xml"> return this.removeAt(index);</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.indexOf = function(element){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var current = head,</span></span><br><span class="line"><span class="xml"> index = 0;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> while (current) {</span></span><br><span class="line"><span class="xml"> if (element === current.element) {</span></span><br><span class="line"><span class="xml"> return index;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> index++;</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> return -1;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.isEmpty = function() {</span></span><br><span class="line"><span class="xml"> return length === 0;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.size = function() {</span></span><br><span class="line"><span class="xml"> return length;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.getHead = function(){</span></span><br><span class="line"><span class="xml"> return head;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.toString = function(){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var current = head,</span></span><br><span class="line"><span class="xml"> string = '';</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> while (current) {</span></span><br><span class="line"><span class="xml"> string = current.element;</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return string;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.print = function(){</span></span><br><span class="line"><span class="xml"> console.log(this.toString());</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"><span class="xml">}</span></span><br><span class="line"></span><br><span class="line"><span class="xml">// hash map的实现</span></span><br><span class="line"><span class="xml">function HashTableSeparateChaining(){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var table = [];</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var ValuePair = function(key, value){</span></span><br><span class="line"><span class="xml"> this.key = key;</span></span><br><span class="line"><span class="xml"> this.value = value;</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.toString = function() {</span></span><br><span class="line"><span class="xml"> return '[' + this.key + ' - ' + this.value + ']';</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> // 散列函数-除法散列法,运算效率低,不够均匀分布。</span></span><br><span class="line"><span class="xml"> var getHashByDivision = function (key) {</span></span><br><span class="line"><span class="xml"> var hash = 0;</span></span><br><span class="line"><span class="xml"> for (var i = 0; i <span class="tag">< <span class="attr">key.length</span>; <span class="attr">i</span>++) {</span></span></span><br><span class="line"><span class="xml"> hash += key.charCodeAt(i);</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return hash % 16;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> // 散列函数-平方散列法,乘法运算效率稍微高,但还是不够均匀分布。</span></span><br><span class="line"><span class="xml"> var getHashBySquare = function (key) {</span></span><br><span class="line"><span class="xml"> var hash = 0;</span></span><br><span class="line"><span class="xml"> for (var i = 0; i <span class="tag">< <span class="attr">key.length</span>; <span class="attr">i</span>++) {</span></span></span><br><span class="line"><span class="xml"> hash += key.charCodeAt(i);</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return (hash * hash) >>> 28;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> // 散列函数-斐波那契(Fibonacci)散列法</span></span><br><span class="line"><span class="xml"> // 位操作时将会转换32位整数,再无符号右移28,结果只有4位,范围在0~15间</span></span><br><span class="line"><span class="xml"> var getHashBySquare = function (key) {</span></span><br><span class="line"><span class="xml"> var hash = 0;</span></span><br><span class="line"><span class="xml"> for (var i = 0; i <span class="tag">< <span class="attr">key.length</span>; <span class="attr">i</span>++) {</span></span></span><br><span class="line"><span class="xml"> hash += key.charCodeAt(i);</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return (hash * 2654435769) >>> 28;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var hashCode = function(key){</span></span><br><span class="line"><span class="xml"> return getHashBySquare(key);</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> // 拉链法,计算code得到重复position时,建立一个链表存放</span></span><br><span class="line"><span class="xml"> // 此实现仍有 bug,比如说无法更改 key-value 中的 value,因为只会在链表中append</span></span><br><span class="line"><span class="xml"> this.put = function(key, value){</span></span><br><span class="line"><span class="xml"> var position = hashCode(key);</span></span><br><span class="line"><span class="xml"> console.log(position + ' - ' + key);</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> if (table[position] == undefined) {</span></span><br><span class="line"><span class="xml"> table[position] = new LinkedList();</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> table[position].append(new ValuePair(key, value));</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.get = function(key) {</span></span><br><span class="line"><span class="xml"> var position = hashCode(key);</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> if (table[position] !== undefined && !table[position].isEmpty()){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //iterate linked list to find key/value</span></span><br><span class="line"><span class="xml"> var current = table[position].getHead();</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> while(current.next){</span></span><br><span class="line"><span class="xml"> if (current.element.key === key){</span></span><br><span class="line"><span class="xml"> return current.element.value;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //check in case first or last element</span></span><br><span class="line"><span class="xml"> if (current.element.key === key){</span></span><br><span class="line"><span class="xml"> return current.element.value;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return undefined;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.remove = function(key){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> var position = hashCode(key);</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> if (table[position] !== undefined){</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //iterate linked list to find key/value</span></span><br><span class="line"><span class="xml"> var current = table[position].getHead();</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> while(current.next){</span></span><br><span class="line"><span class="xml"> if (current.element.key === key){</span></span><br><span class="line"><span class="xml"> table[position].remove(current.element);</span></span><br><span class="line"><span class="xml"> if (table[position].isEmpty()){</span></span><br><span class="line"><span class="xml"> table[position] = undefined;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return true;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> current = current.next;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> //check in case first or last element</span></span><br><span class="line"><span class="xml"> if (current.element.key === key){</span></span><br><span class="line"><span class="xml"> table[position].remove(current.element);</span></span><br><span class="line"><span class="xml"> if (table[position].isEmpty()){</span></span><br><span class="line"><span class="xml"> table[position] = undefined;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> return true;</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> return false;</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"></span><br><span class="line"><span class="xml"> this.print = function() {</span></span><br><span class="line"><span class="xml"> for (var i = 0; i <span class="tag">< <span class="attr">table.length</span>; ++<span class="attr">i</span>) {</span></span></span><br><span class="line"><span class="xml"> if (table[i] !== undefined) {</span></span><br><span class="line"><span class="xml"> console.log(table[i].toString());</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> }</span></span><br><span class="line"><span class="xml"> };</span></span><br><span class="line"><span class="xml">}</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>alorigam</category>
</categories>
</entry>
<entry>
<title>模式匹配算法DFA与敏感词识别</title>
<url>/2019/11/08/alorigam/dfa/</url>
<content><![CDATA[<p>DFA(Deterministic Finite Automaton,即确定有穷自动机。其原理为:有一个有限状态集合和一些从一个状态通向另一个状态的边,每条边上标记有一个符号,其中一个状态是初态,某些状态是终态。但不同于不确定的有限自动机,DFA中不会有从同一状态出发的两条边标志有相同的符号。</p>
<p>举例有限状态机字典如下</p>
<img src=http://www.plantuml.com/plantuml/svg/qtZUrwsfe6kdeF6qTRKc5vW4Sr_CxaRcFjyt1SW5aH35QoTe0W00>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> '王': {</span><br><span class="line"> '八': {</span><br><span class="line"> '蛋': {</span><br><span class="line"> empty: true</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> '羔': {</span><br><span class="line"> '子': {</span><br><span class="line"> empty: true</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>输入为王八端时,逐字对比有限状态机的字典</p>
<ol>
<li>王字命中</li>
<li>八字命中</li>
<li>端没有命中,则返回八字继续开始匹配</li>
<li>八字没有命中有限状态机,over</li>
</ol>
<p>输入为王八蛋时</p>
<ol>
<li>王字命中</li>
<li>八字命中</li>
<li>蛋命中</li>
<li>下一个 empty 为 true 命中,匹配成功。</li>
</ol>
<h2 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h2><p>找出敏感词代码</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="meta">'use strict'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 特殊符号过滤逻辑</span></span><br><span class="line"><span class="keyword">const</span> ignoreChars = <span class="string">" \t\r\n~!@#$%^&*()_+-=【】、{}|;':\",。、《》?αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ。,、;:?!…—·ˉ¨‘’“”々~‖∶"'`|〃〔〕〈〉《》「」『』.〖〗【】()[]{}ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩①②③④⑤⑥⑦⑧⑨⑩⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇≈≡≠=≤≥<>≮≯∷±+-×÷/∫∮∝∞∧∨∑∏∪∩∈∵∴⊥∥∠⌒⊙≌∽√§№☆★○●◎◇◆□℃‰€■△▲※→←↑↓〓¤°#&@\︿_ ̄―♂♀┌┍┎┐┑┒┓─┄┈├┝┞┟┠┡┢┣│┆┊┬┭┮┯┰┱┲┳┼┽┾┿╀╁╂╃└┕┖┗┘┙┚┛━┅┉┤┥┦┧┨┩┪┫┃┇┋┴┵┶┷┸┹┺┻╋╊╉╈╇╆╅╄"</span>;</span><br><span class="line"><span class="keyword">const</span> ignoreObj = {};</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>, j = ignoreChars.length; i < j; i++) {</span><br><span class="line"> ignoreObj[ignoreChars.charCodeAt(i)] = <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 构建有限状态机</span></span><br><span class="line"><span class="comment">// 生成的数据结构形制如下</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * {</span></span><br><span class="line"><span class="comment"> * '王': {</span></span><br><span class="line"><span class="comment"> * '八': {</span></span><br><span class="line"><span class="comment"> * '蛋': {</span></span><br><span class="line"><span class="comment"> * empty: true</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> * '羔': {</span></span><br><span class="line"><span class="comment"> * '子': {</span></span><br><span class="line"><span class="comment"> * empty: true</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> * }</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">buildMap</span>(<span class="params">wordList</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> result = {};</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>, len = wordList.length; i < len; ++i) {</span><br><span class="line"> <span class="keyword">let</span> map = result;</span><br><span class="line"> <span class="keyword">const</span> word = wordList[i];</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j < word.length; ++j) {</span><br><span class="line"> <span class="keyword">const</span> ch = word.charAt(j).toLowerCase();</span><br><span class="line"> <span class="keyword">if</span> (map[ch]) {</span><br><span class="line"> map = map[ch];</span><br><span class="line"> <span class="keyword">if</span> (map.empty) {</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (map.empty) {</span><br><span class="line"> <span class="keyword">delete</span> map.empty;</span><br><span class="line"> }</span><br><span class="line"> map[ch] = {</span><br><span class="line"> empty: <span class="literal">true</span>,</span><br><span class="line"> };</span><br><span class="line"> map = map[ch];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取敏感词列表</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getSensitiveWords</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> let words = [];</span></span><br><span class="line"><span class="comment"> if (words.length === 0) {</span></span><br><span class="line"><span class="comment"> const data = fs.readFileSync(path.join(__dirname, './words'), 'utf8');</span></span><br><span class="line"><span class="comment"> words = data.split('\n');</span></span><br><span class="line"><span class="comment"> }</span></span><br><span class="line"><span class="comment"> return words.filter(item => !!item);</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">return</span> [</span><br><span class="line"> <span class="string">'王八蛋'</span>,</span><br><span class="line"> <span class="string">'王八羔子'</span></span><br><span class="line"> ]</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 获取敏感词库对象</span></span><br><span class="line"><span class="keyword">const</span> sensitiveWords = getSensitiveWords();</span><br><span class="line"><span class="keyword">const</span> map = buildMap(sensitiveWords);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体检测代码。</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">check</span>(<span class="params">map, content</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> result = [];</span><br><span class="line"> <span class="keyword">let</span> stack = [];</span><br><span class="line"> <span class="keyword">let</span> point = map;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>, len = content.length; i < len; ++i) {</span><br><span class="line"> <span class="keyword">const</span> code = content.charCodeAt(i);</span><br><span class="line"> <span class="keyword">if</span> (ignoreObj[code]) {</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">const</span> ch = content.charAt(i);</span><br><span class="line"> <span class="keyword">const</span> item = point[ch.toLowerCase()];</span><br><span class="line"> <span class="keyword">if</span> (!item) {</span><br><span class="line"> i = i - stack.length;</span><br><span class="line"> stack = [];</span><br><span class="line"> point = map;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (item.empty) {</span><br><span class="line"> stack.push(ch);</span><br><span class="line"> result.push(stack.join(<span class="string">''</span>));</span><br><span class="line"> stack = [];</span><br><span class="line"> point = map;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> stack.push(ch);</span><br><span class="line"> point = item;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">checkSensitive</span>(<span class="params">content</span>) </span>{</span><br><span class="line"> <span class="keyword">const</span> words = check(map, content);</span><br><span class="line"> <span class="keyword">return</span> words;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = checkSensitive;</span><br></pre></td></tr></table></figure>
<p>测试</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">checkSensitive(<span class="string">'老板黄鹤*王&八&(&蛋,吃喝嫖赌,欠下了3.5个亿,带着他的小姨子跑了'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// ['王八蛋']</span></span><br></pre></td></tr></table></figure>
<h2 id="缺陷"><a href="#缺陷" class="headerlink" title="缺陷"></a>缺陷</h2><p>若用火星文、异体字、同音字来替代,这类算法没什么好的办法能识别</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">checkSensitive(<span class="string">'王八羔仔'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// []</span></span><br></pre></td></tr></table></figure>
<p>若敏感词短,则误伤很大,若前文设置的是 <code>王八</code> 作为敏感词。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">checkSensitive(<span class="string">'虎躯一震,散发一阵王八之气'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// ['王八']</span></span><br></pre></td></tr></table></figure>
<p>自然还有大名鼎鼎的 <code>江阴毛纺织厂</code> 怕也会很容易被误伤。</p>
<p>此外,敏感词收集的过程也是一个可以扩展来说的点。</p>
]]></content>
<categories>
<category>alorigam</category>
</categories>
</entry>
<entry>
<title>npm installation integrity checksum failure</title>
<url>/2018/07/26/node/npm-installation-integrity-checksum-failure/</url>
<content><![CDATA[<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ npm install </span><br><span class="line"></span><br><span class="line">> [email protected] i /Users/everlose/workspace/souche/dafenche_hostling_manage_rn</span><br><span class="line">> npm install --registry=http://registry.npm.souche-inc.com</span><br><span class="line"></span><br><span class="line">npm ERR! code EINTEGRITY</span><br><span class="line">npm ERR! sha1-wn2eY/Tj6rCpvd6nyEtHhL1+ty0= integrity checksum failed when using sha1: wanted sha1-wn2eY/Tj6rCpvd6nyEtHhL1+ty0= but got sha1-w2ZcER/THiTjko+588ibWZmtkUI=. (2313436 bytes)</span><br><span class="line"></span><br><span class="line">npm ERR! A complete <span class="built_in">log</span> of this run can be found <span class="keyword">in</span>:</span><br><span class="line">npm ERR! /Users/everlose/.npm/_logs/2018-07-26T09_31_57_935Z-debug.log</span><br><span class="line">npm ERR! code ELIFECYCLE</span><br><span class="line">npm ERR! errno 1</span><br><span class="line">npm ERR! [email protected] i: `npm install --registry=http://registry.npm.souche-inc.com`</span><br><span class="line">npm ERR! Exit status 1</span><br><span class="line">npm ERR!</span><br><span class="line">npm ERR! Failed at the [email protected] i script.</span><br><span class="line">npm ERR! This is probably not a problem with npm. There is likely additional logging output above.</span><br><span class="line"></span><br><span class="line">npm ERR! A complete <span class="built_in">log</span> of this run can be found <span class="keyword">in</span>:</span><br><span class="line">npm ERR! /Users/everlose/.npm/_logs/2018-07-26T09_31_57_981Z-debug.log</span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">npm cache --force clean</span><br><span class="line"></span><br><span class="line">npm install --update-binary --no-shrinkwrap</span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果前面两部都做了,但还是无法解决,则重新启动计算机吧,本人最终重启下才得以解决</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>node</category>
</categories>
</entry>
<entry>
<title>浏览器发送的 http 请求是复用一个 tcp 连接么</title>
<url>/2018/07/25/tcp-http/is-http-reuse-a-tcp/</url>
<content><![CDATA[<h2 id="答案"><a href="#答案" class="headerlink" title="答案"></a>答案</h2><p>不一定。</p>
<p>如果发的不同域名,肯定不复用。</p>
<p>发的同域名。若第一个请求与第二个请求并行发送,不复用。</p>
<p>发的同域名,并且是第一个请求完事了才发第二个请求。则看是否有 connection: keep-alive 请求头,没有则不复用。</p>
<p>发的同域名,第一个请求完了后发第二个请求,有 connection: keep-alive 请求头。则复用同一个 TCP 连接。</p>
<h2 id="补充说明"><a href="#补充说明" class="headerlink" title="补充说明"></a>补充说明</h2><p>HTTP 1.1 里大概规范了几项提高性能的手段:</p>
<ol>
<li>持久连接 (keep-alive/persistent connection)</li>
<li>并行连接</li>
<li>Pipelining</li>
</ol>
<h3 id="持久连接"><a href="#持久连接" class="headerlink" title="持久连接"></a>持久连接</h3><p>每一个请求都会重新建立一个 TCP 连接,一旦响应返回,就关闭连接。 而建立一个连接,则需要进行三次握手。HTTP 1.1 出了一个请求头 connection,默认 keep-alive,告诉服务器不关闭 TCP 连接。</p>
<h3 id="并行连接"><a href="#并行连接" class="headerlink" title="并行连接"></a>并行连接</h3><p>由于现代网页通常包含了复数个(>=10)资源,而按照默认设定,一个连接中的每一个请求必须等待收到响应后才能发送下一个请求,所以如果复数的资源请求全部在一个连接 one by one 发送给服务器显然会很慢,而为了弥补这一缺陷,浏览器通常会默认开启多个 TCP 连接,然后再根据每个连接的状态在其中依次发送数据请求,而且客户端有权任意关闭超发的连接。各个浏览器允许的并行连接数大致是这样的(From SO):</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Firefox 2: 2</span><br><span class="line">Firefox 3+: 6</span><br><span class="line">Opera 9.26: 4</span><br><span class="line">Opera 12: 6</span><br><span class="line">Safari 3: 4</span><br><span class="line">Safari 5: 6</span><br><span class="line">IE 7: 2</span><br><span class="line">IE 8: 6</span><br><span class="line">IE 10: 8</span><br><span class="line">Chrome: 6</span><br></pre></td></tr></table></figure>
<p>由于 TCP 协议本身有慢启动的特征,会随着时间调谐连接的最大速度,因此在现代浏览器中持久连接和并行连接通常是搭配在一起使用的—— 一方面由于持久连接的存在,每个 TCP 连接已经处于调谐后的状态,另一方面持久连接可以避免重新三次握手的开销。</p>
<p>在 Chrome 中,页面初始并行加载一堆静态资源是会最大开 6 个 TCP 连接去并行运作,其后发 Ajax 请求则是复用之前的 TCP 连接。</p>
<h3 id="Pipelining"><a href="#Pipelining" class="headerlink" title="Pipelining"></a>Pipelining</h3><p>按照 HTTP 1.1 的描述,还有种可以提升性能的方案是管道化,可以在一个 TCP 连接中并行执行多个请求并返回。</p>
<p>因为这项技术比较复杂,如何能在一个 TCP 中有序的处理所接收到的包,并且不会乱序返回,这在早期没有规范,所以各大浏览器都没有支持此功能,形同鸡肋。</p>
<h2 id="关于-HTTP-2"><a href="#关于-HTTP-2" class="headerlink" title="关于 HTTP 2"></a>关于 HTTP 2</h2><p>HTTP 2 为了性能做了不少努力,比如提供了规范以支持连接的多路复用。</p>
<p>如前文所说,在同一个 TCP 连接里面同时发生两个请求响应就不是那么简单。而 HTTP 2 正是提供了这样的规范,可以给数据拆成包,并打上包的顺序标签以供 TCP 能正确认知接收的包的顺序。</p>
<p>所以很多网络优化的知识已经过时</p>
<ul>
<li>因为“所有的 HTTP 2.0 的请求都在一个 TCP 链接上”,“资源合并减少请求”,比如 CSS Sprites ,多个 JS 文件、CSS 文件合并等手段没有效果,或者说没有必要。</li>
<li>因为“多路复用”,采用“cdn1.cn,cdn2.cn,cdn3.cn,打开多个 TCP 会话,突破浏览器对同一域名的链接数的限制”的手段是没有必要的。因为因为资源都是并行交错发送,且没有限制,不需要额外的多域名并行下载。</li>
<li>内嵌资源(如base64的图片)的优化手段也变得没有意义了。而且使用服务器推送的资源的方式更加高效,因为客户端还可以缓存起来,甚至可以由不同的页面共享(依旧遵循同源策略)</li>
</ul>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><ul>
<li><a href="https://linjunzhu.github.io/blog/2016/03/10/http2-zongjie/" target="_blank" rel="noopener">https://linjunzhu.github.io/blog/2016/03/10/http2-zongjie/</a></li>
<li><a href="https://www.zhihu.com/question/36469741" target="_blank" rel="noopener">https://www.zhihu.com/question/36469741</a></li>
</ul>
]]></content>
<categories>
<category>tcp-http</category>
</categories>
</entry>
<entry>
<title>经典数组操作方法</title>
<url>/2018/07/24/javascript/array-api/</url>
<content><![CDATA[<h2 id="Arrays"><a href="#Arrays" class="headerlink" title="Arrays"></a>Arrays</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list = [a,b,c,d,e]</span><br></pre></td></tr></table></figure>
<p>{: .-setup}</p>
<h2 id="子集"><a href="#子集" class="headerlink" title="子集"></a>子集</h2><h4 id="Immutable"><a href="#Immutable" class="headerlink" title="Immutable"></a>Immutable</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.slice(<span class="number">0</span>,<span class="number">1</span>) <span class="comment">// → [a]</span></span><br><span class="line">list.slice(<span class="number">1</span>) <span class="comment">// → [b,c,d,e]</span></span><br><span class="line">list.slice(<span class="number">1</span>,<span class="number">2</span>) <span class="comment">// → [b]</span></span><br></pre></td></tr></table></figure>
<h3 id="Mutative"><a href="#Mutative" class="headerlink" title="Mutative"></a>Mutative</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">re = list.splice(<span class="number">1</span>) <span class="comment">// re = [b,c,d,e] list == [a]</span></span><br><span class="line">re = list.splice(<span class="number">1</span>,<span class="number">2</span>) <span class="comment">// re = [b,c] list == [a,d,e]</span></span><br></pre></td></tr></table></figure>
<h2 id="增"><a href="#增" class="headerlink" title="增"></a>增</h2><h4 id="Mutative-1"><a href="#Mutative-1" class="headerlink" title="Mutative"></a>Mutative</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.push(X) <span class="comment">// list == [_,_,_,_,_,X]</span></span><br><span class="line">list.unshift(X) <span class="comment">// list == [X,_,_,_,_,_]</span></span><br><span class="line">list.splice(<span class="number">2</span>, <span class="number">0</span>, X) <span class="comment">// list == [_,_,X,_,_,_]</span></span><br></pre></td></tr></table></figure>
<h4 id="Immutable-1"><a href="#Immutable-1" class="headerlink" title="Immutable"></a>Immutable</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.concat([X,Y]) <span class="comment">// → [_,_,_,_,_,X,Y]</span></span><br></pre></td></tr></table></figure>
<h2 id="改"><a href="#改" class="headerlink" title="改"></a>改</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.splice(<span class="number">2</span>, <span class="number">1</span>, X) <span class="comment">// list == [a,b,X,d,e]</span></span><br></pre></td></tr></table></figure>
<h2 id="删"><a href="#删" class="headerlink" title="删"></a>删</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.pop() <span class="comment">// → e list == [a,b,c,d]</span></span><br><span class="line">list.shift() <span class="comment">// → a list == [b,c,d,e]</span></span><br><span class="line">list.splice(<span class="number">2</span>, <span class="number">1</span>) <span class="comment">// → [c] list == [a,b,d,e]</span></span><br></pre></td></tr></table></figure>
<h2 id="迭代"><a href="#迭代" class="headerlink" title="迭代"></a>迭代</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> list = [</span><br><span class="line"> { <span class="attr">id</span>: <span class="number">1</span>, <span class="attr">name</span>: <span class="string">'张三'</span>, <span class="attr">age</span>: <span class="number">18</span> }, </span><br><span class="line"> { <span class="attr">id</span>: <span class="number">2</span>, <span class="attr">name</span>: <span class="string">'李四'</span>, <span class="attr">age</span>: <span class="number">24</span> }, </span><br><span class="line"> { <span class="attr">id</span>: <span class="number">3</span>, <span class="attr">name</span>: <span class="string">'王小二'</span>, <span class="attr">age</span>: <span class="number">22</span> }</span><br><span class="line">];</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.forEach(<span class="function"><span class="params">item</span> =></span> <span class="built_in">console</span>.log(item.id)); <span class="comment">// 1, 2, 3</span></span><br></pre></td></tr></table></figure>
<h4 id="产生新数组"><a href="#产生新数组" class="headerlink" title="产生新数组"></a>产生新数组</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list.map(<span class="function"><span class="params">item</span> =></span> item.name); <span class="comment">// [ '张三', '李四', '王小二' ]</span></span><br></pre></td></tr></table></figure>
<h4 id="筛选"><a href="#筛选" class="headerlink" title="筛选"></a>筛选</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">list</span><br><span class="line"> .filter(<span class="function"><span class="params">item</span> =></span> item.age > <span class="number">18</span>);</span><br><span class="line"> .map(<span class="function"><span class="params">item</span> =></span> item.name);</span><br><span class="line"> </span><br><span class="line"><span class="comment">// [ '李四', '王小二' ]</span></span><br></pre></td></tr></table></figure>
<h4 id="some方法测试数组中的某些元素是否通过指定函数的测试"><a href="#some方法测试数组中的某些元素是否通过指定函数的测试" class="headerlink" title="some方法测试数组中的某些元素是否通过指定函数的测试"></a>some方法测试数组中的某些元素是否通过指定函数的测试</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">isRepeat</span> (<span class="params">array, props, value</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> array.some(<span class="function"><span class="params">item</span> =></span> item[props] === value);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">isRepeat(list, <span class="string">'name'</span>, <span class="string">'张三'</span>); <span class="comment">// true</span></span><br><span class="line">isRepeat(list, <span class="string">'name'</span>, <span class="string">'李白'</span>); <span class="comment">// false</span></span><br></pre></td></tr></table></figure>
<h4 id="检测某个数组里的每个对象是否都具有某种属性"><a href="#检测某个数组里的每个对象是否都具有某种属性" class="headerlink" title="检测某个数组里的每个对象是否都具有某种属性"></a>检测某个数组里的每个对象是否都具有某种属性</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">hasSomeProps</span> (<span class="params">array, props</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> array.every(<span class="function"><span class="params">item</span> =></span> item[props]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">hasSomeProps(list, <span class="string">'name'</span>); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>
<h4 id="获取累计结果"><a href="#获取累计结果" class="headerlink" title="获取累计结果"></a>获取累计结果</h4><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line"></span><br><span class="line">arr.reduce(<span class="function">(<span class="params">prev, curr</span>) =></span> prev + curr, <span class="number">0</span>) <span class="comment">// 6</span></span><br></pre></td></tr></table></figure>
<h2 id="数组去重"><a href="#数组去重" class="headerlink" title="数组去重"></a>数组去重</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">unique</span> (<span class="params">arr</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> <span class="keyword">set</span> = new Set(arr);</span><br><span class="line"> return Array.from(<span class="keyword">set</span>);</span><br><span class="line">}</span><br><span class="line">var arr = [2, NaN, 2, 3, NaN, {}, {}];</span><br><span class="line">unique(arr); <span class="comment">// [2, NaN, 3, Object, Object]</span></span><br></pre></td></tr></table></figure>
<h2 id="数组深度拷贝"><a href="#数组深度拷贝" class="headerlink" title="数组深度拷贝"></a>数组深度拷贝</h2><p>同对象的深度拷贝</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 遍历法,对象需递归</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">copyObject</span> (<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> result = {};</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> x <span class="keyword">in</span> obj) {</span><br><span class="line"> result[x] = <span class="keyword">typeof</span> obj === <span class="string">'object'</span> ?</span><br><span class="line"> copyObject(obj[x]) :</span><br><span class="line"> obj[x]</span><br><span class="line"> <span class="comment">//如果拷贝的值仍然是一个对象,那么重复执行当前方法。</span></span><br><span class="line"> } </span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">copyObject</span> (<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">JSON</span>.parse(<span class="built_in">JSON</span>.stringify(obj));</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="伪数组转真数组"><a href="#伪数组转真数组" class="headerlink" title="伪数组转真数组"></a>伪数组转真数组</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> arr = { <span class="number">0</span>: <span class="string">'a'</span>, <span class="number">1</span>: <span class="string">'b'</span>, <span class="number">2</span>: <span class="string">'c'</span>, <span class="attr">length</span>: <span class="number">3</span>, <span class="attr">splice</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{} };</span><br><span class="line">arr = <span class="built_in">Array</span>.prototype.slice.call(arr);</span><br><span class="line">arr; <span class="comment">// ["a", "b", "c"] 真数组</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>经典日期操作方法</title>
<url>/2018/07/24/javascript/date-api/</url>
<content><![CDATA[<h3 id="Date"><a href="#Date" class="headerlink" title="Date"></a>Date</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// Now</span></span><br><span class="line">date = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line"></span><br><span class="line"><span class="comment">// ms since epoch</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="number">1419785527580</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// ISO date format</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2013-03-01T01:10:00'</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 年月日时分秒,注意月份从0开始计数</span></span><br><span class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="number">2014</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">13</span>, <span class="number">0</span>, <span class="number">59</span>, <span class="number">0</span>)</span><br></pre></td></tr></table></figure>
<p>{: .-setup}</p>
<h3 id="获取时间戳"><a href="#获取时间戳" class="headerlink" title="获取时间戳"></a>获取时间戳</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line">date.getTime();</span><br><span class="line"><span class="comment">// or</span></span><br><span class="line">+date</span><br></pre></td></tr></table></figure>
<h2 id="时间格式转化"><a href="#时间格式转化" class="headerlink" title="时间格式转化"></a>时间格式转化</h2><h3 id="moment"><a href="#moment" class="headerlink" title="moment"></a>moment</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> moment = <span class="built_in">require</span>(<span class="string">'moment'</span>)</span><br><span class="line">date = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line">m = moment(date)</span><br><span class="line"></span><br><span class="line">m.format(<span class="string">'YYYY-MM-DD hh:mm:ss'</span>)</span><br><span class="line"><span class="comment">// 2018-03-26 12:13:58</span></span><br></pre></td></tr></table></figure>
<h3 id="简化版本"><a href="#简化版本" class="headerlink" title="简化版本"></a>简化版本</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> temp = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line"><span class="keyword">var</span> regex = <span class="regexp">/\//g</span>;</span><br><span class="line">(temp.toLocaleDateString() + <span class="string">' '</span> + temp.toLocaleTimeString().slice(<span class="number">2</span>)).replace(regex,<span class="string">'-'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// "2015-5-7 9:04:10"</span></span><br></pre></td></tr></table></figure>
<h3 id="全面版本"><a href="#全面版本" class="headerlink" title="全面版本"></a>全面版本</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> parseTime = <span class="function"><span class="keyword">function</span> (<span class="params">value, format</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (!value || (+value) !== (+value)) {</span><br><span class="line"> <span class="keyword">return</span> value;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (value.toString().length === <span class="number">10</span>) {</span><br><span class="line"> value = (+value) * <span class="number">1000</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> date = <span class="keyword">new</span> <span class="built_in">Date</span>(value);</span><br><span class="line"> <span class="keyword">var</span> o = {</span><br><span class="line"> <span class="string">'M+'</span>: date.getMonth() + <span class="number">1</span>, <span class="comment">//month</span></span><br><span class="line"> <span class="string">'D+'</span>: date.getDate(), <span class="comment">//day</span></span><br><span class="line"> <span class="string">'h+'</span>: date.getHours(), <span class="comment">//hour</span></span><br><span class="line"> <span class="string">'m+'</span>: date.getMinutes(), <span class="comment">//minute</span></span><br><span class="line"> <span class="string">'s+'</span>: date.getSeconds(), <span class="comment">//second</span></span><br><span class="line"> <span class="string">'S'</span>: date.getMilliseconds() <span class="comment">//millisecond</span></span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (<span class="regexp">/(Y+)/</span>.test(format)) {</span><br><span class="line"> format = format.replace(<span class="built_in">RegExp</span>.$<span class="number">1</span>,</span><br><span class="line"> date.getFullYear().toString().substr(<span class="number">4</span> - <span class="built_in">RegExp</span>.$<span class="number">1.</span>length));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> k <span class="keyword">in</span> o) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">'('</span>+ k +<span class="string">')'</span>).test(format)) {</span><br><span class="line"> format = format.replace(<span class="built_in">RegExp</span>.$<span class="number">1</span>,</span><br><span class="line"> <span class="built_in">RegExp</span>.$<span class="number">1.</span>length == <span class="number">1</span> ? o[k] : (<span class="string">'00'</span>+ o[k]).substr((<span class="string">''</span>+ o[k]).length));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> format;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> date = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br><span class="line">parseTime(date.getTime(), <span class="string">'YYYY-MM-DD hh:mm:ss'</span>)</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>git tag 简化操作</title>
<url>/2018/07/16/source-control/git-tag-simple/</url>
<content><![CDATA[<h2 id="目录层级"><a href="#目录层级" class="headerlink" title="目录层级"></a>目录层级</h2><p>项目中与本篇相关的几个文件</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">.</span><br><span class="line">├── build</span><br><span class="line">│ ├── check-versions.js</span><br><span class="line">│ ├── tag.js</span><br><span class="line">├── package.json</span><br></pre></td></tr></table></figure>
<h2 id="前置依赖安装"><a href="#前置依赖安装" class="headerlink" title="前置依赖安装"></a>前置依赖安装</h2><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ npm install inquirer chalk moment semver shelljs --save-dev</span><br></pre></td></tr></table></figure>
<h2 id="tag-js"><a href="#tag-js" class="headerlink" title="tag.js"></a>tag.js</h2><p>贴入其中代码</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="built_in">require</span>(<span class="string">'./check-versions'</span>)();</span><br><span class="line"><span class="built_in">require</span>(<span class="string">'shelljs/global'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> inquirer = <span class="built_in">require</span>(<span class="string">'inquirer'</span>);</span><br><span class="line"><span class="keyword">var</span> chalk = <span class="built_in">require</span>(<span class="string">'chalk'</span>);</span><br><span class="line"><span class="keyword">var</span> moment = <span class="built_in">require</span>(<span class="string">'moment'</span>);</span><br><span class="line"><span class="keyword">var</span> path = <span class="built_in">require</span>(<span class="string">'path'</span>);</span><br><span class="line"><span class="keyword">var</span> fs = <span class="built_in">require</span>(<span class="string">'fs'</span>);</span><br><span class="line"><span class="keyword">var</span> semver = <span class="built_in">require</span>(<span class="string">'semver'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> packageJsonPath = path.resolve(process.cwd(), <span class="string">'package.json'</span>);</span><br><span class="line"><span class="keyword">var</span> packageJson = <span class="built_in">require</span>(packageJsonPath);</span><br><span class="line"><span class="keyword">var</span> packageJsonVersion = packageJson.version;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> verOptList = getVersionOptions(packageJsonVersion);</span><br><span class="line"></span><br><span class="line">inquirer.prompt([{</span><br><span class="line"> name: <span class="string">'version'</span>,</span><br><span class="line"> message: <span class="string">`选择将要升级的版本(当前版本 <span class="subst">${packageJsonVersion}</span> ):`</span>,</span><br><span class="line"> type: <span class="string">'list'</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="number">0</span>,</span><br><span class="line"> choices: verOptList</span><br><span class="line">}, {</span><br><span class="line"> name: <span class="string">'week'</span>,</span><br><span class="line"> message: <span class="string">'是否添加发布次数 tag (格式如 16w12a <year>w<week>[a-z])'</span>,</span><br><span class="line"> type: <span class="string">'confirm'</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="literal">false</span></span><br><span class="line">}, {</span><br><span class="line"> name: <span class="string">'message'</span>,</span><br><span class="line"> message: <span class="string">'版本发布说明'</span>,</span><br><span class="line"> type: <span class="string">'input'</span>,</span><br><span class="line"> <span class="keyword">default</span>: <span class="string">''</span></span><br><span class="line">}]).then(<span class="function"><span class="keyword">function</span> (<span class="params">answers</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> weekSuffix = answers.week ? <span class="string">'+'</span> + getWeekSubfix(packageJsonVersion) : <span class="string">''</span>;</span><br><span class="line"> <span class="keyword">var</span> version = <span class="string">`<span class="subst">${answers.version}</span><span class="subst">${weekSuffix}</span>`</span>;</span><br><span class="line"> <span class="keyword">var</span> commitMessage = <span class="string">`"chore(package.json): bump version to <span class="subst">${version}</span>"`</span>;</span><br><span class="line"> <span class="keyword">var</span> message = <span class="string">`"<span class="subst">${answers.message}</span>"`</span> || <span class="string">'v'</span> + version;</span><br><span class="line"> packageJson.version = version;</span><br><span class="line"> fs.writeFileSync(process.cwd() + <span class="string">'/package.json'</span>, <span class="built_in">JSON</span>.stringify(packageJson, <span class="literal">null</span>, <span class="string">' '</span>));</span><br><span class="line"> <span class="keyword">var</span> cmd = <span class="string">`git add package.json && git commit -m <span class="subst">${commitMessage}</span> && git tag -a <span class="subst">${version}</span> -m <span class="subst">${message}</span> && git push origin master && git push origin --tags`</span>;</span><br><span class="line"></span><br><span class="line"> exec(cmd);</span><br><span class="line"></span><br><span class="line"> <span class="built_in">console</span>.log();</span><br><span class="line"> <span class="built_in">console</span>.log(chalk.green(<span class="string">` 成功,当前版本为( <span class="subst">${version}</span> ) `</span>));</span><br><span class="line"> <span class="built_in">console</span>.log();</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取发布周数 patch</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getWeekSubfix</span> (<span class="params">version</span>) </span>{</span><br><span class="line"> version = version.split(<span class="string">'+'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> versionSuffix = version[<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">var</span> year = moment().format(<span class="string">'gg'</span>);</span><br><span class="line"> <span class="keyword">var</span> week = moment().format(<span class="string">'ww'</span>);</span><br><span class="line"> <span class="keyword">var</span> pubSuffix = <span class="string">''</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!versionSuffix) {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">`<span class="subst">${year}</span>w<span class="subst">${week}</span>a`</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> currentWeek = versionSuffix.match(<span class="regexp">/\d+w(\d+)(\w+)/</span>)[<span class="number">1</span>];</span><br><span class="line"> <span class="keyword">var</span> currentPubSuffix = versionSuffix.match(<span class="regexp">/\d+w(\d+)(\w+)/</span>)[<span class="number">2</span>];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(<span class="built_in">parseInt</span>(week) === <span class="built_in">parseInt</span>(currentWeek)) {</span><br><span class="line"> <span class="comment">// 没有处理达到 Z 的情况</span></span><br><span class="line"> <span class="keyword">if</span> (currentPubSuffix === <span class="string">'z'</span>) {</span><br><span class="line"> pubSuffix = <span class="string">'A'</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 如果是 Z 那么下一个没有处理</span></span><br><span class="line"> pubSuffix = <span class="built_in">String</span>.fromCharCode(currentPubSuffix.charCodeAt(<span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> pubSuffix = <span class="string">'a'</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="string">`<span class="subst">${year}</span>w<span class="subst">${week}</span><span class="subst">${pubSuffix}</span>`</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取升级版本列表</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getVersionOptions</span> (<span class="params">version</span>) </span>{</span><br><span class="line"> version = version.split(<span class="string">'+'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> currentVersion = version[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">var</span> levels = [<span class="string">'patch'</span>, <span class="string">'minor'</span>, <span class="string">'major'</span>];</span><br><span class="line"> <span class="keyword">var</span> opts = [];</span><br><span class="line"></span><br><span class="line"> levels.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">item</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> val = semver.inc(currentVersion, item);</span><br><span class="line"> opts.push({</span><br><span class="line"> name: val,</span><br><span class="line"> value: val</span><br><span class="line"> })</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> opts;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">process.on(<span class="string">'unhandledRejection'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(a, b);</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<h2 id="check-versions-js"><a href="#check-versions-js" class="headerlink" title="check-versions.js"></a>check-versions.js</h2><p>这个文件其实是 vue-cli 建的,主要做了检查 package.json 里的版本的功能,代码如下</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> chalk = <span class="built_in">require</span>(<span class="string">'chalk'</span>)</span><br><span class="line"><span class="keyword">var</span> semver = <span class="built_in">require</span>(<span class="string">'semver'</span>)</span><br><span class="line"><span class="keyword">var</span> packageConfig = <span class="built_in">require</span>(<span class="string">'../package.json'</span>)</span><br><span class="line"><span class="keyword">var</span> shell = <span class="built_in">require</span>(<span class="string">'shelljs'</span>)</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">exec</span> (<span class="params">cmd</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">require</span>(<span class="string">'child_process'</span>).execSync(cmd).toString().trim()</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> versionRequirements = [</span><br><span class="line"> {</span><br><span class="line"> name: <span class="string">'node'</span>,</span><br><span class="line"> currentVersion: semver.clean(process.version),</span><br><span class="line"> versionRequirement: packageConfig.engines.node</span><br><span class="line"> },</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (shell.which(<span class="string">'npm'</span>)) {</span><br><span class="line"> versionRequirements.push({</span><br><span class="line"> name: <span class="string">'npm'</span>,</span><br><span class="line"> currentVersion: exec(<span class="string">'npm --version'</span>),</span><br><span class="line"> versionRequirement: packageConfig.engines.npm</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> warnings = []</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < versionRequirements.length; i++) {</span><br><span class="line"> <span class="keyword">var</span> mod = versionRequirements[i]</span><br><span class="line"> <span class="keyword">if</span> (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {</span><br><span class="line"> warnings.push(mod.name + <span class="string">': '</span> +</span><br><span class="line"> chalk.red(mod.currentVersion) + <span class="string">' should be '</span> +</span><br><span class="line"> chalk.green(mod.versionRequirement)</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (warnings.length) {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">''</span>)</span><br><span class="line"> <span class="built_in">console</span>.log(chalk.yellow(<span class="string">'To use this template, you must update following to modules:'</span>))</span><br><span class="line"> <span class="built_in">console</span>.log()</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < warnings.length; i++) {</span><br><span class="line"> <span class="keyword">var</span> warning = warnings[i]</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">' '</span> + warning)</span><br><span class="line"> }</span><br><span class="line"> <span class="built_in">console</span>.log()</span><br><span class="line"> process.exit(<span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="运行"><a href="#运行" class="headerlink" title="运行"></a>运行</h2><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ node build/tag.js</span><br><span class="line"></span><br><span class="line">? 选择将要升级的版本(当前版本 1.1.8 ): (Use arrow keys)</span><br><span class="line">❯ 1.1.9</span><br><span class="line"> 1.2.0</span><br><span class="line"> 2.0.0</span><br><span class="line"></span><br><span class="line">? 是否添加发布次数 tag (格式如 16w12a <year>w<week>[a-z]) (y/N)</span><br><span class="line"></span><br><span class="line">? 版本发布说明 ()</span><br><span class="line"></span><br><span class="line">[master 976e906] chore(package.json): bump version to 1.1.9</span><br><span class="line"> 1 file changed, 1 insertion(+), 1 deletion(-)</span><br><span class="line">To git.souche-inc.com:bigBusiness/dafengche-reorganize-manage.git</span><br><span class="line"> 31bbfe9..976e906 master -> master</span><br><span class="line">To git.souche-inc.com:bigBusiness/dafengche-reorganize-manage.git</span><br><span class="line"> * [new tag] 1.1.9 -> 1.1.9</span><br><span class="line"></span><br><span class="line"> 成功,当前版本为( 1.1.9 )</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>source-control</category>
</categories>
</entry>
<entry>
<title>postcss 简单使用</title>
<url>/2018/07/13/css/postcss-introduce/</url>
<content><![CDATA[<h2 id="引入"><a href="#引入" class="headerlink" title="引入"></a>引入</h2><p>在 webpack 中 css 的 loader 写上 postcss 支持。而后在 .postcssrc.js 中配置想要引入的插件。而 vue-cli 构建的项目已经集成</p>
<p>接着在 .postcssrc.js 以下介绍几种常用插件</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> plugins: [</span><br><span class="line"> <span class="built_in">require</span>(<span class="string">'postcss-autoprefixer'</span>),</span><br><span class="line"> <span class="built_in">require</span>(<span class="string">'postcss-cssnext'</span>)({</span><br><span class="line"> browsers: [<span class="string">'ie > 8'</span>, <span class="string">'last 2 versions'</span>]</span><br><span class="line"> }),</span><br><span class="line"> <span class="built_in">require</span>(<span class="string">'postcss-mixins'</span>),</span><br><span class="line"> <span class="built_in">require</span>(<span class="string">'postcss-css-reset'</span>)</span><br><span class="line"> ]</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h2 id="autoprefixer"><a href="#autoprefixer" class="headerlink" title="autoprefixer"></a>autoprefixer</h2><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-tag">div</span> {</span><br><span class="line"> <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 被最终编译成 */</span></span><br><span class="line"><span class="selector-tag">div</span> {</span><br><span class="line"> <span class="attribute">-webkit-box-sizing</span>: border-box;</span><br><span class="line"> <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="cssnext"><a href="#cssnext" class="headerlink" title="cssnext"></a>cssnext</h2><p>可定义变量</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span> {</span><br><span class="line"> <span class="attribute">--white</span>: <span class="number">#fff</span>;</span><br><span class="line"> <span class="attribute">--grey</span>: <span class="number">#1e1e1d</span>;</span><br><span class="line"> <span class="attribute">--yellow</span>: <span class="number">#ffad15</span>;</span><br><span class="line"> <span class="attribute">--offwhite</span>: <span class="number">#f8f8f8</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 使用如 */</span></span><br><span class="line"><span class="selector-tag">a</span> {</span><br><span class="line"> <span class="attribute">color</span>: <span class="built_in">var</span>(--yellow);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 编译为 */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-tag">a</span> {</span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#ffad15</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>可扩展和类占位符,@apply可以复制每个属性的规则和值。</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span> {</span><br><span class="line"> ...</span><br><span class="line"> <span class="selector-tag">--franklin</span>: {</span><br><span class="line"> <span class="attribute">font-family</span>: <span class="string">'futura-pt'</span>, helvetica, sans-serif;</span><br><span class="line"> </span><br><span class="line"> }; </span><br><span class="line"> <span class="selector-tag">--franklin-heading</span>: { </span><br><span class="line"> @apply --franklin; font-weight: 700; line-height: 1.1; text-transform: uppercase; </span><br><span class="line"> }; </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 使用如 */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.my-heading</span> {</span><br><span class="line"> @apply --franklin-heading;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 编译为 */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.my-heading</span> {</span><br><span class="line"> <span class="attribute">font-family</span>: <span class="string">'futura-pt'</span>, helvetica, sans-serif;</span><br><span class="line"> <span class="attribute">font-weight</span>: <span class="number">700</span>;</span><br><span class="line"> <span class="attribute">line-height</span>: <span class="number">1.1</span>;</span><br><span class="line"> <span class="attribute">text-transform</span>: uppercase; </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="mixins"><a href="#mixins" class="headerlink" title="mixins"></a>mixins</h2><p>带参数的混合宏</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">@<span class="keyword">mixin</span> project-block ($c) {</span><br><span class="line"> background-color: $c;</span><br><span class="line"> <span class="selector-tag">a</span> { </span><br><span class="line"> <span class="attribute">color</span>: $c;</span><br><span class="line"> &:hover {</span><br><span class="line"> background-color: $c;</span><br><span class="line"> <span class="selector-tag">color</span>: <span class="selector-id">#fff</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 使用如 */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.p-jribbble</span> {</span><br><span class="line"> @include project-block(#ff0066);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 编译为 */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.p-jribbble</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: <span class="number">#ff0066</span>;</span><br><span class="line"> a { </span><br><span class="line"> <span class="selector-tag">color</span>: <span class="selector-id">#ff0066</span>;</span><br><span class="line"> &<span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: <span class="number">#ff0066</span>;</span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h2 id="css-reset"><a href="#css-reset" class="headerlink" title="css reset"></a>css reset</h2><p>可选两种模式,<code>@reset-global: [pc|mobile];</code>,在 css 文件头部加入以下一句话就可以生效。</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line">@<span class="keyword">reset</span>-<span class="keyword">global</span> pc;</span><br></pre></td></tr></table></figure>
<p>会被编译为</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-tag">html</span> {</span><br><span class="line"> <span class="attribute">font-family</span>: sans-serif;</span><br><span class="line"> <span class="attribute">-ms-text-size-adjust</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">-webkit-text-size-adjust</span>: <span class="number">100%</span></span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">body</span> {</span><br><span class="line"> <span class="attribute">margin</span>: <span class="number">0</span></span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">article</span>, <span class="selector-tag">aside</span>, <span class="selector-tag">details</span>, <span class="selector-tag">figcaption</span>, <span class="selector-tag">figure</span>, <span class="selector-tag">footer</span>, <span class="selector-tag">header</span>, <span class="selector-tag">main</span>, <span class="selector-tag">menu</span>, <span class="selector-tag">nav</span>, <span class="selector-tag">section</span>, <span class="selector-tag">summary</span> {</span><br><span class="line"> <span class="attribute">display</span>: block</span><br><span class="line">}</span><br><span class="line">.......</span><br></pre></td></tr></table></figure>
<p>需要注意的是这个作者在 <code>@reset-global mobile;</code> 模式下,加入了 <code>* { box-sizing: border-box }</code> </p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="http://www.tuicool.com/articles/aayEF3" target="_blank" rel="noopener">PostCSS深入学习: 结合BEM和SUIT方法使用PostCSS</a></p>
<p><a href="http://cssnext.io/playground/" target="_blank" rel="noopener">css next playground</a></p>
]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css 3</tag>
</tags>
</entry>
<entry>
<title>CommonJS 中的 require/exports 和 ES6 中的 import/export 区别?</title>
<url>/2018/07/10/javascript/commonjs-vs-import/</url>
<content><![CDATA[<h2 id="一"><a href="#一" class="headerlink" title="一"></a>一</h2><p>require理论上可以运用在代码的任何地方,甚至不需要赋值给某个变量之后再使用</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// ...a lot code</span></span><br><span class="line"><span class="built_in">require</span>(process.cwd() + <span class="string">'/a'</span>);</span><br></pre></td></tr></table></figure>
<p>但是import则不同,它是编译时的(require是运行时的),它必须放在文件开头,而且使用格式也是确定的,不容置疑。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> a <span class="keyword">from</span> <span class="string">'./a'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// ...a lot code</span></span><br></pre></td></tr></table></figure>
<h2 id="二"><a href="#二" class="headerlink" title="二"></a>二</h2><p>CommonJS 模块的重要特性是加载时执行,即脚本代码在 require 的时候,就会全部执行。一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。</p>
<p>而ES6 模块是动态引用,如果使用 import 从一个模块加载变量,那些变量不会被缓存,而是成为一个指向被加载模块的引用,需要开发者自己保证,真正取值的时候能够取到值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// counter.js</span></span><br><span class="line">exports.count = <span class="number">0</span></span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'increase count to'</span>, ++exports.count, <span class="string">'in counter.js after 500ms'</span>)</span><br><span class="line">}, <span class="number">500</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">// commonjs.js</span></span><br><span class="line"><span class="keyword">const</span> {count} = <span class="built_in">require</span>(<span class="string">'./counter'</span>)</span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'read count after 1000ms in commonjs is'</span>, count)</span><br><span class="line">}, <span class="number">1000</span>)</span><br><span class="line"><span class="comment">// increase count to 1 in counter.js after 500ms</span></span><br><span class="line"><span class="comment">// read count after 1000ms in commonjs is 0</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//es6.js</span></span><br><span class="line"><span class="keyword">import</span> {count} <span class="keyword">from</span> <span class="string">'./counter'</span></span><br><span class="line">setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'read count after 1000ms in es6 is'</span>, count)</span><br><span class="line">}, <span class="number">1000</span>)</span><br><span class="line"><span class="comment">// node 9,when I run with babel-node</span></span><br><span class="line"><span class="comment">// increase count to 1 in counter.js after 500ms</span></span><br><span class="line"><span class="comment">// read count after 1000ms in es6 is 1</span></span><br></pre></td></tr></table></figure>
<h2 id="三"><a href="#三" class="headerlink" title="三"></a>三</h2><p>CommonJS 规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(即 module.exports )是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。</p>
<p>export 命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。</p>
<p>就如下面module.export 只能导出一个对象,而es6的export可以多次,用解构去一一对应。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> a: <span class="number">1</span>,</span><br><span class="line"> b: <span class="number">2</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> b = <span class="number">2</span>;</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>linux find 命令详解</title>
<url>/2018/07/10/os/linux-find/</url>
<content><![CDATA[<h3 id="Usage"><a href="#Usage" class="headerlink" title="Usage"></a>Usage</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">find <path> <conditions> <actions></span><br></pre></td></tr></table></figure>
<h3 id="Conditions"><a href="#Conditions" class="headerlink" title="Conditions"></a>Conditions</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-name <span class="string">"*.c"</span></span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-<span class="built_in">type</span> f <span class="comment"># File</span></span><br><span class="line">-<span class="built_in">type</span> d <span class="comment"># Directory</span></span><br><span class="line">-<span class="built_in">type</span> l <span class="comment"># Symlink</span></span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-depth 2 <span class="comment"># At least 3 levels deep</span></span><br><span class="line">-regex PATTERN</span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-newer file.txt</span><br><span class="line">-newerm file.txt <span class="comment"># modified newer than file.txt</span></span><br><span class="line">-newerX file.txt <span class="comment"># [c]hange, [m]odified, [B]create</span></span><br><span class="line">-newerXt <span class="string">"1 hour ago"</span> <span class="comment"># [t]imestamp</span></span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-path <span class="string">"*/node_modules"</span> -prune <span class="comment"># 忽略任意node_modules文件夹</span></span><br></pre></td></tr></table></figure>
<h3 id="Condition-flow"><a href="#Condition-flow" class="headerlink" title="Condition flow"></a>Condition flow</h3><p>查找当前文件夹且忽略node_modules文件夹下的,所有后缀为js的文件,-o是短路语句</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">find . -path <span class="string">"*/node_modules"</span> -prune -o -<span class="built_in">type</span> f -name <span class="string">"*.js"</span> -<span class="built_in">print</span></span><br></pre></td></tr></table></figure>
<h3 id="Actions"><a href="#Actions" class="headerlink" title="Actions"></a>Actions</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">-<span class="built_in">exec</span> rm {} \; <span class="comment"># 花括号代表前面find查找出来的文件名,反斜杠分号代表语句结束</span></span><br><span class="line">-<span class="built_in">print</span> <span class="comment"># 打印</span></span><br><span class="line">-delete</span><br></pre></td></tr></table></figure>
<h3 id="Examples"><a href="#Examples" class="headerlink" title="Examples"></a>Examples</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">find . -name <span class="string">'*.jpg'</span></span><br><span class="line">find . -name <span class="string">'*.jpg'</span> -<span class="built_in">exec</span> rm {} \;</span><br></pre></td></tr></table></figure>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">find . -newerBt <span class="string">"24 hours ago"</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>os</category>
</categories>
</entry>
<entry>
<title>CentOS 安装 nodejs 一件套</title>
<url>/2018/07/05/node/centos-install-node/</url>
<content><![CDATA[<p>首先进入node官网寻找一个合适的版本</p>
<p><a href="http://nodejs.org/dist/" target="_blank" rel="noopener">http://nodejs.org/dist/</a></p>
<p>以 node-v9.0.0-linux-x64.tar.gz 为例</p>
<p>运行命令获取node资源</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">wget http://nodejs.org/dist/v9.0.0/node-v9.0.0-linux-x64.tar.gz</span><br></pre></td></tr></table></figure>
<p>下载到当前目录后解压</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">tar -zxvf node-v9.0.0-linux-x64.tar.gz</span><br><span class="line"></span><br><span class="line">mv node-v9.0.0-linux-x64 node-v9</span><br></pre></td></tr></table></figure>
<p>查看node程序是否能正常执行</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">cd</span> node-v9/bin && ./node -v</span><br><span class="line"></span><br><span class="line"><span class="comment"># v9.0.0</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">pwd</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># /root/node-v9/bin</span></span><br></pre></td></tr></table></figure>
<p>接着设置全局变量</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">vim ~/.bash_profile</span><br><span class="line"></span><br><span class="line"><span class="comment"># 找到 PATH=$PATH:$HOME/bin,在后面添加路径为:</span></span><br><span class="line"></span><br><span class="line">PATH=<span class="variable">$PATH</span>:<span class="variable">$HOME</span>/bin:/root/node-v9/bin</span><br></pre></td></tr></table></figure>
<p>保存后重载</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="built_in">source</span> ~/.bash_profile</span><br></pre></td></tr></table></figure>
<h2 id="其他一些node技术栈软件"><a href="#其他一些node技术栈软件" class="headerlink" title="其他一些node技术栈软件"></a>其他一些node技术栈软件</h2><p>npm install pm2 -g</p>
<p>yum install -y mongodb</p>
<p>常用命令</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># 查看mongo安装位置</span></span><br><span class="line">whereis mongod</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看修改配置文件</span></span><br><span class="line">vi /etc/mongod.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启动mongodb</span></span><br><span class="line">systemctl start mongod.service</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">service mongod start</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重新启动mongodb</span></span><br><span class="line">systemctl restart mongod.service</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">service mongod restart</span><br><span class="line"></span><br><span class="line"><span class="comment"># 停止mongodb</span></span><br><span class="line">systemctl stop mongod.service</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">service mongod stop</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看mongodb的状态</span></span><br><span class="line">systemctl status mongod.service</span><br><span class="line"></span><br><span class="line"><span class="comment"># mongo登录</span></span><br><span class="line">mongo</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看数据库</span></span><br><span class="line">show dbs</span><br></pre></td></tr></table></figure>
<p>用supervisord开机启动,加入配置</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line"><span class="comment"># whereis mongod</span></span><br><span class="line">mongod: /usr/bin/mongod /etc/mongod.conf /usr/share/man/man1/mongod.1.gz</span><br><span class="line"></span><br><span class="line"><span class="comment"># 在 /etc/supervisord.conf 里加入</span></span><br><span class="line">[program:mongodb]</span><br><span class="line"><span class="built_in">command</span>=/usr/bin/mongod -f /etc/mongod.conf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 重启</span></span><br><span class="line">supervisorctl reload</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看目前守护的进程</span></span><br><span class="line">supervisorctl</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>node</category>
</categories>
</entry>
<entry>
<title>在 node 程序中写 es6 语法</title>
<url>/2018/07/05/node/node-es6/</url>
<content><![CDATA[<h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>本人 node 环境是 9.0.0,直接起项目时发现</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ node server.js</span><br><span class="line">/Users/everlose/workspace/fedidea/graphql-server/server.js:1</span><br><span class="line">(<span class="keyword">function</span> (exports, require, module, __filename, __dirname) { import Koa from <span class="string">'koa'</span></span><br><span class="line"> ^^^^^^</span><br><span class="line"></span><br><span class="line">SyntaxError: Unexpected token import</span><br><span class="line"> at createScript (vm.js:80:10)</span><br><span class="line"> at Object.runInThisContext (vm.js:152:10)</span><br><span class="line"> at Module._compile (module.js:605:28)</span><br><span class="line"> at Object.Module._extensions..js (module.js:652:10)</span><br><span class="line"> at Module.load (module.js:560:32)</span><br><span class="line"> at tryModuleLoad (module.js:503:12)</span><br><span class="line"> at Function.Module._load (module.js:495:3)</span><br><span class="line"> at Function.Module.runMain (module.js:682:10)</span><br><span class="line"> at startup (bootstrap_node.js:191:16)</span><br><span class="line"> at bootstrap_node.js:613:3</span><br></pre></td></tr></table></figure>
<p>在本机可以检测 node 所支持的 es6 语法,如下所示,由此可知我本地其他 es6 语法大体上都支持,除了 import 和 export。而 es6 注定绕不过这个。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ node -v</span><br><span class="line">v9.0.0</span><br><span class="line"></span><br><span class="line">$ npm install -g es-checker</span><br><span class="line"></span><br><span class="line">$ es-checker</span><br><span class="line"></span><br><span class="line">ECMAScript 6 Feature Detection (v1.4.1)</span><br><span class="line"></span><br><span class="line">Variables</span><br><span class="line"> √ <span class="built_in">let</span> and const</span><br><span class="line"> √ TDZ error <span class="keyword">for</span> too-early access of <span class="built_in">let</span> or const declarations</span><br><span class="line"> √ Redefinition of const declarations not allowed</span><br><span class="line"> √ destructuring assignments/declarations <span class="keyword">for</span> arrays and objects</span><br><span class="line"> √ ... operator</span><br><span class="line"></span><br><span class="line">Data Types</span><br><span class="line"> √ For...of loop</span><br><span class="line"> √ Map, Set, WeakMap, WeakSet</span><br><span class="line"> √ Symbol</span><br><span class="line"> √ Symbols cannot be implicitly coerced</span><br><span class="line"></span><br><span class="line">Number</span><br><span class="line"> √ Octal (e.g. 0o1 ) and binary (e.g. 0b10 ) literal forms</span><br><span class="line"> √ Old octal literal invalid now (e.g. 01 )</span><br><span class="line"> √ Static <span class="built_in">functions</span> added to Math (e.g. Math.hypot(), Math.acosh(), Math.imul() )</span><br><span class="line"> √ Static <span class="built_in">functions</span> added to Number (Number.isNaN(), Number.isInteger() )</span><br><span class="line"></span><br><span class="line">String</span><br><span class="line"> √ Methods added to String.prototype (String.prototype.includes(), String.prototype.repeat() )</span><br><span class="line"> √ Unicode code-point escape form <span class="keyword">in</span> string literals (e.g. \u{20BB7} )</span><br><span class="line"> √ Unicode code-point escape form <span class="keyword">in</span> identifier names (e.g. var \u{20BB7} = 42; )</span><br><span class="line"> √ Unicode code-point escape form <span class="keyword">in</span> regular expressions (e.g. var regexp = /\u{20BB7}/u; )</span><br><span class="line"> √ y flag <span class="keyword">for</span> sticky regular expressions (e.g. /b/y )</span><br><span class="line"> √ Template String Literals</span><br><span class="line"></span><br><span class="line">Function</span><br><span class="line"> √ arrow <span class="keyword">function</span></span><br><span class="line"> √ default <span class="keyword">function</span> parameter values</span><br><span class="line"> √ destructuring <span class="keyword">for</span> <span class="keyword">function</span> parameters</span><br><span class="line"> √ Inferences <span class="keyword">for</span> <span class="keyword">function</span> name property <span class="keyword">for</span> anonymous <span class="built_in">functions</span></span><br><span class="line"> × Tail-call optimization <span class="keyword">for</span> <span class="keyword">function</span> calls and recursion</span><br><span class="line"></span><br><span class="line">Array</span><br><span class="line"> × Methods added to Array.prototype ([].fill(), [].find(), [].findIndex(), [].entries(), [].keys(), [].values() )</span><br><span class="line"> √ Static <span class="built_in">functions</span> added to Array (Array.from(), Array.of() )</span><br><span class="line"> √ TypedArrays like Uint8Array, ArrayBuffer, Int8Array(), Int32Array(), Float64Array()</span><br><span class="line"> √ Some Array methods (e.g. Int8Array.prototype.slice(), Int8Array.prototype.join(), Int8Array.prototype.forEach() ) added to the TypedArray prototypes</span><br><span class="line"> √ Some Array statics (e.g. Uint32Array.from(), Uint32Array.of() ) added to the TypedArray constructors</span><br><span class="line"></span><br><span class="line">Object</span><br><span class="line"> √ __proto__ <span class="keyword">in</span> object literal definition sets [[Prototype]] link</span><br><span class="line"> √ Static <span class="built_in">functions</span> added to Object (Object.getOwnPropertySymbols(), Object.assign() )</span><br><span class="line"> √ Object Literal Computed Property</span><br><span class="line"> √ Object Literal Property Shorthands</span><br><span class="line"> √ Proxies</span><br><span class="line"> √ Reflect</span><br><span class="line"></span><br><span class="line">Generator and Promise</span><br><span class="line"> √ Generator <span class="keyword">function</span></span><br><span class="line"> √ Promises</span><br><span class="line"></span><br><span class="line">Class</span><br><span class="line"> √ Class</span><br><span class="line"> √ super allowed <span class="keyword">in</span> object methods</span><br><span class="line"> √ class ABC extends Array { .. }</span><br><span class="line"></span><br><span class="line">Module</span><br><span class="line"> × Module <span class="built_in">export</span> <span class="built_in">command</span></span><br><span class="line"> × Module import <span class="built_in">command</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">=========================================</span><br><span class="line">Passes 38 feature Detections</span><br><span class="line">Your runtime supports 90% of ECMAScript 6</span><br><span class="line">=========================================</span><br></pre></td></tr></table></figure>
<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><ol>
<li>安装三个依赖</li>
</ol>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">npm install --save-dev babel-cli babel-preset-stage-2 babel-preset-es2015 babel-plugin-transform-runtime</span><br></pre></td></tr></table></figure>
<p>其中 babel-cli 自带 babel-node 命令</p>
<ol start="2">
<li>修改 package.json 的 script</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="string">"scripts"</span>: {</span><br><span class="line"> <span class="string">"start"</span>: <span class="string">"babel-node server.js"</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure>
<ol start="3">
<li>再加入.babelrc</li>
</ol>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"presets"</span>: [</span><br><span class="line"> <span class="string">"es2015"</span>,</span><br><span class="line"> <span class="string">"stage-2"</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="string">"plugins"</span>: [<span class="string">"transform-runtime"</span>]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<ol start="4">
<li>最后运行 <code>npm run start</code> 启动程序</li>
</ol>
<h2 id="如果要在-vscode-中调试-es6-代码"><a href="#如果要在-vscode-中调试-es6-代码" class="headerlink" title="如果要在 vscode 中调试 es6 代码"></a>如果要在 vscode 中调试 es6 代码</h2><p>在 package.json 里加入一下代码,能将除了 node_modules 以外的代码都打包入 dist 文件夹</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">"scripts": {</span><br><span class="line"> // 省略其他...</span><br><span class="line"> "build": "babel ./ --ignore node_modules -d dist --source-maps",</span><br><span class="line">},</span><br></pre></td></tr></table></figure>
<p>接着在 .vscode 文件夹下加入 task.json</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"version"</span>: <span class="string">"0.1.0"</span>,</span><br><span class="line"> <span class="string">"command"</span>: <span class="string">"npm"</span>,</span><br><span class="line"> <span class="string">"isShellCommand"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"showOutput"</span>: <span class="string">"always"</span>,</span><br><span class="line"> <span class="string">"suppressTaskName"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"tasks"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"taskName"</span>: <span class="string">"build"</span>,</span><br><span class="line"> <span class="string">"args"</span>: [ <span class="string">"run"</span>, <span class="string">"build"</span> ],</span><br><span class="line"> <span class="string">"isBuildCommand"</span>: <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>再于 .vscode 加入 launch.json </p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="comment">// 使用 IntelliSense 了解相关属性。</span></span><br><span class="line"> <span class="comment">// 悬停以查看现有属性的描述。</span></span><br><span class="line"> <span class="comment">// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387</span></span><br><span class="line"> <span class="string">"version"</span>: <span class="string">"0.1.0"</span>,</span><br><span class="line"> <span class="string">"configurations"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"Launch"</span>,</span><br><span class="line"> <span class="string">"type"</span>: <span class="string">"node"</span>,</span><br><span class="line"> <span class="string">"request"</span>: <span class="string">"launch"</span>,</span><br><span class="line"> <span class="string">"program"</span>: <span class="string">"${workspaceRoot}/server.js"</span>,</span><br><span class="line"> <span class="string">"stopOnEntry"</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="string">"args"</span>: [],</span><br><span class="line"> <span class="string">"cwd"</span>: <span class="string">"${workspaceRoot}"</span>,</span><br><span class="line"> <span class="string">"preLaunchTask"</span>: <span class="string">"build"</span>,</span><br><span class="line"> <span class="string">"runtimeExecutable"</span>: <span class="literal">null</span>,</span><br><span class="line"> <span class="string">"runtimeArgs"</span>: [ <span class="string">"--nolazy"</span> ],</span><br><span class="line"> <span class="string">"env"</span>: {</span><br><span class="line"> <span class="string">"NODE_ENV"</span>: <span class="string">"development"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">"console"</span>: <span class="string">"integratedTerminal"</span>,</span><br><span class="line"> <span class="string">"sourceMaps"</span>: <span class="literal">true</span>,</span><br><span class="line"> <span class="string">"outFiles"</span>: [<span class="string">"${workspaceRoot}/dist/*.js"</span>]</span><br><span class="line"> }</span><br><span class="line"> ]</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>最后按F5启动,每次启动都会由 preLaunchTask 来预先 运行 build task 来把 es6 代码编译了,再启动</p>
]]></content>
<categories>
<category>node</category>
</categories>
</entry>
<entry>
<title>JS 对象内部属性遍历的顺序乱了</title>
<url>/2018/06/14/javascript/object-property-order/</url>
<content><![CDATA[<h2 id="问题重现"><a href="#问题重现" class="headerlink" title="问题重现"></a>问题重现</h2><p>需求是要获取一个车型列表,并且输出到页面上按年份排序,故而接口提供的对象简化如下</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = {</span><br><span class="line"> <span class="string">'2018'</span>: {</span><br><span class="line"> modelCode: <span class="string">"204313"</span>,</span><br><span class="line"> modelName: <span class="string">"2018款 Vanquish 6.0L S Coupe"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">'2017'</span>: {</span><br><span class="line"> modelCode: <span class="string">"202479"</span>,</span><br><span class="line"> modelName: <span class="string">"2017款 Rapide 6.0L AMR"</span></span><br><span class="line"> },</span><br><span class="line"> <span class="string">'2013'</span>: {</span><br><span class="line"> modelCode: <span class="string">"139705"</span>,</span><br><span class="line"> modelName: <span class="string">"2013款 Rapide 6.0L S"</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(obj)</span><br><span class="line"><span class="comment">// {2013: {…}, 2017: {…}, 2018: {…}}</span></span><br></pre></td></tr></table></figure>
<p>??? 为什么 2013 在前面了,用户肯定希望先看到新的车型的,这不科学!</p>
<h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><p>查阅了一些文档后,得出了以下有效结论:</p>
<ol>
<li>An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive value, object, or function. A function stored in a property of an object is called a method.</li>
<li>Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历书序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。</li>
</ol>
<p>而 Chrome Opera 中使用 for-in 语句遍历对象属性时会遵循一个规律:</p>
<p><strong>它们会先提取所有 key 的 parseFloat 值为非负整数的属性,然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。</strong></p>
<h2 id="猜想"><a href="#猜想" class="headerlink" title="猜想"></a>猜想</h2><p>按照上面的解释,那么我来一个例子</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> obj = {</span><br><span class="line"> <span class="string">'a'</span>: <span class="string">'testa'</span>,</span><br><span class="line"> <span class="string">'1'</span>: <span class="string">'test1'</span>,</span><br><span class="line"> <span class="string">'测'</span>: <span class="string">'test测'</span>,</span><br><span class="line"> <span class="string">'2'</span>: <span class="string">'test2'</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">Object</span>.keys(obj));</span><br><span class="line"></span><br><span class="line"><span class="comment">// [1, 2, 'a', '测']</span></span><br></pre></td></tr></table></figure>
<p>果然会把 ‘1’ 和 ‘2’ 这种能被 parseFloat 转化为正整数的提到前面并且按照升序排</p>
<p>而 ‘a’ 和 ‘测’ 没法转为整数那就排在 ‘1’、’2’ 后并按照构建时的顺序拍</p>
<h2 id="解决问题"><a href="#解决问题" class="headerlink" title="解决问题"></a>解决问题</h2><p>回到问题,对象既然不能保证其顺序,那么使用数组来进行遍历吧。</p>
<p>当然业务中如果需要查某个年份的车型,而不想要每次都遍历一遍的来找的话。可以维护两份数据。一份数组,用于遍历输出,一份对象,用于查。</p>
<h2 id="参照"><a href="#参照" class="headerlink" title="参照"></a>参照</h2><p><a href="http://jartto.wang/2016/10/25/does-js-guarantee-object-property-order/" target="_blank" rel="noopener">js能够保证object属性的输出顺序吗?</a></p>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>为什么 0.1 + 0.2 !== 0.3</title>
<url>/2018/03/27/javascript/why-0.1+0.2!==0.3/</url>
<content><![CDATA[<h2 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h2><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="number">0.1</span> + <span class="number">0.2</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//0.30000000000000004</span></span><br></pre></td></tr></table></figure>
<h2 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h2><p>浮点数在计算机中的表示是用阶码与尾数结合的形式。</p>
<p>0.75 的二进制表现模式就是<code>(1 + 1 * 2 ^ -1) * 2 ^ -1</code>,为了看得直观,这里表达式中的2没有用10来表示</p>
<p>二进制中<code>2 ^ -1</code>表示的其实是十进制中的0.5。想想十进制中幂次方多1代表数值10倍,那么二进制中幂次方多1代表数值2倍。</p>
<p>0.75 在二进制中是可以妥善表现出来的。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> num = <span class="number">0.75</span>;</span><br><span class="line">num.toString(<span class="number">2</span>);</span><br><span class="line"><span class="comment">// 0.11</span></span><br></pre></td></tr></table></figure>
<p>而0.1在二进制中却是一个表现不出来的无限不循环数,所以只能取一个近似数。</p>
<p>而计算机精度有限,所能表现的值而非真正的0.1,0.2,所以自然相加时有偏差</p>
<h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="number">0.1</span> + <span class="number">0.2</span> <span class="comment">// 0.30000000000000004</span></span><br><span class="line">(<span class="number">0.1</span> + <span class="number">0.2</span>).toFixed(<span class="number">2</span>) <span class="comment">// "0.30"</span></span><br><span class="line"><span class="built_in">parseFloat</span>((<span class="number">0.1</span> + <span class="number">0.2</span>).toFixed(<span class="number">2</span>)) <span class="comment">// 0.3</span></span><br><span class="line"></span><br><span class="line"><span class="number">24.99</span> * <span class="number">10000</span> <span class="comment">// 249899.99999999997</span></span><br><span class="line"><span class="built_in">parseFloat</span>((<span class="number">24.99</span> * <span class="number">10000</span>).toFixed(<span class="number">2</span>)); <span class="comment">// 249900</span></span><br></pre></td></tr></table></figure>
<p>But why ? see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-number.prototype.tofixed" target="_blank" rel="noopener">es6文档 20.1.3.3 Number.prototype.toFixed ( fractionDigits ) </a></p>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>浏览器市场份额统计</title>
<url>/2018/03/18/browser/browser-market-share/</url>
<content><![CDATA[<p>根据此站点显示的份额统计 <a href="http://gs.statcounter.com/browser-market-share/desktop/china" target="_blank" rel="noopener">http://gs.statcounter.com/browser-market-share/desktop/china</a></p>
<p><img src="http://7xn4mw.com1.z0.glb.clouddn.com/18-8-5/97324376.jpg" alt=""></p>
<p>chrome 占比在50%上下,半壁江山。</p>
]]></content>
<categories>
<category>browser</category>
</categories>
</entry>
<entry>
<title>简述浏览器渲染流程</title>
<url>/2018/03/07/browser/chrome-rendering/</url>
<content><![CDATA[<h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><p>chrome –》 Timeline</p>
<p><img src="http://images2015.cnblogs.com/blog/751661/201702/751661-20170210141057729-386070939.png" alt=""></p>
<h2 id="解释"><a href="#解释" class="headerlink" title="解释"></a>解释</h2><p>浏览器的渲染过程</p>
<ol>
<li>Create/Update DOM And request css/image/js:浏览器请求到HTML代码后,在生成DOM的最开始阶段(应该是 Bytes → characters 后),并行发起css、图片、js的请求,无论他们是否在HEAD里。</li>
</ol>
<p>注意:发起 js 文件的下载 request 并不需要 DOM 处理到那个 script 节点,比如:简单的正则匹配就能做到这一点,虽然实际上并不一定是通过正则:)。这是很多人在理解渲染机制的时候存在的误区。</p>
<ol start="2">
<li><p>Create/Update Render CSSOM:CSS文件下载完成,开始构建CSSOM</p>
</li>
<li><p>Create/Update Render Tree:所有CSS文件下载完成,CSSOM构建结束后,和 DOM 一起生成 Render Tree。</p>
</li>
<li><p>Layout:有了Render Tree,浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系。下一步操作称之为Layout,顾名思义就是计算出每个节点在屏幕中的位置。</p>
</li>
<li><p>Painting:Layout后,浏览器已经知道了哪些节点要显示(which nodes are visible)、每个节点的CSS属性是什么(their computed styles)、每个节点在屏幕中的位置是哪里(geometry)。就进入了最后一步:Painting,按照算出来的规则,通过显卡,把内容画到屏幕上。</p>
</li>
</ol>
<p>以上五个步骤前3个步骤之所有使用 “Create/Update” 是因为DOM、CSSOM、Render Tree都可能在第一次Painting后又被更新多次,比如JS修改了DOM或者CSS属性。</p>
<p>Layout 和 Painting 也会被重复执行,除了DOM、CSSOM更新的原因外,图片下载完成后也需要调用Layout 和 Painting来更新网页。</p>
<h4 id="重绘"><a href="#重绘" class="headerlink" title="重绘"></a>重绘</h4><p>当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作。</p>
<h4 id="回流"><a href="#回流" class="headerlink" title="回流"></a>回流</h4><p>当改变的操作响应文档内容或者结构,或者元素位置时,就会触发回流。有以下几种情况:</p>
<ul>
<li>页面首次渲染</li>
<li>DOM操作(对元素的增删改、顺序变化等)</li>
<li>内容变化,包括表单区域内的文本变化</li>
<li>css属性的更改或者重新计算</li>
<li>增删样式表内容</li>
<li>修改class属性</li>
<li>浏览器窗口变化(滚动或缩放)</li>
<li>伪类样式激活(:hover等)</li>
</ul>
<p>一些常用且会导致回流的属性和方法:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">clientWidth、clientHeight、clientTop、clientLeft</span><br><span class="line">offsetWidth、offsetHeight、offsetTop、offsetLeft</span><br><span class="line">scrollWidth、scrollHeight、scrollTop、scrollLeft</span><br><span class="line">scrollIntoView()、scrollIntoViewIfNeeded()</span><br><span class="line">getComputedStyle()</span><br><span class="line">getBoundingClientRect()</span><br><span class="line">scrollTo()</span><br></pre></td></tr></table></figure>
<h2 id="css和js执行的时机"><a href="#css和js执行的时机" class="headerlink" title="css和js执行的时机"></a>css和js执行的时机</h2><p>css和js在chrome浏览器里都是并行下载的,只是执行时机不同。</p>
<p>CSS是一种渲染阻塞资源,它需要完全被解析完毕之后才能进入生成渲染树的环节。CSS并不像HTML那样能执行部分并显示,因为CSS具有继承属性, 后面定义的样式会覆盖或者修改前面的样式。如果我们只使用样式表中部分解析好的样式,我们可能会得到错误的页面效果。所以,我们只能等待CSS完全解析之后,才能进入关键渲染路径的下一环节。</p>
<p>Js脚本执行应该实在CSSOM生成之后,所以说CSS也会阻塞脚本(script blocking)。按script标签出现的顺序逐个执行,证据是jsonp请求之前必须定义全局方法,而jsonp请求后再定义全局方法将无效。</p>
<h2 id="问题的答案"><a href="#问题的答案" class="headerlink" title="问题的答案"></a>问题的答案</h2><p>问题:script标签的位置会影响首屏时间么?</p>
<p>分析:“页面渲染出来了” 指的是什么?</p>
<ol>
<li>没有图片的首屏(后面统称StepA)</li>
<li>显示了全部图片的首屏(后面统称StepB)</li>
<li>页面完整地加载好了(后面统称StepC)</li>
</ol>
<p>答:如果 “页面渲染出来了” 指的是StepA,那么问题变成:script标签的位置会影响首屏时间么?</p>
<p>不影响(如果这里的首屏指的是页面从白板变成网页画面——也就是第一次Painting),但有可能截断首屏的内容,使其只显示上面一部分。</p>
<p>如果 “页面渲染出来了” 指的是 StepC,那么script标签不放在body底部不会拖慢页面完整地加载好的时间。</p>
<h2 id="script-的-defer属性"><a href="#script-的-defer属性" class="headerlink" title="script 的 defer属性"></a>script 的 defer属性</h2><p>如果 async=”async”:脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)</p>
<p>如果不使用 async 且 defer=”defer”:脚本将在页面完成解析时执行</p>
<p>如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"><script defer="defer"></span><br></pre></td></tr></table></figure>
<p>有了这条属性,script标签放在头部也不要紧。</p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="http://www.cnblogs.com/Christeen/p/6524797.html" target="_blank" rel="noopener">http://www.cnblogs.com/Christeen/p/6524797.html</a></p>
<p><a href="http://www.cnblogs.com/BurtBlog/p/6386195.html#commentform" target="_blank" rel="noopener">http://www.cnblogs.com/BurtBlog/p/6386195.html#commentform</a></p>
]]></content>
<categories>
<category>browser</category>
</categories>
</entry>
<entry>
<title>树的深搜与广搜</title>
<url>/2018/03/06/alorigam/tree-traversal/</url>
<content><![CDATA[<h2 id="深搜,递归"><a href="#深搜,递归" class="headerlink" title="深搜,递归"></a>深搜,递归</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">deepTraversal</span>(<span class="params">node</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (node != <span class="literal">null</span>) {</span><br><span class="line"> <span class="built_in">console</span>.log(node);</span><br><span class="line"> <span class="keyword">let</span> children = node.children;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < children.length; i++) {</span><br><span class="line"> deepTraversal(children[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">deepTraversal(<span class="built_in">document</span>.body);</span><br><span class="line"><span class="string">``</span><span class="string">` </span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">## 广搜,非递归</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">`</span><span class="string">``</span>js</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">wideTraversal</span>(<span class="params">node</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> queue = [];</span><br><span class="line"> <span class="keyword">if</span> (node != <span class="literal">null</span>) {</span><br><span class="line"> <span class="built_in">console</span>.log(node);</span><br><span class="line"> queue.unshift(node);</span><br><span class="line"> <span class="keyword">while</span> (queue.length != <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">let</span> item = queue.shift();</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'search: '</span> , item );</span><br><span class="line"> <span class="keyword">let</span> children = item.children;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < children.length; i++)</span><br><span class="line"> queue.push(children[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> queue;</span><br><span class="line">}</span><br><span class="line">wideTraversal(<span class="built_in">document</span>.body);</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>alorigam</category>
</categories>
</entry>
<entry>
<title>浏览器的重绘与回流(Reflow & Repaint)</title>
<url>/2018/03/06/browser/reflow-repaint/</url>
<content><![CDATA[<h2 id="重绘"><a href="#重绘" class="headerlink" title="重绘"></a>重绘</h2><p>当页面元素样式改变不影响元素在文档流中的位置时(如background-color,border-color,visibility),浏览器只会将新样式赋予元素并进行重新绘制操作。</p>
<h2 id="回流"><a href="#回流" class="headerlink" title="回流"></a>回流</h2><p>当改变的操作响应文档内容或者结构,或者元素位置时,就会触发回流。有以下几种情况:</p>
<ul>
<li>页面首次渲染</li>
<li>DOM操作(对元素的增删改、顺序变化等)</li>
<li>内容变化,包括表单区域内的文本变化</li>
<li>css属性的更改或者重新计算</li>
<li>增删样式表内容</li>
<li>修改class属性</li>
<li>浏览器窗口变化(滚动或缩放)</li>
<li>伪类样式激活(:hover等)</li>
</ul>
<p>一些常用且会导致回流的属性和方法:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">clientWidth、clientHeight、clientTop、clientLeft</span><br><span class="line">offsetWidth、offsetHeight、offsetTop、offsetLeft</span><br><span class="line">scrollWidth、scrollHeight、scrollTop、scrollLeft</span><br><span class="line">scrollIntoView()、scrollIntoViewIfNeeded()</span><br><span class="line">getComputedStyle()</span><br><span class="line">getBoundingClientRect()</span><br><span class="line">scrollTo()</span><br></pre></td></tr></table></figure>
<h2 id="性能影响"><a href="#性能影响" class="headerlink" title="性能影响"></a>性能影响</h2><p>回流比重绘的代价要更高。</p>
<p>有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。</p>
<p>现代浏览器会对频繁的回流或重绘操作进行优化:</p>
<p>浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。</p>
<p>当你访问以下属性或方法时,浏览器会立刻清空队列:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">clientWidth、clientHeight、clientTop、clientLeft</span><br><span class="line">offsetWidth、offsetHeight、offsetTop、offsetLeft</span><br><span class="line">scrollWidth、scrollHeight、scrollTop、scrollLeft</span><br><span class="line">scrollIntoView()、scrollIntoViewIfNeeded()</span><br><span class="line">getComputedStyle()</span><br><span class="line">getBoundingClientRect()</span><br><span class="line">scrollTo()</span><br></pre></td></tr></table></figure>
<p>因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。</p>
<h2 id="如何避免频繁的回流"><a href="#如何避免频繁的回流" class="headerlink" title="如何避免频繁的回流"></a>如何避免频繁的回流</h2><h4 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h4><ul>
<li>避免使用table布局。</li>
<li>尽可能在DOM树的最末端改变class。</li>
<li>避免设置多层内联样式。</li>
<li>将动画效果应用到position属性为absolute或fixed的元素上。</li>
<li>避免使用CSS表达式(例如:calc())。</li>
</ul>
<h4 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h4><ul>
<li>避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。</li>
<li>避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。</li>
<li>也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。</li>
<li>避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。</li>
<li>对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。</li>
</ul>
]]></content>
<categories>
<category>browser</category>
</categories>
</entry>
<entry>
<title>js 变量类型检测</title>
<url>/2018/01/18/javascript/variable-type-checking/</url>
<content><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>javascript的变量类型分为原始类型和引用类型。</p>
<ul>
<li>原始类型有6种, 注意多了 Symbol<ul>
<li>Number</li>
<li>String</li>
<li>Boolean</li>
<li>Null</li>
<li>Undefined</li>
<li>Symbol</li>
</ul>
</li>
<li>引用类型包括<ul>
<li>Function</li>
<li>Array</li>
<li>Date</li>
<li>Object</li>
<li>RegExp</li>
</ul>
</li>
</ul>
<p>而检测这些类型的变量有3种办法:<code>typeof</code>,<code>instanceof</code>,<code>Object.prototype.toString.call</code>。让我来一一例举,废话不多说,上代码。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//首先是typeof</span></span><br><span class="line"><span class="keyword">var</span> obj = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"number"</span></span><br><span class="line">obj = <span class="string">"abc"</span></span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"string"</span></span><br><span class="line">obj = <span class="literal">false</span></span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"boolean"</span></span><br><span class="line">obj = <span class="literal">undefined</span>;</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"undefined"</span></span><br><span class="line">obj = <span class="literal">null</span>;</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"object",WTF,其实这是js的一个bug,人艰不拆 T_T</span></span><br><span class="line">obj = <span class="built_in">Symbol</span>();</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"symbol"</span></span><br><span class="line"></span><br><span class="line">obj = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{};</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"function"</span></span><br><span class="line">obj = [];</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"object"</span></span><br><span class="line">obj = {};</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"object"</span></span><br><span class="line">obj = <span class="regexp">/w/g</span>;</span><br><span class="line"><span class="keyword">typeof</span> obj <span class="comment">//"object"</span></span><br></pre></td></tr></table></figure>
<p>从上面我们可以得出type能检测原始类型<code>number</code>,<code>string</code>,<code>boolean</code>,<code>undefined</code>,引用类型的<code>function</code>。但是对于数组和对象却是无法区分。</p>
<p>而关于引用类型,还可以尝试下<code>instanceof</code>操作符。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{};</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">Function</span>; <span class="comment">//true</span></span><br><span class="line">obj = [];</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">Array</span>; <span class="comment">//true</span></span><br><span class="line">obj = {};</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">Object</span>; <span class="comment">//true</span></span><br><span class="line">obj = <span class="keyword">new</span> <span class="built_in">Date</span>()</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">Date</span>; <span class="comment">//true</span></span><br><span class="line">obj = <span class="regexp">/w/g</span>;</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">RegExp</span>; <span class="comment">//true</span></span><br><span class="line"><span class="comment">//....wait for it, 事情其实还没完呢</span></span><br><span class="line">obj = [];</span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">Object</span>; <span class="comment">//true 所有引用类型其实都是继承自Object对象的,所以你懂的。</span></span><br></pre></td></tr></table></figure>
<p>incetanceof 操作符能鉴别引用类型,可惜有个缺憾是,如果想鉴别一个变量object类型而不是其他的<code>function</code>,<code>array</code>,<code>date</code>什么的,仍然需要花一番力气。</p>
<p>这里我们是不是漏了什么,如果..</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="keyword">new</span> <span class="built_in">String</span>(<span class="string">'abc'</span>);</span><br><span class="line"><span class="keyword">typeof</span> obj; <span class="comment">//"object" 。 </span></span><br><span class="line">obj <span class="keyword">instanceof</span> <span class="built_in">String</span>; <span class="comment">//true 。</span></span><br></pre></td></tr></table></figure>
<p>天了个撸,不能愉快玩耍了。要解释这个, 就得解释js里变量的赋值规则。 </p>
<ul>
<li>原始类型的变量直接保存原始值,而不是一个指向对象的指针。如果一个变量赋值给另一个变量,那么每个变量都它自己的一份数据拷贝,并不会相互影响。</li>
<li>引用类型的变量保存的是一个指向内存中实际对象所在的指针(或者说引用)。因此当你将一个对象赋值给变量时,实际是赋值给这个变量一个指针。意味着将一个变量赋值给另一个变量时,两个变量指向的是内存中同一个对象。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="string">'abc'</span>;</span><br><span class="line">obj.something = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">var</span> firstChar = obj.charAt(<span class="number">0</span>); <span class="comment">//"a"</span></span><br><span class="line"><span class="built_in">console</span>.log(obj.something); <span class="comment">//undefined</span></span><br><span class="line"><span class="comment">//实际上js做了这样的处理</span></span><br><span class="line"><span class="keyword">var</span> obj = <span class="string">'abc'</span>;</span><br><span class="line"><span class="keyword">var</span> temp = <span class="keyword">new</span> <span class="built_in">String</span>(obj);</span><br><span class="line"><span class="keyword">var</span> firstChar = temp.charAt(<span class="number">0</span>); <span class="comment">//"a"</span></span><br><span class="line">temp.something = <span class="number">1</span>;</span><br><span class="line">temp = <span class="literal">null</span>;</span><br><span class="line"><span class="built_in">console</span>.log(obj.something); <span class="comment">//undefined</span></span><br></pre></td></tr></table></figure>
<p>创建了一个临时的引用类型变量去访问属性,修改属性,然后就被释放了,扯远了。</p>
<p>总而言之,如果指定<code>obj = "abc"</code>则obj保存的实际上就是abc的值,是一个基本类型。而如果指定<code>obj = new String('abc')</code>那么obj实际上保存的是一个指向字符串对象的指针。所以就不难理解两者对于<code>typeof</code>和<code>instanceof</code>的差别了<br>额,读者:“说了这么多,你有没有一种万全的手段哇”。好吧, 我们来一个简单又粗暴的鉴别手段。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="number">1</span>;</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Number]'</span>; <span class="comment">//true</span></span><br><span class="line">obj = <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">1</span>);</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Number]'</span>; <span class="comment">//true</span></span><br><span class="line">obj = <span class="built_in">Symbol</span>();</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Symbol]'</span>; <span class="comment">//true</span></span><br><span class="line"></span><br><span class="line">obj = [];</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Array]'</span>; <span class="comment">//true</span></span><br><span class="line">obj = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Array]'</span>; <span class="comment">//true</span></span><br><span class="line"><span class="built_in">Object</span>.prototype.toString.call(obj) === <span class="string">'[object Object]'</span>; <span class="comment">//false</span></span><br></pre></td></tr></table></figure>
<p>这个方法是不是很好用呢, 哇哈哈哈哈。</p>
<p><strong>总结归纳了下,我列举了一些校验函数:</strong></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//低版本ie中undefined变量可以被修改,所以使用void 0 获取真实的undefined值,</span></span><br><span class="line"><span class="keyword">var</span> isUndefined = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//or: return typeof obj === 'undefined';</span></span><br><span class="line"> <span class="keyword">return</span> obj === <span class="keyword">void</span> <span class="number">0</span>;</span><br><span class="line">};</span><br><span class="line"><span class="comment">//typeof null 的结果是"object"。</span></span><br><span class="line"><span class="keyword">var</span> isNull = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> obj === <span class="literal">null</span>;</span><br><span class="line">};</span><br><span class="line"><span class="comment">// boolean值,number值和string值需要考虑两种情况,值为字面量时使用typeof和Object.prototype.toString能检测; </span></span><br><span class="line"><span class="comment">// 值为构造函数构建的时候需要使用Object.prototype.toString或者instanceof检测</span></span><br><span class="line"><span class="keyword">var</span> isBoolean = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Boolean]'</span>;</span><br><span class="line">};</span><br><span class="line"><span class="keyword">var</span> isNumber = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Number]'</span>;</span><br><span class="line">};</span><br><span class="line"><span class="keyword">var</span> isString = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object String]'</span>;</span><br><span class="line">};</span><br><span class="line"><span class="keyword">var</span> isSymbol = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Symbol]'</span>;</span><br><span class="line">};</span><br><span class="line"><span class="keyword">var</span> <span class="built_in">isNaN</span> = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> obj !== obj;</span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="comment">//typeof 操作符在引用类型的变量里能对function有效。</span></span><br><span class="line"><span class="keyword">var</span> isFunction = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//or: return Object.prototype.toString.call(obj) == '[object Function]';</span></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> obj === <span class="string">'function'</span>;</span><br><span class="line"></span><br><span class="line">};</span><br><span class="line"><span class="keyword">var</span> isDate = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Date]'</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> isArray = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Array]'</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> isObject = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//or: return obj === Object(obj);</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object Object]'</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> isRegExp = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//or: return obj === Object(obj);</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(obj) == <span class="string">'[object RegExp]'</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> has = <span class="function"><span class="keyword">function</span>(<span class="params">obj, key</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.hasOwnProperty.call(obj, key);</span><br><span class="line">};</span><br><span class="line"><span class="comment">//判断数组,字符串,对象是否为空</span></span><br><span class="line"><span class="keyword">var</span> isEmpty = <span class="function"><span class="keyword">function</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (obj == <span class="literal">null</span>) <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (isArray(obj) || isString(obj)) <span class="keyword">return</span> obj.length === <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> key <span class="keyword">in</span> obj) <span class="keyword">if</span> (has(obj, key)) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h2 id="最后再来一个好用的识别方法"><a href="#最后再来一个好用的识别方法" class="headerlink" title="最后再来一个好用的识别方法"></a>最后再来一个好用的识别方法</h2><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getType</span>(<span class="params">p</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (obj === <span class="keyword">void</span> <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'Undefined'</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (obj === <span class="literal">null</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'Null'</span>;</span><br><span class="line"> }</span><br><span class="line"> /<span class="function"><span class="keyword">function</span>.(<span class="params">\w*</span>)\(<span class="params">\</span>)/.<span class="title">test</span>(<span class="params">p.constructor</span>); //通过其构造函数来获取对应的类型。</span></span><br><span class="line"><span class="function"> <span class="title">return</span> <span class="title">RegExp</span>.<span class="title">$1</span>;</span></span><br><span class="line"><span class="function">}</span></span><br><span class="line"><span class="function"><span class="title">getType</span>(<span class="params"><span class="string">'1'</span></span>); //"<span class="title">String</span>"</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>new 操作符都做了什么</title>
<url>/2018/01/18/javascript/what-does-new-in-js-do/</url>
<content><![CDATA[<h2 id="解答"><a href="#解答" class="headerlink" title="解答"></a>解答</h2><p>stackoverflow 原提问,<a href="https://stackoverflow.com/questions/9468055/what-does-new-in-javascript-do-anyway" target="_blank" rel="noopener">https://stackoverflow.com/questions/9468055/what-does-new-in-javascript-do-anyway</a></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">new</span> f(a, b, c)</span><br></pre></td></tr></table></figure>
<p>is eaqal to </p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// Create a new instance using f's prototype.</span></span><br><span class="line"><span class="keyword">var</span> newInstance = <span class="built_in">Object</span>.create(f.prototype), result;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Call the function</span></span><br><span class="line">result = f.call(newInstance, a, b, c);</span><br><span class="line"></span><br><span class="line"><span class="comment">// If the result is a non-null object, use it, otherwise use the new instance.</span></span><br><span class="line">result && <span class="keyword">typeof</span> result === <span class="string">'object'</span> ? result : newInstance;</span><br></pre></td></tr></table></figure>
<h2 id="testing"><a href="#testing" class="headerlink" title="testing"></a>testing</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> f = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.test = <span class="number">1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> newInstance = <span class="built_in">Object</span>.create(f.prototype), result;</span><br><span class="line"></span><br><span class="line">result = f.call(newInstance);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(result, <span class="string">'--'</span>, newInstance);</span><br><span class="line"><span class="comment">// undefined -- f {test: 1}</span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> f = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.test = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> newInstance = <span class="built_in">Object</span>.create(f.prototype), result;</span><br><span class="line"></span><br><span class="line">result = f.call(newInstance);</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(result, <span class="string">'--'</span>, newInstance);</span><br><span class="line"><span class="comment">// f {test: 1} -- f {test: 1}</span></span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>ES6 标准研读笔记</title>
<url>/2018/01/16/javascript/es6-standard-reading/</url>
<content><![CDATA[<p>阮一峰,读懂 ECMAScript 规格:<a href="http://www.ruanyifeng.com/blog/2015/11/ecmascript-specification.html" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2015/11/ecmascript-specification.html</a></p>
<p><a href="http://www.ecma-international.org/ecma-262/6.0/" target="_blank" rel="noopener">ES6标准在线英文文档</a></p>
<p><a href="https://www.w3.org/html/ig/zh/wiki/ES5#.E8.AF.8D.E6.B3.95" target="_blank" rel="noopener">wiki百科ES5中文翻译</a></p>
<p><a href="某个人整理的ES5中文翻译">http://yanhaijing.com/es5</a></p>
<h2 id="有人问-obj-sub-amp-amp-obj-sub-name-为什么返回的不是一个bool值,而是name值。"><a href="#有人问-obj-sub-amp-amp-obj-sub-name-为什么返回的不是一个bool值,而是name值。" class="headerlink" title="有人问 obj.sub && obj.sub.name 为什么返回的不是一个bool值,而是name值。"></a>有人问 obj.sub && obj.sub.name 为什么返回的不是一个bool值,而是name值。</h2><p>翻了翻es5标准,得到<a href="https://www.w3.org/html/ig/zh/wiki/ES5/%E8%A1%A8%E8%BE%BE%E5%BC%8F" target="_blank" rel="noopener">ES5/表达式</a>找到如下答案。</p>
<p>二元按位运算符</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">LogicalANDExpression :</span><br><span class="line"> BitwiseORExpression</span><br><span class="line"> LogicalANDExpression && BitwiseORExpression</span><br></pre></td></tr></table></figure>
<p>语义:</p>
<p>产生式 LogicalANDExpression : LogicalANDExpression && BitwiseORExpression 按照下面的过程执行:</p>
<ol>
<li>令 lref 为解释执行 LogicalANDExpression 的结果。</li>
<li>令 lval 为 GetValue(lref)。</li>
<li>如果 ToBoolean(lval) 为 false,返回 lval。</li>
<li>令 rref 为解释执行 BitwiseORExpression 的结果。</li>
<li>返回 GetValue(rref)。</li>
</ol>
<p>总之如果左表达式执行后不能转化为false,那么返回右表达式的value</p>
<h2 id="toFixed为何能解决js浮点数运算问题"><a href="#toFixed为何能解决js浮点数运算问题" class="headerlink" title="toFixed为何能解决js浮点数运算问题"></a>toFixed为何能解决js浮点数运算问题</h2><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="number">0.1</span> + <span class="number">0.2</span> <span class="comment">// 0.30000000000000004</span></span><br><span class="line">(<span class="number">0.1</span> + <span class="number">0.2</span>).toFixed(<span class="number">2</span>) <span class="comment">// "0.30"</span></span><br><span class="line"><span class="built_in">parseFloat</span>((<span class="number">0.1</span> + <span class="number">0.2</span>).toFixed(<span class="number">2</span>)) <span class="comment">// 0.3</span></span><br><span class="line"></span><br><span class="line"><span class="number">24.99</span>*<span class="number">10000</span> <span class="comment">// 249899.99999999997</span></span><br><span class="line"><span class="built_in">parseFloat</span>((<span class="number">24.99</span>*<span class="number">10000</span>).toFixed(<span class="number">2</span>)); <span class="comment">// 249900</span></span><br></pre></td></tr></table></figure>
<p>toFixed解决精度问题,parseFloat解决不定小数点问题。那么问题来了,为何toFixed能够解决精度问题,而非简单的省却小数点做法。翻开<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-number.prototype.tofixed" target="_blank" rel="noopener">es6文档 20.1.3.3 Number.prototype.toFixed ( fractionDigits ) 有答案</a></p>
<p>注意最为关键的一步</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Number.prototype.toFixed ( fractionDigits )</span><br><span class="line"></span><br><span class="line">1. Let x be thisNumberValue(this value).</span><br><span class="line">2. ReturnIfAbrupt(x).</span><br><span class="line">3. Let f be ToInteger(fractionDigits). (If fractionDigits is undefined, this step produces the value 0).</span><br><span class="line">...</span><br><span class="line">10. Else x < 10^21,</span><br><span class="line"> a. Let n be an integer for which the exact mathematical value of n ÷ 10f – x is as close to zero as possible. If there are two such n, pick the larger n.</span><br><span class="line">...</span><br></pre></td></tr></table></figure>
<p>令 x 为运算结果的数值,令 f 为toFixed的参数转化的数值。</p>
<p>如果x小于10的21次方,则令 n 为一个整数,让 (n / 10^f – x) 准确的数学值尽可能接近零。如果有两个这样 n 值,选择较大的 n。</p>
<p>也就是意味着(0.1 + 0.2).toFixed(2)时,n值为300则其运算结果最接近0。</p>
<p>另外注意标准里 fractionDigits 小于 0 或大于 20 时会抛出 RangeError 错误,而在 Chrome 62 版浏览器中笔者亲测小于 0 或大于 100 才会抛出</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(0.1 + 0.2).toFixed(101)</span><br><span class="line">VM586:1 Uncaught RangeError: toFixed() digits argument must be between 0 and 100</span><br><span class="line"> at Number.toFixed (<anonymous>)</span><br><span class="line"> at <anonymous>:1:13</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>javascript</category>
</categories>
</entry>
<entry>
<title>video 标签加载视频有声音却黑屏</title>
<url>/2018/01/14/mobile-h5/video-black/</url>
<content><![CDATA[<p>昨天用户上传了一个<a href="http://ukee.oss-cn-shanghai.aliyuncs.com/admin/cover/2018-1-4/71aff139-3fbc-4b82-9d7a-d693715edb25.mp4?avinfo" target="_blank" rel="noopener">视频文件</a>,然而发现虽然有声音但是黑屏。</p>
<p>因为原视频的编码是用mpeg-4标准的,chrome并不支持,所以无法播放</p>
<p>然后如果用转码功能转成用h.264编码,就可以播放了</p>
<p>最后chrome的视频解码格式参考这里:<a href="http://en.wikipedia.org/wiki/Html_video_tag" target="_blank" rel="noopener">http://en.wikipedia.org/wiki/Html_video_tag</a></p>
]]></content>
<categories>
<category>mobile-h5</category>
</categories>
</entry>
<entry>
<title>ES6标准之逻辑与的规则</title>
<url>/2017/12/16/javascript/ES6-standard-LogicalANDExpression/</url>
<content><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>最近看到了阮一峰的一篇(读懂 ECMAScript 规格](<a href="http://www.ruanyifeng.com/blog/2015/11/ecmascript-specification.html),颇受鼓舞,特此收录一些在ES标准中能给我解惑的知识点。" target="_blank" rel="noopener">http://www.ruanyifeng.com/blog/2015/11/ecmascript-specification.html),颇受鼓舞,特此收录一些在ES标准中能给我解惑的知识点。</a></p>
<p>恰逢写RN的原生同事有下面的问题相问:</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">obj.subObj && obj.subObj.name <span class="comment">// 如果subObj存在,则表达式会输出name而非输出一个布尔值,为何?</span></span><br></pre></td></tr></table></figure>
<h2 id="解答"><a href="#解答" class="headerlink" title="解答"></a>解答</h2><h3 id="ES6原版文档"><a href="#ES6原版文档" class="headerlink" title="ES6原版文档"></a>ES6原版文档</h3><p><a href="http://www.ecma-international.org/ecma-262/6.0/" target="_blank" rel="noopener">ES6标准在线英文文档地址</a></p>
<blockquote>
<p>12.12.3 Runtime Semantics: Evaluation</p>
</blockquote>
<p>LogicalANDExpression : LogicalANDExpression && BitwiseORExpression</p>
<ol>
<li>Let lref be the result of evaluating LogicalANDExpression.</li>
<li>Let lval be GetValue(lref).</li>
<li>Let lbool be ToBoolean(lval).</li>
<li>ReturnIfAbrupt(lbool).</li>
<li>If lbool is false, return lval.</li>
<li>Let rref be the result of evaluating BitwiseORExpression.</li>
<li>Return GetValue(rref).</li>
</ol>
<h3 id="翻译"><a href="#翻译" class="headerlink" title="翻译"></a>翻译</h3><ol>
<li>令 lref 为解释执行 LogicalANDExpression 的结果。</li>
<li>令 lval 为 GetValue(lref)。</li>
<li>如果 ToBoolean(lval) 为 false,返回 lval。</li>
<li>令 rref 为解释执行 BitwiseORExpression 的结果。</li>
<li>返回 GetValue(rref)。</li>
</ol>
<p>关键在第三部 ,如果 lref 左表达式执行得到的值 lval 不能被当作 false 的时候直接返回 lval,否则就要返回右表达式的执行值 rref 的具体value,而不是 bool 值。</p>
<h3 id="ToBoolean"><a href="#ToBoolean" class="headerlink" title="ToBoolean"></a>ToBoolean</h3><table>
<thead>
<tr>
<th>Argument Type</th>
<th>Result</th>
</tr>
</thead>
<tbody><tr>
<td>Completion Record</td>
<td>If argument is an abrupt completion, return argument. Otherwise return ToBoolean(argument.[[value]])</td>
</tr>
<tr>
<td>Undefined</td>
<td>Return false.</td>
</tr>
<tr>
<td>Null</td>
<td>Return false.</td>
</tr>
<tr>
<td>Boolean</td>
<td>Return argument.</td>
</tr>
<tr>
<td>Number</td>
<td>Return false if argument is +0, −0, or NaN; otherwise return true.</td>
</tr>
<tr>
<td>String</td>
<td>Return false if argument is the empty String (its length is zero); otherwise return true.</td>
</tr>
<tr>
<td>Symbol</td>
<td>Return true.</td>
</tr>
<tr>
<td>Object</td>
<td>Return true.</td>
</tr>
</tbody></table>
<p>可知左表达式如果为 <code>undefeind</code>、<code>null</code>、<code>false</code>、<code>0</code>、<code>NaN</code>、<code>空字符串</code> 的时候被当作 <code>false</code>。反之为 <code>true</code>,则返回<code>GetValue(rref)</code>。</p>
<h3 id="GetValue"><a href="#GetValue" class="headerlink" title="GetValue"></a>GetValue</h3><ol>
<li>ReturnIfAbrupt(V).</li>
<li>If Type(V) is not Reference, return V.</li>
<li>Let base be GetBase(V).</li>
<li>If IsUnresolvableReference(V), throw a ReferenceError exception.</li>
<li>If IsPropertyReference(V), then<ol>
<li>If HasPrimitiveBase(V) is true, then<ol>
<li>Assert: In this case, base will never be null or undefined.</li>
<li>Let base be ToObject(base).</li>
</ol>
</li>
<li>Return base.<a href="GetReferencedName(V">[Get]</a>, GetThisValue(V)).</li>
</ol>
</li>
<li>Else base must be an Environment Record,<ol>
<li>Return base.GetBindingValue(GetReferencedName(V), IsStrictReference(V)) (see 8.1.1).</li>
</ol>
</li>
</ol>
<p>NOTE: The object that may be created in step 5.a.ii is not accessible outside of the above abstract operation and the ordinary object [[Get]] internal method. An implementation might choose to avoid the actual creation of the object.</p>
<p>第二步谈到如果不是一个引用类型的变量则直接返回这个变量本身,所以 <code>obj.subObj.name</code> 返回的就是 name 属性。</p>
<h2 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h2><p>那么逻辑或也是同理</p>
<p>LogicalORExpression : LogicalORExpression || LogicalANDExpression</p>
<ol>
<li>Let lref be the result of evaluating LogicalORExpression.</li>
<li>Let lval be GetValue(lref).</li>
<li>Let lbool be ToBoolean(lval).</li>
<li>ReturnIfAbrupt(lbool).</li>
<li>If lbool is true, return lval.</li>
<li>Let rref be the result of evaluating LogicalANDExpression.</li>
<li>Return GetValue(rref).</li>
</ol>
<p>只是判断 lval 能被当成 true 的时候则返回 lval 本身,否则返回 GetValue(rref).</p>
]]></content>
<categories>
<category>javascript</category>
</categories>
<tags>
<tag>ES6</tag>
</tags>
</entry>
<entry>
<title>webpack 把你的 vue 项目编译成了什么</title>
<url>/2017/12/11/js-util/what-webpack-has-compiled-vue-project/</url>
<content><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>往 main.js 里写入最简单的 vue 项目结构如下</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span>;</span><br><span class="line"><span class="keyword">import</span> App <span class="keyword">from</span> <span class="string">'./App.vue'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> Vue({</span><br><span class="line"> el: <span class="string">'#app'</span>,</span><br><span class="line"> template: <span class="string">'<App/>'</span>,</span><br><span class="line"> components: {</span><br><span class="line"> App</span><br><span class="line"> }</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>App.vue 如下</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">template</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"app"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">h1</span>></span>{{ msg }}<span class="tag"></<span class="name">h1</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">h2</span>></span>Essential Links<span class="tag"></<span class="name">h2</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">ul</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://vuejs.org"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>Core Docs<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://forum.vuejs.org"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>Forum<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://chat.vuejs.org"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>Community Chat<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://twitter.com/vuejs"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>Twitter<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">h2</span>></span>Ecosystem<span class="tag"></<span class="name">h2</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">ul</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://router.vuejs.org/"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>vue-router<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://vuex.vuejs.org/"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>vuex<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"http://vue-loader.vuejs.org/"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>vue-loader<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"https://github.com/vuejs/awesome-vue"</span> <span class="attr">target</span>=<span class="string">"_blank"</span>></span>awesome-vue<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">li</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">ul</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">template</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span> {</span></span><br><span class="line"><span class="actionscript"> name: <span class="string">'app'</span>,</span></span><br><span class="line"> data() {</span><br><span class="line"><span class="actionscript"> <span class="keyword">return</span> {</span></span><br><span class="line"><span class="actionscript"> msg: <span class="string">'Welcome to Your Vue.js App'</span></span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"><<span class="name">style</span>></span></span><br><span class="line"><span class="css"><span class="selector-id">#app</span> {</span></span><br><span class="line"> font-family: 'Avenir', Helvetica, Arial, sans-serif;</span><br><span class="line"> -webkit-font-smoothing: antialiased;</span><br><span class="line"> -moz-osx-font-smoothing: grayscale;</span><br><span class="line"> text-align: center;</span><br><span class="line"><span class="css"> <span class="selector-tag">color</span>: <span class="selector-id">#2c3e50</span>;</span></span><br><span class="line"> margin-top: 60px;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">h1,</span><br><span class="line">h2 {</span><br><span class="line"> font-weight: normal;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">ul {</span><br><span class="line"> list-style-type: none;</span><br><span class="line"> padding: 0;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">li {</span><br><span class="line"> display: inline-block;</span><br><span class="line"> margin: 0 10px;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">a {</span><br><span class="line"><span class="css"> <span class="selector-tag">color</span>: <span class="selector-id">#42b983</span>;</span></span><br><span class="line">}</span><br><span class="line"><span class="tag"></<span class="name">style</span>></span></span><br></pre></td></tr></table></figure>
<p>编译生成后得到一个316kb的文件,而在316Kb中包含着什么,我很好奇想探索一番。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">npm run build</span><br><span class="line"></span><br><span class="line">> [email protected] build /Users/everlose/workspace/github/learningInVue</span><br><span class="line">> cross-env NODE_ENV=production webpack --progress --hide-modules</span><br><span class="line"></span><br><span class="line">Hash: 18d868a423b48dc263e9</span><br><span class="line">Version: webpack 3.9.1</span><br><span class="line">Time: 3693ms</span><br><span class="line"> Asset Size Chunks Chunk Names</span><br><span class="line"> build.js 316 kB 0 [emitted] [big] main</span><br><span class="line">build.js.map 399 kB 0 [emitted] main</span><br></pre></td></tr></table></figure>
<h2 id="代码分解"><a href="#代码分解" class="headerlink" title="代码分解"></a>代码分解</h2><p>按顺序往下解读,<a href="https://github.com/everlose/learningInVue/blob/v0.0.2/dist/build.js" target="_blank" rel="noopener">本篇编译后的代码在这儿</a>,如果只想看结论那么请拉到最后有一张结构梳理图。</p>
<h3 id="webpack-模块机制"><a href="#webpack-模块机制" class="headerlink" title="webpack 模块机制"></a>webpack 模块机制</h3><p>前面70行还是熟悉的 webpack 模块机制的基础代码,关于它的细致解读参见上一篇<a href="https://github.com/everlose/learningInVue/blob/master/docs/webpack%E6%A8%A1%E5%9D%97%E6%9C%BA%E5%88%B6.md" target="_blank" rel="noopener">webpack模块机制</a>,编译后的代码格式如下,并且我做了代码美化,并且插上了中文注释</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The module cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 缓存模块,所有被加载过的模块都会成为installedModules对象的属性,靠函数__webpack_require__做到。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> installedModules = {};</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The require function 核心加载方法</span></span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">__webpack_require__</span>(<span class="params">moduleId</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Check if module is in cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 检查模块是否已在缓存中,是则直接返回缓存中的模块不需要再次加载</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(installedModules[moduleId]) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> installedModules[moduleId].exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Create a new module (and put it into the cache)</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 创造一个新模块并放入缓存中,i是模块标识,l意为是否加载此模块完毕,exports是此模块执行后的输出对象</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> <span class="built_in">module</span> = installedModules[moduleId] = {</span><br><span class="line"><span class="comment">/******/</span> i: moduleId,</span><br><span class="line"><span class="comment">/******/</span> l: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> exports: {}</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Execute the module function</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 传入参数并执行模块函数</span></span><br><span class="line"><span class="comment">/******/</span> modules[moduleId].call(<span class="built_in">module</span>.exports, <span class="built_in">module</span>, <span class="built_in">module</span>.exports, __webpack_require__);</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Flag the module as loaded 标为true代表模块执行完成。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">module</span>.l = <span class="literal">true</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Return the exports of the module 返回此模块输出的对象</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> <span class="built_in">module</span>.exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the modules object (__webpack_modules__)</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// webpack 私有变量,保存传入的modules,即所有的模块组成的数组</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.m = modules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the module cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 保存缓存中的模块数组</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.c = installedModules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// define getter function for harmony exports</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 为 es6 exports 定义 getter</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d = <span class="function"><span class="keyword">function</span>(<span class="params">exports, name, getter</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 如果 exports 输出的对象本身不包含 name 属性时,定义一个。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(!__webpack_require__.o(exports, name)) {</span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">Object</span>.defineProperty(exports, name, {</span><br><span class="line"><span class="comment">/******/</span> configurable: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> enumerable: <span class="literal">true</span>,</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">get</span>: getter</span><br><span class="line">/******/ });</span><br><span class="line">/******/ }</span><br><span class="line">/******/ };</span><br><span class="line">/******/</span><br><span class="line">/******/ // getDefaultExport function for compatibility with non-harmony modules</span><br><span class="line">/******/ // 解决 ES module 和 Common js module 的冲突,ES 则返回 module['default']</span><br><span class="line">/******/ __webpack_require__.n = function(module) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> getter = <span class="built_in">module</span> && <span class="built_in">module</span>.__esModule ?</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getDefault</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>[<span class="string">'default'</span>]; } :</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getModuleExports</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>; };</span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d(getter, <span class="string">'a'</span>, getter);</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> getter;</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Object.prototype.hasOwnProperty.call</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 工具方法,判断是否object有property属性。</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.o = <span class="function"><span class="keyword">function</span>(<span class="params">object, property</span>) </span>{ <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.hasOwnProperty.call(object, property); };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// __webpack_public_path__</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 大概和 webpack.config.js 的 output 有关吧,webpack 的公共路径</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.p = <span class="string">"/dist/"</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Load entry module and return exports 执行第一个依赖模块并且返回它输出。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> __webpack_require__(__webpack_require__.s = <span class="number">0</span>);</span><br><span class="line"><span class="comment">/******/</span> })</span><br></pre></td></tr></table></figure>
<h3 id="0号模块"><a href="#0号模块" class="headerlink" title="0号模块"></a>0号模块</h3><p>导出一个全局变量,在web端就是指代window</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> g;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// This works in non-strict mode</span></span><br><span class="line"> g = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>;</span><br><span class="line"> })();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// This works if eval is allowed (see CSP)</span></span><br><span class="line"> g = g || <span class="built_in">Function</span>(<span class="string">"return this"</span>)() || (<span class="number">1</span>, <span class="built_in">eval</span>)(<span class="string">"this"</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (e) {</span><br><span class="line"> <span class="comment">// This works if the window reference is available</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">window</span> === <span class="string">"object"</span>)</span><br><span class="line"> g = <span class="built_in">window</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// g can still be undefined, but nothing to do about it...</span></span><br><span class="line"> <span class="comment">// We return undefined, instead of nothing here, so it's</span></span><br><span class="line"> <span class="comment">// easier to handle this case. if(!global) { ...}</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">module</span>.exports = g;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br></pre></td></tr></table></figure>
<h3 id="1号模块"><a href="#1号模块" class="headerlink" title="1号模块"></a>1号模块</h3><p>实际上做的事情很明显,就是导出了 main.js 的代码,一个vue实例对象</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 1 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(<span class="number">2</span>);</span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_1__App_vue__ = __webpack_require__(<span class="number">6</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 从2号模块导出的一个叫a的变量,就是Vue对象本身</span></span><br><span class="line"><span class="keyword">new</span> __WEBPACK_IMPORTED_MODULE_0_vue__[<span class="string">"a"</span> <span class="comment">/* default */</span>]({</span><br><span class="line"> el: <span class="string">'#app'</span>,</span><br><span class="line"> template: <span class="string">'<App/>'</span>,</span><br><span class="line"> components: {</span><br><span class="line"> App: __WEBPACK_IMPORTED_MODULE_1__App_vue__[<span class="string">"a"</span> <span class="comment">/* default */</span>]</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br></pre></td></tr></table></figure>
<h3 id="2号模块"><a href="#2号模块" class="headerlink" title="2号模块"></a>2号模块</h3><p>即是 Vue 源码本身,从114行一直到了10818行,一共是10705行代码,啧啧啧</p>
<p>webpack 有所配置,所以导出的 Vue 实际上是 vue/dist/vue.esm.js 的完整编译版本。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 2 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span> (<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="comment">/*!</span></span><br><span class="line"><span class="comment"> * Vue.js v2.5.9</span></span><br><span class="line"><span class="comment"> * (c) 2014-2017 Evan You</span></span><br><span class="line"><span class="comment"> * Released under the MIT License.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 作用域指向__webpack_exports__,并把__webpack_require__(0)作为global,实际上就是window</span></span><br><span class="line"><span class="comment">// __webpack_require__(3).setImmediate)作为setsetImmediate参数传入函数</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">global, setImmediate</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 省略近1w行的代码,关于vue原本本身的解读以后再做......</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 最终 export 出来一个叫 Vue$3的对象</span></span><br><span class="line"> <span class="comment">/* harmony default export */</span></span><br><span class="line"> __webpack_exports__[<span class="string">"a"</span>] = (Vue$<span class="number">3</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* WEBPACK VAR INJECTION */</span></span><br><span class="line">}.call(__webpack_exports__, __webpack_require__(<span class="number">0</span>), __webpack_require__(<span class="number">3</span>).setImmediate))</span><br><span class="line"></span><br><span class="line">}),</span><br></pre></td></tr></table></figure>
<h3 id="3,4,5号模块"><a href="#3,4,5号模块" class="headerlink" title="3,4,5号模块"></a>3,4,5号模块</h3><p>都和 node_modules/setimmediate 有关,由于 vue 的 DOM 异步更新机制使用到了它,所以被引入。</p>
<p>这里也不做详解,只给出结构。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 3 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 省略代码...</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// setimmediate attaches itself to the global object</span></span><br><span class="line"> __webpack_require__(<span class="number">4</span>);</span><br><span class="line"> exports.setImmediate = setImmediate;</span><br><span class="line"> exports.clearImmediate = clearImmediate;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 4 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* WEBPACK VAR INJECTION */</span></span><br><span class="line"> (<span class="function"><span class="keyword">function</span> (<span class="params">global, process</span>) </span>{</span><br><span class="line"> <span class="comment">// 省略代码...</span></span><br><span class="line"> }.call(exports, __webpack_require__(<span class="number">0</span>), __webpack_require__(<span class="number">5</span>)))</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 5 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// shim for using process in browser</span></span><br><span class="line"> <span class="keyword">var</span> process = <span class="built_in">module</span>.exports = {};</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 省略代码...</span></span><br><span class="line"></span><br><span class="line"> process.cwd = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'/'</span></span><br><span class="line"> };</span><br><span class="line"> process.chdir = <span class="function"><span class="keyword">function</span> (<span class="params">dir</span>) </span>{</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">'process.chdir is not supported'</span>);</span><br><span class="line"> };</span><br><span class="line"> process.umask = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> };</span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br></pre></td></tr></table></figure>
<h3 id="6号模块"><a href="#6号模块" class="headerlink" title="6号模块"></a>6号模块</h3><p>和 App.vue 的解析有关,把 App.vue 中的 template 和 script 编译为一个 vue components,并把 style 标签内的样式插入到DOM中。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 6 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta"> "use strict"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 返回具体 App.vue 中 的script 中的代码</span></span><br><span class="line"> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0__babel_loader_node_modules_vue_loader_lib_selector_type_script_index_0_App_vue__ = __webpack_require__(<span class="number">13</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 把App.vue 的 template 解析为一堆 vue render 函数。</span></span><br><span class="line"> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_1__node_modules_vue_loader_lib_template_compiler_index_id_data_v_66ce2159_hasScoped_false_buble_transforms_node_modules_vue_loader_lib_selector_type_template_index_0_App_vue__ = __webpack_require__(<span class="number">14</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 注入vue文件里写入的css函数</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">injectStyle</span>(<span class="params">ssrContext</span>) </span>{</span><br><span class="line"> <span class="comment">// 由此可知7号模块是编译并插入vue中的css到DOM上的</span></span><br><span class="line"> __webpack_require__(<span class="number">7</span>)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 12号模块用于输出components渲染函数</span></span><br><span class="line"> <span class="keyword">var</span> normalizeComponent = __webpack_require__(<span class="number">12</span>)</span><br><span class="line"> <span class="comment">/* script */</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">/* template */</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">/* template functional */</span></span><br><span class="line"> <span class="keyword">var</span> __vue_template_functional__ = <span class="literal">false</span></span><br><span class="line"> <span class="comment">/* styles */</span></span><br><span class="line"> <span class="keyword">var</span> __vue_styles__ = injectStyle</span><br><span class="line"> <span class="comment">/* scopeId */</span></span><br><span class="line"> <span class="keyword">var</span> __vue_scopeId__ = <span class="literal">null</span></span><br><span class="line"> <span class="comment">/* moduleIdentifier (server only) */</span></span><br><span class="line"> <span class="keyword">var</span> __vue_module_identifier__ = <span class="literal">null</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// 编译模块,混杂template和script。</span></span><br><span class="line"> <span class="keyword">var</span> Component = normalizeComponent(</span><br><span class="line"> __WEBPACK_IMPORTED_MODULE_0__babel_loader_node_modules_vue_loader_lib_selector_type_script_index_0_App_vue__[<span class="string">"a"</span> <span class="comment">/* default */</span> ],</span><br><span class="line"> __WEBPACK_IMPORTED_MODULE_1__node_modules_vue_loader_lib_template_compiler_index_id_data_v_66ce2159_hasScoped_false_buble_transforms_node_modules_vue_loader_lib_selector_type_template_index_0_App_vue__[<span class="string">"a"</span> <span class="comment">/* default */</span> ],</span><br><span class="line"> __vue_template_functional__,</span><br><span class="line"> __vue_styles__,</span><br><span class="line"> __vue_scopeId__,</span><br><span class="line"> __vue_module_identifier__</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* harmony default export */</span></span><br><span class="line"> __webpack_exports__[<span class="string">"a"</span>] = (Component.exports);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br></pre></td></tr></table></figure>
<h3 id="7、8、9、10、11"><a href="#7、8、9、10、11" class="headerlink" title="7、8、9、10、11"></a>7、8、9、10、11</h3><p>都和样式有关,简言之就是7号模块加载8号模块获取css代码作为参数,并作为参数传入10号模块进行插入</p>
<p>太长也只大意上列出结构</p>
<ul>
<li>7号模块由 style-loader 带入,把所有的css插入到 style 标签里</li>
<li>8号模块加载具体的css代码,</li>
<li>9号模块由css-loader代入,用于做css的sourceMap</li>
<li>10号模块返回具体插入动作函数,供7号模块调用</li>
<li>11号模块把所有的样式组成的数组转为字符串,给10号模块做插入。</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 7 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// style-loader: Adds some css to the DOM by adding a <style> tag</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// load the styles</span></span><br><span class="line"> <span class="keyword">var</span> content = __webpack_require__(<span class="number">8</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> content === <span class="string">'string'</span>) content = [</span><br><span class="line"> [<span class="built_in">module</span>.i, content, <span class="string">''</span>]</span><br><span class="line"> ];</span><br><span class="line"> <span class="keyword">if</span> (content.locals) <span class="built_in">module</span>.exports = content.locals;</span><br><span class="line"> <span class="comment">// add the styles to the DOM</span></span><br><span class="line"> <span class="keyword">var</span> update = __webpack_require__(<span class="number">10</span>)(<span class="string">"15459d21"</span>, content, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 8 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// css-loader 用于做css的sourceMap</span></span><br><span class="line"> exports = <span class="built_in">module</span>.exports = __webpack_require__(<span class="number">9</span>)(<span class="literal">undefined</span>);</span><br><span class="line"> <span class="comment">// imports</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">// module</span></span><br><span class="line"> <span class="comment">// 这就是 App.vue 文件中 style 里的的 css</span></span><br><span class="line"> exports.push([<span class="built_in">module</span>.i, <span class="string">"#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:60px}h1,h2{font-weight:400}ul{list-style-type:none;padding:0}li{display:inline-block;margin:0 10px}a{color:#42b983}"</span>, <span class="string">""</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// exports</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 9 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports</span>) </span>{</span><br><span class="line"> <span class="comment">// css base code, injected by the css-loader</span></span><br><span class="line"> <span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> (<span class="params">useSourceMap</span>) </span>{</span><br><span class="line"> <span class="comment">// 省略代码...</span></span><br><span class="line"> }</span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 10 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> MIT License http://www.opensource.org/licenses/mit-license.php</span></span><br><span class="line"><span class="comment"> Author Tobias Koppers @sokra</span></span><br><span class="line"><span class="comment"> Modified by Evan You @yyx990803</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// ...太长只贴了关键步骤,总之关键的函数就是这些</span></span><br><span class="line"> <span class="keyword">var</span> hasDocument = <span class="keyword">typeof</span> <span class="built_in">document</span> !== <span class="string">'undefined'</span></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">var</span> listToStyles = __webpack_require__(<span class="number">11</span>)</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">var</span> head = hasDocument && (<span class="built_in">document</span>.head || <span class="built_in">document</span>.getElementsByTagName(<span class="string">'head'</span>)[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> (<span class="params">parentId, list, _isProduction</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">var</span> styles = listToStyles(parentId, list)</span><br><span class="line"> addStylesToDom(styles)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="title">update</span> (<span class="params">newList</span>) </span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">addStylesToDom</span> (<span class="params">styles <span class="regexp">/* Array<StyleObject> */</span></span>) </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < styles.length; i++) {</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> domStyle.parts.push(addStyle(item.parts[j]))</span><br><span class="line"> <span class="comment">// ....</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 总之先调用了addStylesToDom,接着是addStyle,再是createStyleElement插入样式到head中。</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">createStyleElement</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> styleElement = <span class="built_in">document</span>.createElement(<span class="string">'style'</span>)</span><br><span class="line"> styleElement.type = <span class="string">'text/css'</span></span><br><span class="line"> head.appendChild(styleElement)</span><br><span class="line"> <span class="keyword">return</span> styleElement</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">addStyle</span> (<span class="params">obj <span class="regexp">/* StyleObjectPart */</span></span>) </span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> styleElement = createStyleElement()</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 11 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Translates the list format produced by css-loader into something</span></span><br><span class="line"><span class="comment"> * easier to manipulate.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">listToStyles</span>(<span class="params">parentId, list</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> styles = []</span><br><span class="line"> <span class="keyword">var</span> newStyles = {}</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < list.length; i++) {</span><br><span class="line"> <span class="keyword">var</span> item = list[i]</span><br><span class="line"> <span class="keyword">var</span> id = item[<span class="number">0</span>]</span><br><span class="line"> <span class="keyword">var</span> css = item[<span class="number">1</span>]</span><br><span class="line"> <span class="keyword">var</span> media = item[<span class="number">2</span>]</span><br><span class="line"> <span class="keyword">var</span> sourceMap = item[<span class="number">3</span>]</span><br><span class="line"> <span class="keyword">var</span> part = {</span><br><span class="line"> id: parentId + <span class="string">':'</span> + i,</span><br><span class="line"> css: css,</span><br><span class="line"> media: media,</span><br><span class="line"> sourceMap: sourceMap</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (!newStyles[id]) {</span><br><span class="line"> styles.push(newStyles[id] = {</span><br><span class="line"> id: id,</span><br><span class="line"> parts: [part]</span><br><span class="line"> })</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> newStyles[id].parts.push(part)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> styles</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br></pre></td></tr></table></figure>
<h3 id="12、13、14号模块"><a href="#12、13、14号模块" class="headerlink" title="12、13、14号模块"></a>12、13、14号模块</h3><p>12号做 .vue 文件中的 template 和 script 解析并供6号输出,最终返回了一个 vue components 对象,在浏览器控制台打印如下:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Object</span><br><span class="line"> beforeCreate: [ƒ]</span><br><span class="line"> data: ƒ data()</span><br><span class="line"> inject: {}</span><br><span class="line"> name: "app"</span><br><span class="line"> render: ƒ ()</span><br><span class="line"> staticRenderFns: (2) [ƒ, ƒ, cached: Array(2)]</span><br><span class="line"> _Ctor: {0: ƒ}</span><br><span class="line"> _compiled: true</span><br><span class="line"> __proto__: Object</span><br></pre></td></tr></table></figure>
<p>而13号模块返回具体 script 中的代码,而14号模块则是把 template 解析为一堆 vue render 函数。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/* 12 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* globals __VUE_SSR_CONTEXT__ */</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">// IMPORTANT: Do NOT use ES2015 features in this file.</span></span><br><span class="line"> <span class="comment">// This module is a runtime utility for cleaner component module output and will</span></span><br><span class="line"> <span class="comment">// be included in the final webpack user bundle.</span></span><br><span class="line"></span><br><span class="line"> <span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> <span class="title">normalizeComponent</span>(<span class="params"></span></span></span><br><span class="line"><span class="function"><span class="params"> rawScriptExports,</span></span></span><br><span class="line"><span class="function"><span class="params"> compiledTemplate,</span></span></span><br><span class="line"><span class="function"><span class="params"> functionalTemplate,</span></span></span><br><span class="line"><span class="function"><span class="params"> injectStyles,</span></span></span><br><span class="line"><span class="function"><span class="params"> scopeId,</span></span></span><br><span class="line"><span class="function"><span class="params"> moduleIdentifier <span class="regexp">/* server only */</span></span></span></span><br><span class="line"><span class="function"><span class="params"> </span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> esModule</span><br><span class="line"> <span class="keyword">var</span> scriptExports = rawScriptExports = rawScriptExports || {}</span><br><span class="line"></span><br><span class="line"> <span class="comment">// ES6 modules interop</span></span><br><span class="line"> <span class="keyword">var</span> type = <span class="keyword">typeof</span> rawScriptExports.default</span><br><span class="line"> <span class="keyword">if</span> (type === <span class="string">'object'</span> || type === <span class="string">'function'</span>) {</span><br><span class="line"> esModule = rawScriptExports</span><br><span class="line"> scriptExports = rawScriptExports.default</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// Vue.extend constructor export interop</span></span><br><span class="line"> <span class="keyword">var</span> options = <span class="keyword">typeof</span> scriptExports === <span class="string">'function'</span> ?</span><br><span class="line"> scriptExports.options :</span><br><span class="line"> scriptExports</span><br><span class="line"></span><br><span class="line"> <span class="comment">// render functions</span></span><br><span class="line"> <span class="keyword">if</span> (compiledTemplate) {</span><br><span class="line"> options.render = compiledTemplate.render</span><br><span class="line"> options.staticRenderFns = compiledTemplate.staticRenderFns</span><br><span class="line"> options._compiled = <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// functional template</span></span><br><span class="line"> <span class="keyword">if</span> (functionalTemplate) {</span><br><span class="line"> options.functional = <span class="literal">true</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// scopedId</span></span><br><span class="line"> <span class="keyword">if</span> (scopeId) {</span><br><span class="line"> options._scopeId = scopeId</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> hook</span><br><span class="line"> <span class="keyword">if</span> (moduleIdentifier) { <span class="comment">// server build</span></span><br><span class="line"> hook = <span class="function"><span class="keyword">function</span> (<span class="params">context</span>) </span>{</span><br><span class="line"> <span class="comment">// 2.3 injection</span></span><br><span class="line"> context =</span><br><span class="line"> context || <span class="comment">// cached call</span></span><br><span class="line"> (<span class="keyword">this</span>.$vnode && <span class="keyword">this</span>.$vnode.ssrContext) || <span class="comment">// stateful</span></span><br><span class="line"> (<span class="keyword">this</span>.parent && <span class="keyword">this</span>.parent.$vnode && <span class="keyword">this</span>.parent.$vnode.ssrContext) <span class="comment">// functional</span></span><br><span class="line"> <span class="comment">// 2.2 with runInNewContext: true</span></span><br><span class="line"> <span class="keyword">if</span> (!context && <span class="keyword">typeof</span> __VUE_SSR_CONTEXT__ !== <span class="string">'undefined'</span>) {</span><br><span class="line"> context = __VUE_SSR_CONTEXT__</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// inject component styles</span></span><br><span class="line"> <span class="keyword">if</span> (injectStyles) {</span><br><span class="line"> injectStyles.call(<span class="keyword">this</span>, context)</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// register component module identifier for async chunk inferrence</span></span><br><span class="line"> <span class="keyword">if</span> (context && context._registeredComponents) {</span><br><span class="line"> context._registeredComponents.add(moduleIdentifier)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// used by ssr in case component is cached and beforeCreate</span></span><br><span class="line"> <span class="comment">// never gets called</span></span><br><span class="line"> options._ssrRegister = hook</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (injectStyles) {</span><br><span class="line"> hook = injectStyles</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (hook) {</span><br><span class="line"> <span class="keyword">var</span> functional = options.functional</span><br><span class="line"> <span class="keyword">var</span> existing = functional ?</span><br><span class="line"> options.render :</span><br><span class="line"> options.beforeCreate</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!functional) {</span><br><span class="line"> <span class="comment">// inject component registration as beforeCreate hook</span></span><br><span class="line"> options.beforeCreate = existing ?</span><br><span class="line"> [].concat(existing, hook) :</span><br><span class="line"> [hook]</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// for template-only hot-reload because in that case the render fn doesn't</span></span><br><span class="line"> <span class="comment">// go through the normalizer</span></span><br><span class="line"> options._injectStyles = hook</span><br><span class="line"> <span class="comment">// register for functioal component in vue file</span></span><br><span class="line"> options.render = <span class="function"><span class="keyword">function</span> <span class="title">renderWithStyleInjection</span>(<span class="params">h, context</span>) </span>{</span><br><span class="line"> hook.call(context)</span><br><span class="line"> <span class="keyword">return</span> existing(h, context)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> esModule: esModule,</span><br><span class="line"> exports: scriptExports,</span><br><span class="line"> options: options</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 13 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta"> "use strict"</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/* harmony default export */</span></span><br><span class="line"> <span class="comment">// 这就是 App.vue 中 script 的部分</span></span><br><span class="line"> __webpack_exports__[<span class="string">"a"</span>] = ({</span><br><span class="line"> name: <span class="string">'app'</span>,</span><br><span class="line"> data: <span class="function"><span class="keyword">function</span> <span class="title">data</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> msg: <span class="string">'Welcome to Your Vue.js App'</span></span><br><span class="line"> };</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">}),</span><br><span class="line"><span class="comment">/* 14 */</span></span><br><span class="line"><span class="comment">/***/</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta"> "use strict"</span>;</span><br><span class="line"> <span class="comment">// 把template 解析为一堆 render 函数,扔给vue处理最终编译成Vnode节点在渲染成DOM输出到视图</span></span><br><span class="line"> <span class="keyword">var</span> render = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _vm = <span class="keyword">this</span>;</span><br><span class="line"> <span class="keyword">var</span> _h = _vm.$createElement;</span><br><span class="line"> <span class="keyword">var</span> _c = _vm._self._c || _h;</span><br><span class="line"> <span class="keyword">return</span> _c(<span class="string">'div'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"id"</span>: <span class="string">"app"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_c(<span class="string">'h1'</span>, [_vm._v(_vm._s(_vm.msg))]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'h2'</span>, [_vm._v(<span class="string">"Essential Links"</span>)]), _vm._v(<span class="string">" "</span>), _vm._m(<span class="number">0</span>, <span class="literal">false</span>, <span class="literal">false</span>), _vm._v(<span class="string">" "</span>), _c(<span class="string">'h2'</span>, [_vm._v(<span class="string">"Ecosystem"</span>)]), _vm._v(<span class="string">" "</span>), _vm._m(<span class="number">1</span>, <span class="literal">false</span>, <span class="literal">false</span>)])</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> staticRenderFns = [<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _vm = <span class="keyword">this</span>;</span><br><span class="line"> <span class="keyword">var</span> _h = _vm.$createElement;</span><br><span class="line"> <span class="keyword">var</span> _c = _vm._self._c || _h;</span><br><span class="line"> <span class="keyword">return</span> _c(<span class="string">'ul'</span>, [_c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"https://vuejs.org"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"Core Docs"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"https://forum.vuejs.org"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"Forum"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"https://chat.vuejs.org"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"Community Chat"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"https://twitter.com/vuejs"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"Twitter"</span>)])])])</span><br><span class="line"> }, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _vm = <span class="keyword">this</span>;</span><br><span class="line"> <span class="keyword">var</span> _h = _vm.$createElement;</span><br><span class="line"> <span class="keyword">var</span> _c = _vm._self._c || _h;</span><br><span class="line"> <span class="keyword">return</span> _c(<span class="string">'ul'</span>, [_c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"http://router.vuejs.org/"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"vue-router"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"http://vuex.vuejs.org/"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"vuex"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"http://vue-loader.vuejs.org/"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"vue-loader"</span>)])]), _vm._v(<span class="string">" "</span>), _c(<span class="string">'li'</span>, [_c(<span class="string">'a'</span>, {</span><br><span class="line"> attrs: {</span><br><span class="line"> <span class="string">"href"</span>: <span class="string">"https://github.com/vuejs/awesome-vue"</span>,</span><br><span class="line"> <span class="string">"target"</span>: <span class="string">"_blank"</span></span><br><span class="line"> }</span><br><span class="line"> }, [_vm._v(<span class="string">"awesome-vue"</span>)])])])</span><br><span class="line"> }]</span><br><span class="line"> <span class="keyword">var</span> esExports = {</span><br><span class="line"> render: render,</span><br><span class="line"> staticRenderFns: staticRenderFns</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/* harmony default export */</span></span><br><span class="line"> __webpack_exports__[<span class="string">"a"</span>] = (esExports);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/***/</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>结构梳理,一图胜千言,并且有关于<a href="http://naotu.baidu.com/file/89611b9bc6cd0ac214a98abbd5062ade?token=60ef60d5ed3a60cf" target="_blank" rel="noopener">此图的附注请自行点击参考</a></p>
<p><img src="http://7xn4mw.com1.z0.glb.clouddn.com/17-12-10/52589634.jpg" alt=""></p>
<p>上一篇:<a href="https://github.com/everlose/learningInVue/blob/master/docs/webpack%E6%A8%A1%E5%9D%97%E6%9C%BA%E5%88%B6.md" target="_blank" rel="noopener">webpack模块机制</a></p>
]]></content>
<categories>
<category>js-util</category>
</categories>
<tags>
<tag>vue</tag>
<tag>webpack</tag>
</tags>
</entry>
<entry>
<title>webpack 打包机制</title>
<url>/2017/12/11/js-util/webpack-core/</url>
<content><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>示例项目由以下命令检出,或者可以翻<a href="https://github.com/everlose/learningInVue" target="_blank" rel="noopener">我的 github</a>,示例所使用的 webpack3 的版本为 3.9.1。</p>
<figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">vue init webpack-simple learning-in-vue</span><br></pre></td></tr></table></figure>
<h2 id="一个最简单的例子"><a href="#一个最简单的例子" class="headerlink" title="一个最简单的例子"></a>一个最简单的例子</h2><p>修改入口文件 <code>src/main.js</code></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="string">'This is src/main.js'</span></span><br></pre></td></tr></table></figure>
<p>并且我找到 <code>webpack.config.js</code> 注释掉了 <code>UglifyJsPlugin</code></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// new webpack.optimize.UglifyJsPlugin({</span></span><br><span class="line"><span class="comment">// sourceMap: true,</span></span><br><span class="line"><span class="comment">// compress: {</span></span><br><span class="line"><span class="comment">// warnings: false</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"><span class="comment">// }),</span></span><br></pre></td></tr></table></figure>
<p>最后在 <code>npm run build</code> 后产生了大概70行的代码。且看 <code>dist/build.js</code>,我写上了英文注释的翻译</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The module cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> installedModules = {};</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The require function</span></span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">__webpack_require__</span>(<span class="params">moduleId</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Check if module is in cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(installedModules[moduleId]) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> installedModules[moduleId].exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Create a new module (and put it into the cache)</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> <span class="built_in">module</span> = installedModules[moduleId] = {</span><br><span class="line"><span class="comment">/******/</span> i: moduleId,</span><br><span class="line"><span class="comment">/******/</span> l: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> exports: {}</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Execute the module function</span></span><br><span class="line"><span class="comment">/******/</span> modules[moduleId].call(<span class="built_in">module</span>.exports, <span class="built_in">module</span>, <span class="built_in">module</span>.exports, __webpack_require__);</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Flag the module as loaded</span></span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">module</span>.l = <span class="literal">true</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Return the exports of the module</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> <span class="built_in">module</span>.exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the modules object (__webpack_modules__)</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.m = modules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the module cache</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.c = installedModules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// define getter function for harmony exports</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d = <span class="function"><span class="keyword">function</span>(<span class="params">exports, name, getter</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(!__webpack_require__.o(exports, name)) {</span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">Object</span>.defineProperty(exports, name, {</span><br><span class="line"><span class="comment">/******/</span> configurable: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> enumerable: <span class="literal">true</span>,</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">get</span>: getter</span><br><span class="line">/******/ });</span><br><span class="line">/******/ }</span><br><span class="line">/******/ };</span><br><span class="line">/******/</span><br><span class="line">/******/ // getDefaultExport function for compatibility with non-harmony modules</span><br><span class="line">/******/ __webpack_require__.n = function(module) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> getter = <span class="built_in">module</span> && <span class="built_in">module</span>.__esModule ?</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getDefault</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>[<span class="string">'default'</span>]; } :</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getModuleExports</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>; };</span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d(getter, <span class="string">'a'</span>, getter);</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> getter;</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Object.prototype.hasOwnProperty.call</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.o = <span class="function"><span class="keyword">function</span>(<span class="params">object, property</span>) </span>{ <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.hasOwnProperty.call(object, property); };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// __webpack_public_path__</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.p = <span class="string">"/dist/"</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Load entry module and return exports</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> __webpack_require__(__webpack_require__.s = <span class="number">0</span>);</span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"><span class="comment">/* harmony default export */</span> __webpack_exports__[<span class="string">"default"</span>] = (<span class="string">'This is src/main.js'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<p>这么多星号看着好唬人,没想到区区一行 <code>console.log</code> 都能被编译成 70 多行的代码!来简化一下,这个结构无非就是立即调用的函数表达式罢了,并且把所有引用模块包装成一个数组作为参数传入,就如下面代码所展示的:</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{</span><br><span class="line"> <span class="comment">//...</span></span><br><span class="line">})([</span><br><span class="line"> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports</span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'This is src/main.js'</span>);</span><br><span class="line"> })</span><br><span class="line">]);</span><br></pre></td></tr></table></figure>
<p>而这个立即调用的函数表达式,前60多行的代码就是 webpack require 的核心。我大概翻译一下</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The module cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 缓存模块,所有被加载过的模块都会成为installedModules对象的属性,靠函数__webpack_require__做到。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> installedModules = {};</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// The require function 核心加载方法</span></span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">__webpack_require__</span>(<span class="params">moduleId</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Check if module is in cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 检查模块是否已在缓存中,是则直接返回缓存中的模块不需要再次加载</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(installedModules[moduleId]) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> installedModules[moduleId].exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Create a new module (and put it into the cache)</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 创造一个新模块并放入缓存中,i是模块标识,l意为是否加载此模块完毕,exports是此模块执行后的输出对象</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> <span class="built_in">module</span> = installedModules[moduleId] = {</span><br><span class="line"><span class="comment">/******/</span> i: moduleId,</span><br><span class="line"><span class="comment">/******/</span> l: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> exports: {}</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Execute the module function</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 传入参数并执行模块函数</span></span><br><span class="line"><span class="comment">/******/</span> modules[moduleId].call(<span class="built_in">module</span>.exports, <span class="built_in">module</span>, <span class="built_in">module</span>.exports, __webpack_require__);</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Flag the module as loaded 标为true代表模块执行完成。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">module</span>.l = <span class="literal">true</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Return the exports of the module 返回此模块输出的对象</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> <span class="built_in">module</span>.exports;</span><br><span class="line"><span class="comment">/******/</span> }</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the modules object (__webpack_modules__)</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// webpack 私有变量,保存传入的modules,即所有的模块组成的数组</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.m = modules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// expose the module cache</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 保存缓存中的模块数组</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.c = installedModules;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// define getter function for harmony exports</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 为 es6 exports 定义 getter</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d = <span class="function"><span class="keyword">function</span>(<span class="params">exports, name, getter</span>) </span>{</span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 如果 exports 输出的对象本身不包含 name 属性时,定义一个。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">if</span>(!__webpack_require__.o(exports, name)) {</span><br><span class="line"><span class="comment">/******/</span> <span class="built_in">Object</span>.defineProperty(exports, name, {</span><br><span class="line"><span class="comment">/******/</span> configurable: <span class="literal">false</span>,</span><br><span class="line"><span class="comment">/******/</span> enumerable: <span class="literal">true</span>,</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">get</span>: getter</span><br><span class="line">/******/ });</span><br><span class="line">/******/ }</span><br><span class="line">/******/ };</span><br><span class="line">/******/</span><br><span class="line">/******/ // getDefaultExport function for compatibility with non-harmony modules</span><br><span class="line">/******/ // 解决 ES module 和 Common js module 的冲突,ES 则返回 module['default']</span><br><span class="line">/******/ __webpack_require__.n = function(module) {</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">var</span> getter = <span class="built_in">module</span> && <span class="built_in">module</span>.__esModule ?</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getDefault</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>[<span class="string">'default'</span>]; } :</span><br><span class="line"><span class="comment">/******/</span> <span class="function"><span class="keyword">function</span> <span class="title">getModuleExports</span>(<span class="params"></span>) </span>{ <span class="keyword">return</span> <span class="built_in">module</span>; };</span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.d(getter, <span class="string">'a'</span>, getter);</span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> getter;</span><br><span class="line"><span class="comment">/******/</span> };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Object.prototype.hasOwnProperty.call</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 工具方法,判断是否object有property属性。</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.o = <span class="function"><span class="keyword">function</span>(<span class="params">object, property</span>) </span>{ <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.hasOwnProperty.call(object, property); };</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// __webpack_public_path__</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// 大概和 webpack.config.js 的 output 有关吧,webpack 的公共路径</span></span><br><span class="line"><span class="comment">/******/</span> __webpack_require__.p = <span class="string">"/dist/"</span>;</span><br><span class="line"><span class="comment">/******/</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// Load entry module and return exports 执行第一个依赖模块并且返回它输出。</span></span><br><span class="line"><span class="comment">/******/</span> <span class="keyword">return</span> __webpack_require__(__webpack_require__.s = <span class="number">0</span>);</span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"><span class="comment">/* harmony default export */</span> __webpack_exports__[<span class="string">"default"</span>] = (<span class="string">'This is src/main.js'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<p>注意关键的一步,在下面完成了模块注入最为关键的一步。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// moduleId第一次执行时为0,modules[0]既是外部第一个依赖</span></span><br><span class="line"><span class="comment">// 执行时 this 作用域指向 module.exports 的那个对象</span></span><br><span class="line"><span class="comment">// 并传入参数 module, module.exports, __webpack_require__</span></span><br><span class="line">modules[moduleId].call(<span class="built_in">module</span>.exports, <span class="built_in">module</span>, <span class="built_in">module</span>.exports, __webpack_require__);</span><br><span class="line"></span><br><span class="line"><span class="comment">//...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体模块执行收到参数 module, module.exports, __webpack_require__</span></span><br><span class="line"><span class="comment">// 并且修改了 __webpack_exports__ 给他加入了 default 属性对象。</span></span><br><span class="line"><span class="comment">// __esModule标记本模块是es6模块,__webpack_require__.n 将会处理它输出 module['default']</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"><span class="meta"> "use strict"</span>;</span><br><span class="line"> <span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"> <span class="comment">/* harmony default export */</span> __webpack_exports__[<span class="string">"default"</span>] = (<span class="string">'This is src/main.js'</span>);</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<h2 id="其他引入方式"><a href="#其他引入方式" class="headerlink" title="其他引入方式"></a>其他引入方式</h2><p>就如 <a href="https://doc.webpack-china.org/concepts/modules#-webpack-" target="_blank" rel="noopener">webpack 3</a> 官网所说</p>
<blockquote>
<p>对比 Node.js 模块,webpack 模块能够以各种方式表达它们的依赖关系,几个例子如下:</p>
</blockquote>
<ul>
<li>ES2015 import 语句</li>
<li>CommonJS require() 语句</li>
<li>AMD define 和 require 语句</li>
<li>css/sass/less 文件中的 @import 语句。</li>
<li>样式(url(…))或 HTML 文件中的图片链接(image url)</li>
</ul>
<p>webpack 能处理的模块类型比较多,上面的例子里我们只演示 ES2015 import 语句。</p>
<h3 id="CommonJs-require"><a href="#CommonJs-require" class="headerlink" title="CommonJs require()"></a>CommonJs require()</h3><p>src/main.js 写成</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="built_in">module</span>.exports = <span class="string">'This is src/main.js'</span>;</span><br></pre></td></tr></table></figure>
<p>那么 dist/build.js 将会是</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// ...</span></span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// 具体模块执行收到参数 module, module.exports(空对象), __webpack_require__</span></span><br><span class="line"><span class="comment">// 这里正好修改 module.exports。</span></span><br><span class="line"><span class="built_in">module</span>.exports = <span class="string">'This is src/main.js'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<h3 id="Amd-模块"><a href="#Amd-模块" class="headerlink" title="Amd 模块"></a>Amd 模块</h3><p>src/main.js 写成</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line">define([], <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> amd: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'AMD'</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<p>那么 dist/build.js 将会是</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// ...</span></span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> amd: <span class="function"><span class="keyword">function</span> <span class="title">amd</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'AMD'</span>);</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line">}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),</span><br><span class="line"> __WEBPACK_AMD_DEFINE_RESULT__ !== <span class="literal">undefined</span> && (<span class="built_in">module</span>.exports = __WEBPACK_AMD_DEFINE_RESULT__));</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<p>生成了好啰嗦的的一段,简言之还是跳不脱 <code>module.exports = __WEBPACK_AMD_DEFINE_RESULT__</code> 这句话</p>
<h3 id="image"><a href="#image" class="headerlink" title="image"></a>image</h3><p>webpack 竟然能把这些静态资源作为模块,但其实这是通过loader实现的。 image 则可配置 url-loader 设置,被编译成base 64编码的串。</p>
<p>在 <code>webpack.config.js</code> 中配置 url-loader 并 舍弃 file-loader,配置 url-loader 若在 1Mb 大小内的图片则直接编译为base 64编码。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// {</span></span><br><span class="line"><span class="comment">// test: /\.(png|jpg|gif|svg)$/,</span></span><br><span class="line"><span class="comment">// loader: 'file-loader',</span></span><br><span class="line"><span class="comment">// options: {</span></span><br><span class="line"><span class="comment">// name: '[name].[ext]?[hash]'</span></span><br><span class="line"><span class="comment">// }</span></span><br><span class="line"><span class="comment">// },</span></span><br><span class="line">{</span><br><span class="line"> test: <span class="regexp">/\.(png|jpg|gif|svg)$/</span>,</span><br><span class="line"> loader: <span class="string">'url-loader'</span>,</span><br><span class="line"> options: {</span><br><span class="line"> limit: <span class="number">10000</span>,</span><br><span class="line"> name: <span class="string">'[name].[ext]?[hash]'</span></span><br><span class="line"> }</span><br><span class="line">},</span><br><span class="line"><span class="comment">//...</span></span><br></pre></td></tr></table></figure>
<p>修改 <code>src/main.js</code>,使其引入图片</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> image <span class="keyword">from</span> <span class="string">'./assets/images/logo.png'</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> image</span><br></pre></td></tr></table></figure>
<p>编译后的 <code>dist/build.js</code> 则</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// ...</span></span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"><span class="comment">// 0号模块 从 1号模块导出中获得了图片,__webpack_require__ 实际上是所有的以来模块数组</span></span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0__assets_images_logo_png__ = __webpack_require__(<span class="number">1</span>);</span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0__assets_images_logo_png___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__assets_images_logo_png__);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/* harmony default export */</span> __webpack_exports__[<span class="string">"default"</span>] = (__WEBPACK_IMPORTED_MODULE_0__assets_images_logo_png___default.a);</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 1 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// 省略真正的base 64图片编码,太长了</span></span><br><span class="line"><span class="built_in">module</span>.exports = <span class="string">"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgA..........."</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> })</span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<h3 id="css"><a href="#css" class="headerlink" title="css"></a>css</h3><p>css 在本项目中则通过 vue-style-loader 与 css-loader 转化为js代码,调用时就是被插入。</p>
<p>在 <code>src/main.js</code> 下写入</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> style <span class="keyword">from</span> <span class="string">'./assets/styles/reset.css'</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> style;</span><br></pre></td></tr></table></figure>
<p>编译后的 <code>dist/build.js</code> 将会多出一大堆的函数,首先0号依赖还是熟悉的面孔</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/******/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">modules</span>) </span>{ <span class="comment">// webpackBootstrap</span></span><br><span class="line"><span class="comment">/******/</span> <span class="comment">// ...</span></span><br><span class="line"><span class="comment">/******/</span> })</span><br><span class="line"><span class="comment">/************************************************************************/</span></span><br><span class="line"><span class="comment">/******/</span> ([</span><br><span class="line"><span class="comment">/* 0 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, __webpack_exports__, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// 0号模块依旧是熟悉的代码,依赖于 1号模块输出的对象。</span></span><br><span class="line"><span class="meta">"use strict"</span>;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(__webpack_exports__, <span class="string">"__esModule"</span>, { <span class="attr">value</span>: <span class="literal">true</span> });</span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0__assets_styles_reset_css__ = __webpack_require__(<span class="number">1</span>);</span><br><span class="line"><span class="comment">/* harmony import */</span> <span class="keyword">var</span> __WEBPACK_IMPORTED_MODULE_0__assets_styles_reset_css___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__assets_styles_reset_css__);</span><br><span class="line"></span><br><span class="line"><span class="comment">/* harmony default export */</span> __webpack_exports__[<span class="string">"default"</span>] = (__WEBPACK_IMPORTED_MODULE_0__assets_styles_reset_css___default.a);</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 1 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// style-loader: Adds some css to the DOM by adding a <style> tag</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// load the styles 调用2号模块获取css具体内容</span></span><br><span class="line"><span class="keyword">var</span> content = __webpack_require__(<span class="number">2</span>);</span><br><span class="line"><span class="keyword">if</span>(<span class="keyword">typeof</span> content === <span class="string">'string'</span>) content = [[<span class="built_in">module</span>.i, content, <span class="string">''</span>]];</span><br><span class="line"><span class="keyword">if</span>(content.locals) <span class="built_in">module</span>.exports = content.locals;</span><br><span class="line"><span class="comment">// add the styles to the DOM 调用4号模块去具体插入css内容</span></span><br><span class="line"><span class="keyword">var</span> update = __webpack_require__(<span class="number">4</span>)(<span class="string">"0b88176b"</span>, content, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 2 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line">exports = <span class="built_in">module</span>.exports = __webpack_require__(<span class="number">3</span>)(<span class="literal">undefined</span>);</span><br><span class="line"><span class="comment">// imports</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// module 这里就是我们写的 reset.css 的具体内容了,</span></span><br><span class="line">exports.push([<span class="built_in">module</span>.i, <span class="string">"*{margin:0;padding:0}"</span>, <span class="string">""</span>]);</span><br><span class="line"></span><br><span class="line"><span class="comment">// exports</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 3 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// css base code, injected by the css-loader</span></span><br><span class="line"><span class="comment">// 3号模块太长,不贴,调试后得知貌似只是暴露了两个方法出来</span></span><br><span class="line"><span class="comment">// ......</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 4 */</span></span><br><span class="line"><span class="comment">/***/</span> (<span class="function"><span class="keyword">function</span>(<span class="params">module, exports, __webpack_require__</span>) </span>{</span><br><span class="line"></span><br><span class="line"><span class="comment">// ...太长只贴了关键步骤,总之关键的函数就是这些</span></span><br><span class="line"><span class="keyword">var</span> hasDocument = <span class="keyword">typeof</span> <span class="built_in">document</span> !== <span class="string">'undefined'</span></span><br><span class="line"><span class="keyword">var</span> head = hasDocument && (<span class="built_in">document</span>.head || <span class="built_in">document</span>.getElementsByTagName(<span class="string">'head'</span>)[<span class="number">0</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="built_in">module</span>.exports = <span class="function"><span class="keyword">function</span> (<span class="params">parentId, list, _isProduction</span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> <span class="keyword">var</span> styles = listToStyles(parentId, list)</span><br><span class="line"> addStylesToDom(styles)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> <span class="title">update</span> (<span class="params">newList</span>) </span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addStylesToDom</span> (<span class="params">styles <span class="regexp">/* Array<StyleObject> */</span></span>) </span>{</span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < styles.length; i++) {</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> domStyle.parts.push(addStyle(item.parts[j]))</span><br><span class="line"> <span class="comment">// ....</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 总之先调用了addStylesToDom,接着是addStyle,再是createStyleElement插入样式到head中。</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createStyleElement</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> styleElement = <span class="built_in">document</span>.createElement(<span class="string">'style'</span>)</span><br><span class="line"> styleElement.type = <span class="string">'text/css'</span></span><br><span class="line"> head.appendChild(styleElement)</span><br><span class="line"> <span class="keyword">return</span> styleElement</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">addStyle</span> (<span class="params">obj <span class="regexp">/* StyleObjectPart */</span></span>) </span>{</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> styleElement = createStyleElement()</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/***/</span> }),</span><br><span class="line"><span class="comment">/* 5 */</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"><span class="comment">/******/</span> ]);</span><br><span class="line"><span class="comment">//# sourceMappingURL=build.js.map</span></span><br></pre></td></tr></table></figure>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://juejin.im/post/59b9d2336fb9a00a636a3158" target="_blank" rel="noopener">探索webpack模块以及webpack3新特性</a><br><a href="https://segmentfault.com/a/1190000004144950" target="_blank" rel="noopener">webpack把你的项目编译成了什么</a></p>
]]></content>
<categories>
<category>js-util</category>
</categories>
<tags>
<tag>vue</tag>
<tag>webpack</tag>
</tags>
</entry>
<entry>
<title>canvas 高清屏兼容</title>
<url>/2017/12/07/canvas/canvas-retina/</url>
<content><![CDATA[<h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>废话不多说,直接上代码</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使canvas在不同分辨率屏幕上显示最佳像素</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> CanvasModule = (<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 功能 获取屏幕的分辨率 方便canvas在不同分辨率屏幕上显示最佳像素</span></span><br><span class="line"><span class="comment"> * 返回合适的分辨率</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> getRatio = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> ctx = <span class="built_in">document</span>.createElement(<span class="string">"canvas"</span>).getContext(<span class="string">"2d"</span>),</span><br><span class="line"> dpr = <span class="built_in">window</span>.devicePixelRatio || <span class="number">1</span>,</span><br><span class="line"> bsr = ctx.webkitBackingStorePixelRatio ||</span><br><span class="line"> ctx.mozBackingStorePixelRatio ||</span><br><span class="line"> ctx.msBackingStorePixelRatio ||</span><br><span class="line"> ctx.oBackingStorePixelRatio ||</span><br><span class="line"> ctx.backingStorePixelRatio || <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> dpr / bsr;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 功能 创建适应屏幕分辨率的canvas画布</span></span><br><span class="line"><span class="comment"> * 返回相应canvas</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> createHiDPICanvas = <span class="function"><span class="keyword">function</span>(<span class="params">canvas</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> w = canvas.clientWidth; </span><br><span class="line"> <span class="keyword">var</span> h = canvas.clientHeight;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> ratio = getRatio();</span><br><span class="line"></span><br><span class="line"> canvas.width = w * ratio;</span><br><span class="line"> canvas.height = h * ratio;</span><br><span class="line"> canvas.style.width = w + <span class="string">'px'</span>;</span><br><span class="line"> canvas.style.height = h + <span class="string">'px'</span>;</span><br><span class="line"> canvas.getContext(<span class="string">"2d"</span>).setTransform(ratio, <span class="number">0</span>, <span class="number">0</span>, ratio, <span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line"> <span class="keyword">return</span> canvas;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> createHiDPICanvas: createHiDPICanvas,</span><br><span class="line"> ratio: getRatio()</span><br><span class="line"> }</span><br><span class="line">})();</span><br></pre></td></tr></table></figure>
<h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">canvas</span> <span class="attr">id</span>=<span class="string">"canvas"</span> <span class="attr">width</span>=<span class="string">"600"</span> <span class="attr">style</span>=<span class="string">"border:1px solid #aaa; display:block"</span>></span></span><br><span class="line"> ...</span><br><span class="line"> <span class="tag"></<span class="name">canvas</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br></pre></td></tr></table></figure>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">var</span> canvas = <span class="built_in">document</span>.getElementById(<span class="string">'canvas'</span>)</span><br><span class="line">CanvasModule.createHiDPICanvas(canvas);</span><br></pre></td></tr></table></figure>
]]></content>
<categories>
<category>canvas</category>
</categories>
<tags>
<tag>canvas</tag>
</tags>
</entry>
<entry>
<title>控制 webkit 的滚动条样式</title>
<url>/2017/12/04/css/webkit-scrollbar/</url>
<content><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>修改webkit内核浏览器的滚动条样式</p>
<h2 id="伪元素"><a href="#伪元素" class="headerlink" title="伪元素"></a>伪元素</h2><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-pseudo">::-webkit-scrollbar</span> { <span class="comment">/* 1 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-button</span> { <span class="comment">/* 2 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-track</span> { <span class="comment">/* 3 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-track-piece</span> { <span class="comment">/* 4 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-thumb</span> { <span class="comment">/* 5 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-corner</span> { <span class="comment">/* 6 */</span> }</span><br><span class="line"><span class="selector-pseudo">::-webkit-resizer</span> { <span class="comment">/* 7 */</span> }</span><br></pre></td></tr></table></figure>
<p><img src="https://cdn.css-tricks.com/wp-content/uploads/2011/05/scrollbarparts.png" alt=""></p>
<h2 id="伪类"><a href="#伪类" class="headerlink" title="伪类"></a>伪类</h2><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-pseudo">:horizontal</span></span><br><span class="line"><span class="selector-pseudo">:vertical</span></span><br><span class="line"><span class="selector-pseudo">:decrement</span></span><br><span class="line"><span class="selector-pseudo">:increment</span></span><br><span class="line"><span class="selector-pseudo">:start</span></span><br><span class="line"><span class="selector-pseudo">:end</span> </span><br><span class="line"><span class="selector-pseudo">:double-button</span></span><br><span class="line"><span class="selector-pseudo">:single-button</span></span><br><span class="line"><span class="selector-pseudo">:no-button</span></span><br><span class="line"><span class="selector-pseudo">:corner-present</span></span><br><span class="line"><span class="selector-pseudo">:window-inactive</span></span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">:horizontal – 作用于水平方向的滚动条</span><br><span class="line"></span><br><span class="line">:vertical – 作用于垂直方向滚动条</span><br><span class="line"></span><br><span class="line">:decrement – The decrement pseudo-class applies to buttons and track pieces. It indicates whether or not the button or track piece will decrement the view’s position when used (e.g., up on a vertical scrollbar, left on a horizontal scrollbar).</span><br><span class="line"></span><br><span class="line">:increment – The increment pseudo-class applies to buttons and track pieces. It indicates whether or not a button or track piece will increment the view’s position when used (e.g., down on a vertical scrollbar, right on a horizontal scrollbar).</span><br><span class="line"></span><br><span class="line">:start – The start pseudo-class applies to buttons and track pieces. It indicates whether the object is placed before the thumb.</span><br><span class="line"></span><br><span class="line">:end – The end pseudo-class applies to buttons and track pieces. It indicates whether the object is placed after the thumb.</span><br><span class="line"></span><br><span class="line">:double-button – The double-button pseudo-class applies to buttons and track pieces. It is used to detect whether a button is part of a pair of buttons that are together at the same end of a scrollbar. For track pieces it indicates whether the track piece abuts a pair of buttons.</span><br><span class="line"></span><br><span class="line">:single-button – The single-button pseudo-class applies to buttons and track pieces. It is used to detect whether a button is by itself at the end of a scrollbar. For track pieces it indicates whether the track piece abuts a singleton button.</span><br><span class="line"></span><br><span class="line">:no-button – Applies to track pieces and indicates whether or not the track piece runs to the edge of the scrollbar, i.e., there is no button at that end of the track.</span><br><span class="line"></span><br><span class="line">:corner-present – Applies to all scrollbar pieces and indicates whether or not a scrollbar corner is present.</span><br><span class="line"></span><br><span class="line">:window-inactive – Applies to all scrollbar pieces and indicates whether or not the window containing the scrollbar is currently active. (In recent nightlies, this pseudo-class now applies to ::selection as well. We plan to extend it to work with any content and to propose it as a new standard pseudo-class.)</span><br></pre></td></tr></table></figure>
<h2 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h2><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-pseudo">::-webkit-scrollbar</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">12px</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-track</span> {</span><br><span class="line"> <span class="attribute">-webkit-box-shadow</span>: inset <span class="number">0</span> <span class="number">0</span> <span class="number">6px</span> <span class="built_in">rgba</span>(0,0,0,0.3); </span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="selector-pseudo">::-webkit-scrollbar-thumb</span> {</span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">10px</span>;</span><br><span class="line"> <span class="attribute">-webkit-box-shadow</span>: inset <span class="number">0</span> <span class="number">0</span> <span class="number">6px</span> <span class="built_in">rgba</span>(0,0,0,0.5); </span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p><img src="https://cdn.css-tricks.com/wp-content/uploads/2011/05/simplecustomscrollbar.png" alt=""></p>
<h2 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h2><p><a href="https://css-tricks.com/custom-scrollbars-in-webkit/" target="_blank" rel="noopener">https://css-tricks.com/custom-scrollbars-in-webkit/</a></p>
]]></content>
<categories>
<category>css</category>
</categories>
<tags>
<tag>css 2</tag>
</tags>
</entry>
<entry>
<title>Js 关闭当前页面</title>
<url>/2017/12/01/javascript/close-current-page/</url>
<content><![CDATA[<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>以前见到过一个当你保存某表单成功后,显示倒计时并自动关闭页面的效果,现在终于轮到我来实现了。</p>
<p>不过这有何好说,直接调用下面的代码不就关闭了么?</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">window.close()</span><br></pre></td></tr></table></figure>
<p>然而,在最新的 chrome 浏览器上写上却是显示一个警告并且代码并不生效。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Scripts may close only the windows that were opened by it.</span><br></pre></td></tr></table></figure>
<p>翻了好多资料却都于事无补。</p>
<h2 id="close函数的限制"><a href="#close函数的限制" class="headerlink" title="close函数的限制"></a>close函数的限制</h2><p>上面出现的警告信息我在 stackoverflow 上看到有人回答</p>
<blockquote>
<p>If your script did not initiate opening the window (with something like window.open), then the script in that window is not allowed to close it. Its a security to prevent a website taking control of your browser and closing windows.</p>
</blockquote>
<p>简而言之,<code>window.close()</code> 是有限制的,window.open 会返回一个对象,这个对象就是打开的新页面的 window 对象,</p>
<p>在 pageA 中写入</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">let pageB = window.open('xxx pageB');</span><br><span class="line">pageB.close();</span><br></pre></td></tr></table></figure>