-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
1412 lines (1221 loc) · 508 KB
/
atom.xml
File metadata and controls
1412 lines (1221 loc) · 508 KB
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"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Sagittarius Love Libra</title>
<link href="/atom.xml" rel="self"/>
<link href="http://www.i0011.com/"/>
<updated>2017-08-03T13:23:34.000Z</updated>
<id>http://www.i0011.com/</id>
<author>
<name>徐祁</name>
<email>github.xq@gmail.com</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Lodash源码祭「Object」</title>
<link href="http://www.i0011.com/2017/07/20/lodash-object/"/>
<id>http://www.i0011.com/2017/07/20/lodash-object/</id>
<published>2017-07-20T14:33:33.000Z</published>
<updated>2017-08-03T13:23:34.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Object"><a href="#Object" class="headerlink" title="Object"></a>Object</h1><h2 id="assign"><a href="#assign" class="headerlink" title="assign"></a>assign</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.assign(object, [sources])</div></pre></td></tr></table></figure>
<p>将source(可多个,参数列表)中可枚举的字符串属性赋到object,合并顺序是从左到右合并到object,同名会覆盖,方法返回object<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> assign = <span class="function">(<span class="params">object, ...sources</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> object = {};</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (sources && sources.length > <span class="number">0</span>) {</div><div class="line"> sources.forEach(<span class="function"><span class="params">source</span> =></span> {</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> source) {</div><div class="line"> <span class="keyword">if</span> (source.hasOwnProperty(key)) {</div><div class="line"> object[key] = source[key];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"> }</div><div class="line"> <span class="comment">// Or: 直接Object.assign,行为一致</span></div><div class="line"></div><div class="line"> <span class="keyword">return</span> object;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="assignIn"><a href="#assignIn" class="headerlink" title="assignIn"></a>assignIn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.assignIn(object, [sources])</div></pre></td></tr></table></figure>
<p>类似<code>assign</code>,但是也会将source中的继承熟悉合并过去,那就不要<code>hasOwnproperty</code>的判断咯?</p>
<h2 id="forIn"><a href="#forIn" class="headerlink" title="forIn"></a>forIn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.forIn(object, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>遍历所有可枚举的<code>字符串</code>(非symbol)键和对应的值,iteratee接受三个参数:value、key、object…跟数组的forEach一样,<code>return false</code>会退出遍历<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> forIn = <span class="function">(<span class="params">object, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="comment">//let attrs = Object.keys(object); // 获取所有可枚举属性</span></div><div class="line"> <span class="keyword">let</span> attrs = [];</div><div class="line"></div><div class="line"> <span class="comment">// 通过原生for in获取所有可枚举的属性</span></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> attr <span class="keyword">in</span> object) {</div><div class="line"> attrs.push(attr);</div><div class="line"> }</div><div class="line"> <span class="comment">// 或者通过如下方式获取,但是要保存object副本</span></div><div class="line"> <span class="comment">//while (object) {</span></div><div class="line"> <span class="comment">// let attr = Object.keys(object);</span></div><div class="line"></div><div class="line"> <span class="comment">// attrs = [...attrs, ...attr];</span></div><div class="line"></div><div class="line"> <span class="comment">// object = Object.getPrototypeOf(object);</span></div><div class="line"> <span class="comment">//}</span></div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < attrs.length) {</div><div class="line"> <span class="keyword">let</span> attr = attrs[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (iteratee(object[attr], attr, object) === <span class="literal">false</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> object;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="forOwn"><a href="#forOwn" class="headerlink" title="forOwn"></a>forOwn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.forOwn(object, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>类似于<code>forIn</code>,但是只遍历自己的可枚举属性,直接用<code>Object.keys</code>就可以啦<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> forOwn = <span class="function">(<span class="params">object, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> attrs = <span class="built_in">Object</span>.keys(object);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < attrs.length) {</div><div class="line"> <span class="keyword">let</span> attr = attrs[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (iteratee(object[attr], attr, object) === <span class="literal">false</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> object;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="keys"><a href="#keys" class="headerlink" title="keys"></a>keys</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.keys(object)</div></pre></td></tr></table></figure>
<p>返回可枚举的键名。非对象变量会强制转化为对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> keys = <span class="function"><span class="params">object</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.keys(obejct);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="keysIn"><a href="#keysIn" class="headerlink" title="keysIn"></a>keysIn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.keysIn(object)</div></pre></td></tr></table></figure>
<p>类似<code>keys</code>,返回原型链上的所有属性<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> keysIn = <span class="function"><span class="params">object</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> attrs = [];</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> attr <span class="keyword">in</span> object) {</div><div class="line"> attrs.push(attr);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> attrs;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pick"><a href="#pick" class="headerlink" title="pick"></a>pick</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pick(object, [paths])</div></pre></td></tr></table></figure>
<p>pick出obejct中对应path(字符串或数组)的键值对,返回pick到的新对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pick = <span class="function">(<span class="params">object, paths</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || paths === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(paths)) {</div><div class="line"> paths = [<span class="built_in">String</span>(paths)];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < paths.length; i++) {</div><div class="line"> <span class="keyword">let</span> key = paths[i];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (object[key] === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> result[key] = object[key];</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pickBy"><a href="#pickBy" class="headerlink" title="pickBy"></a>pickBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pickBy(object, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>pick除满足predicate为truthy值的属性。predicate接受两个参数(value、key)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pickBy = <span class="function">(<span class="params">object, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> predicate !== <span class="string">'function'</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> attr <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (predicate(object[attr], attr)) {</div><div class="line"> result[attr] = object[attr];</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="omit"><a href="#omit" class="headerlink" title="omit"></a>omit</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.omit(object, [paths])</div></pre></td></tr></table></figure>
<p>pick的逆操作,排除某些paths(字符串或数组)指定的属性(自身属性和继承属性)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> omit = <span class="function">(<span class="params">object, paths</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (paths === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(paths)) {</div><div class="line"> paths = [<span class="built_in">String</span>(paths)];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> attr <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (paths.indexOf(attr) < <span class="number">0</span>) {</div><div class="line"> result[attr] = object[attr];</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="omitBy"><a href="#omitBy" class="headerlink" title="omitBy"></a>omitBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.omitBy(object, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>排除<strong>不</strong>满足predicate的object的属性,predicate接受两个参数(value, key)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> omitBy = <span class="function">(<span class="params">object, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || predicate === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> predicate !== <span class="string">'function'</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> attr <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (predicate(object[attr], attr)) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"> result[attr] = object[attr];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="has"><a href="#has" class="headerlink" title="has"></a>has</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.has(object, path)</div></pre></td></tr></table></figure>
<p>object<strong>自身</strong>是否包含path所提供的属性。path可以是字符串(单个属性或者以<code>.</code>分割的路径),也可以是数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> has = <span class="function">(<span class="params">object, path</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || !path) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> path = <span class="built_in">Array</span>.isArray(path) ? path : path.split(<span class="string">'.'</span>);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < path.length) {</div><div class="line"> <span class="keyword">let</span> attr = path[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (object.hasOwnProperty(attr)) {</div><div class="line"> object = object[attr];</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="hasIn"><a href="#hasIn" class="headerlink" title="hasIn"></a>hasIn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.hasIn(object, path)</div></pre></td></tr></table></figure>
<p>跟<code>has</code>类似,但是可以查找原型链上的属性,可以直接用<code>in</code>操作符<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> hasIn = <span class="function">(<span class="params">object, path</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || !path) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> path = <span class="built_in">Array</span>.isArray(path) ? path : path.split(<span class="string">'.'</span>);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < path.length) {</div><div class="line"> <span class="keyword">let</span> attr = path[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (attr <span class="keyword">in</span> object) {</div><div class="line"> object = object[attr];</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="invert"><a href="#invert" class="headerlink" title="invert"></a>invert</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.invert(object)</div></pre></td></tr></table></figure>
<p>反转对象的键值对,反转后重复的键的值会被覆盖<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> invert = <span class="function"><span class="params">object</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = {};</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> object) {</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (object.hasOwnProperty(key)) {</div><div class="line"> res[object[key]] = key;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="invertBy"><a href="#invertBy" class="headerlink" title="invertBy"></a>invertBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.invertBy(object, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>与<code>invert</code>类似,参数可有iteratee函数去迭代每个值…另外,对于重复键的该方法不会覆盖,键转化成值后是一个数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> invertBy = <span class="function">(<span class="params">object, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">value</span> =></span> value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = {};</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (object.hasOwnProperty(key)) {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> _key = iteratee(object[key]);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (res[_key]) {</div><div class="line"> res[_key].push(key);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> res[_key] = [key];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="mapKeys"><a href="#mapKeys" class="headerlink" title="mapKeys"></a>mapKeys</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.mapKeys(object, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>保留对象的值,通过iteratee重新映射键,iteratee接受3个参数(value, key, object),返回map后的新对象<br>PS: 对于官网<code>_.mapKeys({a: 1, b:2})</code>输出{1:1, 2:2}持保留意见啊,这个方法直接用Object.keys去遍历也太随便了吧,怎么滴也应该原样返回啊,这块就按照自己的想法去实现啊<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> mapKeys = <span class="function">(<span class="params">object, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee || <span class="keyword">typeof</span> iteratee !== <span class="string">'function'</span>) {</div><div class="line"> iteratee = <span class="function">(<span class="params">value, key</span>) =></span> key;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = {};</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (object.hasOwnProperty(key)) {</div><div class="line"> res[iteratee(object[key], key, object)] = object[key];</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>如果值是个引用( 比如:{a: {b: ‘hello world’}} ),怎么解决map后的对象和源对象的值是指向同一内存的事实啊…</p>
<h2 id="mapValues"><a href="#mapValues" class="headerlink" title="mapValues"></a>mapValues</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.mapValues(object, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>同<code>mapKeys</code>,会映射值<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> mapValues = <span class="function">(<span class="params">object, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> {};</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee || <span class="keyword">typeof</span> iteratee !== <span class="string">'function'</span>) {</div><div class="line"> iteratee = <span class="function">(<span class="params">value, key</span>) =></span> value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = {};</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> object) {</div><div class="line"> <span class="keyword">if</span> (object.hasOwnProperty(key)) {</div><div class="line"> res[key] = iteratee(object[key], key, object);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="get"><a href="#get" class="headerlink" title="get"></a>get</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.get(object, path, [defaultValue])</div></pre></td></tr></table></figure>
<p>获取object指定path的值,如果设置了defaultValue,在value为undefined时返回defaultValue<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> get = <span class="function">(<span class="params">obejct, path, defaultValue</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || path === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(path)) {</div><div class="line"> path = path.join(<span class="string">'.'</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> path = <span class="built_in">String</span>(path).replace(<span class="regexp">/\[([^\]]*)\]/g</span>, <span class="string">'.$1'</span>).split(<span class="string">'.'</span>); <span class="comment">// 处理[0]这种情况的路径访问</span></div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> value;</div><div class="line"> <span class="keyword">while</span> (++index < path.length) {</div><div class="line"> <span class="keyword">let</span> cur = path[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index === <span class="number">0</span>) {</div><div class="line"> value = object[cur];</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> value = value[cur];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (value === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (value === <span class="literal">undefined</span>) {</div><div class="line"> value = defaultValue;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> value;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="set"><a href="#set" class="headerlink" title="set"></a>set</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.set(object, path, value)</div></pre></td></tr></table></figure>
<p>设置指定路径的值,若中间路径不存在就新建,对于索引(数字)的情况,新建数组,其他情况新建对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> set = <span class="function">(<span class="params">object, path, value</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span> || path === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> object;</div><div class="line"> }</div><div class="line"></div><div class="line"> object = <span class="built_in">Object</span>(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(path)) {</div><div class="line"> path = path.join(<span class="string">'.'</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> path = <span class="built_in">String</span>(path).replace(<span class="regexp">/\[([^\]]*)\]/g</span>, <span class="string">'.$1'</span>).split(<span class="string">'.'</span>);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> nest = object;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> length = path.length;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> cur = path[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> val = nest[cur];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index !== length - <span class="number">1</span>) {</div><div class="line"> <span class="keyword">if</span> (val === <span class="literal">undefined</span>) {</div><div class="line"> val = <span class="regexp">/^(?:0|[1-9]\d*)$/</span>.test(path[index + <span class="number">1</span>]) ? [] : {};</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> val = value;</div><div class="line"> }</div><div class="line"></div><div class="line"> nest[cur] = val;</div><div class="line"></div><div class="line"> nest = nest[cur];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> object;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toPairs"><a href="#toPairs" class="headerlink" title="toPairs"></a>toPairs</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toPairs(object)</div></pre></td></tr></table></figure>
<p>以对象自身可枚举的键和值组成的数组做为返回的数组的每项,如果是Map或者Set,直接返回entries<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toPairs = <span class="function"><span class="params">object</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">const</span> toString = <span class="built_in">Object</span>.prototype.toString.call(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (toString === <span class="string">'[object Set]'</span> || toString === <span class="string">'[object Map]'</span>) {</div><div class="line"> <span class="keyword">return</span> object.entries();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = [];</div><div class="line"> <span class="built_in">Object</span>.keys(object).forEach(<span class="function"><span class="params">key</span> =></span> {</div><div class="line"> res.push([key, object[key]]);</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toPairsIn"><a href="#toPairsIn" class="headerlink" title="toPairsIn"></a>toPairsIn</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toPairsIn(object)</div></pre></td></tr></table></figure>
<p>类似<code>toPairs</code>,可遍历出继承的枚举属性<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toPairsIn = <span class="function"><span class="params">object</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (object == <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">const</span> toString = <span class="built_in">Object</span>.prototype.toString.call(object);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (toString === <span class="string">'[object Set]'</span> || toString === <span class="string">'[object Map]'</span>) {</div><div class="line"> <span class="keyword">return</span> object.entries();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = [];</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> object) {</div><div class="line"> res.push([key, object[key]]);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Object"><a href="#Object" class="headerlink" title="Object
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="String" scheme="http://www.i0011.com/tags/String/"/>
</entry>
<entry>
<title>Lodash源码祭「Array」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-array/"/>
<id>http://www.i0011.com/2017/07/12/lodash-array/</id>
<published>2017-07-12T11:09:17.000Z</published>
<updated>2017-07-13T14:45:58.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h1><h2 id="chunk"><a href="#chunk" class="headerlink" title="chunk"></a>chunk</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.chunk(array, [size=1])</div></pre></td></tr></table></figure>
<p>猜想下实现方法,功能就是将数组拆分成<code>arrar.length / size</code>个数组,每个数组<code>size</code>个元素,剩余的元素作为最后一个分组,数组操作中<code>slice</code>不改变原数组并实现数组切分:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> chunk = <span class="function">(<span class="params">array, size = <span class="number">1</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> count = <span class="built_in">Math</span>.ceil(array.length / size);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> _chunk = <span class="keyword">new</span> <span class="built_in">Array</span>(count);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> start = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < count) {</div><div class="line"> _chunk[index] = array.slice(start, start += size);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _chunk;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>验证下,功能OK,再来看下lodash的实现方法:</p>
<ul>
<li>首先,<strong>对参数进行验证</strong><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">size = <span class="built_in">Math</span>.max(size, <span class="number">0</span>)</div><div class="line"><span class="keyword">const</span> length = array == <span class="literal">null</span> ? <span class="number">0</span> : array.length</div><div class="line"><span class="keyword">if</span> (!length || size < <span class="number">1</span>) {</div><div class="line"> <span class="keyword">return</span> []</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>确保size非负以及length为合法值…</p>
<p>虽然处理了数组,但是需不需要考虑ArrayLike的Object伪装Array的情况<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.chunk({<span class="attr">a</span>:<span class="number">1</span>, <span class="attr">b</span>:<span class="number">2</span>, <span class="attr">length</span>:<span class="number">2</span>}, <span class="number">2</span>)</div></pre></td></tr></table></figure></p>
<p>将得到一个包含两个undefined的数组的数组,是否加上数组判断是更nice呢:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (!length || !(array <span class="keyword">instanceof</span> <span class="built_in">Array</span>) || size < <span class="number">1</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>再看<code>import baseSlice from './.internal/baseSlice.js'</code>,lodash并未用Array.prototype.slice去做数组切割,而是自己写了一个,为啥?slice是基础特性啊,浏览器都支持的,咋不直接用的…实现上首先将<code>start</code>和<code>end</code>都转化为正值并做start <= end的验证,在算切割的数组length的时候,用了这样的语句,可以关注一下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">length = start > end ? <span class="number">0</span> : ((end - start) >>> <span class="number">0</span>)</div></pre></td></tr></table></figure></p>
<p><code>>>> 0</code>有什么用?Check <a href="http://stackoverflow.com/questions/1822350/what-is-the-javascript-operator-and-how-do-you-use-it" target="_blank" rel="external">stackoverlfow</a>…其实就是将值转化为32位无符号整数,即Array.length的合法值,参见<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length" target="_blank" rel="external">MDN</a>,非”数字”转化后值为0,比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="literal">null</span> >>> <span class="number">0</span> <span class="comment">// 0</span></div><div class="line"></div><div class="line"><span class="string">'1'</span> >>> <span class="number">0</span> <span class="comment">// 1 数字字符串将转化为对应的数字</span></div></pre></td></tr></table></figure></p>
<h2 id="compact"><a href="#compact" class="headerlink" title="compact"></a>compact</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.compact(array)</div></pre></td></tr></table></figure>
<p>compact -> “压紧、简化”,这个就简单了,移除数组中所有的<code>falsey</code>值:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> compact = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> _compact = [];</div><div class="line"> <span class="keyword">if</span> (array && array.length && array <span class="keyword">instanceof</span> <span class="built_in">Array</span>) {</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> length = array.length;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (index++ <span class="xml"><span class="tag">< <span class="attr">length</span>) {</span></span></div><div class="line"> <span class="attr">if</span> (<span class="attr">array</span>[<span class="attr">index</span>]) {</div><div class="line"> <span class="attr">_compact.push</span>(<span class="attr">array</span>[<span class="attr">index</span>]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> <span class="attr">return</span> <span class="attr">_compact</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>下意识的用<code>push</code>插入数组项,而源码惯用下标递增:<code>result[resIndex++] = value</code>。性能有影响?</p>
<h2 id="concat"><a href="#concat" class="headerlink" title="concat"></a>concat</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.concat(array, [values])</div></pre></td></tr></table></figure>
<p>实现的就是原生concat的功能,参数处理一下即可:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> concat = <span class="function">(<span class="params">array, ...values</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (array && array <span class="keyword">instanceof</span> <span class="built_in">Array</span>) {</div><div class="line"> <span class="keyword">return</span> array.concat(...values);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>Done! rest参数和数组析构教你做人…对比对比源码看看自己的实现漏了些啥…</p>
<ul>
<li>基础方法实现es6提供的一些便利,包括arguments对象的参数拆分、数组flatten</li>
<li>array参数可以接受非数组,若array非数组,[array]将作为基础数组参与运算<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">return</span> arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, <span class="number">1</span>));</div></pre></td></tr></table></figure>
</li>
</ul>
<p>关于<strong>数组类型</strong>的判断,我们上面用了<code>array instanceof Array</code>这种方式,lodash中<code>isArray</code>即<code>Array.isArray</code>,来看MDN关于isArray的Polyfill:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray) {</div><div class="line"> <span class="built_in">Array</span>.isArray = <span class="function"><span class="keyword">function</span>(<span class="params">arg</span>) </span>{</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(arg) === <span class="string">'[object Array]'</span>;</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>如果toString能吐出<code>[object Array]</code>我们就认为他是一个数组,那<code>instanceof Array</code>和<code>isArray</code>有啥区别?</p>
<blockquote>
<p>When checking for Array instance, Array.isArray is preferred over instanceof because it works through iframes.<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> xArray = otherFrame.Array;</div><div class="line"></div><div class="line"><span class="keyword">let</span> arr = <span class="keyword">new</span> xArray(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>);</div><div class="line"></div><div class="line">arr <span class="keyword">instanceof</span> <span class="built_in">Array</span>; <span class="comment">// false</span></div><div class="line"></div><div class="line"><span class="built_in">Array</span>.isArray(arr); <span class="comment">// true</span></div></pre></td></tr></table></figure></p>
</blockquote>
<p>显然,arr只是xArray(ohterFrame的Array)的instance而并非当前frame的Array的instance,而isArray不受此影响</p>
<h2 id="difference"><a href="#difference" class="headerlink" title="difference"></a>difference</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.difference(array, [values])</div></pre></td></tr></table></figure>
<p>生成一个从array中过滤掉values中所有元素的数组,即做个数组去重:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> difference = <span class="function">(<span class="params">array, values</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!values || values.length === <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">let</span> the = array[i];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (values.indexOf(the) === <span class="number">-1</span>) {</div><div class="line"> result.push(the);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>源码如何实现,坑有点深啊…</p>
<h2 id="differenceBy"><a href="#differenceBy" class="headerlink" title="differenceBy"></a>differenceBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.differenceBy(array, [values], [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>不同于difference的是,differenceBy接受第三个参数iteratee,会按照array中每项转化后的值进行去重,比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.differenceBy([<span class="number">2.1</span>, <span class="number">1.2</span>], [<span class="number">2.3</span>, <span class="number">3.4</span>], <span class="built_in">Math</span>.floor); <span class="comment">// [1.2]</span></div></pre></td></tr></table></figure></p>
<p>另外,对于对象数组,iteratee可以为属性字符串,这其实是_.property的简写</p>
<p>不严谨实现方法:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> differenceBy = <span class="function">(<span class="params">array, ...params</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (params.length === <span class="number">1</span>) {</div><div class="line"> <span class="keyword">return</span> difference(array, params);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> ite = params.pop();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> exclude = params.shift().map(<span class="function"><span class="params">i</span> =></span> ite(i));</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">let</span> computed = ite(array[i]);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (exclude.indexOf(computed)) {</div><div class="line"> result.push(array[i]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>还有一个difference方法…</p>
<h2 id="differenceWith"><a href="#differenceWith" class="headerlink" title="differenceWith"></a>differenceWith</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.differenceWith(array, [values], [comparator])</div></pre></td></tr></table></figure>
<p>differenceWith通过指定comparator,改变默认比较方式去得到相应的去重数组</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> differenceWith = <span class="function">(<span class="params">array, ...params</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (params.length === <span class="number">1</span>) {</div><div class="line"> <span class="keyword">return</span> difference(array, params);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> comparator = params.pop();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> exclude = params.shift();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> eLen = exclude.length;</div><div class="line"></div><div class="line"> outer:</div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < array.length; i++) {</div><div class="line"> <span class="keyword">let</span> the = array[i];</div><div class="line"> <span class="keyword">let</span> index = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (index++ <span class="xml"><span class="tag">< <span class="attr">eLen</span>) {</span></span></div><div class="line"> <span class="attr">if</span> (<span class="attr">comparator</span>(<span class="attr">the</span>, <span class="attr">exclude</span>[<span class="attr">index</span>])) {</div><div class="line"> <span class="attr">continue</span> <span class="attr">outer</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="attr">result.push</span>(<span class="attr">the</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="attr">return</span> <span class="attr">result</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>上述三个difference方法在去重操作上统一,可以抽象出来个baseDifference基础方法,且上面我们只考虑了简单的值类型的比较,并未考虑引用类型和NaN这种特殊类型的情况<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/**</span></div><div class="line"> * base difference</div><div class="line"> * @param array [Array]</div><div class="line"> * @param exclude [Array]</div><div class="line"> * @param iteratee [function] 迭代器,对每个元素转化后进行比较</div><div class="line"> * @param comparator [function] 比较器,比较方法</div><div class="line"> * @param return [array]</div><div class="line"> */</div><div class="line"><span class="keyword">const</span> isArray = <span class="built_in">Array</span>.isArray;</div><div class="line"></div><div class="line"><span class="keyword">const</span> baseDifference = <span class="function">(<span class="params">array, exclude, iteratee, comparator</span>) =></span> {</div><div class="line"></div><div class="line"> <span class="comment">// 非数组或者数组为空</span></div><div class="line"> <span class="keyword">if</span> (!isArray(array) || !array.length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 非数组或为空直接返回源数组</span></div><div class="line"> <span class="keyword">if</span> (!isArray(exclude) || !exclude.length) {</div><div class="line"> <span class="keyword">return</span> array;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (iteratee) {</div><div class="line"> exclude = exclude.map(<span class="function"><span class="params">i</span> =></span> iteratee(i));</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!comparator) {</div><div class="line"> comparator = <span class="function"><span class="keyword">function</span>(<span class="params">a, b</span>) </span>{</div><div class="line"> <span class="keyword">if</span> (a === b) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> outer:</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> val = array[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> iteVal = iteratee ? iteratee(val) : val;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (iteVal === iteVal) {</div><div class="line"> <span class="comment">// 值类型</span></div><div class="line"></div><div class="line"> <span class="keyword">let</span> excludeLength = exclude.length;</div><div class="line"> <span class="keyword">while</span> (excludeLength--) {</div><div class="line"> <span class="keyword">let</span> excludei = exclude[excludeLength];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (comparator(iteVal, iteratee ? iteratee(excludei) : excludei)) {</div><div class="line"> <span class="keyword">continue</span> outer;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> result.push(val);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">};</div></pre></td></tr></table></figure></p>
<h2 id="drop"><a href="#drop" class="headerlink" title="drop"></a>drop</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.drop(array, [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>生成一个从array开头移除n个元素后剩余的元素的切片,相当于<code>array.slice(n)</code>,源数组不变<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> drop = <span class="function">(<span class="params">array, n = <span class="number">1</span></span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(array)) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> n = n < <span class="number">0</span> ? <span class="number">0</span> : n;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(n);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>同理,可以从右侧移除n个元素…</p>
<h2 id="dropRight"><a href="#dropRight" class="headerlink" title="dropRight"></a>dropRight</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.dropRight(array, [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>与drop类似,从右侧移除n个元素后返回剩余元素的切片即可</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> dropRight = <span class="function">(<span class="params">array, [n = <span class="number">1</span>]</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!<span class="built_in">Array</span>.isArray(array)) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> n = n < <span class="number">0</span> ? <span class="number">0</span> : n;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>, length - n);</div><div class="line"> <span class="comment">//return array.reverse().slice(n).reverse();</span></div><div class="line">}</div></pre></td></tr></table></figure>
<p>在某些情况下,我们需要drop的可能不是从头或者从尾的N个元素这么简单,而是需要从满足某一条件的元素开始,此时就需要用到<code>dropWhile</code>和<code>dropRightWhile</code></p>
<h2 id="dropWhile-和-dropRightWhile"><a href="#dropWhile-和-dropRightWhile" class="headerlink" title="dropWhile 和 dropRightWhile"></a>dropWhile 和 dropRightWhile</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.drop[Right]While(array, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>接受参数<code>predicate</code>,接受三个参数<code>(value, key, array)</code>,从左/右找到满足条件的第一个元素后返回切片<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseDropWhile = <span class="function">(<span class="params">array, predicate, fromRight</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length || !<span class="built_in">Array</span>.isArray(array) ||</div><div class="line"> !predicate || <span class="keyword">typeof</span> predicate !== <span class="string">'function'</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = fromRight ? length : <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="comment">// nice code</span></div><div class="line"> <span class="keyword">while</span> ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}</div><div class="line"></div><div class="line"> <span class="comment">// 注意从右slice时index的值需要+1</span></div><div class="line"> <span class="comment">// slice(start, end)是不包括end元素的</span></div><div class="line"> <span class="keyword">return</span> fromRight ? array.slice(<span class="number">0</span>, index + <span class="number">1</span>) : array.slice(index);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="fill"><a href="#fill" class="headerlink" title="fill"></a>fill</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.fill(array, value, [start=<span class="number">0</span>], [end=array.length])</div></pre></td></tr></table></figure>
<p>将array从start到end位置填充value</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> fill = <span class="function">(<span class="params">array, value, start = <span class="number">0</span>, end = array.length >>> <span class="number">0</span></span>) =></span> {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 确保正确的start和end</span></div><div class="line"> <span class="keyword">if</span> (start < <span class="number">0</span>) {</div><div class="line"> start = -start > length ? <span class="number">0</span> : (length + start);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (end < <span class="number">0</span>) {</div><div class="line"> end += length;</div><div class="line"> }</div><div class="line"></div><div class="line"> end = start > end ? <span class="number">0</span> : end;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (start < end) {</div><div class="line"> array[start++] = value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array;</div><div class="line">};</div></pre></td></tr></table></figure>
<h2 id="findLastIndex"><a href="#findLastIndex" class="headerlink" title="findLastIndex"></a>findLastIndex</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.findIndex(array, [predicate=_.identity], [fromIndex=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>找到array中满足predicate返回为true值的条件的第一个元素的index,可指定查找的起始索引<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> findIndex = <span class="function">(<span class="params">array, predicate, fromIndex = <span class="number">0</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!predicate || <span class="keyword">typeof</span> predicate !== <span class="string">'function'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = fromIndex >> <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index < <span class="number">0</span>) {</div><div class="line"> index += length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index > length) {</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (index < length) {</div><div class="line"> <span class="keyword">if</span> (predicate(array[index])) {</div><div class="line"> <span class="keyword">return</span> index;</div><div class="line"> }</div><div class="line"> index++;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>同理,也可用findLastIndex从数组尾部找第一个满足条件的元素的index,不赘述</p>
<p>另外,lodash也提供了一些针对predicate的快捷方法,例如:predicate为字符串时,默认使用_.property(predicate)去做条件判断</p>
<h2 id="flatten"><a href="#flatten" class="headerlink" title="flatten"></a>flatten</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.flatten(array)</div></pre></td></tr></table></figure>
<p>扁平array,一层<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> flatten = <span class="function">(<span class="params">array</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length || !<span class="built_in">Array</span>.isArray(array)) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> item = array[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(item)) {</div><div class="line"> result.push(...item);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> result.push(item);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>关于flatten,还有2个方法flattenDeep(array)和flattenDepth(array, [depth=1]),前者递归扁平所有嵌套数组,后者可指定扁平层级,可以实现baseFlatten基础功能<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseFlatten = <span class="function">(<span class="params">array, depth = <span class="number">1</span>, result = []</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span>(++index < length) {</div><div class="line"> <span class="keyword">let</span> item = array[index];</div><div class="line"> <span class="keyword">if</span> (depth > <span class="number">0</span>) {</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(item)) {</div><div class="line"> baseFlatten(item, depth - <span class="number">1</span>, result);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> result.push(item);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>flattenDepth即直接调用baseFlatten并传入array和depth参数;flattenDeep的depth为无穷大,lodash使用<code>const INFINITY = 1 / 0</code>重新算出来Infinity,怕覆盖么</p>
<h2 id="fromPairs"><a href="#fromPairs" class="headerlink" title="fromPairs"></a>fromPairs</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.fromPairs(pairs)</div></pre></td></tr></table></figure>
<p>将[[key, value]…]转化为键值对对象{key: value…}<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> fromPairs = <span class="function"><span class="params">pairs</span> =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = pairs;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> item = pairs[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> key = item[<span class="number">0</span>];</div><div class="line"> <span class="keyword">let</span> val = item[<span class="number">1</span>];</div><div class="line"></div><div class="line"> result[key] = val;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="head"><a href="#head" class="headerlink" title="head"></a>head</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.head(array)</div></pre></td></tr></table></figure>
<p>获取数组的第一个元素<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> head = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (array && array.length) {</div><div class="line"> <span class="keyword">return</span> array[<span class="number">0</span>];</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="indexOf"><a href="#indexOf" class="headerlink" title="indexOf"></a>indexOf</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.indexOf(array, value, [fromIndex=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>从array的指定位置fromIndex开始查找value值的索引,若无则返回-1<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> indexOf = <span class="function">(<span class="params">array, value, fromIndex = <span class="number">0</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// index转化为正整数</span></div><div class="line"> <span class="keyword">let</span> index = fromIndex >> <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index < <span class="number">0</span>) {</div><div class="line"> index = <span class="built_in">Math</span>.max(index + length, <span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 需要考虑NaN的情况</span></div><div class="line"> <span class="keyword">if</span> (value === value) {</div><div class="line"> <span class="keyword">while</span> (index < length) {</div><div class="line"> <span class="keyword">if</span> (array[index] === value) {</div><div class="line"> <span class="keyword">return</span> index;</div><div class="line"> }</div><div class="line"></div><div class="line"> index++;</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">while</span> (index < length) {</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">isNaN</span>(array[index])) {</div><div class="line"> <span class="keyword">return</span> index;</div><div class="line"> }</div><div class="line"></div><div class="line"> index++;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="initial"><a href="#initial" class="headerlink" title="initial"></a>initial</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.initial(array)</div></pre></td></tr></table></figure>
<p>获取数组除最后一个元素外的切片<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> initial = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>, <span class="number">-1</span>);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="intersection"><a href="#intersection" class="headerlink" title="intersection"></a>intersection</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">_.intersection([arrays])</div><div class="line">_.intersectionBy([arrays], [iteratee=_.identity])</div><div class="line">_.intersectionWith([arrays], [comparator])</div></pre></td></tr></table></figure>
<p>取数组的元素交集,并可以通过iteratee和comparator指定元素预处理或者比较方法来纠正计算结果,此处可以抽象下基础方法<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> include = <span class="function">(<span class="params">array, value, comparator</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (comparator) {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (length--) {</div><div class="line"> <span class="keyword">if</span> (comparator(array[length], value)) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> array.indexOf(value) > <span class="number">-1</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">const</span> baseIntersection = <span class="function">(<span class="params">arrays, iteratee, comparator</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = arrays;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (length < <span class="number">2</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> first = arrays.shift();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < first.length) {</div><div class="line"> <span class="keyword">let</span> item = first[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> computed = iteratee ? iteratee(item) : item;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> i = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> has = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++i < length - <span class="number">1</span>) {</div><div class="line"> <span class="keyword">let</span> inner = arrays[i];</div><div class="line"></div><div class="line"> iteratee && (inner = inner.map(iteratee));</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (include(inner, computed, comparator)) {</div><div class="line"> has++;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (has === length - <span class="number">1</span>) {</div><div class="line"> result.push(item);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="join"><a href="#join" class="headerlink" title="join"></a>join</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.join(array, [separator=<span class="string">','</span>])</div></pre></td></tr></table></figure>
<p>array join<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> join = <span class="function">(<span class="params">array, separator = <span class="string">','</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array && array.length;</div><div class="line"></div><div class="line"> length = length || <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (length) {</div><div class="line"> <span class="keyword">return</span> array.join(separator);</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="last"><a href="#last" class="headerlink" title="last"></a>last</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.last(array)</div></pre></td></tr></table></figure>
<p>获取数组的最后一个元素<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> last = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array && array.length;</div><div class="line"></div><div class="line"> length = length || <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (length) {</div><div class="line"> <span class="keyword">return</span> array[length - <span class="number">1</span>];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="lastIndexOf"><a href="#lastIndexOf" class="headerlink" title="lastIndexOf"></a>lastIndexOf</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.lastIndexOf(array, value, [fromIndex=array.length<span class="number">-1</span>])</div></pre></td></tr></table></figure>
<p>获取最后一个匹配的元素的index,可指定查找位置,默认length-1,即从后往前查找<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> lastIndexOf = <span class="function">(<span class="params">array, value, fromIndex</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array && array.length;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> fromIndex = fromIndex || length - <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = indexOf(array.reverse(), value, (length - <span class="number">1</span> - fromIndex)); <span class="comment">// 调indexOf方法查找反转的数组</span></div><div class="line"></div><div class="line"> <span class="keyword">return</span> index === <span class="number">-1</span> ? <span class="number">-1</span> : ((length - <span class="number">1</span>) - index);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="nth"><a href="#nth" class="headerlink" title="nth"></a>nth</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.nth(array, [n=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>获取数组的第n个元素,n可为负数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> nth = <span class="function">(<span class="params">array, n = <span class="number">0</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array && array.length;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 转化or验证?</span></div><div class="line"></div><div class="line"> <span class="comment">// 数字</span></div><div class="line"> <span class="comment">// n < maxinter</span></div><div class="line"> <span class="comment">// /^(?:0|[1-9]\d*)$/ 验证无符号整数</span></div><div class="line"> <span class="comment">// n > -1 && n < length</span></div><div class="line"> <span class="comment">// n % 1 === 0</span></div><div class="line"> n = n >> <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (n < <span class="number">0</span>) {</div><div class="line"> n = n + length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (n > length - <span class="number">1</span> || n < <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array[n];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pullAll"><a href="#pullAll" class="headerlink" title="pullAll"></a>pullAll</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pullAll(array, values)</div></pre></td></tr></table></figure>
<p>移除array中所有values包含的值,会改变目标数组,接受参数values为数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pullAll = <span class="function">(<span class="params">array, values</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> values.forEach(<span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">while</span> (<span class="literal">true</span>) {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = array.indexOf(value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index === <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> array.splice(index, <span class="number">1</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pull"><a href="#pull" class="headerlink" title="pull"></a>pull</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pull(array, [values])</div></pre></td></tr></table></figure>
<p>类似pullAll,只是接受的移除的参数为参数列表</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pull = <span class="function">(<span class="params">array, ...values</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> pullAll(array, values);</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="pullAllBy"><a href="#pullAllBy" class="headerlink" title="pullAllBy"></a>pullAllBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pullAllBy(array, values, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>使用iteratee迭代每个元素进行后进行比较排除<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pullAllBy = <span class="function">(<span class="params">array, values, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (iteratee) {</div><div class="line"></div><div class="line"> values.forEach(<span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">while</span> (<span class="literal">true</span>) {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = array.map(iteratee).indexOf(iteratee(value));</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index === <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> array.splice(index, <span class="number">1</span>);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> pullAll(array, values)</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pullAllWith"><a href="#pullAllWith" class="headerlink" title="pullAllWith"></a>pullAllWith</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pullAllWith(array, values, [comparator])</div></pre></td></tr></table></figure>
<p>按指定比较规则进行排除<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pullAllWith = <span class="function">(<span class="params">array, values, comparator</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (comparator) {</div><div class="line"></div><div class="line"> values.forEach(<span class="function"><span class="params">value</span> =></span> {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"> <span class="keyword">let</span> removes = [];</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">if</span> (comparator(value, array[index])) {</div><div class="line"> removes.push(index);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// removes为升序index的序列</span></div><div class="line"> <span class="keyword">let</span> offset = <span class="number">0</span>;</div><div class="line"> removes.forEach(<span class="function"><span class="params">i</span> =></span> {</div><div class="line"> array.splice(i - offset++, <span class="number">1</span>);</div><div class="line"> })</div><div class="line"></div><div class="line"> });</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> pullAll(array, values);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pullAt"><a href="#pullAt" class="headerlink" title="pullAt"></a>pullAt</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pullAt(array, [indexes])</div></pre></td></tr></table></figure>
<p>移除指定位置的元素,并返回移除元素的数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> pullAt = <span class="function">(<span class="params">array, indexes = []</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!array) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> offset = <span class="number">0</span>; <span class="comment">// index偏移修正 </span></div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="comment">// 从小到大排序,方便进行偏移修正</span></div><div class="line"> indexes.sort().forEach(<span class="function"><span class="params">i</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (!(<span class="regexp">/^\d+$/</span>).test(i + <span class="string">''</span>)) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (i < <span class="number">0</span>) {</div><div class="line"> i += length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (i >= length) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> result.push(...array.splice(i - offset++, <span class="number">1</span>));</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="remove"><a href="#remove" class="headerlink" title="remove"></a>remove</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.remove(array, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>移除array中满足predicate为truthy的元素,predicate接收三个参数(value, index, array);remove返回删除的元素,并会改变array<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> remove = <span class="function">(<span class="params">array, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length || !predicate) {</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">let</span> indexes = [];</div><div class="line"> result = array.filter(<span class="function">(<span class="params">item, index</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (predicate(item, index, array)) {</div><div class="line"> indexes.push(index);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> });</div><div class="line"></div><div class="line"> pullAt(array, indexes);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="reverse"><a href="#reverse" class="headerlink" title="reverse"></a>reverse</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> reverse = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.reverse();</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="slice"><a href="#slice" class="headerlink" title="slice"></a>slice</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.slice(array, [start=<span class="number">0</span>], [end=array.length])</div></pre></td></tr></table></figure>
<p>slice的功能我们在实现chunk的时候就已经完整实现过了,在原生slice方法的基础上,做一些参数的限定和转化<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> slice = <span class="function">(<span class="params">array, start, end</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!lenght) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> start = start ? start : <span class="number">0</span>;</div><div class="line"> end = end ? end : length;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (start < <span class="number">0</span>) {</div><div class="line"> start = -start > length ? <span class="number">0</span> : (start + length);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (end < <span class="number">0</span>) {</div><div class="line"> end += length;</div><div class="line"> }</div><div class="line"></div><div class="line"> end = end > length ? length : end;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (start > end) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(start, end);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="sortedIndex"><a href="#sortedIndex" class="headerlink" title="sortedIndex"></a>sortedIndex</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sortedIndex(array, value)</div></pre></td></tr></table></figure>
<p>在已排序的array数组中,插入value后维持顺序,确定并返回最小的插入位置索引</p>
<p>实现sortIndex基础方法:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseSortedIndex = <span class="function">(<span class="params">array, value, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> low = <span class="number">0</span>;</div><div class="line"> <span class="keyword">let</span> high = length;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> iteValue = iteratee ? iteratee(value) : value;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> iteValue === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> high;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 二分查找</span></div><div class="line"> <span class="comment">// 即找第一个大于待插入元素值的元素的位置</span></div><div class="line"> <span class="keyword">while</span> (low < high) {</div><div class="line"> <span class="keyword">let</span> middle = (low + high) >>> <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> midValue = iteratee ? iteratee(array[middle]) : array[middle];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (midValue < iteValue) {</div><div class="line"> low = middle + <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> high = middle;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> high;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">const</span> sortedIndex = <span class="function">(<span class="params">array, value</span>) =></span> baseSortedIndex(array, value);</div></pre></td></tr></table></figure></p>
<p>源码中,利用位运算求中间值,可关注: <code>const mid = (low + high) >>> 1</code></p>
<h2 id="sortedIndexBy"><a href="#sortedIndexBy" class="headerlink" title="sortedIndexBy"></a>sortedIndexBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sortedIndexBy(array, value, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>iteratee转化后进行元素比较,iteratee接受一个参数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> sortedIndexBy = <span class="function">(<span class="params">array, value, iteratee</span>) =></span> baseSortedIndex(array, value, iteratee);</div></pre></td></tr></table></figure></p>
<h2 id="sortedIndexOf"><a href="#sortedIndexOf" class="headerlink" title="sortedIndexOf"></a>sortedIndexOf</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sortedIndexOf(array, value)</div></pre></td></tr></table></figure>
<p>使用<code>二分法</code>binary search查找一个value在已排序数组中的索引<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> sortedIndexOf = <span class="function">(<span class="params">array, value</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (length) {</div><div class="line"> <span class="comment">// 调用baseSortedIndex找到value插入的位置,再判断插入位置的值是否与value相等</span></div><div class="line"> <span class="comment">// 若不等,则无对应值存在于数组中,返回-1</span></div><div class="line"> <span class="comment">// 另外,需要满足条件,得到的index需要小于length,排出插入到最后的情况</span></div><div class="line"> <span class="keyword">let</span> index = baseSortedIndex(array, value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (index < length && array[index] === value) {</div><div class="line"> <span class="keyword">return</span> index;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="sortedLastIndex、-sortedLastIndexBy、sortedLastIndexOf"><a href="#sortedLastIndex、-sortedLastIndexBy、sortedLastIndexOf" class="headerlink" title="sortedLastIndex、 sortedLastIndexBy、sortedLastIndexOf"></a>sortedLastIndex、 sortedLastIndexBy、sortedLastIndexOf</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">_.sortedLastIndex(array, value)</div><div class="line">_.sortedLastIndexBy(array, value, [iteratee=_.identity])</div><div class="line">_.sortedLastIndexOf(array, value)</div></pre></td></tr></table></figure>
<p>对于之前的三个sortedIndex的方法,还有三个对应的逆序,在原有的baseSortedIndex的基础上,将二分查找的条件修改下即可:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"></div><div class="line"> <span class="comment">//[ < ] ---> [<=]这样在遇到第一个相等的元素后会继续向右查找直到找到最后一个</span></div><div class="line"> <span class="keyword">if</span> (midValue <= iteValue) {</div><div class="line"> low = middle + <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> high = middle;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>在此要求下对baseSortedIndex做个修正并提取baseSortedIndexBy方法,控制一下参数:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseSortedIndex = <span class="function">(<span class="params">array, value, highest</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> baseSortedIndexBy(array, value, val => val, highest);</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">const</span> baseSortedIndexBy = <span class="function">(<span class="params">array, value, iteratee, highest</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> low = <span class="number">0</span>;</div><div class="line"> <span class="keyword">let</span> high = length;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">val</span> =></span> val;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> iteValue = iteratee(value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> iteValue === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> high;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 二分查找</span></div><div class="line"> <span class="comment">// 即找第一个大于待插入元素值的元素的位置</span></div><div class="line"> <span class="keyword">while</span> (low < high) {</div><div class="line"> <span class="keyword">let</span> middle = (low + high) >>> <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> midValue = iteratee(array[middle]);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (highest ? (midValue <= iteValue) : (midValue < iteValue)) {</div><div class="line"> low = middle + <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> high = middle;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> high;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">// 实现...</span></div><div class="line"><span class="keyword">const</span> sortedLastIndex = <span class="function">(<span class="params">array, value</span>) =></span> baseSortedIndex(array, value, <span class="literal">true</span>);</div><div class="line"><span class="keyword">const</span> sortedLastIndexBy = <span class="function">(<span class="params">array, value, ite</span>) =></span> baseSortedIndexBy(array, value, ite, <span class="literal">true</span>);</div><div class="line"><span class="comment">// sortedLastIndexOf类似</span></div></pre></td></tr></table></figure></p>
<h2 id="sortedUniq"><a href="#sortedUniq" class="headerlink" title="sortedUniq"></a>sortedUniq</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sortedUniq(array)</div></pre></td></tr></table></figure>
<p>对已排序数组去重,返回新数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> sortedUniq = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> seen;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> value = array[index];</div><div class="line"></div><div class="line"> <span class="comment">// 相邻元素值不相等的</span></div><div class="line"> <span class="comment">// 注意:!index判断seen有没有被初始化,不可用!seen,因为seen可能是falsely值</span></div><div class="line"> <span class="keyword">if</span> (!index || !eq(value, seen)) {</div><div class="line"></div><div class="line"> seen = value;</div><div class="line"> result.push(seen);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="comment">/**</span></div><div class="line"> * value与other是否相等,NaN !== NaN</div><div class="line"> */</div><div class="line"><span class="keyword">const</span> eq = <span class="function">(<span class="params">value, other</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> value === other || (value !== value && other !== other);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="sortedUniqBy"><a href="#sortedUniqBy" class="headerlink" title="sortedUniqBy"></a>sortedUniqBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sortedUniqBy(array, [iteratee])</div></pre></td></tr></table></figure>
<p>功能类似,接受迭代器参数,将值转化后做比较,综合<code>sortedUniq</code>提取baseSortedUniq方法…<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseSortedUniq = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">x</span> =></span> x;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> seen;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> value = array[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> computed = iteratee(value);</div><div class="line"></div><div class="line"> <span class="comment">// 相邻元素值不相等的</span></div><div class="line"> <span class="comment">// 注意:!index判断seen有没有被初始化,不可用!seen,因为seen可能是falsely值</span></div><div class="line"> <span class="keyword">if</span> (!index || !eq(computed, seen)) {</div><div class="line"></div><div class="line"> seen = computed;</div><div class="line"> result.push(value);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">const</span> sortedUniqBy = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> baseSortedUniq(array, iteratee);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="tail"><a href="#tail" class="headerlink" title="tail"></a>tail</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.tail(array)</div></pre></td></tr></table></figure>
<p>获取除第一个元素的数组切片<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> tail = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">1</span>);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>看了下源码的实现,直接用slice有点小low啊,别人都用数组的解构啦!<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> [head, ...res] = array; <span class="comment">// 666</span></div><div class="line"><span class="keyword">return</span> res;</div></pre></td></tr></table></figure></p>
<h2 id="take"><a href="#take" class="headerlink" title="take"></a>take</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.take(array, [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>获取从数组开始的n个元素的切片<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> take = <span class="function">(<span class="params">array, n = <span class="number">1</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> n = n > <span class="number">0</span> ? n : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>, n);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="takeRight"><a href="#takeRight" class="headerlink" title="takeRight"></a>takeRight</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.takeRight(array, [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>获取数组结尾的n个元素的切片<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> takeRight = <span class="function">(<span class="params">array, n = <span class="number">1</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (n > length) {</div><div class="line"> n = length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(length - n);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="takeWhile"><a href="#takeWhile" class="headerlink" title="takeWhile"></a>takeWhile</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.takeWhile(array, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>从左侧开始切片数组,直到第一个predicate判断返回为false的值位置<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> takeWhile = <span class="function">(<span class="params">array, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!predicate) {</div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">if</span> (!predicate(array[index])) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>, index);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="takeRightWhile"><a href="#takeRightWhile" class="headerlink" title="takeRightWhile"></a>takeRightWhile</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.takeRightWhile(array, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>类似takeWhile,takeRightWhile从数组右侧开始寻找,综合takeWhile,来一个<code>baseTakeWhile</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseTakeWhile = <span class="function">(<span class="params">array, predicate, fromRight</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!predicate) {</div><div class="line"> <span class="keyword">return</span> array.slice(<span class="number">0</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = fromRight ? length : <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (fromRight ? index-- : ++index < length) {</div><div class="line"> <span class="keyword">if</span> (!predicate(array[index])) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> fromRight ? array.slice(index + <span class="number">1</span>) : array.slice(<span class="number">0</span>, index);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="union"><a href="#union" class="headerlink" title="union"></a>union</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.union([arrays])</div></pre></td></tr></table></figure>
<p>数组元素组合,参数接受n个数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> union = <span class="function">(<span class="params">...arrays</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = arrays ? arrays.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> result.splice(result.length, <span class="number">0</span>, ...arrays[index]);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Set</span>(result));</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="unionBy"><a href="#unionBy" class="headerlink" title="unionBy"></a>unionBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.unionBy([arrays], [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>接受迭代参数,迭代后相同的项入坑…这样就坑爹啦,上面那个简易的办法用不上啦<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> unionBy = <span class="function">(<span class="params">...arrays</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = arrays ? arrays.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// let iteratee = last(arrays);</span></div><div class="line"> <span class="keyword">let</span> iteratee = arrays[length - <span class="number">1</span>];</div><div class="line"></div><div class="line"> length--;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> seen = [];</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> array = arrays[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> computed = array.map(iteratee);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> inner = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> innerLen = array.length;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++inner < innerLen) {</div><div class="line"> <span class="keyword">if</span> (seen.indexOf(computed[inner]) === <span class="number">-1</span>) {</div><div class="line"> seen.push(computed[inner]);</div><div class="line"></div><div class="line"> result.push(array[inner]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"></div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>上述方法时间复杂度O(n<sup>2</sup>),应该可以简化到O(n)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 先参考union的方法将所有元素合并到数组中,然后再针对iteratee做去重</span></div><div class="line"><span class="keyword">const</span> unionBy = <span class="function">(<span class="params">...arrays</span>) =></span> {</div><div class="line"> <span class="comment">// 参数拆解同上</span></div><div class="line"> <span class="keyword">let</span> length = arrays ? arrays.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> iteratee = arrays[length - <span class="number">1</span>];</div><div class="line"></div><div class="line"> length--;</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> inter = [];</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> inter.splice(inter.length, <span class="number">0</span>, ...arrays[index]);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 去重</span></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> seen = [];</div><div class="line"></div><div class="line"> index = <span class="number">-1</span>;</div><div class="line"> length = inter.length;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> val = inter[index];</div><div class="line"> <span class="keyword">let</span> computed = iteratee(val);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (seen.indexOf(computed) > <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> seen.push(computed);</div><div class="line"> result.push(val);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="unionWith"><a href="#unionWith" class="headerlink" title="unionWith"></a>unionWith</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.unionWith([arrays], [comparator])</div></pre></td></tr></table></figure>
<p>老三样,可指定元素间比较方式,只是O(n<sup>3</sup>)的复杂度啊…comparator也需要遍历比较</p>
<h2 id="uniq"><a href="#uniq" class="headerlink" title="uniq"></a>uniq</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.uniq(array)</div></pre></td></tr></table></figure>
<p>所以这是跟<code>union</code>是有什么区别呢?一个参数是数组,一个是参数别表,每个参数项是数组?<br>包括<code>uniqBy</code>和<code>uniqWith</code>都是同理的实现</p>
<h2 id="zip"><a href="#zip" class="headerlink" title="zip"></a>zip</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.zip([arrays])</div></pre></td></tr></table></figure>
<p>接受参数为n个数组的参数列表,将参数列表中的数组按照index进行分组,返回分组的新数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> zip = <span class="function">(<span class="params">...arrays</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = arrays.length ? arrays.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> max = <span class="number">0</span>;</div><div class="line"> arrays.forEach(<span class="function"><span class="params">array</span> =></span> {</div><div class="line"> max = <span class="built_in">Math</span>.max(max, array.length);</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> result = <span class="keyword">new</span> <span class="built_in">Array</span>(max);</div><div class="line"> <span class="keyword">while</span> (++index < max) {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> sub = [];</div><div class="line"> <span class="keyword">let</span> inner = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++inner < length) {</div><div class="line"> sub[inner] = arrays[inner][index];</div><div class="line"> }</div><div class="line"></div><div class="line"> result[index] = sub;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="unzip"><a href="#unzip" class="headerlink" title="unzip"></a>unzip</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.unzip(array)</div></pre></td></tr></table></figure>
<p>接收参数跟zip不同,其实功能与<code>zip</code>一样,把对应index的元素组合即可,这个操作可以理解为双向操作, 因此通过<code>...</code>将列表转化为数组后,执行过程就一致了,我们将上述zip的执行移植过来:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> unzip = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> length = array.length ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> max = <span class="number">0</span>;</div><div class="line"> array.forEach(<span class="function"><span class="params">array</span> =></span> {</div><div class="line"> max = <span class="built_in">Math</span>.max(max, array.length);</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> result = <span class="keyword">new</span> <span class="built_in">Array</span>(max);</div><div class="line"> <span class="keyword">while</span> (++index < max) {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> sub = [];</div><div class="line"> <span class="keyword">let</span> inner = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++inner < length) {</div><div class="line"> sub[inner] = array[inner][index];</div><div class="line"> }</div><div class="line"></div><div class="line"> result[index] = sub;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>这样zip操作就可以直接调用unzip<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> zip = <span class="function">(<span class="params">...arrays</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> unzip(arrays);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="unzipWith"><a href="#unzipWith" class="headerlink" title="unzipWith"></a>unzipWith</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.unzipWith(array, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>对位的元素使用iteratee进行结合后吐出来,可以先试用unzip转化,然后对没个数组元素进行组合, <code>iteratee</code>为接收参数列表的函数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> unzipWith = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array.length ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = unzip(array);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result.map(<span class="function"><span class="params">res</span> =></span> {</div><div class="line"></div><div class="line"> <span class="comment">// 数组参数转参数列表</span></div><div class="line"> <span class="keyword">return</span> iteratee ? iteratee.apply(<span class="literal">null</span>, res) : res</div><div class="line"> });</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>zip然后unzipWith能实现某种神奇的转化?yes…比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// iteratee</span></div><div class="line"><span class="keyword">const</span> add = <span class="function">(<span class="params">...arr</span>) =></span> arr.reduce(<span class="function">(<span class="params">acc, val</span>) =></span> acc + val, <span class="number">0</span>);</div><div class="line"></div><div class="line">unzipWith(zip([<span class="number">1</span>, <span class="number">2</span>], [<span class="number">10</span>, <span class="number">20</span>], [<span class="number">100</span>, <span class="number">200</span>]), add)</div></pre></td></tr></table></figure></p>
<p>可实现原数组转化为每项的元素和的数组</p>
<h2 id="without"><a href="#without" class="headerlink" title="without"></a>without</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.without(array, [values])</div></pre></td></tr></table></figure>
<p>生成一个数组中排出指定元素的新数组,与<code>pull</code>功能类似,pull会改变源数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> without = <span class="function">(<span class="params">array, ...values</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">if</span> (values.indexOf(array[index]) > <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> result.push(array[index]);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="xor"><a href="#xor" class="headerlink" title="xor"></a>xor</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.xor([arrays])</div></pre></td></tr></table></figure>
<p>亦或运算<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> xor = ...arrays => {</div><div class="line"> <span class="keyword">let</span> length = arrays.length;</div><div class="line"></div><div class="line"> <span class="comment">// 如果参数只传入一个数组,则对该数组元素去重后返回</span></div><div class="line"> <span class="keyword">if</span> (length < <span class="number">2</span>) {</div><div class="line"> <span class="keyword">return</span> length ? uniq(arrays[<span class="number">0</span>]) : [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="comment">// TODO</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Array"><a href="#Array" class="headerlink" title="Array"></a>Array</h1><h2 id="chunk"><a href="#chunk" class="headerlink" title="chunk"></a>chunk</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.chunk(array, [size=1])</div></pre></td></tr></table></figure>
<p>猜想下实现方法,功能就是将数组拆分成<code>arrar.length / size</code>个数组,每个数组<code>size</code>个元素,剩余的元素作为最后一个分组,数组操作中<code>slice</code>不改变原数组并实现数组切分:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> chunk = <span class="function">(<span class="params">array, size = <span class="number">1</span></span>) =&gt;</span> &#123;</div><div class="line"> <span class="keyword">let</span> count = <span class="built_in">Math</span>.ceil(array.length / size);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> _chunk = <span class="keyword">new</span> <span class="built_in">Array</span>(count);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> start = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index &lt; count) &#123;</div><div class="line"> _chunk[index] = array.slice(start, start += size);</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _chunk;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Array" scheme="http://www.i0011.com/tags/Array/"/>
</entry>
<entry>
<title>Lodash源码祭「Date」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-date/"/>
<id>http://www.i0011.com/2017/07/12/lodash-date/</id>
<published>2017-07-12T11:08:11.000Z</published>
<updated>2017-07-12T11:17:37.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Date"><a href="#Date" class="headerlink" title="Date"></a>Date</h1><h2 id="now"><a href="#now" class="headerlink" title="now"></a>now</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.now()</div></pre></td></tr></table></figure>
<p>获取当前时间的毫秒时间戳<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> now () => {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Date</span>().getTime();</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Date"><a href="#Date" class="headerlink" title="Date"></a>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Date" scheme="http://www.i0011.com/tags/Date/"/>
</entry>
<entry>
<title>Lodash源码祭「Collection」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-collection/"/>
<id>http://www.i0011.com/2017/07/12/lodash-collection/</id>
<published>2017-07-12T11:05:36.000Z</published>
<updated>2017-07-12T11:17:34.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Collection"><a href="#Collection" class="headerlink" title="Collection"></a>Collection</h1><h2 id="countBy"><a href="#countBy" class="headerlink" title="countBy"></a>countBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.countBy(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>collection中统计各项的数目,也可指定iteratee进行迭代处理<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> countBy = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"></div><div class="line"> collection.forEach(<span class="function"><span class="params">key</span> =></span> {</div><div class="line"></div><div class="line"> <span class="keyword">let</span> ite = iteratee ? iteratee(key) : key;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> result[ite] === <span class="string">'undefined'</span>) {</div><div class="line"> result[ite] = <span class="number">1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> result[ite] += <span class="number">1</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>reduce?<br><a id="more"></a></p>
<h2 id="forEach"><a href="#forEach" class="headerlink" title="forEach"></a>forEach</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.forEach(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>遍历元素,iteratee接受三个参数<code>value</code>,’key’,’collection’。但是对于对象的each,官方更推荐使用<code>forIn</code>或者<code>forOwn</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> forEach = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> collection.forEach(iteratee);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// 对象情况,用forin遍历,顺序不可控</span></div><div class="line"> <span class="built_in">Object</span>.keys(collection).forEach(<span class="function"><span class="params">key</span> =></span> {</div><div class="line"> iteratee(collection[key], key, collection);</div><div class="line"> });</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> collection;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>有一点忽略了,某一次iteratee执行<code>return false</code>是可以终结整个的循环的,原生的就没有此功能了,因此在上面的基础上要略做改造<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> forEach = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> <span class="keyword">let</span> length = collection.length;</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> res = iteratee(collection[index], index, collection);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (res === <span class="literal">false</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// 对象情况,用forin遍历,顺序不可控</span></div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection);</div><div class="line"> <span class="keyword">let</span> length = keys.length;</div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> key = keys[index];</div><div class="line"> <span class="keyword">let</span> res = iteratee(collection[key], key, collection);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (res === <span class="literal">false</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> collection;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="forEachRight"><a href="#forEachRight" class="headerlink" title="forEachRight"></a>forEachRight</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.forEachRight(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>与forEach类似,只是从尾向头迭代,不赘述</p>
<h2 id="every"><a href="#every" class="headerlink" title="every"></a>every</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.every(collection, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>若collection所有项通过predicate check则返回true,否则返回false。需要注意的是,对空的collection返回值为true,约定<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> every = <span class="function">(<span class="params">collection, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> keys = !isArr && <span class="built_in">Object</span>.keys(collection);</div><div class="line"> <span class="keyword">let</span> length = isArr ? collection.length : keys.length;</div><div class="line"></div><div class="line"> <span class="comment">// 空collection返回true</span></div><div class="line"> <span class="keyword">if</span> (length === <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> key;</div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> key = index;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> key = keys[index];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!predicate(collection[key], key, collection)) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="filter"><a href="#filter" class="headerlink" title="filter"></a>filter</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.filter(collection, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>满足preficate为truthy的元素的数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> filter = <span class="function">(<span class="params">collection, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> <span class="keyword">return</span> collection.filter(predicate);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> length = keys.length;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> key = keys[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (predicate(collection[key], key, collection)) {</div><div class="line"> result.push({</div><div class="line"> [key]: collection[key]</div><div class="line"> });</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="reject"><a href="#reject" class="headerlink" title="reject"></a>reject</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.reject(collection, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p><code>filter</code>的反向操作,过滤掉predicate为truthy值的想,返回剩余项的数组集合<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> filter = <span class="function">(<span class="params">collection, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> forEach(collection, (item, index, collection) => {</div><div class="line"> <span class="keyword">if</span> (predicate(item)) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> result.push(<span class="built_in">Array</span>.isArray(collection) ? item : {</div><div class="line"> [index]: item</div><div class="line"> });</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="find"><a href="#find" class="headerlink" title="find"></a>find</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.find(collection, [predicate=_.identity], [fromIndex=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>从指定的fromIndex开始查找满足predicate的项并返回,若无则返回undefined<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> find = <span class="function">(<span class="params">collection, predicate, fromIndex</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection); <span class="comment">// turn array key to string</span></div><div class="line"> <span class="keyword">let</span> length = keys.length;</div><div class="line"> <span class="keyword">let</span> index = fromIndex ? fromIndex - <span class="number">1</span> : <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> key = keys[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> key = key >>> <span class="number">0</span>; <span class="comment">// turn key to number</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (predicate(collection[key], key, collection)) {</div><div class="line"></div><div class="line"> <span class="keyword">return</span> isArr ? collection[key] : {</div><div class="line"> [key]: collection[key]</div><div class="line"> };</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="findLast"><a href="#findLast" class="headerlink" title="findLast"></a>findLast</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.findLast(collection, [predicate=_.identity], [fromIndex=collection.length<span class="number">-1</span>])</div></pre></td></tr></table></figure>
<p>与find类似,只是从右往左查找<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> findLast = <span class="function">(<span class="params">collection, predicate, fromIndex</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> isArr = <span class="built_in">Array</span>.isArray(collection);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection); <span class="comment">// turn array key to string</span></div><div class="line"> <span class="keyword">let</span> length = keys.length;</div><div class="line"> <span class="keyword">let</span> index;</div><div class="line"></div><div class="line"> <span class="comment">// 下标为范围</span></div><div class="line"> <span class="keyword">if</span> (fromIndex !== <span class="literal">undefined</span>) {</div><div class="line"> index = fromIndex < <span class="number">0</span> ? <span class="built_in">Math</span>.max(fromIndex + length, <span class="number">0</span>) : <span class="built_in">Math</span>.min(length - <span class="number">1</span>, fromIndex);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> index = length - <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> index += <span class="number">1</span>;</div><div class="line"> <span class="keyword">while</span> (--index > <span class="number">0</span>) {</div><div class="line"> <span class="keyword">let</span> key = keys[index];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArr) {</div><div class="line"> key = key >>> <span class="number">0</span>; <span class="comment">// turn key to number</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (predicate(collection[key], key, collection)) {</div><div class="line"></div><div class="line"> <span class="keyword">return</span> isArr ? collection[key] : {</div><div class="line"> [key]: collection[key]</div><div class="line"> };</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="groupBy"><a href="#groupBy" class="headerlink" title="groupBy"></a>groupBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.groupBy(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>根据指定iteratee分组,iteratee迭代每个元素后的值为键,对应的值为之前的元素对应的值所组成的数组,这个借助之前的<code>forEach</code>可以很轻松的实现,但这个对单层数组还可以一用,对多层数组或者对象完全鸡肋啊…<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> groupBy = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"></div><div class="line"> forEach(collection, <span class="function"><span class="keyword">function</span>(<span class="params">val, key, collection</span>) </span>{</div><div class="line"> <span class="keyword">let</span> tag = iteratee(val, key, collection);</div><div class="line"></div><div class="line"> tag = tag.toString();</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!result[tag]) {</div><div class="line"> result[tag] = [];</div><div class="line"> }</div><div class="line"></div><div class="line"> result[tag].push(val);</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="includes"><a href="#includes" class="headerlink" title="includes"></a>includes</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.includes(collection, value, [fromIndex=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>检查collection中从指定的fromIndex开始是否包含value值,此处collection可以为数组、对象和<strong>字符串</strong>,字符串按照<code>substring</code>进行查找<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> includes = <span class="function">(<span class="params">collection, value, fromIndex = <span class="number">0</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> length;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> isStr = <span class="keyword">typeof</span> collection === <span class="string">'string'</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isStr) {</div><div class="line"> length = collection.length;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> length = <span class="built_in">Object</span>.keys(collection).length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (fromIndex < <span class="number">0</span>) {</div><div class="line"> fromIndex += length;</div><div class="line"> }</div><div class="line"></div><div class="line"> fromIndex = (fromIndex >= length - <span class="number">1</span>) ? (length - <span class="number">1</span>) : fromIndex;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isStr) {</div><div class="line"> <span class="keyword">return</span> collection.substring(fromIndex).indexOf(value) > <span class="number">-1</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">let</span> ite = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> _include = <span class="literal">false</span>;</div><div class="line"> forEach(collection, <span class="function"><span class="keyword">function</span>(<span class="params">val</span>) </span>{</div><div class="line"> ite++;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (ite < fromIndex) {</div><div class="line"> <span class="keyword">return</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">if</span> (val === value) {</div><div class="line"> _include = <span class="literal">true</span>;</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">// take it over</span></div><div class="line"> }</div><div class="line"> }</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _include;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="keyBy"><a href="#keyBy" class="headerlink" title="keyBy"></a>keyBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.keyBy(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>生成键值对,键名由iteratee迭代每个元素后生成,值为collection对应项,注意iteratee只接受一个参数value,并且对于迭代后重复的键名会覆盖,同样使用<code>forEach</code>可以简单的完成这个功能<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> keyBy = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = {};</div><div class="line"> forEach(collection, (val, key, collection) => {</div><div class="line"> result[iteratee(val)] = val;</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="invokeMap"><a href="#invokeMap" class="headerlink" title="invokeMap"></a>invokeMap</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.invokeMap(collection, path, [args])</div></pre></td></tr></table></figure>
<p>path可接收<code>Array</code>、<code>String</code>和<code>Function</code>…接收数组参数是什么套路,没理解?先以函数为例吧,函数的this在迭代中绑定到collection中的每个元素。最后,还有一个可选参数args,可作为参数传给path<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> invokeMap = <span class="function">(<span class="params">collection, path, ...args</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> forEach(collection, val => {</div><div class="line"> result.push(path.apply(val, args));</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="orderBy"><a href="#orderBy" class="headerlink" title="orderBy"></a>orderBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.orderBy(collection, [iteratees=[_.identity]], [orders])</div></pre></td></tr></table></figure>
<p>TODO留坑</p>
<h2 id="sample"><a href="#sample" class="headerlink" title="sample"></a>sample</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sample(collection)</div></pre></td></tr></table></figure>
<p>任意返回collection中的一个抽样值<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> sample = <span class="function"><span class="params">collection</span> =></span> {</div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {length} = keys;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> rand = keys[<span class="built_in">Math</span>.floor((<span class="built_in">Math</span>.random() * length))]; <span class="comment">// 0 ~ length-1</span></div><div class="line"></div><div class="line"> <span class="keyword">return</span> collection[<span class="built_in">Array</span>.isArray(collection) ? ~~rand : rand];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="sampleSize"><a href="#sampleSize" class="headerlink" title="sampleSize"></a>sampleSize</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sampleSize(collection, [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>获取n个collection中的随机元素,扩展下<code>sample</code>方法,然后返回的是个数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> sampleSize = <span class="function">(<span class="params">collection, n = <span class="number">1</span></span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"> <span class="keyword">let</span> keys = <span class="built_in">Object</span>.keys(collection)</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {length} = keys;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (n > length) {</div><div class="line"> n = length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (n < <span class="number">1</span>) {</div><div class="line"> n = <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 生成n个不同的随机数</span></div><div class="line"> <span class="keyword">let</span> i = <span class="number">0</span>;</div><div class="line"> <span class="keyword">let</span> chosed = [];</div><div class="line"> <span class="keyword">while</span> (i < n) {</div><div class="line"> <span class="keyword">let</span> rand = keys[<span class="built_in">Math</span>.floor((<span class="built_in">Math</span>.random() * length))]; <span class="comment">// 随机数</span></div><div class="line"></div><div class="line"> <span class="comment">// 保证键值不同</span></div><div class="line"> <span class="keyword">if</span> (chosed.indexOf(rand) > <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> i++;</div><div class="line"></div><div class="line"> chosed.push(rand);</div><div class="line"></div><div class="line"> result.push(collection[<span class="built_in">Array</span>.isArray(collection) ? ~~rand : rand])</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="map"><a href="#map" class="headerlink" title="map"></a>map</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.map(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>返回映射后的数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> map = <span class="function">(<span class="params">collection, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = [];</div><div class="line"></div><div class="line"> forEach(collection, (val, key, collection) => {</div><div class="line"> result.push(iteratee(val, key, collection));</div><div class="line"> });</div><div class="line"> </div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="size"><a href="#size" class="headerlink" title="size"></a>size</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.size(collection)</div></pre></td></tr></table></figure>
<p>可求数组、对象和字符串的尺寸,包括Map和Set<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> size = <span class="function"><span class="params">collection</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> collection === <span class="string">'string'</span>) {</div><div class="line"> <span class="keyword">return</span> collection.length;</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="keyword">let</span> tag = collection.toString();</div><div class="line"> <span class="keyword">if</span> (tag === <span class="string">'[object Set]'</span> || tag === <span class="string">'[object Map]'</span>){</div><div class="line"> <span class="keyword">return</span> collection.size;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.keys(collection).length; <span class="comment">// 数组或者对象</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>源码一直将包含<code>length</code>的非函数变量作为arrayLike,包括数组、字符串和含length属性的类数组对象,可以直接访问到length属性作为size返回。需要修正一下,要不然对于<code>{a: 1, length: 1}</code>这样的类数组会出现问题<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> size = <span class="function"><span class="params">collection</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (isArrayLike(collection)) {</div><div class="line"> <span class="keyword">return</span> collection.length;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> tag = collection.toString();</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (tag === <span class="string">'[object Set]'</span> || tag === <span class="string">'[object Map]'</span>){</div><div class="line"> <span class="keyword">return</span> collection.size;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.keys(collection).length;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="some"><a href="#some" class="headerlink" title="some"></a>some</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.some(collection, [predicate=_.identity])</div></pre></td></tr></table></figure>
<p>collection中任一元素predicate返回truthy值,循环<strong>终止</strong>并返回true,否则返回false<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> some = <span class="function">(<span class="params">collection, predicate</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> _some = <span class="literal">false</span>;</div><div class="line"></div><div class="line"> forEach(collection, (val, key, collection) => {</div><div class="line"> <span class="keyword">if</span> (predicate(val, key, collection)) {</div><div class="line"> _some = <span class="literal">true</span>;</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"> });</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _some;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Collection"><a href="#Collection" class="headerlink" title="Collection"></a>Collection</h1><h2 id="countBy"><a href="#countBy" class="headerlink" title="countBy"></a>countBy</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.countBy(collection, [iteratee=_.identity])</div></pre></td></tr></table></figure>
<p>collection中统计各项的数目,也可指定iteratee进行迭代处理<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> countBy = <span class="function">(<span class="params">collection, iteratee</span>) =&gt;</span> &#123;</div><div class="line"> <span class="keyword">let</span> result = &#123;&#125;;</div><div class="line"></div><div class="line"> collection.forEach(<span class="function"><span class="params">key</span> =&gt;</span> &#123;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> ite = iteratee ? iteratee(key) : key;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> result[ite] === <span class="string">'undefined'</span>) &#123;</div><div class="line"> result[ite] = <span class="number">1</span>;</div><div class="line"> &#125; <span class="keyword">else</span> &#123;</div><div class="line"> result[ite] += <span class="number">1</span>;</div><div class="line"> &#125;</div><div class="line"> &#125;);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>reduce?<br>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Collection" scheme="http://www.i0011.com/tags/Collection/"/>
</entry>
<entry>
<title>Lodash源码祭「Math」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-math/"/>
<id>http://www.i0011.com/2017/07/12/lodash-math/</id>
<published>2017-07-12T11:02:21.000Z</published>
<updated>2017-07-12T11:17:43.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h1><h2 id="mean"><a href="#mean" class="headerlink" title="mean"></a>mean</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.mean(array)</div></pre></td></tr></table></figure>
<p>求数字平均数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> mean = <span class="function"><span class="params">array</span> =></span> {</div><div class="line"> <span class="keyword">let</span> sum = array.reduce(<span class="function">(<span class="params">total, i</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> total + i;</div><div class="line"> }, <span class="number">0</span>);</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">NaN</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> sum / length;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h2 id="add"><a href="#add" class="headerlink" title="add"></a>add</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.add(augend, addend)</div></pre></td></tr></table></figure>
<p>不仅可以数字相加,也可以实现字符串的相加,并且参数为空时返回默认值0<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> add = <span class="function">(<span class="params">augend, addend</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> augend === <span class="string">'undefined'</span> && <span class="keyword">typeof</span> addend === <span class="string">'undefined'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>; <span class="comment">// default val</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> addend === <span class="string">'undefined'</span>) {</div><div class="line"> addend = <span class="keyword">typeof</span> augend === <span class="string">'string'</span> ? <span class="string">''</span> : <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> augend + addend;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="divide"><a href="#divide" class="headerlink" title="divide"></a>divide</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.divide(dividend, divisor)</div></pre></td></tr></table></figure>
<p>两数字相除,默认值为1<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> divide = <span class="function">(<span class="params">dividend, divisor</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> dividend === <span class="string">'undefined'</span> && <span class="keyword">typeof</span> divisor === <span class="string">'undefined'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>; <span class="comment">// default val</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> divisor === <span class="string">'undefined'</span>) {</div><div class="line"> divisor = <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> dividend / divisor;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="ceil"><a href="#ceil" class="headerlink" title="ceil"></a>ceil</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.ceil(number, [precision=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>数字向上取整,并可指定精度<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> ceil = <span class="function">(<span class="params">number, precision = <span class="number">0</span></span>) =></span> {</div><div class="line"> <span class="comment">// 这一波precision操作666啊,保持关注</span></div><div class="line"> <span class="keyword">if</span> (precision) {</div><div class="line"></div><div class="line"> <span class="comment">// 排除科学计数法的数字影响?</span></div><div class="line"> <span class="keyword">let</span> pair = <span class="string">`<span class="subst">${number}</span>e`</span>.split(<span class="string">'e'</span>);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> val = <span class="built_in">Math</span>.ceil(<span class="string">`<span class="subst">${pair[<span class="number">0</span>]}</span>e<span class="subst">${~~pair[<span class="number">1</span>] + precision}</span>`</span>); <span class="comment">// 可以接受字符串参数...</span></div><div class="line"></div><div class="line"> pair = <span class="string">`<span class="subst">${val}</span>e`</span>.split(<span class="string">'e'</span>);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> +<span class="string">`<span class="subst">${pair[<span class="number">0</span>]}</span>e<span class="subst">${~~pair[<span class="number">1</span>] - precision}</span>`</span></div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.ceil(number);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p><code>Math.ceil(4.231, -2) === 100</code>哈哈</p>
<h2 id="floor"><a href="#floor" class="headerlink" title="floor"></a>floor</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.floor(number, [precision=<span class="number">0</span>])</div></pre></td></tr></table></figure>
<p>同理ceil,方法换为<code>Math.floor</code>;还有<code>round</code>实现四舍五入的同理</p>
<h2 id="max"><a href="#max" class="headerlink" title="max"></a>max</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.max(array)</div></pre></td></tr></table></figure>
<p>接受数字数组,求max… 还有另外一个扩展的方法<code>_.maxBy(array, [iteratee=_.identity])</code>可以一起实现<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseMax = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> index = <span class="number">0</span>;</div><div class="line"> <span class="keyword">let</span> length = array ? array.length : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">val</span> =></span> val;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> max = array[<span class="number">0</span>];</div><div class="line"> <span class="keyword">let</span> computedMax = iteratee(max);</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (++index < length) {</div><div class="line"> <span class="keyword">let</span> cur = array[index];</div><div class="line"></div><div class="line"> <span class="keyword">let</span> computed = iteratee(cur);</div><div class="line"></div><div class="line"> <span class="comment">// NOTE:symbol不可隐式转化为数字参与比较</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> computed !== <span class="string">'symbol'</span> && computed > computedMax) {</div><div class="line"> max = cur;</div><div class="line"> computedMax = computed;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> max;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>另外,同理的还有<code>min</code>和<code>minBy</code>,不赘述</p>
<h2 id="mean-1"><a href="#mean-1" class="headerlink" title="mean"></a>mean</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.mean(array)</div></pre></td></tr></table></figure>
<p>求数组的平均值… 同样也有扩展方法<code>_.meanBy(array, [iteratee=_.identity])</code>,iteratee接受一个参数value<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseMean = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">NaN</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">val</span> =></span> val;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 因为iteratee的因素,还不能直接用reduce来求sum值</span></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> sum = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(++index < length) {</div><div class="line"> <span class="keyword">let</span> cur = iteratee(array[index]);</div><div class="line"> sum += (cur === <span class="literal">undefined</span> ? <span class="number">0</span> : cur);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> sum / length;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="multiply"><a href="#multiply" class="headerlink" title="multiply"></a>multiply</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.multiply(multiplier, multiplicand)</div></pre></td></tr></table></figure>
<p>两变量相乘,参数为空时默认值为1<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> multiply = <span class="function">(<span class="params">multiplier, multiplicand</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (multiplier === <span class="literal">undefined</span> && multiplicand === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (multiplicand === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> multiplier;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> multiplier * multiplicand;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="subtract"><a href="#subtract" class="headerlink" title="subtract"></a>subtract</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.subtract(minuend, subtrahend)</div></pre></td></tr></table></figure>
<p>减法,有默认值为0…类似乘法不赘述</p>
<h2 id="sum"><a href="#sum" class="headerlink" title="sum"></a>sum</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.sum(array)</div></pre></td></tr></table></figure>
<p>求数组的“加法”运算,也包括字符串,引用上面<code>mean</code>求值的sum算式即可。另外,也有<code>sumBy</code>方法,接收2个参数,另外一个参数<code>iteratee</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> baseSum = <span class="function">(<span class="params">array, iteratee</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> {length} = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) {</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!iteratee) {</div><div class="line"> iteratee = <span class="function"><span class="params">val</span> =></span> val;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"> <span class="keyword">let</span> sum = <span class="number">0</span>;</div><div class="line"> <span class="keyword">while</span>(++index < length) {</div><div class="line"> <span class="keyword">let</span> cur = iteratee(array[index]);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (cur === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">continue</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> sum += cur;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> sum;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Math"><a href="#Math" class="headerlink" title="Math"></a>Math</h1><h2 id="mean"><a href="#mean" class="headerlink" title="mean"></a>mean</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.mean(array)</div></pre></td></tr></table></figure>
<p>求数字平均数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> mean = <span class="function"><span class="params">array</span> =&gt;</span> &#123;</div><div class="line"> <span class="keyword">let</span> sum = array.reduce(<span class="function">(<span class="params">total, i</span>) =&gt;</span> &#123;</div><div class="line"> <span class="keyword">return</span> total + i;</div><div class="line"> &#125;, <span class="number">0</span>);</div><div class="line"> <span class="keyword">let</span> &#123;length&#125; = array;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!length) &#123;</div><div class="line"> <span class="keyword">return</span> <span class="literal">NaN</span>;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> sum / length;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Math" scheme="http://www.i0011.com/tags/Math/"/>
</entry>
<entry>
<title>Lodash源码祭「Number」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-number/"/>
<id>http://www.i0011.com/2017/07/12/lodash-number/</id>
<published>2017-07-12T11:02:12.000Z</published>
<updated>2017-07-12T11:17:46.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Number"><a href="#Number" class="headerlink" title="Number"></a>Number</h1><h2 id="random"><a href="#random" class="headerlink" title="random"></a>random</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.random([lower=<span class="number">0</span>], [upper=<span class="number">1</span>], [floating])</div></pre></td></tr></table></figure>
<p>返回lower-upper之间任意的随机数,若lower为传则从0开始,floating=true则会返回浮点数,另外,如果lower或者upper为浮点数,也会返回一个浮点数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> random = <span class="function">(<span class="params">lower, upper, floating</span>) =></span> {</div><div class="line"> <span class="comment">// 接收参数情况较多,需进行参数校准</span></div><div class="line"></div><div class="line"> <span class="comment">// 参数不满</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> floating === <span class="string">'undefined'</span>) {</div><div class="line"></div><div class="line"> <span class="comment">// 2个参数,第2个参数为浮点数,则第一个参数为upper</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> upper === <span class="string">'boolean'</span>) {</div><div class="line"> floating = upper;</div><div class="line"></div><div class="line"> upper = lower;</div><div class="line"></div><div class="line"> lower = <span class="literal">undefined</span>;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> lower === <span class="string">'boolean'</span>) {</div><div class="line"> <span class="comment">// 1个参数</span></div><div class="line"></div><div class="line"> floating = lower;</div><div class="line"> lower = <span class="literal">undefined</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> lower === <span class="string">'undefined'</span>) {</div><div class="line"> lower = <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> upper === <span class="string">'undefined'</span>) {</div><div class="line"> upper = <span class="number">1</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// lower > upper的情况则交换</span></div><div class="line"> <span class="keyword">if</span> (lower > upper) {</div><div class="line"> [lower, upper] = [upper, lower];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 通过number % 1判断是否为浮点数</span></div><div class="line"> <span class="keyword">if</span> (floating || lower % <span class="number">1</span> || upper % <span class="number">1</span>) {</div><div class="line"> <span class="comment">// 范围浮点数的方法有点诡异啊...</span></div><div class="line"> <span class="keyword">let</span> rand = <span class="built_in">Math</span>.random(); <span class="comment">// 0 - 1</span></div><div class="line"> <span class="keyword">let</span> len = <span class="string">`<span class="subst">${rand}</span>`</span>.length;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.min(lower + (rand * (upper - lower + <span class="built_in">parseFloat</span>(<span class="string">`1e-<span class="subst">${len}</span>`</span>))), upper); <span class="comment">// ...</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 整数</span></div><div class="line"> <span class="keyword">return</span> lower + <span class="built_in">Math</span>.floor((<span class="built_in">Math</span>.random() * (upper - lower + <span class="number">1</span>)));</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h2 id="inRange"><a href="#inRange" class="headerlink" title="inRange"></a>inRange</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.inRange(number, [start=<span class="number">0</span>], end)</div></pre></td></tr></table></figure>
<p>判断一个数字是否在start和end(不包含end)之间,start为可选参数,默认为0,如果start大于end<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> inRange = <span class="function">(<span class="params">number, start, end</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> end === <span class="string">'undefined'</span>) {</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> start === <span class="string">'undefined'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>; <span class="comment">// 无range</span></div><div class="line"> }</div><div class="line"></div><div class="line"> end = start;</div><div class="line"> start = <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (end > start) {</div><div class="line"> <span class="keyword">return</span> number >= start && number < end;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> number > end && number <= start;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="clamp"><a href="#clamp" class="headerlink" title="clamp"></a>clamp</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.clamp(number, [lower], upper)</div></pre></td></tr></table></figure>
<p>名字好隐晦…保证返回值在lower和upper之间,小于lower则返回lower,大于upper则返回upper<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> clamp = <span class="function">(<span class="params">number, lower, upper</span>) =></span> {</div><div class="line"> number = ~~number;</div><div class="line"> lower = ~~lower;</div><div class="line"> upper = ~~upper;</div><div class="line"></div><div class="line"> <span class="comment">// 判断NaN</span></div><div class="line"> lower = lower === lower ? lower : <span class="number">0</span>;</div><div class="line"> upper = upper === upper ? upper : <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (number === number) {</div><div class="line"> <span class="comment">// compare to upper</span></div><div class="line"> number = number <= upper ? number : upper;</div><div class="line"></div><div class="line"> <span class="comment">// compare to lower</span></div><div class="line"> number = number >= lower ? number : lower;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> number;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Number"><a href="#Number" class="headerlink" title="Number"></a>Number</h1><h2 id="random"><a href="#random" class="headerlink" title="random"></a>random</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.random([lower=<span class="number">0</span>], [upper=<span class="number">1</span>], [floating])</div></pre></td></tr></table></figure>
<p>返回lower-upper之间任意的随机数,若lower为传则从0开始,floating=true则会返回浮点数,另外,如果lower或者upper为浮点数,也会返回一个浮点数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> random = <span class="function">(<span class="params">lower, upper, floating</span>) =&gt;</span> &#123;</div><div class="line"> <span class="comment">// 接收参数情况较多,需进行参数校准</span></div><div class="line"></div><div class="line"> <span class="comment">// 参数不满</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> floating === <span class="string">'undefined'</span>) &#123;</div><div class="line"></div><div class="line"> <span class="comment">// 2个参数,第2个参数为浮点数,则第一个参数为upper</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> upper === <span class="string">'boolean'</span>) &#123;</div><div class="line"> floating = upper;</div><div class="line"></div><div class="line"> upper = lower;</div><div class="line"></div><div class="line"> lower = <span class="literal">undefined</span>;</div><div class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> lower === <span class="string">'boolean'</span>) &#123;</div><div class="line"> <span class="comment">// 1个参数</span></div><div class="line"></div><div class="line"> floating = lower;</div><div class="line"> lower = <span class="literal">undefined</span>;</div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> lower === <span class="string">'undefined'</span>) &#123;</div><div class="line"> lower = <span class="number">0</span>;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> upper === <span class="string">'undefined'</span>) &#123;</div><div class="line"> upper = <span class="number">1</span>;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="comment">// lower &gt; upper的情况则交换</span></div><div class="line"> <span class="keyword">if</span> (lower &gt; upper) &#123;</div><div class="line"> [lower, upper] = [upper, lower];</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="comment">// 通过number % 1判断是否为浮点数</span></div><div class="line"> <span class="keyword">if</span> (floating || lower % <span class="number">1</span> || upper % <span class="number">1</span>) &#123;</div><div class="line"> <span class="comment">// 范围浮点数的方法有点诡异啊...</span></div><div class="line"> <span class="keyword">let</span> rand = <span class="built_in">Math</span>.random(); <span class="comment">// 0 - 1</span></div><div class="line"> <span class="keyword">let</span> len = <span class="string">`<span class="subst">$&#123;rand&#125;</span>`</span>.length;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.min(lower + (rand * (upper - lower + <span class="built_in">parseFloat</span>(<span class="string">`1e-<span class="subst">$&#123;len&#125;</span>`</span>))), upper); <span class="comment">// ...</span></div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="comment">// 整数</span></div><div class="line"> <span class="keyword">return</span> lower + <span class="built_in">Math</span>.floor((<span class="built_in">Math</span>.random() * (upper - lower + <span class="number">1</span>)));</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Number" scheme="http://www.i0011.com/tags/Number/"/>
</entry>
<entry>
<title>Lodash源码祭「String」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-string/"/>
<id>http://www.i0011.com/2017/07/12/lodash-string/</id>
<published>2017-07-12T11:00:27.000Z</published>
<updated>2017-07-12T11:32:27.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="String"><a href="#String" class="headerlink" title="String"></a>String</h1><h2 id="loweFrirst"><a href="#loweFrirst" class="headerlink" title="loweFrirst"></a>loweFrirst</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.lowerFirst([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>小写字符串的首字母<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> lowerFirst = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string !== <span class="literal">null</span>) {</div><div class="line"> string = <span class="keyword">typeof</span> string === <span class="string">'string'</span> ? string : string.toString();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> head = string.match(<span class="regexp">/^[A-Z]/</span>);</div><div class="line"></div><div class="line"> head = head ? head[<span class="number">0</span>] : head;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (head) {</div><div class="line"> <span class="keyword">return</span> string.replace(<span class="regexp">/^([A-Z])(.*)/</span>, <span class="string">`<span class="subst">${head.toLowerCase()}</span>$2`</span>)</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> string;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>同理,首字母大写是同样的实现,不赘述</p>
<h2 id="toLower-toUpper"><a href="#toLower-toUpper" class="headerlink" title="toLower / toUpper"></a>toLower / toUpper</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 小写</span></div><div class="line">_.toLower([string=<span class="string">''</span>])</div><div class="line"><span class="comment">// 大写</span></div><div class="line">_.toUpper([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>将字符串中的字母转换为小写或者大写,直接调用标准方法即可<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toLower = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string !== <span class="literal">null</span>) {</div><div class="line"> string = <span class="keyword">typeof</span> string === <span class="string">'string'</span> ? string : string.toString();</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string.toLowerCase();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="capitalize"><a href="#capitalize" class="headerlink" title="capitalize"></a>capitalize</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.capitalize([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>首字母大写,剩余的小写。先全部转化为小写,再首字母大写就可以了<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> capitalize = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">return</span> upperFirst(toLower(string));</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="endsWith"><a href="#endsWith" class="headerlink" title="endsWith"></a>endsWith</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.endsWith([string=<span class="string">''</span>], [target], [position=string.length])</div></pre></td></tr></table></figure>
<p>判断字符串到position位置是否是以target结尾的<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> endsWith = <span class="function">(<span class="params">string, target, position</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string === <span class="literal">undefined</span> || target === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> position = position === <span class="literal">undefined</span> ? string.length : +position;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (position < <span class="number">0</span> || position !== position) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 正则</span></div><div class="line"> <span class="keyword">let</span> sliceStr = string.slice(<span class="number">0</span>, position);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> regx = <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">`<span class="subst">${target}</span>$`</span>);</div><div class="line"></div><div class="line"> <span class="keyword">return</span> regx.test(sliceStr);</div><div class="line"></div><div class="line"> <span class="comment">// 或者也可以通过字符串截取</span></div><div class="line"> <span class="comment">// let end = position;</span></div><div class="line"> <span class="comment">// position -= target.length;</span></div><div class="line"></div><div class="line"> <span class="comment">// return position >= 0 && string.slice(position, end) == target; // 未强等,'123'找数字3也是可以的</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="pad"><a href="#pad" class="headerlink" title="pad"></a>pad</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.pad([string=<span class="string">''</span>], [length=<span class="number">0</span>], [chars=<span class="string">' '</span>])</div></pre></td></tr></table></figure>
<p>用chars补全字符串到指定length<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> repeat = <span class="function">(<span class="params">str, times</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> res = str;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (--times) {</div><div class="line"> res += str;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">const</span> pad = <span class="function">(<span class="params">string, length, chars</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> length = +length;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {<span class="attr">length</span>: len} = string;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (length <= len) {</div><div class="line"> <span class="keyword">return</span> string;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> offset = length - len;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> left = <span class="built_in">Math</span>.floor(offset / <span class="number">2</span>);</div><div class="line"> <span class="keyword">let</span> right = offset - left;</div><div class="line"></div><div class="line"> chars = chars === <span class="literal">undefined</span> ? <span class="string">' '</span> : chars.toString();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> charsLen = chars.length;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> repeat(chars, <span class="built_in">Math</span>.ceil(left / charsLen)).slice(<span class="number">0</span>, left) +</div><div class="line"> string +</div><div class="line"> repeat(chars, <span class="built_in">Math</span>.ceil(right / charsLen)).slice(<span class="number">0</span>, right)</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="padEnd-padStart"><a href="#padEnd-padStart" class="headerlink" title="padEnd / padStart"></a>padEnd / padStart</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">_.padEnd([string=<span class="string">''</span>], [length=<span class="number">0</span>], [chars=<span class="string">' '</span>])</div><div class="line"><span class="comment">//</span></div><div class="line">_.padStart([string=<span class="string">''</span>], [length=<span class="number">0</span>], [chars=<span class="string">' '</span>])</div></pre></td></tr></table></figure>
<p>类似于pad,向字符串尾部或者头部补全指定字符串</p>
<h2 id="repeat"><a href="#repeat" class="headerlink" title="repeat"></a>repeat</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.repeat([string=<span class="string">''</span>], [n=<span class="number">1</span>])</div></pre></td></tr></table></figure>
<p>在实现<code>pad</code>功能的时候,我们有一个重复字符串的函数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> repeat = <span class="function">(<span class="params">str, times</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> res = str;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (--times) {</div><div class="line"> res += str;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>So easy?no,至少不是那么完美。比如把’a’重复4次,上面做法需要执行4次字符串合并,那常规做法,我可以把第一次合并的结果再做一次合并就可以了。优化的算法:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> repeat = <span class="function">(<span class="params">str, times</span>) =></span> {</div><div class="line"> <span class="keyword">let</span> result = <span class="string">''</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!str || times < <span class="number">1</span>) {</div><div class="line"> <span class="keyword">return</span> result;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">do</span> {</div><div class="line"> <span class="keyword">if</span> (times % <span class="number">2</span>) {</div><div class="line"> result += str;</div><div class="line"> }</div><div class="line"></div><div class="line"> times = <span class="built_in">Math</span>.floor(times / <span class="number">2</span>);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (times) {</div><div class="line"> str += str;</div><div class="line"> }</div><div class="line"> } <span class="keyword">while</span> (times)</div><div class="line"></div><div class="line"> <span class="keyword">return</span> result;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="escape"><a href="#escape" class="headerlink" title="escape"></a>escape</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.escape([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>转义特殊字符:<code>&</code>、<code><</code>、<code>></code>、<code>"</code>、<code>'</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> escapeMap = {</div><div class="line"> <span class="string">'&'</span>: <span class="string">'&amp'</span>,</div><div class="line"> <span class="string">'<'</span>: <span class="string">'&lt'</span>,</div><div class="line"> <span class="string">'>'</span>: <span class="string">'&gt'</span>,</div><div class="line"> <span class="string">'"'</span>: <span class="string">'&quot'</span>,</div><div class="line"> <span class="string">"'"</span>: <span class="string">'&#39'</span></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">const</span> <span class="built_in">escape</span> = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string && <span class="regexp">/[&<>"']/g</span>.test(string)) {</div><div class="line"> <span class="keyword">return</span> string.replace(<span class="regexp">/[&<>"']/g</span>, char => escapeMap[char]);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="escapeRegExp"><a href="#escapeRegExp" class="headerlink" title="escapeRegExp"></a>escapeRegExp</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.escapeRegExp([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>转义字符串中的正则表达式字符<code>^</code>、 <code>$</code>、 <code>.</code>、 <code>\</code>、 <code>*</code>、 <code>+</code>、 <code>?</code>、 <code>(</code>、 <code>)</code>、 <code>[</code>、 <code>]</code>、 <code>{</code>、 <code>}</code>、 <code>|</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> reg = <span class="regexp">/[\\^$.*+?()[\]{}|]/g</span>; <span class="comment">// 这里注意\],防止闭合正则的前[</span></div><div class="line"></div><div class="line"><span class="keyword">const</span> escapeRegExp = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string && reg.test(string)) {</div><div class="line"> <span class="keyword">return</span> string.replace(reg, <span class="string">'\\$&'</span>); <span class="comment">// $& is matched substring</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>顺带小case,除<code>$&</code>,字符串替换还有多种模式,Turn to <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_string_as_a_parameter" target="_blank" rel="external">MDN</a></p>
<h2 id="parseInt"><a href="#parseInt" class="headerlink" title="parseInt"></a>parseInt</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.parseInt(string, [radix=<span class="number">10</span>])</div></pre></td></tr></table></figure>
<p>字符串转化为数字<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> <span class="built_in">parseInt</span> = <span class="function">(<span class="params">string, radix</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (radix === <span class="literal">null</span>) {</div><div class="line"> radix = <span class="number">0</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> radix = +radix;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> nativeParseInt(string.replace(<span class="regexp">/^\s+/</span>, <span class="string">''</span>), radix); <span class="comment">// 调native的parseint实现,补:消除头尾空格</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>脑补radix值的以及默认参数转化方法,如果radix是<code>undefined</code>或者<code>0</code>,会自动根据字符串的前缀进行对应的转换数字操作:</p>
<ul>
<li>If the input string begins with “0x” or “0X”, radix is 16 (hexadecimal) and the remainder of the string is parsed.</li>
<li>If the input string begins with “0”, radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet. For this reason always specify a radix when using parseInt.(对于<code>0</code>开头的字符串,浏览器解析有差异,所以建议parseInt指定radix参数)</li>
<li>If the input string begins with any other value, the radix is 10 (decimal).</li>
</ul>
<h2 id="replace"><a href="#replace" class="headerlink" title="replace"></a>replace</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.replace([string=<span class="string">''</span>], pattern, replacement)</div></pre></td></tr></table></figure>
<p>字符串替换,pattern可以是正则表达式或者字符串<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> replace = <span class="function">(<span class="params">...args</span>) =></span> {</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (args.length < <span class="number">3</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="string">`<span class="subst">${args[<span class="number">0</span>]}</span>`</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">let</span> [string, pattern, replacement] = args;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="string">`<span class="subst">${string}</span>`</span>.replace(pattern, replacement);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="split"><a href="#split" class="headerlink" title="split"></a>split</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.split([string=<span class="string">''</span>], separator, [limit])</div></pre></td></tr></table></figure>
<p>字符串分割,也可以指定界限(也就是最终得到的数组的元素个数,原生也有这个参数…);<br>另外,separator可以是字符串也可以是正则,原生也是支持的…当separator=undefined或者separator没有出现在string中时,返回原字符串;当separator=’’时,返回字符串分割成单个字母的数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> MAX_ARRAY_LENGTH = <span class="number">4294967295</span>;</div><div class="line"></div><div class="line"><span class="keyword">const</span> split = <span class="function">(<span class="params">string, separator, limit</span>) =></span> {</div><div class="line"> <span class="comment">// 确保limit是一个正整数</span></div><div class="line"> limit = limit === <span class="literal">undefined</span> ? MAX_ARRAY_LENGTH : limit >>> <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (limit === <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (string === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string.toString().split(separator, limit);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>源码<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">if</span> (string && (</div><div class="line"> <span class="keyword">typeof</span> separator == <span class="string">'string'</span> ||</div><div class="line"> (separator != <span class="literal">null</span> && !isRegExp(separator))</div><div class="line"> )) {</div><div class="line"> <span class="keyword">if</span> (!separator && hasUnicode(string)) {</div><div class="line"> <span class="keyword">return</span> castSlice(stringToArray(string), <span class="number">0</span>, limit)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>这是什么样的一个套路,没看明白…</p>
<h2 id="trim"><a href="#trim" class="headerlink" title="trim"></a>trim</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.trim([string=<span class="string">''</span>], [chars=whitespace])</div></pre></td></tr></table></figure>
<p>移除字符串开头和结尾的空格或者指定的字符<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> trim = <span class="function">(<span class="params">string, chars</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (string === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> string !== <span class="string">'string'</span>) {</div><div class="line"> string = string.toString();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 默认替换空格</span></div><div class="line"> <span class="keyword">if</span> (chars === <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> string.trim();</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> {length} = string;</div><div class="line"> <span class="keyword">let</span> start = <span class="number">0</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (start < length) {</div><div class="line"> <span class="keyword">if</span> (chars.indexOf(string[start]) === <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> start++;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> end = length - <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (end > <span class="number">0</span>) {</div><div class="line"> <span class="keyword">if</span> (chars.indexOf(string[end]) === <span class="number">-1</span>) {</div><div class="line"> <span class="keyword">break</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> end--;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string.slice(start, end + <span class="number">1</span>);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>然后trimStart和trimEnd同理,<code>String</code>也有<code>trimLeft</code>和<code>trimRight</code>方法</p>
<h2 id="words"><a href="#words" class="headerlink" title="words"></a>words</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.words([string=<span class="string">''</span>], [pattern])</div></pre></td></tr></table></figure>
<p>字符串分解为单词的数组,而且可以指定匹配的单词的模式<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> words = <span class="function">(<span class="params">string, pattern</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!string) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (pattern === <span class="literal">undefined</span>) {</div><div class="line"> pattern = <span class="regexp">/\w+/g</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> string.match(pattern) || []; <span class="comment">// match也是可以接受字符串pattern的...</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>这边对于pattern=undefined的情况其实考虑的很简单了,源码还考虑了<code>ascii</code>和<code>unicode</code>的情况分别处理…这个跑<code>中文 你好</code>的时候就挂了… <code>word.js</code>有点弱鸡啊,急需靠拢源码</p>
<h2 id="camelCase"><a href="#camelCase" class="headerlink" title="camelCase"></a>camelCase</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.camelCase([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>字符串驼峰,这之类的所有的字符串格式化方法都基于之前的单词匹配,匹配到单词后拼接起来<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> camelCase = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">return</span> toLower(string).match(<span class="regexp">/\w+/g</span>).reduce(<span class="function">(<span class="params">res, world, index</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> res + (index ? upperFirst(world) : world);</div><div class="line"> }, <span class="string">''</span>); <span class="comment">// reduce函数的初始值可选,不给时默认为数组第一个元素,但当数组是空的时候会报错,此处有风险,应当赋默认值</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="kebabCase"><a href="#kebabCase" class="headerlink" title="kebabCase"></a>kebabCase</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.kebabCase([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>转化为中划线分割单词的字符串<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> kebabCase = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =></span> {</div><div class="line"> <span class="keyword">return</span> toLower(string).match(<span class="regexp">/\w+/g</span>).join(<span class="string">'-'</span>);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>包括<code>lowerCase</code>小写空格分割、<code>snakeCase</code>以下划线分割,也是同理</p>
<h2 id="template"><a href="#template" class="headerlink" title="template"></a>template</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//TODO</span></div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="String"><a href="#String" class="headerlink" title="String"></a>String</h1><h2 id="loweFrirst"><a href="#loweFrirst" class="headerlink" title="loweFrirst"></a>loweFrirst</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.lowerFirst([string=<span class="string">''</span>])</div></pre></td></tr></table></figure>
<p>小写字符串的首字母<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> lowerFirst = <span class="function">(<span class="params">string = <span class="string">''</span></span>) =&gt;</span> &#123;</div><div class="line"> <span class="keyword">if</span> (string !== <span class="literal">null</span>) &#123;</div><div class="line"> string = <span class="keyword">typeof</span> string === <span class="string">'string'</span> ? string : string.toString();</div><div class="line"></div><div class="line"> <span class="keyword">let</span> head = string.match(<span class="regexp">/^[A-Z]/</span>);</div><div class="line"></div><div class="line"> head = head ? head[<span class="number">0</span>] : head;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (head) &#123;</div><div class="line"> <span class="keyword">return</span> string.replace(<span class="regexp">/^([A-Z])(.*)/</span>, <span class="string">`<span class="subst">$&#123;head.toLowerCase()&#125;</span>$2`</span>)</div><div class="line"> &#125; <span class="keyword">else</span> &#123;</div><div class="line"> <span class="keyword">return</span> string;</div><div class="line"> &#125;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="String" scheme="http://www.i0011.com/tags/String/"/>
</entry>
<entry>
<title>Lodash源码祭「Lang」</title>
<link href="http://www.i0011.com/2017/07/12/lodash-lang/"/>
<id>http://www.i0011.com/2017/07/12/lodash-lang/</id>
<published>2017-07-12T10:58:41.000Z</published>
<updated>2017-07-22T15:00:09.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Lang"><a href="#Lang" class="headerlink" title="Lang"></a>Lang</h1><h2 id="clone"><a href="#clone" class="headerlink" title="clone"></a>clone</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.clone(value)</div></pre></td></tr></table></figure>
<h2 id="castArray"><a href="#castArray" class="headerlink" title="castArray"></a>castArray</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.castArray(value)</div></pre></td></tr></table></figure>
<p>如果value不是一个数组,就给他包成一个数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> castArray = <span class="function">(<span class="params">...arg</span>) =></span> {</div><div class="line"> <span class="comment">// 没有参数的情况,返回空数组,需要特殊处理,跟参数为undefined不同</span></div><div class="line"> <span class="keyword">if</span> (arg.length === <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">let</span> value = arg[<span class="number">0</span>];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(value)) {</div><div class="line"> <span class="keyword">return</span> value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> [value];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<h2 id="eq"><a href="#eq" class="headerlink" title="eq"></a>eq</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.eq(value, other)</div></pre></td></tr></table></figure>
<p>value和other是否「强相等」,但这里NaN和NaN相等<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> eq = <span class="function">(<span class="params">value, other</span>) =></span> value === other || (value !== value && other !== other);</div></pre></td></tr></table></figure></p>
<h2 id="gt"><a href="#gt" class="headerlink" title="gt"></a>gt</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.gt(value, other)</div></pre></td></tr></table></figure>
<p>value > other则返回true,否则返回false;需要注意的时,当两个参数都是字符串时,进行字符串比较,其余的都转化为数字进行比较<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> gt = <span class="function">(<span class="params">value, other</span>) =></span> {</div><div class="line"> <span class="keyword">if</span> (!(<span class="keyword">typeof</span> value === <span class="string">'string'</span> && <span class="keyword">typeof</span> other === <span class="string">'string'</span>)) {</div><div class="line"> value = +value;</div><div class="line"> other = +other;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> value > other;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p><code>lt</code>、<code>lte</code>和<code>gte</code>同理…</p>
<h2 id="isArguments"><a href="#isArguments" class="headerlink" title="isArguments"></a>isArguments</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isArguments(value)</div></pre></td></tr></table></figure>
<p>检查传入值是否是arguments对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isArguments = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> value === <span class="string">'object'</span> && value !== <span class="literal">null</span> && value.toString() === <span class="string">'[object Arguments]'</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isArray"><a href="#isArray" class="headerlink" title="isArray"></a>isArray</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isArray(value)</div></pre></td></tr></table></figure>
<p>判断是否为数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isArray = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">const</span> _isArray = <span class="built_in">Array</span>.isArray;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (!_isArray) {</div><div class="line"> _isArray = <span class="function"><span class="keyword">function</span>(<span class="params">arg</span>) </span>{</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(arg) === <span class="string">'[object Array]'</span>;</div><div class="line"> };</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> _isArray(value);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isArrayBuffer"><a href="#isArrayBuffer" class="headerlink" title="isArrayBuffer"></a>isArrayBuffer</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isArrayBuffer(value)</div></pre></td></tr></table></figure>
<p>判断是否为ArrayBuffer。同样,通过<code>toString</code>也能得到ArrayBuffer的tag为<code>[object ArrayBuffer]</code></p>
<h2 id="isArrayLike"><a href="#isArrayLike" class="headerlink" title="isArrayLike"></a>isArrayLike</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isArrayLike(value)</div></pre></td></tr></table></figure>
<p>首先,明确ArrayLike的特征为:非函数的value有length属性,length为整数且0 <= value.length <= Number.MAX_SAFE_INTEGER<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isLength = <span class="function"><span class="params">val</span> =></span> {</div><div class="line"></div><div class="line"> <span class="comment">// 数字 && 非负 && 除「-0」的非负「整数」 && 小于最大正整数</span></div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> val === <span class="string">'number'</span> && val > <span class="number">-1</span> && val % <span class="number">1</span> === <span class="number">0</span> && val <= <span class="built_in">Number</span>.MAX_SAFE_INTEGER;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">const</span> isArrayLike = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> value !== <span class="literal">null</span> && <span class="keyword">typeof</span> value !== <span class="string">'function'</span> && isLength(value.length);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isArrayLikeObject"><a href="#isArrayLikeObject" class="headerlink" title="isArrayLikeObject"></a>isArrayLikeObject</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isArrayLikeObject(value)</div></pre></td></tr></table></figure>
<p>在<code>isArrayLike</code>的基础上加了个条件:判断value得是Object</p>
<h2 id="isBoolean"><a href="#isBoolean" class="headerlink" title="isBoolean"></a>isBoolean</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isBoolean(value)</div></pre></td></tr></table></figure>
<p>可以检验值是否为布尔型变量,可以是原始值类型(true / false)也可以是Boolean的实例对象<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isBoolean = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> value === <span class="literal">true</span> || value === <span class="literal">false</span> ||</div><div class="line"> (value !== <span class="literal">null</span> && <span class="built_in">Object</span>.prototype.toString.call(value) === <span class="string">'[object Boolean]'</span>)</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isNumber"><a href="#isNumber" class="headerlink" title="isNumber"></a>isNumber</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isNumber(value);</div></pre></td></tr></table></figure>
<p>判断参数是否为数字,同样对于原始类型和Number的实例都适用<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isNumber = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> value === <span class="string">'number'</span> ||</div><div class="line"> <span class="built_in">Object</span>.prototype.toString.call(value) === <span class="string">'[object Number]'</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isNaN"><a href="#isNaN" class="headerlink" title="isNaN"></a>isNaN</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isNaN(value)</div></pre></td></tr></table></figure>
<p>原生<code>isNaN</code>方法会对非数字都返回true,而不光是NaN,lodash仅对NaN本身以及<code>new Number(NaN)</code>的情况返回true<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> <span class="built_in">isNaN</span> = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"></div><div class="line"> <span class="comment">// 首先判断是否为数字</span></div><div class="line"> <span class="comment">// 然后区分是否跟本身相等</span></div><div class="line"></div><div class="line"> <span class="keyword">return</span> isNumber(value) && value != +value; <span class="comment">// 非强等</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isNil"><a href="#isNil" class="headerlink" title="isNil"></a>isNil</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isNil(value)</div></pre></td></tr></table></figure>
<p>判断参数是否为undefined或者null<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isNil = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> value === <span class="literal">undefined</span> || value === <span class="literal">null</span>; <span class="comment">// value == null</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isNull"><a href="#isNull" class="headerlink" title="isNull"></a>isNull</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isNull(value)</div></pre></td></tr></table></figure>
<p>判断参数是否为null<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isNull = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> value === <span class="literal">null</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isObject"><a href="#isObject" class="headerlink" title="isObject"></a>isObject</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isObject(value)</div></pre></td></tr></table></figure>
<p>是否为对象(包括数组、函数、对象、正则等等非原始数据类型…)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isObject = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">var</span> type = <span class="keyword">typeof</span> value;</div><div class="line"></div><div class="line"> <span class="comment">// null && 对象或者函数</span></div><div class="line"> <span class="keyword">return</span> value != <span class="literal">null</span> && (type === <span class="string">'object'</span> || type === <span class="string">'function'</span>);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isObjectLike"><a href="#isObjectLike" class="headerlink" title="isObjectLike"></a>isObjectLike</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isObjectLike(value)</div></pre></td></tr></table></figure>
<p>检查value是否为Object-Like(非null并满足typeof vlaue === ‘object’)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isObjectLike = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> value !== <span class="literal">null</span> && <span class="keyword">typeof</span> value === <span class="string">'object'</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isPlainObject"><a href="#isPlainObject" class="headerlink" title="isPlainObject"></a>isPlainObject</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isPlainObject(value)</div></pre></td></tr></table></figure>
<p>检查是否为plain object(object.constructor === Object || object.[[prototype]] === null)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isPlainObject = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="comment">// 首先满足是个对象并且排除掉一些内置的对象,比如Date这些</span></div><div class="line"> <span class="keyword">if</span> (!isObjectLike(value) || <span class="built_in">Object</span>.prototype.toString.call(value) !== <span class="string">'[object Object]'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 先看value.[[prototype]]是否为null,[[prototype]]是不可见的属性,通过Object.getPrototype可以获取</span></div><div class="line"> <span class="keyword">let</span> proto = <span class="built_in">Object</span>.getPrototypeOf(value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (proto === <span class="literal">null</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"> <span class="comment">// 承上,这边需要说一下,默认创建的总是有[[prototype]]指向Object.prototype的,但是为啥会有null的情况呢,因为有Object.create(null)啊!指定[[prototype]]是null,也就变成了食物链顶端的男人...需要考虑这种情况</span></div><div class="line"></div><div class="line"> <span class="comment">// 接下来判断对象是不是通过Object构造函数构造出来的</span></div><div class="line"> <span class="comment">// contructor是可以篡改的...</span></div><div class="line"> <span class="keyword">let</span> <span class="keyword">constructor</span> = Object.prototype.hasOwnProperty.call(proto, '<span class="keyword">constructor</span>') && proto.<span class="keyword">constructor</span>;</div><div class="line"></div><div class="line"> if (typeof <span class="keyword">constructor</span> === 'function' &&</div><div class="line"> // instanceof 检查是是否在左参数是否在右参数的原型链中</div><div class="line"> // 除<span class="keyword">constructor</span>是Object外,其他构造函数不满足此条件</div><div class="line"> // 对于Object,Object.__proto__ === Function.prototype,Function.prototype.__proto__ === Object.prototype</div><div class="line"> <span class="keyword">constructor</span> instanceof <span class="keyword">constructor</span> &&</div><div class="line"> // 检查contructor字符串是否是Object的字符串</div><div class="line"> Function.prototype.toString.call(<span class="keyword">constructor</span>) === Function.prototype.toString.call(Object)) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</div><div class="line"> }</div><div class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isRegExp"><a href="#isRegExp" class="headerlink" title="isRegExp"></a>isRegExp</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isRegExp(value)</div></pre></td></tr></table></figure>
<p>检查是否为正则<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isRegExp = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="comment">// 官网似乎还做了个node环境下直接用util.isRegExp去判断的,但是看Node API似乎已经被Deprecated啦</span></div><div class="line"> <span class="keyword">return</span> isObjectLike(value) && <span class="built_in">Object</span>.prototype.toString.call(value) === <span class="string">'[object RegExp]'</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isSafeInteger"><a href="#isSafeInteger" class="headerlink" title="isSafeInteger"></a>isSafeInteger</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isSafeInteger(value)</div></pre></td></tr></table></figure>
<p>也就是 -(2^53 - 1) ~ (2^53 - 1)之间的整数。ES6直接提供了方法<code>Number.isSafeInteger</code>可以直接实现…当然,考虑IE的话还是需要Polyfill的<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isInteger = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">typeof</span> value === <span class="string">'number'</span> &&</div><div class="line"> <span class="built_in">isFinite</span>(value) &&</div><div class="line"> <span class="built_in">Math</span>.floor(value) === value;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">const</span> isSafeInteger = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">return</span> isInteger(value) && <span class="built_in">Math</span>.abs(value) <= <span class="built_in">Number</span>.MAX_SAFE_INTEGER;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="isSet-isWeekSet-isMap-isWeekMap"><a href="#isSet-isWeekSet-isMap-isWeekMap" class="headerlink" title="isSet / isWeekSet / isMap / isWeekMap"></a>isSet / isWeekSet / isMap / isWeekMap</h2><p>Set和Map都可以通过<code>Object.prototype.toString.call(value)</code>的值去判断,分别为’[object Set]’、’[object WeekSet]’、’[object Map]’、’[object WeekMap]’</p>
<h2 id="isString"><a href="#isString" class="headerlink" title="isString"></a>isString</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isString(value)</div></pre></td></tr></table></figure>
<p>检查是否为字符串<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isString = <span class="function"><span class="params">value</span> =></span> <span class="keyword">typeof</span> value === <span class="string">'string'</span> ||</div><div class="line"> Obejct.prototype.toString.call(value) === <span class="string">'[object String]'</span>;</div></pre></td></tr></table></figure></p>
<h2 id="isSymbol"><a href="#isSymbol" class="headerlink" title="isSymbol"></a>isSymbol</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isSymbol(value)</div></pre></td></tr></table></figure>
<p>检查是否为symbol值<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isSymbol = <span class="function"><span class="params">value</span> =></span> <span class="keyword">typeof</span> value === <span class="string">'symbol'</span> ||</div><div class="line"> Obejct.prototype.toString.call(value) === <span class="string">'[object Symbol]'</span>;</div></pre></td></tr></table></figure></p>
<h2 id="isTypedArray"><a href="#isTypedArray" class="headerlink" title="isTypedArray"></a>isTypedArray</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isTypedArray(value)</div></pre></td></tr></table></figure>
<p>检查是否为typed array。对应的不同类型的数组,有不同的toString展示,通过正则规则统一匹配</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> reTypedTag = <span class="regexp">/^\[object (?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)\]$/</span>;</div><div class="line"></div><div class="line"><span class="keyword">const</span> isTypedArray = <span class="function"><span class="params">value</span> =></span> <span class="keyword">typeof</span> value === <span class="string">'object'</span> && reTypedTag.test(value);</div></pre></td></tr></table></figure>
<p>link to description of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays" target="_blank" rel="external">typed array</a>…就是什么是Unit8ClampedArray好诡异的数据结构,限制数组元素值在0-255</p>
<h2 id="isUndefined"><a href="#isUndefined" class="headerlink" title="isUndefined"></a>isUndefined</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.isUndefined(value)</div></pre></td></tr></table></figure>
<p>检查是否为undefined<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> isUndefined = <span class="function"><span class="params">value</span> =></span> value === <span class="literal">undefined</span>;</div></pre></td></tr></table></figure></p>
<h2 id="toArray"><a href="#toArray" class="headerlink" title="toArray"></a>toArray</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toArray(value)</div></pre></td></tr></table></figure>
<p>转化value为数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toArray = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (!value) {</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (isArrayLike(value)) {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">'string'</span>) {</div><div class="line"> <span class="keyword">return</span> [].slice.call(value)</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="comment">// arguments</span></div><div class="line"> <span class="comment">// DOM Nodes</span></div><div class="line"> <span class="keyword">let</span> {length} = value;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> index = <span class="number">-1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = [];</div><div class="line"></div><div class="line"> <span class="keyword">while</span> (index++ <span class="xml"><span class="tag">< <span class="attr">length</span>) {</span></span></div><div class="line"> <span class="attr">res</span>[<span class="attr">index</span>] = <span class="string">value[index];</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="attr">return</span> <span class="attr">res</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> // <span class="attr">map</span>/<span class="attr">set</span></div><div class="line"> <span class="attr">let</span> <span class="attr">tag</span> = <span class="string">Object.prototype.toString.call(value)</span></div><div class="line"> <span class="attr">if</span> (<span class="attr">tag</span> === <span class="string">'[object Set]'</span> || <span class="attr">tag</span> === <span class="string">'[object Map]'</span>) {</div><div class="line"> <span class="attr">return</span> <span class="attr">Array.from</span>(<span class="attr">value</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> // <span class="attr">NOTICE:</span>还有迭代器对象</div><div class="line"> <span class="attr">if</span> (<span class="attr">Symbol</span> && <span class="attr">Symbol.iterator</span> && <span class="attr">value</span>[<span class="attr">Symbol.iterator</span>]) {</div><div class="line"> <span class="attr">let</span> <span class="attr">res</span> = <span class="string">[];</span></div><div class="line"> <span class="attr">for</span> (<span class="attr">let</span> <span class="attr">val</span> <span class="attr">of</span> <span class="attr">value</span>) {</div><div class="line"> <span class="attr">res.push</span>(<span class="attr">val</span>);</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="attr">return</span> <span class="attr">res</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> // 其他</div><div class="line"> <span class="attr">return</span> <span class="attr">Object.values</span>(<span class="attr">value</span>); // 兼容性,懒得遍历了</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>源码对于这种<code>_.toArray({ 'a': 1, 'b': 2, length:2 });</code>情况的ArrayLike返回的是[undefined, undefined]…有点不合理了,但是似乎没办法区分这种这种带length的普通对象啊…</p>
<h2 id="toLength"><a href="#toLength" class="headerlink" title="toLength"></a>toLength</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toLength(value)</div></pre></td></tr></table></figure>
<p>转化为一个length的合法值:整数字且0 <= value <= Number.MAX_SAFE_INTEGER<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toLength = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (!value) {</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 化整的神奇方法</span></div><div class="line"> <span class="keyword">let</span> reminder = value % <span class="number">1</span>;</div><div class="line"></div><div class="line"> value = reminder ? value - reminder : value;</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (value < <span class="number">0</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (value > <span class="built_in">Number</span>.MAX_SAFE_INTEGER) {</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Number</span>.MAX_SAFE_INTEGER;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> value;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toString-NaN"><a href="#toString-NaN" class="headerlink" title="toString"></a>toString</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toString(value)</div></pre></td></tr></table></figure>
<p>转化为字符串,对于undefined和null返回空字符串,-0会保留<code>-</code><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> INFINITY = <span class="number">1</span> / <span class="number">0</span>;</div><div class="line"></div><div class="line"><span class="keyword">const</span> toString = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (value == <span class="literal">undefined</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">'string'</span>) {</div><div class="line"> <span class="keyword">return</span> value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 对于数组,递归,并且会flattenDeep</span></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(value)) {</div><div class="line"> <span class="keyword">return</span> <span class="string">`<span class="subst">${value.map(val => toString(val))}</span>`</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 因为symbol类型的变量不可隐式转化为其他数据类型,symbol类型也要单独考虑(只可显示转化为字符串或symbol)</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">'symbol'</span>) {</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Symbol</span> && <span class="built_in">Symbol</span>.prototype.toString) {</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Symbol</span>.prototype.toString.call(value);</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> <span class="string">''</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 其他类型强转</span></div><div class="line"> <span class="keyword">let</span> res = <span class="string">`<span class="subst">${value}</span>`</span>;</div><div class="line"></div><div class="line"> <span class="comment">// 此处有-0的判断技巧</span></div><div class="line"> <span class="keyword">if</span> (res === <span class="string">'0'</span> && <span class="number">1</span> / value === -INFINITY) {</div><div class="line"> <span class="keyword">return</span> <span class="string">'-0'</span>;</div><div class="line"> } <span class="keyword">else</span> {</div><div class="line"> <span class="keyword">return</span> res;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toNumber"><a href="#toNumber" class="headerlink" title="toNumber"></a>toNumber</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toNumber(value)</div></pre></td></tr></table></figure>
<p>转化为数字<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toNumber = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">'number'</span>) {</div><div class="line"> <span class="keyword">return</span> value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// symbol can not covert to number</span></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Object</span>.prototype.toString.call(value) === <span class="string">'[object Symbol]'</span>) {</div><div class="line"> <span class="keyword">return</span> <span class="literal">NaN</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// valueof for object</span></div><div class="line"> <span class="keyword">if</span> (isObject(value)) {</div><div class="line"> <span class="keyword">let</span> val = <span class="keyword">typeof</span> value.valueOf === <span class="string">'function'</span> ? value.valueOf() : value;</div><div class="line"></div><div class="line"> value = isObject(val) ? <span class="string">`<span class="subst">${val}</span>`</span> : val; <span class="comment">// what for?</span></div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="comment">// 字符串</span></div><div class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> value === <span class="string">'string'</span>) {</div><div class="line"> value = value.trim();</div><div class="line"></div><div class="line"> <span class="comment">// 对于2进制(0b)、8进制(0o)、16进制(0x)的转化</span></div><div class="line"> <span class="comment">// if (/^0b[01]+$/i.test(value) ||</span></div><div class="line"> <span class="comment">// /^0o[0-7]+$/i.test(value) ||</span></div><div class="line"> <span class="comment">// /^0x[0-9a-f]+$/i.test(value)) {</span></div><div class="line"> <span class="comment">// return +value;</span></div><div class="line"> <span class="comment">// }</span></div><div class="line"></div><div class="line"> <span class="comment">// 源码对于这个正则的判断是为了啥?</span></div><div class="line"> <span class="comment">// /^[-+]0x[0-9a-f]+$/i,只用判断16进制么,2进制和8进制带符号的同样也转不过来的啊</span></div><div class="line"> <span class="keyword">return</span> +value;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> +value; <span class="comment">// 其他情况</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toFinite"><a href="#toFinite" class="headerlink" title="toFinite"></a>toFinite</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toFinite(value)</div></pre></td></tr></table></figure>
<p>转化为有限数字<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> INFINITY = <span class="number">1</span> / <span class="number">0</span>;</div><div class="line"><span class="keyword">const</span> MAX_INTEGER = <span class="number">1.7976931348623157e+308</span>;</div><div class="line"></div><div class="line"><span class="keyword">const</span> toFinite = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="keyword">if</span> (!value) {</div><div class="line"> <span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"> }</div><div class="line"></div><div class="line"> value = toNumber(value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (value === INFINITY || value === -INFINITY) {</div><div class="line"> <span class="keyword">let</span> sign = value < <span class="number">0</span> ? <span class="number">-1</span> : <span class="number">1</span>;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> sign * MAX_INTEGER;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> value === value ? value : <span class="number">0</span>; <span class="comment">// NaN</span></div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toInteger"><a href="#toInteger" class="headerlink" title="toInteger"></a>toInteger</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toInteger(value)</div></pre></td></tr></table></figure>
<p>转化为整数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toInteger = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> value = toFinite(value);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> reminder = value % <span class="number">1</span>;</div><div class="line"></div><div class="line"></div><div class="line"> <span class="keyword">return</span> value === value ? value - reminder : <span class="number">0</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toSafeInteger"><a href="#toSafeInteger" class="headerlink" title="toSafeInteger"></a>toSafeInteger</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toSafeInteger(value)</div></pre></td></tr></table></figure>
<p>转化为安全整数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toSafeInteger = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> value = toInteger(value);</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (value < <span class="built_in">Number</span>.MIN_SAFE_INTEGER) {</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Number</span>.MIN_SAFE_INTEGER;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (value > <span class="built_in">Number</span>.MAX_SAFE_INTEGER) {</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Number</span>.MAX_SAFE_INTEGER;</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> value;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h2 id="toPlainObject"><a href="#toPlainObject" class="headerlink" title="toPlainObject"></a>toPlainObject</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.toPlainObject(value)</div></pre></td></tr></table></figure>
<p>转化为plain object,就是for…in遍历后取到的所有键值对(包括原型链上的属性值)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> toPlainObject = <span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="comment">// convert to object</span></div><div class="line"> value = <span class="built_in">Object</span>(value);</div><div class="line"></div><div class="line"> <span class="keyword">let</span> res = {};</div><div class="line"></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> key <span class="keyword">in</span> value) {</div><div class="line"> res[key] = value[key];</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="keyword">return</span> res;</div><div class="line">}</div></pre></td></tr></table></figure></p>
]]></content>
<summary type="html">
<blockquote>
<p>巧妙的函数实现吸引着你想去看看他的实现方法,里面会有更多奇思妙想让你欣喜若狂…</p>
</blockquote>
<h1 id="Lang"><a href="#Lang" class="headerlink" title="Lang"></a>Lang</h1><h2 id="clone"><a href="#clone" class="headerlink" title="clone"></a>clone</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.clone(value)</div></pre></td></tr></table></figure>
<h2 id="castArray"><a href="#castArray" class="headerlink" title="castArray"></a>castArray</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">_.castArray(value)</div></pre></td></tr></table></figure>
<p>如果value不是一个数组,就给他包成一个数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> castArray = <span class="function">(<span class="params">...arg</span>) =&gt;</span> &#123;</div><div class="line"> <span class="comment">// 没有参数的情况,返回空数组,需要特殊处理,跟参数为undefined不同</span></div><div class="line"> <span class="keyword">if</span> (arg.length === <span class="number">0</span>) &#123;</div><div class="line"> <span class="keyword">return</span> [];</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">let</span> value = arg[<span class="number">0</span>];</div><div class="line"></div><div class="line"> <span class="keyword">if</span> (<span class="built_in">Array</span>.isArray(value)) &#123;</div><div class="line"> <span class="keyword">return</span> value;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> <span class="keyword">return</span> [value];</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Lodash" scheme="http://www.i0011.com/tags/Lodash/"/>
<category term="Lang" scheme="http://www.i0011.com/tags/Lang/"/>
</entry>
<entry>
<title>Https养成手记</title>
<link href="http://www.i0011.com/2016/10/09/https-config/"/>
<id>http://www.i0011.com/2016/10/09/https-config/</id>
<published>2016-10-09T09:48:42.000Z</published>
<updated>2017-04-07T01:46:44.000Z</updated>
<content type="html"><![CDATA[<p>把大象放进冰箱分三步,那么实现https化你的网站也可以分三步:</p>
<ol>
<li><code>openssl req -newkey rsa:2048 -keyout server.key -out server.csr</code>在服务器上生成key和csr,可以直接扔在nginx目录,方便。此处需要<strong>注意</strong>的是,生成的private key需要移除passphrase,就是运行前面命令时让输入的<code>PEM</code>的值,否则nginx error。<br>执行<code>openssl rsa -in server.key -out unencripted-server.key</code>就OK了,我们在nginx配置中就使用未加密的key文件</li>
<li>去<a href="https://www.startssl.com/Certificates/ApplySSLCert?level=1" target="_blank" rel="external">Startssl</a>,将刚才得到的server.csr文件内容填入表单中,Submit!<br><img src="https://dn-xuqi.qbox.me/https.png" alt="Startssl配置"><br>然后下载生成的证书,因为我用的是nginx,就将NginxServer下面的的crt文件scp到服务器中</li>
<li>配置nginx并将http80重定向到443即可<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line">server {</div><div class="line"> listen 443 ssl;</div><div class="line"> ssl_certificate /path/to/crt;</div><div class="line"> ssl_certificate_key /path/to/unencripted/key;</div><div class="line"> ssl_session_tickets off;</div><div class="line"> ssl_session_cache shared:SSL:10m;</div><div class="line"> server_name yourdomain;</div><div class="line"></div><div class="line"> location / {</div><div class="line"> proxy_redirect off;</div><div class="line"> proxy_pass http://yourUpstream;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">server {</div><div class="line"> listen 80;</div><div class="line"> server_name yourdomain;</div><div class="line"> return 301 https://yourdomain$request_uri;</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ol>
<p>Got it… nginx reload就可以了</p>
<p>Thanks to:<br><a href="https://segmentfault.com/a/1190000007024673?utm_source=weekly&utm_medium=email&utm_campaign=email_weekly" target="_blank" rel="external">给你的网站穿上外衣 - HTTPS 免费部署指南</a><br><a href="http://stackoverflow.com/questions/18101217/error-102-nginx-ssl" target="_blank" rel="external">Nginx 102 error ssl</a></p>
]]></content>
<summary type="html">
<p>把大象放进冰箱分三步,那么实现https化你的网站也可以分三步:</p>
<ol>
<li><code>openssl req -newkey rsa:2048 -keyout server.key -out server.csr</code>在服务器上生成key和csr,
</summary>
<category term="Https" scheme="http://www.i0011.com/tags/Https/"/>
<category term="Ubuntu" scheme="http://www.i0011.com/tags/Ubuntu/"/>
<category term="Nginx" scheme="http://www.i0011.com/tags/Nginx/"/>
</entry>
<entry>
<title>destructuring</title>
<link href="http://www.i0011.com/2016/09/25/destructuring/"/>
<id>http://www.i0011.com/2016/09/25/destructuring/</id>
<published>2016-09-25T03:48:01.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p><strong>destructuring</strong>,解构,可以方便coder们从Object/Array中提取想要的数据,Es6大杀器…</p>
<p>按照阮老师的说法,解构其实就属于一种数据结构的模式匹配,匹配上的模式对应的值会从表达式右侧赋值给表达式左侧,比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> {name, <span class="attr">info</span>: {age}} = {</div><div class="line"> <span class="attr">name</span>: <span class="string">'xuqi'</span>,</div><div class="line"> <span class="attr">info</span>: {</div><div class="line"> <span class="attr">age</span>: <span class="number">27</span></div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line">name; <span class="comment">// 'xuqi'</span></div><div class="line">age; <span class="comment">// 27</span></div></pre></td></tr></table></figure></p>
<p>我们就能直接获取<strong>模式</strong>name和age的值,赋值给<strong>变量</strong>name和age,需要注意的是模式和变量的概念,这是理解解构的基础,<br><code>{mode: var}</code>,<code>:</code>左侧为模式,右侧为变量,上述例子是当模式和变量名相同时的缩写,实际上是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> {<span class="attr">name</span>: name, <span class="attr">info</span>: {</div><div class="line"> <span class="attr">age</span>: age</div><div class="line">}} = ...</div></pre></td></tr></table></figure></p>
<p>这样理解起来就清楚了。解构可以从数组和对象中提取值,分别来说明…<br><a id="more"></a></p>
<h2 id="Array-destructuring"><a href="#Array-destructuring" class="headerlink" title="Array destructuring"></a>Array destructuring</h2><h3 id="basic-variable-assignment"><a href="#basic-variable-assignment" class="headerlink" title="basic variable assignment"></a>basic variable assignment</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> [one, two, three] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</div></pre></td></tr></table></figure>
<p>当然,变量声明和解构赋值可以分开进行:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> one, two, three;</div><div class="line">[one, two, three] = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</div></pre></td></tr></table></figure></p>
<h3 id="default-values"><a href="#default-values" class="headerlink" title="default values"></a>default values</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> [a = <span class="number">1</span>, b = <span class="number">2</span>] = [<span class="number">3</span>];</div><div class="line"></div><div class="line">a; <span class="comment">// 3</span></div><div class="line">b; <span class="comment">// 2</span></div></pre></td></tr></table></figure>
<p>默认值生效的条件是右侧对应位置的值<strong>严格</strong>等于<code>undefined</code>,下述情况是不会发生默认值赋值的:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> [a = <span class="number">1</span>] = [<span class="literal">null</span>];</div><div class="line"></div><div class="line">a; <span class="comment">// null</span></div></pre></td></tr></table></figure></p>
<p>另外,阮老师的书里面说到的一种情况可能平时不太会经常用到,但是还是需要注意下:在默认值是通过函数返回值赋值的情况下,函数是惰性求职的,即在不使用默认值的情况下,函数是不会被执行的<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> fn = <span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'Hey, I am here'</span>);</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">};</div><div class="line"></div><div class="line"><span class="keyword">let</span> [a = fn()] = [<span class="number">1</span>];</div><div class="line"></div><div class="line"><span class="comment">// fn didn't invoke</span></div></pre></td></tr></table></figure></p>
<p>当然默认值也可以引用变量(外部变量/解构变量),当默认值引用解构变量时,需要注意在设置默认值时必须确保引用的解构变量已经声明,否则将报错<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">let a = 1;</div><div class="line">let [x = a, y = x] = [];</div><div class="line"></div><div class="line">x; // 1</div><div class="line">y; // 1</div></pre></td></tr></table></figure></p>
<h3 id="swapping-variable"><a href="#swapping-variable" class="headerlink" title="swapping variable"></a>swapping variable</h3><p>轻松实现变量交换<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> a = <span class="number">1</span>;</div><div class="line"><span class="keyword">let</span> b = <span class="number">2</span>;</div><div class="line"></div><div class="line">[a, b] = [b, a];</div></pre></td></tr></table></figure></p>
<h3 id="parsing-an-array-returned-from-a-function-amp-ignore-some-variable"><a href="#parsing-an-array-returned-from-a-function-amp-ignore-some-variable" class="headerlink" title="parsing an array returned from a function & ignore some variable"></a>parsing an array returned from a function & ignore some variable</h3><p>我们常见的场景,需要通过函数返回多个变量,通过解构的话就可以拿到返回的多个值,并且可以忽略某个或多个值。<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> fn = <span class="function"><span class="params">()</span> =></span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</div><div class="line"></div><div class="line"><span class="keyword">let</span> [a, , b] = fn();</div><div class="line"></div><div class="line">a; <span class="comment">// 1</span></div><div class="line">b; <span class="comment">// 3</span></div></pre></td></tr></table></figure></p>
<h2 id="Object-destructuring"><a href="#Object-destructuring" class="headerlink" title="Object destructuring"></a>Object destructuring</h2><p>同数组,对象也可以按照结构进行解构赋值,文章开头已经举了一个basic assignment的例子,这里就继续说明其他的使用场景和注意事项。</p>
<h3 id="assignment-without-declaration"><a href="#assignment-without-declaration" class="headerlink" title="assignment without declaration"></a>assignment without declaration</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> a, b;</div><div class="line">({a, b} = {<span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>});</div></pre></td></tr></table></figure>
<p>需要注意的是,当解构赋值跟声明分开进行时,解构表达式外的<code>()</code>是必须得,否则解析左侧是会当成一个块级表达式,从而导致因=号的出现而报错。</p>
<h3 id="assignment-to-new-variable-name"><a href="#assignment-to-new-variable-name" class="headerlink" title="assignment to new variable name"></a>assignment to new variable name</h3><p>对象的解构可以指定赋值的变量名:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> {<span class="attr">name</span>: theName, <span class="attr">info</span>: {<span class="attr">age</span>: theAge}} = {</div><div class="line"> <span class="attr">name</span>: <span class="string">'xuqi'</span>,</div><div class="line"> <span class="attr">info</span>: {</div><div class="line"> <span class="attr">age</span>: <span class="number">27</span></div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line">theName; <span class="comment">// 'xuqi'</span></div><div class="line">theAge; <span class="comment">// 27</span></div></pre></td></tr></table></figure></p>
<p>之前已经介绍过模式和变量名的形式,这里就很好理解了,由于指定了变量名,name和age只是模式</p>
<h3 id="default-values-1"><a href="#default-values-1" class="headerlink" title="default values"></a>default values</h3><p>跟数组一样,对象解构也可以设置默认值<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> {a = <span class="number">1</span>, <span class="attr">b</span>:c = <span class="number">2</span>} = {<span class="attr">a</span>: <span class="number">2</span>};</div><div class="line"></div><div class="line">a; <span class="comment">// 2</span></div><div class="line">c; <span class="comment">// 2</span></div></pre></td></tr></table></figure></p>
<p>对象解构的默认值有一种比较重要的应用场景:函数的默认参数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> fn = <span class="function">(<span class="params">{a = <span class="number">1</span>, b = <span class="number">2</span>} = {}</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> [a, b];</div><div class="line">};</div><div class="line"></div><div class="line">fn();</div></pre></td></tr></table></figure></p>
<p>这篇流水账的起因是因为TS2.0发布了然后去看了下文档,瞬间被加了type的解构表达式搞晕了,然后就想着写个文章来捋一捋,毕竟看别人文章跟自己写出来还是有点差别的,想看详细的还是看文档或者阮老师的书比较好,想要了解下或者重新梳理思路,这篇文章适合你</p>
<p>参考资料:<br><a href="http://es6.ruanyifeng.com/#docs/destructuring" target="_blank" rel="external">阮一峰《ECMAScript6入门》变量的解构赋值</a><br><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" target="_blank" rel="external">MDN Destructuring assignment</a></p>
]]></content>
<summary type="html">
<p><strong>destructuring</strong>,解构,可以方便coder们从Object/Array中提取想要的数据,Es6大杀器…</p>
<p>按照阮老师的说法,解构其实就属于一种数据结构的模式匹配,匹配上的模式对应的值会从表达式右侧赋值给表达式左侧,比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> &#123;name, <span class="attr">info</span>: &#123;age&#125;&#125; = &#123;</div><div class="line"> <span class="attr">name</span>: <span class="string">'xuqi'</span>,</div><div class="line"> <span class="attr">info</span>: &#123;</div><div class="line"> <span class="attr">age</span>: <span class="number">27</span></div><div class="line"> &#125;</div><div class="line">&#125;;</div><div class="line"></div><div class="line">name; <span class="comment">// 'xuqi'</span></div><div class="line">age; <span class="comment">// 27</span></div></pre></td></tr></table></figure></p>
<p>我们就能直接获取<strong>模式</strong>name和age的值,赋值给<strong>变量</strong>name和age,需要注意的是模式和变量的概念,这是理解解构的基础,<br><code>{mode: var}</code>,<code>:</code>左侧为模式,右侧为变量,上述例子是当模式和变量名相同时的缩写,实际上是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">let</span> &#123;<span class="attr">name</span>: name, <span class="attr">info</span>: &#123;</div><div class="line"> <span class="attr">age</span>: age</div><div class="line">&#125;&#125; = ...</div></pre></td></tr></table></figure></p>
<p>这样理解起来就清楚了。解构可以从数组和对象中提取值,分别来说明…<br>
</summary>
<category term="Es6" scheme="http://www.i0011.com/tags/Es6/"/>
</entry>
<entry>
<title>What the f**k of Postcss</title>
<link href="http://www.i0011.com/2016/01/28/what-the-fuck-of-postcss/"/>
<id>http://www.i0011.com/2016/01/28/what-the-fuck-of-postcss/</id>
<published>2016-01-28T05:37:31.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<blockquote>
<p>PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.</p>
</blockquote>
<p>对于Postcss,这样介绍来开启话题最合适不过。大部分人对Postcss的认知还是CSS pre-preprocessor,因此经常会有将Postcss和Sass/Less/Stylus进行对比的情况。那Postcss到底是什么?</p>
<p>Postcss只是一个工具,获取CSS内容并将其转化成JS插件可以处理的数据,如此基于Postcss的JS插件便可基于Postcss提供的数据进行对应的处理。目前Postcss Plugin的列表数目已经200+,提供诸于:auto-prefix、next-css、linter、short-name等功能。另外,由于Postcss的职能是类似于工具箱,用户可以选择自己的工具放进去,所以你可以根据自身的开发喜好和需求去开发自己的“工具”扔到工具箱里去,心有多大,世界就有多大,勇敢的少年啊,快去创造奇迹~<br><a id="more"></a></p>
<p>在认清Postcss的真实面目后,搬出下面这段摘抄的话,会显得逼格很高:</p>
<blockquote>
<ul>
<li>It’s not a pre-processor, though it can optionally behave like one.</li>
<li>It’s not a post-processor, though it can optionally behave like one.</li>
<li>It’s not about “future syntax”, though it can facilitate support for future syntax</li>
<li>It’s not a clean up / optimization tool, though it can provide such functionality.</li>
<li>It’s not any one thing; it’s a means to potentially unlimited functionality configured as you choose.</li>
</ul>
</blockquote>
<p>也就是,它看起来什么都是,然而本质上它什么都不是,但是它什么都能干。万剑归宗,万法归一,嗯,就是这种意思了…</p>
<p>口说无凭,祭出插件杀器:</p>
<ul>
<li><a href="https://github.com/postcss/autoprefixer" target="_blank" rel="external">autoprefixer</a> 为指定的browsers生成兼容性CSS,你只需按照W3C的标准去书写你的样式就好了,接下的事autoprefixer帮你摆平</li>
<li><a href="https://github.com/jonathantneal/precss" target="_blank" rel="external">precss</a> 如果你需要像Sass提供的:variables、mixins、conditionals等功能,precss是不二之选</li>
<li><a href="https://github.com/postcss/postcss-import" target="_blank" rel="external">postcss-import</a> 使用@import,并且可以获取第三方的样式(比如bower或者npm)</li>
<li><a href="https://github.com/ben-eb/cssnano" target="_blank" rel="external">cssnano</a> css<strong>优化</strong>(清除注释和尾分号、合并规则,字体权重优化等等等…),压缩…强大</li>
<li><a href="https://github.com/assetsjs/postcss-assets" target="_blank" rel="external">postcss-assets</a> img/font加载路径解决方案,另外还提供获取图片尺寸以及将图片转化为base64写入css的功能</li>
<li><a href="https://github.com/2createStudio/postcss-sprites" target="_blank" rel="external">postcss-sprites</a> image sprite</li>
<li>…颜色处理,可读性处理,简化输入,优化,打包,<a href="http://postcss.parts/" target="_blank" rel="external">自行探索>>></a></li>
</ul>
<p>怎么去用?Gulp!你应该享受现代工具~<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> gulp = <span class="built_in">require</span>(<span class="string">'gulp'</span>),</div><div class="line"> postcss = <span class="built_in">require</span>(<span class="string">'gulp-postcss'</span>),</div><div class="line"> sourcemap = <span class="built_in">require</span>(<span class="string">'gulp-sourcemaps'</span>);</div><div class="line">gulp.task(<span class="string">'css'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> gulp.src(<span class="string">'css/**/*.css'</span>)</div><div class="line"> .pipe(sourcemap.init())</div><div class="line"> .pipe(postcss([</div><div class="line"> <span class="built_in">require</span>(<span class="string">'autoprefixer'</span>)({</div><div class="line"> <span class="attr">browsers</span>: [<span class="string">'not ie < 8'</span>]</div><div class="line"> }),</div><div class="line"> <span class="built_in">require</span>(<span class="string">'precss'</span>),</div><div class="line"> <span class="built_in">require</span>(<span class="string">'postcss-assets'</span>)({</div><div class="line"> <span class="attr">loadPaths</span>: [<span class="string">'font/'</span>, <span class="string">'img/'</span>],</div><div class="line"> <span class="attr">relativeTo</span>: <span class="string">'css/post/'</span></div><div class="line"> }),</div><div class="line"> <span class="built_in">require</span>(<span class="string">'postcss-sprites'</span>).default({</div><div class="line"> <span class="attr">basePath</span>: <span class="string">'./img'</span>, <span class="comment">//img base path</span></div><div class="line"> stylesheetPath: <span class="string">'./css'</span>, <span class="comment">//path of css generated</span></div><div class="line"> spritePath: <span class="string">'./img'</span>, <span class="comment">//path of sprites generated</span></div><div class="line"> spritesmith: {</div><div class="line"> <span class="attr">padding</span>: <span class="number">2</span>,</div><div class="line"> },</div><div class="line"> <span class="attr">groupBy</span>: <span class="function"><span class="keyword">function</span>(<span class="params">file</span>) </span>{</div><div class="line"> <span class="keyword">var</span> group = file.url.split(<span class="string">'/'</span>)[<span class="number">1</span>]; <span class="comment">// 根据目录分组,防止合并后的图片太大</span></div><div class="line"> <span class="keyword">return</span> group ? <span class="built_in">Promise</span>.resolve(group) : <span class="built_in">Promise</span>.reject();</div><div class="line"> }</div><div class="line"> })</div><div class="line"> ]))</div><div class="line"> .pipe(sourcemap.write(<span class="string">'.'</span>))</div><div class="line"> .pipe(gulp.dest(<span class="string">'dist/'</span>))</div><div class="line">});</div></pre></td></tr></table></figure></p>
<h3 id="题外话"><a href="#题外话" class="headerlink" title="题外话"></a>题外话</h3><p>由于正在使用Compass,不自主会把这两个工具进行比较:<br>Compass是Sass的扩展,提供了很多牛X的Minix和功能(比如:无可比拟的image-sprite)。用过Compass的可能会有疑问了,你上面讲的在Compass都能做啊,而且我还不用去找很多插件来实现我的功能,去网站翻使用指南和它的API就可以了,不要太强大…然而,出问题的就是他的强,大:</p>
<ol>
<li>Compass需要依赖Ruby,这一点就足够判死刑</li>
<li>Compass提供了很多@mixin,其中也包括类似于autoprefix的功能,但是,前提是:我得知道我要写的属性需要进行prefix处理,所以对大部分人来说,这个功能属于鸡肋功能。对于一些辅助的功能实现的mixin,我们可能会想到去官网搜索,然而,这个比prefix的处理更让人头疼,在一个全站颜色统一,甚至对搜索结果都不做突出的网站上找到想要的API是有多难,搜索结果下你会发现不知所云的搜索结果</li>
<li>我们并不需要Compass提供的那么多内置mixin</li>
<li>对compass认知程度有限,上述叙述若有偏颇,勿怪,个人观点…当然,不可否认还是有很多出色的功能的~</li>
</ol>
<p>对比Compass,我更喜欢Postcss带来的体验,把一切交给npm,无需其他乱七八糟的环境的配置,通过一些基本的插件,可以实现从Compass到Postcss的无缝切换,而且Postcss的开放性必然会给以后带来诸多Compass所不会有的好处。插件多样性可以帮你处理各种常见问题:嫌每天重复输入相同的width,height…你可以用<code>postcss-short</code>或者<code>postcss-size</code>;嫌<code>#3f3f3f</code>这种输入浪费时间,<code>postcss-color-short</code>帮你解决后顾之忧,你只用输入<code>#3f</code>;想像写Es6那样享受超前的快感,<code>cssnext</code>带你装逼;想摆脱老是写水平居中或者垂直居中的困扰,<code>postcss-center</code>助你一臂之力;clearfix的功能在你只用写<code>clear:fix</code>的情况下,也有插件<code>postcss-clearfix</code>帮你铺平道路;甚至连css的语法检查,也有插件给你两肋插刀…总之大到模块化,小到画三角,应有尽有,各取所需就好…</p>
<p>灵活性+开放性+易用性+扩展性….足够了,写Postcss,挺好~</p>
]]></content>
<summary type="html">
<blockquote>
<p>PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more.</p>
</blockquote>
<p>对于Postcss,这样介绍来开启话题最合适不过。大部分人对Postcss的认知还是CSS pre-preprocessor,因此经常会有将Postcss和Sass/Less/Stylus进行对比的情况。那Postcss到底是什么?</p>
<p>Postcss只是一个工具,获取CSS内容并将其转化成JS插件可以处理的数据,如此基于Postcss的JS插件便可基于Postcss提供的数据进行对应的处理。目前Postcss Plugin的列表数目已经200+,提供诸于:auto-prefix、next-css、linter、short-name等功能。另外,由于Postcss的职能是类似于工具箱,用户可以选择自己的工具放进去,所以你可以根据自身的开发喜好和需求去开发自己的“工具”扔到工具箱里去,心有多大,世界就有多大,勇敢的少年啊,快去创造奇迹~<br>
</summary>
<category term="HandBook" scheme="http://www.i0011.com/tags/HandBook/"/>
<category term="Postcss" scheme="http://www.i0011.com/tags/Postcss/"/>
</entry>
<entry>
<title>React server side render</title>
<link href="http://www.i0011.com/2016/01/24/react-ssr/"/>
<id>http://www.i0011.com/2016/01/24/react-ssr/</id>
<published>2016-01-24T12:20:17.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p>如何使用React开发高效可<del>装B</del>用的WEB应用:) … 融合React以及React-ssr、koa、Es6、Postcss,绽放吧,骚年…</p>
<p><a href="https://github.com/loveLibra/React-ssr-demo" target="_blank" rel="external">DEMO传送门>>>></a></p>
<ol>
<li><p>JSX支持Runtime<br><code>require('node-jsx').install({harmony: true});</code>。添加harmony选项可在JSX中使用部分ES6的特性,但是未完全支持.</p>
</li>
<li><p>browserify打包客户端脚本</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">browserify(<span class="string">'./js/index.js'</span>)</div><div class="line"> .transform(babelify, {</div><div class="line"> <span class="attr">presets</span>: [<span class="string">'es2015'</span>, <span class="string">'react'</span>]</div><div class="line"> })</div><div class="line"> .bundle()</div><div class="line"> .pipe(fs.createWriteStream(<span class="string">'dist/bundle.js'</span>));</div></pre></td></tr></table></figure>
</li>
<li><p>React服务端渲染<br>将一个纯View用在此处其实有点别扭,但是为了SEO以及一些页面渲染性能的考虑,需要服务端渲染。React-SSR就是通过<code>ReactDOMServer.renderToString</code>得到HTML渲染到页面中,然后在客户端重新初始化组件,React并不会蠢的去重新渲染页面,所以此处可以忽略前端再次初始化带来的性能和使用体验的问题…前端初始化组件也是需要带数据的,所以在后端渲染组件时,我们将数据也带带页面中,然后再前端初始化后再删除数据DOM即可.<br>另外,在渲染字符串到页面中时,<code>views/partials/content.html</code>中放置渲染好的HTML的标签:</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment"><!-- 不能有换行,否则客户端渲染时因为识别空白节点的问题在前端初始化失败。--></span></div><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"yoho-container"</span>></span>{{{content}}}<span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></table></figure>
</li>
<li><p>Koa<br>koa + yield真的是太明智了,让代码不再一层层的去嵌套回调,棒!路由,接口取数据,数据格式化,页面渲染能对程序员展现以同步的形式去实现,跳出恶魔金字塔吧,Koa带你飞~</p>
</li>
<li>Postcss<br>Postcss相对于Compass的优势,在于其灵活性和轻便性,需要什么功能,扩展postcss插件就行了,autoprefixer,sprite-image应有尽有,Get what You Need…</li>
</ol>
<p>后记:前端现在愈发膨胀和夸张,无数的轮子和框架来方便你的开发,然而得有度,别让自己的程序失去控制…前端现在就像一匹飞奔的马,跑的很快,但是跑到哪你却不知道,你唯一能做的就是练好骑马的技术,别从马上摔下来。夯实基础,成就你的精湛马术吧</p>
<p>精彩的参考资料:<br><a href="http://www.crmarsh.com/react-ssr/" target="_blank" rel="external">Rendering React Components on the Server</a></p>
]]></content>
<summary type="html">
<p>如何使用React开发高效可<del>装B</del>用的WEB应用:) … 融合React以及React-ssr、koa、Es6、Postcss,绽放吧,骚年…</p>
<p><a href="https://github.com/loveLibra/React-ssr-
</summary>
<category term="Es6" scheme="http://www.i0011.com/tags/Es6/"/>
<category term="React" scheme="http://www.i0011.com/tags/React/"/>
<category term="Ssr" scheme="http://www.i0011.com/tags/Ssr/"/>
<category term="Koa" scheme="http://www.i0011.com/tags/Koa/"/>
<category term="Browserify" scheme="http://www.i0011.com/tags/Browserify/"/>
<category term="Postcss" scheme="http://www.i0011.com/tags/Postcss/"/>
</entry>
<entry>
<title>js-oop</title>
<link href="http://www.i0011.com/2016/01/11/js-oop/"/>
<id>http://www.i0011.com/2016/01/11/js-oop/</id>
<published>2016-01-11T07:50:22.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p>Javascript可能是一门让人感觉“不适”的语言,实现<code>类</code>、<code>继承</code>等OOP概念竟然要通过<code>function</code>和<code>prototype</code>,Jser们可能理解原型机制就能伤半管子HP了。然而,这种情况随着ES6的到来变得好了起来,ES6提供了<code>class</code>、<code>extends</code>等语法糖可以帮你摆脱让人苦闷的原型(当然,如果你有高追求,你得理解),虽然JS的OOP的实现原理还是通过原型的,但是至少对开发者的友好性提升了很多,让JS更有OOP的味道也更接近于其他OOP的语言。现在我们也能很简单的来声明一个类:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>{</div><div class="line"> <span class="keyword">constructor</span>(name, age) {</div><div class="line"> <span class="keyword">this</span>.name = name;</div><div class="line"> <span class="keyword">this</span>.age = age;</div><div class="line"> }</div><div class="line"></div><div class="line"> say() {</div><div class="line"> alert(<span class="string">`Hello, I am <span class="subst">${<span class="keyword">this</span>.name}</span>`</span>);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<a id="more"></a>
<p>这要是放ES5时代呢?<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">People</span>(<span class="params">name, age</span>) </span>{</div><div class="line"> <span class="keyword">this</span>.name = name;</div><div class="line"> <span class="keyword">this</span>.age = age;</div><div class="line">}</div><div class="line"></div><div class="line">People.prototype.say = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> alert(<span class="string">'Hello, I am '</span> + <span class="keyword">this</span>.name);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>两者new对象的实现方式一致:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> p = <span class="keyword">new</span> People(<span class="string">'xuqi'</span>, <span class="number">26</span>);</div><div class="line">p.say();</div></pre></td></tr></table></figure></p>
<p>对比两者的实现,可以大致了解ES6提供的类的实现细节是怎样的。</p>
<p>接下来,我们来构建一个Woman类,继承自People类,并实现<code>buy</code>方法。先看ES5的两种实现方式(PS:可结合扩展,比如添加自己的factory方法等):<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//方法一:Prototype</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">Woman</span>(<span class="params"></span>) </span>{}</div><div class="line"></div><div class="line">Woman.prototype = <span class="keyword">new</span> People();</div><div class="line"></div><div class="line">Woman.prototype.buy = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> alert(<span class="string">'双11,买买买'</span>);</div><div class="line">};</div><div class="line"></div><div class="line">Woman.prototype.constructor = Woman; <span class="comment">//修正constructor</span></div></pre></td></tr></table></figure></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//方法二:call/apply</span></div><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">Woman</span>(<span class="params">name, age</span>) </span>{</div><div class="line"> People.call(<span class="keyword">this</span>, name, age);</div><div class="line">}</div><div class="line"></div><div class="line">Woman.prototype.buy = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> alert(<span class="string">'双11,买买买'</span>);</div><div class="line">};</div></pre></td></tr></table></figure>
<p>方法一通过原型机制实现继承,设置子类的prototype为父类的一个实例化对象即可;方法二通过call,在子类的上下文环境中执行父类的构造函数即可获得父类的属性和方法。两者的方法扩展都需通过prototype去实现。</p>
<p>但是上述两种方法在例子中都有问题:通过原型的实现在绑定子类prototype为父类的实例化对象时,必须初始化父类,要不然父类的参数(name, age)就不能使用了;通过call/apply方法实现的子类的实例化对象无法使用父类绑定在prototype上的方法(say)。因此我们需要结合两者:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">function</span> <span class="title">Woman</span>(<span class="params">name, age</span>) </span>{</div><div class="line"> People.call(<span class="keyword">this</span>, name, age);</div><div class="line">}</div><div class="line"></div><div class="line">Woman.prototype = <span class="keyword">new</span> People();</div><div class="line"></div><div class="line">Woman.prototype.constructor = Woman;</div><div class="line"></div><div class="line">Woman.prototype.buy = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</div><div class="line"> alert(<span class="string">'双11,买买买'</span>);</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>再来看看ES6的继承是怎样实现的:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">Woman</span> <span class="keyword">extends</span> <span class="title">People</span> </span>{</div><div class="line"> <span class="keyword">constructor</span>(name, age) {</div><div class="line"> <span class="keyword">super</span>(name, age);</div><div class="line"> }</div><div class="line"></div><div class="line"> buy() {</div><div class="line"> alert(<span class="string">'双11,买买买'</span>);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>ES6的代码简洁明了,通过<code>extends</code>可以简单的实现类的继承。需要注意的是,子类的构造函数中需先调用<code>super()</code>从而生成一个父类的实例化对象即<code>this</code>,然后再对this进行扩展,因此在super调用前使用this会报错;在ES5中实现对象则相反,先生成子类实例化对象this,然后向this中扩展父类的方法和属性.</p>
<h3 id="扩展:"><a href="#扩展:" class="headerlink" title="扩展:"></a>扩展:</h3><ol>
<li>ES5的继承实现中为什么需要<code>Woman.prototype.constructor = Woman;</code>?<br>对象都有<code>constructor</code>属性,为一个函数,标识构造出该对象的构造函数,对象默认的constructor为<code>function Object(){...}</code>;<br>因此该问题中,若不重新制定constructor到Woman(){…},通过Woman实例化出来的对象的constructor = Woman.prototype.constructor = (new People()).constructor = People(){…}。这显然不是我们想看到的。</li>
<li><p>ES5中父类和子类的关系到底是怎样串联起来的?<br>构造两条<strong>继承链</strong>:<br>(1)实例继承<br>(2)构造函数继承/静态属性方法继承<br>实现模式:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//实例继承</span></div><div class="line"><span class="built_in">Object</span>.setPrototypeOf(Sub.prototype, Parent.prototype);</div><div class="line"><span class="comment">//等同于</span></div><div class="line">Sub.prototype.__proto__ = Parent.prototype;</div><div class="line"></div><div class="line"><span class="comment">//构造函数继承</span></div><div class="line"><span class="built_in">Object</span>.setPrototypeOf(Sub, Parent);</div><div class="line"><span class="comment">//等同于</span></div><div class="line">Sub.__proto__ = Parent;</div></pre></td></tr></table></figure>
</li>
<li><p>在ES5的例子中,我们通过<code>Woman.prototype = new People();</code>实现了实例继承,推导式:Woman.prototype.__proto__ = (new People()).__proto__ = People.prototype;根据2,我们可以完善上述ES5的继承的实现–补充构造函数的继承,添加如下代码:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="built_in">Object</span>.setPrototypeOf ?</div><div class="line"> <span class="built_in">Object</span>.setPrototypeOf(Woman, People) :</div><div class="line"> Woman.__proto__ = People;</div></pre></td></tr></table></figure>
</li>
<li><p>完整的继承实现后,我们可以得到如下等式:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> sub = <span class="keyword">new</span> Sub();</div><div class="line"></div><div class="line"><span class="comment">//true</span></div><div class="line">sub.__proto__ === Sub.prototype;</div><div class="line">sub.constructor === Sub;</div><div class="line"></div><div class="line">sub <span class="keyword">instanceof</span> Sub;</div><div class="line">sub <span class="keyword">instanceof</span> Parent;</div><div class="line">Sub.prototype <span class="keyword">instanceof</span> Parent;</div><div class="line"></div><div class="line">Parent.prototype.constructor === Parent;</div><div class="line"></div><div class="line"><span class="built_in">Object</span>.getPrototypeOf(Sub) === Parent;</div></pre></td></tr></table></figure>
</li>
</ol>
<p>附:<br><img src="https://dn-xuqi.qbox.me/proto.jpg" alt="原型原理图"></p>
]]></content>
<summary type="html">
<p>Javascript可能是一门让人感觉“不适”的语言,实现<code>类</code>、<code>继承</code>等OOP概念竟然要通过<code>function</code>和<code>prototype</code>,Jser们可能理解原型机制就能伤半管子HP了。然而,这种情况随着ES6的到来变得好了起来,ES6提供了<code>class</code>、<code>extends</code>等语法糖可以帮你摆脱让人苦闷的原型(当然,如果你有高追求,你得理解),虽然JS的OOP的实现原理还是通过原型的,但是至少对开发者的友好性提升了很多,让JS更有OOP的味道也更接近于其他OOP的语言。现在我们也能很简单的来声明一个类:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="class"><span class="keyword">class</span> <span class="title">People</span> </span>&#123;</div><div class="line"> <span class="keyword">constructor</span>(name, age) &#123;</div><div class="line"> <span class="keyword">this</span>.name = name;</div><div class="line"> <span class="keyword">this</span>.age = age;</div><div class="line"> &#125;</div><div class="line"></div><div class="line"> say() &#123;</div><div class="line"> alert(<span class="string">`Hello, I am <span class="subst">$&#123;<span class="keyword">this</span>.name&#125;</span>`</span>);</div><div class="line"> &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
</summary>
<category term="Js Basic" scheme="http://www.i0011.com/tags/Js-Basic/"/>
<category term="Es6" scheme="http://www.i0011.com/tags/Es6/"/>
<category term="OOP" scheme="http://www.i0011.com/tags/OOP/"/>
</entry>
<entry>
<title>respondjs-proxy</title>
<link href="http://www.i0011.com/2016/01/08/respond-proxy/"/>
<id>http://www.i0011.com/2016/01/08/respond-proxy/</id>
<published>2016-01-08T02:47:43.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p><strong>respond.js</strong>用来解决IE9以下不支持媒体查询的问题。</p>
<p>在静态资源(CSS)和网站在同一域名的情况下使用起来很简单:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"path/to/cssfile.css"</span>></span></div><div class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"path/to/respond.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure></p>
<p>引入HTML并置于css文件引用位置之后即可。<br><a id="more"></a><br>然而大部分情况下并非如此,静态资源都会放在cdn上进行访问加速,这样就产生了域名不一致而导致respondjs在跨域的情况下失效的问题。Github上作者对该<a href="https://github.com/scottjehl/Respond#cdnx-domain-setup" target="_blank" rel="external">问题</a>的产生给出了阐述,感兴趣的可以去看下。<a href="https://github.com/scottjehl/Respond/tree/master/cross-domain" target="_blank" rel="external">代码</a>中也给出了解决示例。此处给出解决方法:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">link</span> <span class="attr">href</span>=<span class="string">"path/to/respond-proxy.html"</span> <span class="attr">id</span>=<span class="string">"respond-proxy"</span> <span class="attr">rel</span>=<span class="string">"respond-proxy"</span> /></span></div><div class="line"><span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"path/to/respond.proxy.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></div><div class="line"><span class="tag"><<span class="name">link</span> <span class="attr">href</span>=<span class="string">"path/to/respond.proxy.gif"</span> <span class="attr">id</span>=<span class="string">"respond-redirect"</span> <span class="attr">rel</span>=<span class="string">"respond-redirect"</span> /></span></div></pre></td></tr></table></figure></p>
<p>再加载上述三行代码到HTML中即可。需要注意的是<code>respond-proxy.html</code>需要与静态资源放在同一域名下。</p>
<p>Enjoy it~</p>
]]></content>
<summary type="html">
<p><strong>respond.js</strong>用来解决IE9以下不支持媒体查询的问题。</p>
<p>在静态资源(CSS)和网站在同一域名的情况下使用起来很简单:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"stylesheet"</span> <span class="attr">href</span>=<span class="string">"path/to/cssfile.css"</span>&gt;</span></div><div class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">"path/to/respond.js"</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></div></pre></td></tr></table></figure></p>
<p>引入HTML并置于css文件引用位置之后即可。<br>
</summary>
<category term="IE8" scheme="http://www.i0011.com/tags/IE8/"/>
<category term="Solution" scheme="http://www.i0011.com/tags/Solution/"/>
</entry>
<entry>
<title>REM是个坑,精确控制不适合</title>
<link href="http://www.i0011.com/2015/06/18/bad-rem/"/>
<id>http://www.i0011.com/2015/06/18/bad-rem/</id>
<published>2015-06-18T06:56:05.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p>前两天需要做一个涂鸦的活动页面,来瞅瞅<img src="https://dn-xuqi.qbox.me/yoho-q1.png" alt="年中大促"><br><a id="more"></a><br>简要介绍下这个页面,就是一个ABC选择,选中某项后加红色区分然后右侧动画闪动。<em>[图片版权声明:版权归YOHO所有]</em></p>
<p>拿到这个页面第一反应就是好*蛋啊,就是个图片页面了然后需要点击的地方就绝对定位一个div盖在上面。考虑是手机端的页面,那就可以使用REM神器了:</p>
<ol>
<li><p>加上脚本</p>
<pre><code>(function (doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function () {
var clientWidth = docEl.clientWidth;
if (!clientWidth) {
return;
}
docEl.style.fontSize = 20 * (clientWidth / 320) + 'px';
};
if (!doc.addEventListener) {
return;
}
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</code></pre></li>
<li>使用方法<br>css中原来用px的换成rem就可以了,40px = 1rem</li>
<li>脚本根据屏幕尺寸会在html元素上生成个font-size的样式,然后页面渲染时都会根据这个值和rem的数值等比例生成对应屏幕的尺寸或者位置。</li>
</ol>
<p>大体功能都能满足,但是在进行选项图标200ms每帧切换的时候却出现了问题,会抖动,那找原因就是通过雪碧图切换background-position位置不准咯,而且在各个手机上不同的选项各有抖动与不抖动的情况。</p>
<p>就是使用rem的原因,不同的屏幕生成的根font-size不一样然后计算后就会出现定位不准的问题了,最后还是换成了直接切换background-image了,雪碧图用不了。(ps:如果用rem可以实现请告诉我…)</p>
<p>另外这个页面还有另外一个情况,看到会有选中项的颜色区分。最开始做的时候是把整个图片除掉选项右边的小图标(图标会有动画实现因此时单独的)作为底图然后选中后就在对应项上面加一个有颜色的div。事实肯定不如所意了,文字和ABC会被盖住….最后的解决办法是:灰色的底图单独是一层作为最底层,然后页面图片去底图在最上面,选中时的颜色div放在两层中间就可以了…但是这样对上层图切的要求就高了,要不然你会发现边边角角全是白色的锯齿。</p>
]]></content>
<summary type="html">
<p>前两天需要做一个涂鸦的活动页面,来瞅瞅<img src="https://dn-xuqi.qbox.me/yoho-q1.png" alt="年中大促"><br>
</summary>
<category term="Solution" scheme="http://www.i0011.com/tags/Solution/"/>
<category term="CSS" scheme="http://www.i0011.com/tags/CSS/"/>
</entry>
<entry>
<title>Handlebars使用指南</title>
<link href="http://www.i0011.com/2015/04/30/handlebars/"/>
<id>http://www.i0011.com/2015/04/30/handlebars/</id>
<published>2015-04-30T09:49:41.000Z</published>
<updated>2016-11-25T00:34:34.000Z</updated>
<content type="html"><![CDATA[<p><a href="http://handlebarsjs.com/" target="_blank" rel="external">Handlebars</a>为Mustache的超集,即:在完全兼容Mustache语法的基础上,提供了很多语法糖,不要太甜…</p>
<h2 id="Begin-Now"><a href="#Begin-Now" class="headerlink" title="Begin Now"></a>Begin Now</h2><h3 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h3><p>这里我们只介绍一些Handlebars中相对于Mustache超集的部分,若不了解Mustache,请<a href="http://i0011.com/2015/04/30/Mustache%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/" target="_blank" rel="external">移步</a><br><a id="more"></a></p>
<h3 id="Expressions"><a href="#Expressions" class="headerlink" title="Expressions"></a>Expressions</h3><p>表达式就是{{}}里面包的东西,Handlebars中语法的最小单位。{{xx}}表示在<strong>当前上下文环境</strong>中去寻找xx属性,并用xx属性的值去替换之。Handlebars支持<code>.</code>分隔的属性{{xx.yy}},但在有的情况下<code>.</code>不能解决我们的问题,比如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div></pre></td><td class="code"><pre><div class="line">data = {</div><div class="line"> <span class="attr">articles</span>: [</div><div class="line"> {</div><div class="line"> <span class="string">'#comments'</span>: {</div><div class="line"> <span class="attr">author</span>: <span class="string">'dabai'</span>,</div><div class="line"> <span class="attr">date</span>: <span class="string">'2015.4.30'</span></div><div class="line"> }</div><div class="line"> },</div><div class="line"> {</div><div class="line"> <span class="string">'#comments'</span>: [</div><div class="line"> {</div><div class="line"> <span class="attr">author</span>: <span class="string">'xuqi'</span>,</div><div class="line"> <span class="attr">date</span>: <span class="string">'2015.4.30'</span></div><div class="line"> },</div><div class="line"> {</div><div class="line"> <span class="attr">author</span>: <span class="string">'xuqi-two'</span>,</div><div class="line"> <span class="attr">date</span>: <span class="string">'2015.4.30'</span></div><div class="line"> },</div><div class="line"> {</div><div class="line"> <span class="attr">author</span>: <span class="string">'xuqi-three'</span>,</div><div class="line"> <span class="attr">date</span>: <span class="string">'2015.4.30'</span></div><div class="line"> },</div><div class="line"> ...</div><div class="line"> ],</div><div class="line"> ...</div><div class="line"> }</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>需要渲染articles数组第2项的’#comments’的数据,我们用<code>.</code>怎么分隔?<code>articles.2.#comments</code>?…呵呵哒…跟js一样嘛,我们可以用<code>[]</code>:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">{{# each articles.[10].[#comment]}}</div><div class="line"> <span class="tag"><<span class="name">h1</span>></span>{{author}}{{date}}<span class="tag"></<span class="name">h1</span>></span></div><div class="line">{{/ each}}</div></pre></td></tr></table></figure></p>
<p>上述这种情况在需要取数据某一元素或者渲染的属性名不是合理的Handlebars标识名时适用。</p>
<h3 id="Helper"><a href="#Helper" class="headerlink" title="Helper"></a>Helper</h3><p>Handlebars中可以让我们体验飞一般感觉的重量级语法糖,精华所在,可以帮助我们现在前段时间因为使用简单Mustache语法而引入的很多不必要的数据嵌套的问题,我们可以用<code>if</code>了,可以用<code>each</code>了,可以自定义了Helper了~欢呼雀跃吧….好吧,冷静,回归正题。</p>
<p>先从一个例子引入,然后逐步强化,里面有干货:<br>Level1:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">//tpl</div><div class="line">{{link 'http://www.baidu.com' '百度'}}</div><div class="line"></div><div class="line">//helper</div><div class="line">Handlebars.registerHelper('link', function(url, name) {</div><div class="line"> return '<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"' + url + '"</span>></span>' + name + '<span class="tag"></<span class="name">a</span>></span>';</div><div class="line">});</div></pre></td></tr></table></figure></p>
<p>Level2:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">//tpl</div><div class="line">{{link site}}</div><div class="line"> </div><div class="line">//helper</div><div class="line">Handlebars.registerHelper('link', function(site) {</div><div class="line"> return '<span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"' + site.url + '"</span>></span>' + site.name + '<span class="tag"></<span class="name">a</span>></span>'</div><div class="line">});</div><div class="line"> </div><div class="line">//data</div><div class="line">{</div><div class="line"> site: {</div><div class="line"> url: 'http://www.baidu.com',</div><div class="line"> name: '百度'</div><div class="line"> }</div><div class="line">};</div></pre></td></tr></table></figure></p>
<p>Level3:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">//tpl</div><div class="line">{{link '百度' url='http://www.baidu.com' class='site'}}</div><div class="line"></div><div class="line">//helper</div><div class="line">Handlebars.registerHelper('link', function(name, options) {</div><div class="line"> var attrs = [],</div><div class="line"> prop;</div><div class="line"> for (prop in options.hash) {</div><div class="line"> attrs.push(prop + '="' + options.hash[prop] + '"');</div><div class="line"> }</div><div class="line"> </div><div class="line"> return '<span class="tag"><<span class="name">a</span> ' + <span class="attr">attrs.join</span>(' ') + '></span>' + name + '<span class="tag"></<span class="name">a</span>></span>'</div><div class="line">});</div></pre></td></tr></table></figure></p>
<p>上述三个等级分别演示了Helper中参数传递的方法的功能递进, 下面介绍两个Handlebars的API为Helper打辅助:<code>Handlebars.SafeString()</code> 和 <code>Handlebars.escapeExpression()</code>。 </p>
<p>Helper返回的HTML字符串会被默认转义, 显示在界面上的只是文本节点而不是元素节点。所以, 对于这种自定义的Helper, 因为我们能确保返回的字符串是安全的, 因此我们需要告诉编译器这是一个安全的字符串, 放心当成元素节点插进去吧, 使用的方法就是SafeString();<br>另外, 因为Helper函数中有输入参数而我们不能确定这些数据是否含有XSS脚本, 如此那我们便手动将你转化成安全的字符串吧, 如此escapeExpression()的用法也自然就知晓了, 现在用这两个方法完善下上述Level3的Helper的例子:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">Handlebars.registerHelper(<span class="string">'link'</span>, <span class="function"><span class="keyword">function</span>(<span class="params">name, options</span>) </span>{</div><div class="line"> <span class="keyword">var</span> attrs = [],</div><div class="line"> prop;</div><div class="line"> <span class="keyword">for</span> (prop <span class="keyword">in</span> options.hash) {</div><div class="line"> attrs.push(</div><div class="line"> Handlebars.escapeExpression(prop) +<span class="string">'="'</span> +</div><div class="line"> Handlebars.escapeExpression(options.hash[prop]) + <span class="string">'"'</span></div><div class="line"> );</div><div class="line"> }</div><div class="line"> </div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> Handlebars.SafeString(<span class="string">'<a '</span> + attrs.join(<span class="string">' '</span>) + <span class="string">'>'</span> +</div><div class="line"> Handlebars.escapeExpression(name) + <span class="string">'</a>'</span>);</div><div class="line">});</div></pre></td></tr></table></figure></p>
<p>Level4:BLOCK-Heplers<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">{{#bold}}</div><div class="line"> My name is {{name}}</div><div class="line">{{/bold}}</div><div class="line"></div><div class="line">Handlebars.registerHelper('bold', function(options) {</div><div class="line"> return new Handlebars.SafeString('<span class="tag"><<span class="name">b</span>></span>' + options.fn(this) + '<span class="tag"></<span class="name">b</span>></span>');</div><div class="line">});</div><div class="line"></div><div class="line">{name: 'xuqi'}</div></pre></td></tr></table></figure></p>
<p>可以看到跟上述三个步骤中的Tpl不一样,这次好像不是简单的代码替换了,因为Helper变成了一个区块,区块中还有内容, 那该怎么办?注意本例中我需要一个文字加粗的功能,在返回字符串中我加了<code><b></code>标签实现加粗,中间那个options.fn(this)是干啥的?</p>
<p>前面讲了<code><b></code>实现了加粗,那加粗总该有个对象吧,也就是My name is {{name}};<br>那我也总不能直接把这个模板字符串给加粗输出吧,我得编译然后根据上下文环境的属性值name去生成My name is xuqi。所以呢,option.fn的功能就自然出来了,就是在this上下文中执行编译Block中的模板并填充数据得到HTML片段。<br>而this就是Block Helper执行的当前上下文环境。 </p>
<p>另外,可以通过this取得当前上下文的属性值手动进行某些操作,比如可以通过this.name获取name的属性值为xuqi。</p>
<h4 id="Ps-一些有用的Build-In-Helper"><a href="#Ps-一些有用的Build-In-Helper" class="headerlink" title="Ps: 一些有用的Build-In Helper"></a>Ps: 一些有用的Build-In Helper</h4><ul>
<li>{{#each arg}}
<p>循环内可以通过{{@index}}获取当前的循环的索引, 通过{{@../index}}可以获得父级遍历的索引;<br>{{@key}}可以获取当前遍历的数组或者对象的键值,数组中等同于{{@index}};<br>{{@first}},{{@last}}表示遍历中的第一个和最后一个的标识,返回true或false;<br>each可选择性插入{{else}}, 在遍历的list为<strong>空</strong>(遍历对象为非空数组或者对象时不为空值)时执行。</p>
</li>
<li>{{#if condition}} or {{else}} or {{else if conditionElse}}
</li>
<li>{{#unless condition}} inverse of the `if` helper
</li>
<li>{{#with ctx}}
<p>与Js的with一样,改变当前context,可以避免含有深层次嵌套属性时重复书写父级的名字</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">//tpl</div><div class="line"><span class="tag"><<span class="name">h1</span>></span>{{title}}<span class="tag"></<span class="name">h1</span>></span></div><div class="line">{{#with story}}</div><div class="line"> <span class="tag"><<span class="name">div</span>></span>{{intro}}<span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span>></span>{{body}}<span class="tag"></<span class="name">div</span>></span></div><div class="line">{{else}}</div><div class="line"> {{!-- 可选择性插入else,仅当story为false值时渲染 --}}</div><div class="line"> <span class="tag"><<span class="name">div</span>></span>I am Empty<span class="tag"></<span class="name">div</span>></span></div><div class="line">{{/with}}</div><div class="line"> </div><div class="line">//data</div><div class="line">{</div><div class="line"> title: 'Hello world',</div><div class="line"> story: {</div><div class="line"> intro: 'Before the jump',</div><div class="line"> body: 'After the jump'</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li>{{lookup context key}} 获取动态参数进行渲染,相当于获取context.key的值,看例子会容易理解点:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"></div><div class="line">//tpl</div><div class="line">{{#each names}}</div><div class="line"> {{.}} : {{lookup ../foo @key}}</div><div class="line">{{/each}}</div><div class="line"> </div><div class="line">//data</div><div class="line">{</div><div class="line"> names: {</div><div class="line"> a: 'Name1',</div><div class="line"> b: 'Name2',</div><div class="line"> c:'Name3'</div><div class="line"> },</div><div class="line"> foo: {</div><div class="line"> a: 'Foo1',</div><div class="line"> b: 'Foo2',</div><div class="line"> c: 'Foo3'</div><div class="line"> }</div><div class="line">}</div><div class="line"> </div><div class="line">//output</div><div class="line">Name1 :Foo1</div><div class="line">Name2 :Foo2</div><div class="line">Name3 :Foo3</div></pre></td></tr></table></figure>
</li>
<li><p>{{log info}} 打印调试</p>
</li>
</ul>
<h3 id="Partials"><a href="#Partials" class="headerlink" title="Partials"></a>Partials</h3><p>Handlebars.registerPartial(‘parName’, ‘parContent’); 注册一个Partials;</p>
<p>需要调用Partials时{{> parName}}即可。</p>
<p>调用Partials时也可以传入参数:{{> parName parContext}}指定Partials的执行上下文;{{> parName attr=val}}</p>
<h3 id="Path"><a href="#Path" class="headerlink" title="Path"></a>Path</h3>{{xx}}中的xx可以不只是我们熟悉的一个属性的名字,或是xx.yy这样的嵌套路径。也能支持<code>../</code>这样的父级上下文环境和<code>./</code>这样的当前上下文环境的语法啦,来个例子:<br><br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">//tpl</div><div class="line">{{# nest}}</div><div class="line"> {{../hello}}</div><div class="line">{{/ nest}}</div><div class="line"></div><div class="line">//data</div><div class="line">{</div><div class="line"> nest: [</div><div class="line"> ...</div><div class="line"> ],</div><div class="line"> hello: 'I am Hello'</div><div class="line">}</div></pre></td></tr></table></figure>
<p>./是用来解决Helper名字和属性名重名的冲突的情况,例如./xx表示的是属性名而不是Helper名。另外this/name和this.name也实现相同的功能。</p>
<p>当然啦, 如果嵌套层级很深, 而我想访问到根作用域的时候是不是要写成<code>../../..</code>这样呢? 是不是sa! 那该咋办? Handlebars提供了一个@root变量轻轻松松访问到根作用域:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">{{#each sub}}</div><div class="line"> {{@root.someAttr}}</div><div class="line">{{/each}}</div></pre></td></tr></table></figure></p>
<h3 id="Comments"><a href="#Comments" class="headerlink" title="Comments"></a>Comments</h3><p>{{!-- --}}和{{! }}不会将注释内容输出到HTML中,如果想输出注释到HTML中可以使用HTML的注释语法<code><!-- --></code>。另外,如果注释中有}},则必须使用{{!-- --}}。</p>
<h2 id="后语"><a href="#后语" class="headerlink" title="后语"></a>后语</h2><p>上面讲的只是一些基本用法,冰山一角,官网上面还有很多文章中没有提及但是也许会给你的不一样的快感的功能。Helper的实现方式需要着重理解,几个Build-In Helper在官网上都提供了Helper实现方式,明白思想->模仿实现->定义自己的Helper实现特定的功能,go ~</p>
]]></content>
<summary type="html">
<p><a href="http://handlebarsjs.com/">Handlebars</a>为Mustache的超集,即:在完全兼容Mustache语法的基础上,提供了很多语法糖,不要太甜…</p>
<h2 id="Begin-Now"><a href="#Begin-Now" class="headerlink" title="Begin Now"></a>Begin Now</h2><h3 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h3><p>这里我们只介绍一些Handlebars中相对于Mustache超集的部分,若不了解Mustache,请<a href="http://i0011.com/2015/04/30/Mustache%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/">移步</a><br>
</summary>
<category term="HandBook" scheme="http://www.i0011.com/tags/HandBook/"/>
</entry>
<entry>
<title>Mustache使用指南</title>
<link href="http://www.i0011.com/2015/04/30/mustache/"/>