-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
3251 lines (3078 loc) · 688 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
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>YeaseonZhang</title>
<link href="/atom.xml" rel="self"/>
<link href="https://yeaseonzhang.github.io/"/>
<updated>2017-12-17T09:12:49.578Z</updated>
<id>https://yeaseonzhang.github.io/</id>
<author>
<name>Yeaseon</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>高效JavaScript 68诫</title>
<link href="https://yeaseonzhang.github.io/2017/12/17/%E9%AB%98%E6%95%88JavaScript-68%E8%AF%AB/"/>
<id>https://yeaseonzhang.github.io/2017/12/17/高效JavaScript-68诫/</id>
<published>2017-12-17T09:07:09.000Z</published>
<updated>2017-12-17T09:12:49.578Z</updated>
<content type="html"><![CDATA[<p>将《编写高质量JavaScript代码的68个有效方法》书中提到的68个方法分享给大家。</p>
<h3 id="让自己习惯JavaScript"><a href="#让自己习惯JavaScript" class="headerlink" title="让自己习惯JavaScript"></a>让自己习惯<code>JavaScript</code></h3><ol>
<li>了解你使用的JavaScript版本</li>
<li>理解JavaScript的浮点数</li>
<li>当心隐式的强制转换</li>
<li>原始类型优于封装对象</li>
<li>避免对混合类型使用<code>==</code>运算符</li>
<li>了解分号插入的局限</li>
<li>视字符串为16位的代码单元序列</li>
</ol>
<a id="more"></a>
<h3 id="变量作用域"><a href="#变量作用域" class="headerlink" title="变量作用域"></a>变量作用域</h3><ol>
<li>尽量少用全局对象</li>
<li>始终声明局部变量</li>
<li>避免使用<code>with</code></li>
<li>熟练掌握闭包</li>
<li>理解变量声明提升</li>
<li>使用立即调用的函数表达式创建局部函数</li>
<li>当心命名函数表达式笨拙的作用域</li>
<li>当心局部块函数声明笨拙的作用域</li>
<li>避免使用<code>eval</code>创建局部变量</li>
<li>间接调用<code>eval</code>函数优于直接调用</li>
</ol>
<h3 id="使用函数"><a href="#使用函数" class="headerlink" title="使用函数"></a>使用函数</h3><ol>
<li>理解函数调用、方法调用及构造函数</li>
<li>熟练掌握高阶函数</li>
<li>使用<code>call</code>方法自定义接收者来调用函数</li>
<li>使用<code>apply</code>方法通过不同数量的参数调用函数</li>
<li>使用<code>arguments</code>创建可变参数的函数</li>
<li>永远不要修改<code>arguments</code>对象</li>
<li>使用变量保存<code>arguments</code>的引用</li>
<li>使用<code>bind</code>方法提取具有确定接收者的方法</li>
<li>使用<code>bind</code>方法实现函数柯里化</li>
<li>使用闭包而不是字符串来封装代码</li>
<li>不要信赖函数对象的<code>toString</code>方法</li>
<li>避免使用非标准的栈检查属性</li>
</ol>
<h3 id="对象和原型"><a href="#对象和原型" class="headerlink" title="对象和原型"></a>对象和原型</h3><ol>
<li>理解<code>prototype</code>、<code>getPrototypeOf</code>和<code>__proto__</code>之间的不同</li>
<li>使用<code>Object.getPrototypeOf</code>函数而不要使用<code>__proto__</code>属性</li>
<li>始终不要修改<code>__proto__</code>属性</li>
<li>使构造函数与<code>new</code>操作符无关</li>
<li>在原型中存储方法</li>
<li>使用闭包存储私有数据</li>
<li>只将实例状态存储在实例对象中</li>
<li>认识到<code>this</code>变量的隐式绑定问题</li>
<li>在子类的构造函数中调用父类的构造函数</li>
<li>不要重用父类的属性名</li>
<li>避免继承标准类</li>
<li>将原型视为实现细节</li>
<li>避免使用轻率的<strong>猴子补丁</strong>(monkey-patching)</li>
</ol>
<h3 id="数组和字典"><a href="#数组和字典" class="headerlink" title="数组和字典"></a>数组和字典</h3><ol>
<li>使用<code>Object</code>的直接实例构造轻量级的字典</li>
<li>使用<code>null</code>原型以防止原型污染</li>
<li>使用数组而不要使用字典存储有序集合</li>
<li>使用<code>hasOwnProperty</code>方法以避免原型污染</li>
<li>使用数组而不要使用字典来存储有序集合</li>
<li>绝不要在<code>Object.prototype</code>中增加可枚举的属性</li>
<li>避免在枚举期间修改对象</li>
<li>数组迭代要优先使用<code>for</code>循环而不是<code>for...in</code>循环</li>
<li>迭代方法由于循环</li>
<li>在类数组对象上复用通用的数组方法</li>
<li>数组字面量优于数组构造函数</li>
</ol>
<h3 id="库和API设计"><a href="#库和API设计" class="headerlink" title="库和API设计"></a>库和API设计</h3><ol>
<li>保持一致的约定</li>
<li>将<code>undefined</code>看做“没有值”</li>
<li>接收关键字参数的选项对象</li>
<li>避免不必要的状态</li>
<li>使用结构类型设计灵活的接口</li>
<li>区分数组对象和类数组对象</li>
<li>避免过度的强制转换</li>
<li>支持方法链</li>
</ol>
<h3 id="并发"><a href="#并发" class="headerlink" title="并发"></a>并发</h3><ol>
<li>不要阻塞I/O事件队列</li>
<li>在异步序列中使用嵌套或命名的回调函数</li>
<li>当心丢弃错误</li>
<li>对异步循环使用递归</li>
<li>不要在计算时阻塞事件队列</li>
<li>使用计数器来执行并行操作</li>
<li>绝不要同步的调用异步的回调函数</li>
<li>使用<code>promise</code>模式清洁异步逻辑</li>
</ol>
]]></content>
<summary type="html">
<p>将《编写高质量JavaScript代码的68个有效方法》书中提到的68个方法分享给大家。</p>
<h3 id="让自己习惯JavaScript"><a href="#让自己习惯JavaScript" class="headerlink" title="让自己习惯JavaScript"></a>让自己习惯<code>JavaScript</code></h3><ol>
<li>了解你使用的JavaScript版本</li>
<li>理解JavaScript的浮点数</li>
<li>当心隐式的强制转换</li>
<li>原始类型优于封装对象</li>
<li>避免对混合类型使用<code>==</code>运算符</li>
<li>了解分号插入的局限</li>
<li>视字符串为16位的代码单元序列</li>
</ol>
</summary>
<category term="JavaScript" scheme="https://yeaseonzhang.github.io/tags/JavaScript/"/>
</entry>
<entry>
<title>2017年书单</title>
<link href="https://yeaseonzhang.github.io/2017/12/17/2017%E5%B9%B4%E4%B9%A6%E5%8D%95/"/>
<id>https://yeaseonzhang.github.io/2017/12/17/2017年书单/</id>
<published>2017-12-17T08:42:16.000Z</published>
<updated>2017-12-17T08:43:02.115Z</updated>
<content type="html"><![CDATA[<img src="/2017/12/17/2017年书单/library.jpg" alt="營業據點" title="營業據點">
<h1 id="2017年书单(15-12)"><a href="#2017年书单(15-12)" class="headerlink" title="2017年书单(15/12)"></a>2017年书单(15/12)</h1><p>去年计划读12本书,很显然没有完成任务。2017年继续“12本书计划”。</p>
<p>“人丑就该多读书”其实只是前半句,后半句是“不丑多读书也没坏处”。</p>
<a id="more"></a>
<ol>
<li>《你不知道的JavaScript·上卷》 于 #2017.3.16# 读完</li>
<li>《万物简史》 于 #2017.3.17# 读完</li>
<li>《我脑袋里的怪东西》 于 #2017.4.12# 读完</li>
<li>《JavaScript高级程序设计》 于 #2017.4.26# 读完</li>
<li>《你不知道的JavaScript·中卷》 于 #2017.4.29# 读完</li>
<li>《二手时间》 于 #2017.5.11# 读完</li>
<li>《CSS设计指南》 于 #2017.5.14# 读完</li>
<li>《JavaScript语言精粹》 于 #2017.5.26# 读完</li>
<li>《拖延心理学》 于 #2017.6.1# 读完</li>
<li>《CSS揭秘》 于 #2017.6.25# 读完</li>
<li>《极简宇宙史》 于 #2017.6.26# 读完</li>
<li>《巨人的陨落》 于 #2017.7.22# 读完</li>
<li>《Node即学即用》 于 #2017.8.28# 读完</li>
<li>《灰犀牛》 于 #2017.9.25# 读完</li>
<li>《编写高质量JavaScript代码的68个有效方法》 于 #2017.12.17# 读完</li>
</ol>
<p>持续更新…</p>
]]></content>
<summary type="html">
<img src="/2017/12/17/2017年书单/library.jpg" alt="營業據點" title="營業據點">
<h1 id="2017年书单(15-12)"><a href="#2017年书单(15-12)" class="headerlink" title="2017年书单(15/12)"></a>2017年书单(15/12)</h1><p>去年计划读12本书,很显然没有完成任务。2017年继续“12本书计划”。</p>
<p>“人丑就该多读书”其实只是前半句,后半句是“不丑多读书也没坏处”。</p>
</summary>
<category term="阅读" scheme="https://yeaseonzhang.github.io/tags/%E9%98%85%E8%AF%BB/"/>
</entry>
<entry>
<title>Promise深入理解</title>
<link href="https://yeaseonzhang.github.io/2017/12/07/Promise%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3/"/>
<id>https://yeaseonzhang.github.io/2017/12/07/Promise深入理解/</id>
<published>2017-12-07T08:48:57.000Z</published>
<updated>2017-12-11T13:40:23.383Z</updated>
<content type="html"><![CDATA[<h2 id="什么是Promise"><a href="#什么是Promise" class="headerlink" title="什么是Promise"></a>什么是<strong>Promise</strong></h2><p><strong>Promise</strong>的核心理念是一个异步操作的结果,<strong>Promise</strong>包含两部分</p>
<ul>
<li><code>[[PromiseStates]]</code></li>
<li><code>[[PromiseValue]]</code></li>
</ul>
<p><strong>Promise</strong>状态三种可能:</p>
<ul>
<li><code>pending</code>: 悬而未决</li>
<li><code>resolved</code>: 决定</li>
<li><code>rejected</code>: 拒绝</li>
</ul>
<img src="/2017/12/07/Promise深入理解/state.png" alt="Promise状态" title="Promise状态">
<a id="more"></a>
<h2 id="异步性"><a href="#异步性" class="headerlink" title="异步性"></a>异步性</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> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="string">'success'</span>);</div><div class="line">});</div><div class="line"></div><div class="line">p.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(<span class="string">'Called first ?'</span>);</div></pre></td></tr></table></figure>
<p><strong>Promise</strong>的<code>then()</code>具有异步性,当执行到<code>.then()</code>部分,这部分会自动进入到<strong>Promise</strong>的异步事件队列,不会阻塞同步代码的执行,所以<code>Called first?</code>先输出。</p>
<blockquote>
<p>输出结果</p>
</blockquote>
<figure class="highlight plain"><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">Called first ?</div><div class="line">success</div></pre></td></tr></table></figure>
<h2 id="立即执行性"><a href="#立即执行性" class="headerlink" title="立即执行性"></a>立即执行性</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><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'Create a promise'</span>);</div><div class="line"> resolve(<span class="string">'success'</span>);</div><div class="line">});</div><div class="line"></div><div class="line">p.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(<span class="string">'After new Promise'</span>);</div></pre></td></tr></table></figure>
<p>从<strong>Promise</strong>的<strong>异步性</strong>,我们可以推断出,<code>After new Promise</code>,会先于<code>then()</code>方法中的输出。同时<strong>Promise</strong>的<strong>立即执行性</strong>,定义了<code>promise</code>定义的同时就会立即执行,并不依赖于<code>then()</code>的调用。而且与函数明显不同,函数需要主动调用才会执行。</p>
<blockquote>
<p>输出结果</p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line">Create a promise</div><div class="line">After new Promise</div><div class="line">success</div></pre></td></tr></table></figure>
<h2 id="Promise的状态"><a href="#Promise的状态" class="headerlink" title="Promise的状态"></a>Promise的状态</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><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> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="number">1</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">const</span> p2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> resolve(<span class="number">2</span>);</div><div class="line"> }, <span class="number">500</span>);</div><div class="line">});</div><div class="line"><span class="keyword">const</span> p3 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> reject(<span class="number">3</span>);</div><div class="line"> }, <span class="number">500</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(p1);</div><div class="line"><span class="built_in">console</span>.log(p2);</div><div class="line"><span class="built_in">console</span>.log(p3);</div><div class="line"></div><div class="line">setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2-setTimeout:'</span>, p2);</div><div class="line">}, <span class="number">501</span>);</div><div class="line"></div><div class="line">setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p3-setTimeout:'</span>, p3);</div><div class="line">}, <span class="number">501</span>);</div><div class="line"></div><div class="line">p1.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1-then:'</span>, value);</div><div class="line">});</div><div class="line"></div><div class="line">p2.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2-then:'</span>, value);</div><div class="line">});</div><div class="line"></div><div class="line">p3.catch(<span class="function">(<span class="params">err</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p3-catch'</span>, err);</div><div class="line">});</div></pre></td></tr></table></figure>
<p>当<strong>Promise</strong>创建完成时,处于 <em>pending</em> 状态;<br>当<strong>Promise</strong>执行了<code>resolve</code>方法,<strong>Promise</strong>对象的状态会变成 <em>resolved</em> 状态;<br>当<strong>Promise</strong>执行了<code>reject</code>方法,<strong>Promise</strong>对象的状态会变成 <em>rejected</em> 状态;</p>
<img src="/2017/12/07/Promise深入理解/timeline.png" alt="执行顺序" title="执行顺序">
<blockquote>
<p>先输出</p>
</blockquote>
<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">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="number">1</span>}</div><div class="line"><span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"pending"</span>, [[PromiseValue]]: <span class="literal">undefined</span>}</div><div class="line"><span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"pending"</span>, [[PromiseValue]]: <span class="literal">undefined</span>}</div></pre></td></tr></table></figure>
<blockquote>
<p>然后输出</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">p1-then: 1</div></pre></td></tr></table></figure>
<p>500ms之后,<code>p2</code>和<code>p3</code>的<strong>Promise</strong>状态被执行,<code>then</code>被触发,输出:<br><figure class="highlight plain"><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">p2-then: 2</div><div class="line">p3-catch 3</div></pre></td></tr></table></figure></p>
<blockquote>
<p>最后会输出:</p>
</blockquote>
<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">p2-setTimeout: <span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="number">2</span>}</div><div class="line">p3-setTimeout: <span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"rejected"</span>, [[PromiseValue]]: <span class="number">3</span>}</div></pre></td></tr></table></figure>
<h2 id="状态不可逆性"><a href="#状态不可逆性" class="headerlink" title="状态不可逆性"></a>状态不可逆性</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><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> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="string">'p1 success 1'</span>);</div><div class="line"> resolve(<span class="string">'p1 success 2'</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">const</span> p2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="string">'p2 success'</span>);</div><div class="line"> reject(<span class="string">'p2 reject'</span>);</div><div class="line">});</div><div class="line"></div><div class="line">p1.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line">});</div><div class="line"></div><div class="line">p2.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(err);</div><div class="line">});</div></pre></td></tr></table></figure>
<p><strong>Promise</strong>一旦变成<code>resolved</code>或是<code>rejected</code>,这个状态就不能再次变化,这就是<strong>Promise</strong>的不可逆性。</p>
<blockquote>
<p>输出</p>
</blockquote>
<figure class="highlight plain"><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">p1 success 1</div><div class="line">p2 success</div></pre></td></tr></table></figure>
<h2 id="链式调用"><a href="#链式调用" class="headerlink" title="链式调用"></a>链式调用</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><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> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">(resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="number">1</span>);</div><div class="line">}));</div><div class="line"></div><div class="line">p.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line"> <span class="keyword">return</span> value * <span class="number">2</span>;</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.resolve(<span class="string">'resolve'</span>);</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(value);</div><div class="line"> <span class="keyword">return</span> <span class="built_in">Promise</span>.reject(<span class="string">'reject'</span>);</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'resolve: '</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'reject: '</span>, err);</div><div class="line">});</div></pre></td></tr></table></figure>
<p><strong>Jquery</strong>对象链式调用是执行<code>jquery</code>方法之后,会继续返回<code>jquery</code>对象;类似这个原理,<strong>Promise</strong>对象的<code>then</code>方法会返回一个新的<code>Promise对象</code>,这样就可以继续调用<code>then</code>方法。同样<code>then</code>方法中的两个参数还是<code>fulfilled</code>对象和<code>rejected</code>对象。</p>
<img src="/2017/12/07/Promise深入理解/chain.png" alt="链式调用" title="链式调用">
<p>当<code>return</code>一个值或者<code>Promise.resolve()</code>时,状态为 <em>resolved</em><br>当<code>throw</code>一个异常或者<code>return</code> <code>Promise.reject()</code>,状态为 <em>rejected</em></p>
<p><strong>注</strong>: 当<code>then()</code>方法中没有<code>return</code>时,会默认返回<code>undefined</code>,状态为 <em>resolved</em></p>
<blockquote>
<p>输出</p>
</blockquote>
<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">1</div><div class="line">2</div><div class="line">undefined</div><div class="line">resolve</div><div class="line">reject: reject</div></pre></td></tr></table></figure>
<h2 id="Promise中的异常处理"><a href="#Promise中的异常处理" class="headerlink" title="Promise中的异常处理"></a>Promise中的异常处理</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><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> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> foo.bar();</div><div class="line"> resolve(<span class="number">1</span>);</div><div class="line">});</div><div class="line"></div><div class="line">p1.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1 then value: '</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1 then err: '</span>, err);</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1 then then value: '</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1 then then err: '</span>, err);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">var</span> p2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="number">2</span>);</div><div class="line">});</div><div class="line"></div><div class="line">p2.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then value: '</span>, value);</div><div class="line"> foo.bar();</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then err: '</span>, err);</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then then value: '</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then then err: '</span>, err);</div><div class="line"> <span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">}).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then then then value: '</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 then then then err: '</span>, err);</div><div class="line">});</div></pre></td></tr></table></figure>
<p><strong>Promise</strong>中的异常会交给<code>then</code>方法中的第二个回调函数处理,一旦处理完成,会继续返回一个<code>Promise</code>对象给后续<code>then</code>方法。</p>
<p>可以看到输出是<code>p1</code>和<code>p2</code>交替输出的,这个并不一定是交替输出,取决于执行情况,也可能是<code>p2</code>先输出。</p>
<blockquote>
<p>输出</p>
</blockquote>
<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">p1 then err: ReferenceError: foo is not defined</div><div class="line">p2 then value: 2</div><div class="line">p1 then then value: undefined</div><div class="line">p2 then then err: ReferenceError: foo is not defined</div><div class="line">p2 then then then value: 1</div></pre></td></tr></table></figure>
<h2 id="Promise-resolve"><a href="#Promise-resolve" class="headerlink" title="Promise.resolve()"></a>Promise.resolve()</h2><p><code>Promise.resolve()</code>语法:</p>
<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="built_in">Promise</span>.resolve(value);</div></pre></td></tr></table></figure>
<ul>
<li><code>value</code>: 用来解析待返回<code>promise</code>对象的参数,既可以是一个<code>promise</code>对象,也可以是一个<code>thenable</code>(即带有<code>then</code>方法)。</li>
</ul>
<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">const</span> p1 = <span class="built_in">Promise</span>.resolve(<span class="number">1</span>);</div><div class="line"><span class="keyword">const</span> p2 = <span class="built_in">Promise</span>.resolve(p1);</div><div class="line"><span class="keyword">const</span> p3 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="number">1</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">const</span> p4 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(p1);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="comment">// console.log(p1);</span></div><div class="line"><span class="comment">// console.log(p2);</span></div><div class="line"><span class="comment">// console.log(p3);</span></div><div class="line"><span class="comment">// console.log(p4);</span></div><div class="line"></div><div class="line"><span class="built_in">console</span>.log(p1 === p2);</div><div class="line"><span class="built_in">console</span>.log(p1 === p3);</div><div class="line"><span class="built_in">console</span>.log(p1 === p4);</div><div class="line"><span class="built_in">console</span>.log(p3 === p4);</div><div class="line"></div><div class="line">p4.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p4 = '</span>, value);</div><div class="line">});</div><div class="line"></div><div class="line">p2.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2 = '</span>, value);</div><div class="line">});</div><div class="line"></div><div class="line">p1.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1 = '</span>, value);</div><div class="line">})</div></pre></td></tr></table></figure>
<p><code>p1</code>: 接收了一个普通值<code>1</code>,所以会返回一个<code>resolved</code>状态的<strong>Promise</strong>对象,并且值为<code>1</code>。<br><code>p2</code>: 接收了一个promise对象<code>p1</code>,会直接返回这个promise对象。<br><code>p3</code>和<code>p4</code>: 通过<code>new</code>方式创建了一个新的promise对象。</p>
<p>所以,<code>p1 === p2</code>,<code>p3</code>和<code>p4</code>都是创建的新对象,所以自身和其他三个对象都不相等。</p>
<blockquote>
<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></pre></td><td class="code"><pre><div class="line">true</div><div class="line">false</div><div class="line">false</div><div class="line">false</div></pre></td></tr></table></figure></p>
</blockquote>
<p>但是后三个输出是:</p>
<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></pre></td><td class="code"><pre><div class="line">p2 = 1</div><div class="line">p1 = 1</div><div class="line">p4 = 1</div></pre></td></tr></table></figure>
<p>很有意思的是,明明是<code>p4</code>先执行的<code>then</code>方法,但是却是后输出的。</p>
<p>在定义完4个promise对象时,状态分别为:<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="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="number">1</span>}</div><div class="line"><span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="number">1</span>}</div><div class="line"><span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="number">1</span>}</div><div class="line"><span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"pending"</span>, [[PromiseValue]]: <span class="literal">undefined</span>}</div></pre></td></tr></table></figure></p>
<p>很明显,<code>p4</code>是<code>pending</code>状态,与其他三个不同,因为<code>p4</code>的<code>resolve</code>中接收的参数是一个promise对象<code>p1</code>,<code>resolve</code>会对<code>p1</code>进行“拆箱”操作,这个过程是异步的。</p>
<p><strong>注</strong>:把基本数据类型转换为对应的引用类型的操作称为装箱,把引用类型转换为基本的数据类型称为拆箱。</p>
<h2 id="resolve-amp-reject-的区别"><a href="#resolve-amp-reject-的区别" class="headerlink" title="resolve() & reject() 的区别"></a>resolve() & reject() 的区别</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><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> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="built_in">Promise</span>.resolve(<span class="string">'resolve'</span>));</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">const</span> p2 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> resolve(<span class="built_in">Promise</span>.reject(<span class="string">'reject'</span>));</div><div class="line">});</div><div class="line"></div><div class="line"><span class="keyword">const</span> p3 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> reject(<span class="built_in">Promise</span>.resolve(<span class="string">'resolve'</span>));</div><div class="line">});</div><div class="line"></div><div class="line">p1.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1-resolve:'</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p1-reject:'</span>, err);</div><div class="line">});</div><div class="line"></div><div class="line">p2.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2-resolve:'</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p2-reject:'</span>, err);</div><div class="line">});</div><div class="line"></div><div class="line">p3.then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p3-resolve:'</span>, value);</div><div class="line">}, (err) => {</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'p3-reject:'</span>, err);</div><div class="line">});</div></pre></td></tr></table></figure>
<p><code>resolve</code>方法和<code>reject</code>方法除了在状态上有区别,处理方式上也有区别,<code>resolve</code>方法上面提到了会对<strong>promise对象</strong>“拆箱”,但是<code>reject</code>方法不会。</p>
<p><code>p3</code>没有“拆箱”操作,所以会最先输出,直接调用<code>reject</code>方法,输出<code>Promise.resolve('resolve')</code>对象<br><code>p1</code>会“拆箱”得到<code>Promise.resolve('resolve')</code>这个<strong>promise对象</strong>的状态和值,调用<code>resolve</code>方法。<br><code>p2</code>会“拆箱”得到<code>Promise.reject('reject')</code>这个<strong>promise对象</strong>的状态和值,因为得到的状态是<code>rejected</code>,所以会调用<code>reject</code>方法。</p>
<blockquote>
<p>输出</p>
</blockquote>
<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">p3-reject: <span class="built_in">Promise</span> {[[PromiseStatus]]: <span class="string">"resolved"</span>, [[PromiseValue]]: <span class="string">"resolve"</span>}</div><div class="line">p1-resolve: resolve</div><div class="line">p2-reject: reject</div></pre></td></tr></table></figure>
<h2 id="all-amp-race-amp-then-区别"><a href="#all-amp-race-amp-then-区别" class="headerlink" title="all() & race() & then() 区别"></a>all() & race() & then() 区别</h2><p><code>Promise.all()</code>语法:</p>
<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="built_in">Promise</span>.all(iterable);</div></pre></td></tr></table></figure>
<p><code>Promise.race()</code>语法:</p>
<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="built_in">Promise</span>.race(iterable)</div></pre></td></tr></table></figure>
<ul>
<li><code>iterable</code>: 可迭代对象,例如一个数组。</li>
</ul>
<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">let</span> timerPromisefy = <span class="function">(<span class="params">delay</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve</span>) =></span> {</div><div class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> resolve(delay);</div><div class="line"> }, delay);</div><div class="line"> });</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">let</span> timerPromisefyReject = <span class="function">(<span class="params">delay</span>) =></span> {</div><div class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</div><div class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> reject(delay);</div><div class="line"> }, delay);</div><div class="line"> });</div><div class="line">}</div><div class="line"></div><div class="line"><span class="built_in">console</span>.time(<span class="string">'Promise all'</span>);</div><div class="line"><span class="built_in">Promise</span>.all([</div><div class="line"> timerPromisefy(<span class="number">1</span>),</div><div class="line"> timerPromisefy(<span class="number">7</span>),</div><div class="line"> timerPromisefy(<span class="number">10</span>),</div><div class="line"> timerPromisefy(<span class="number">9</span>)</div><div class="line">]).then(<span class="function">(<span class="params">value</span>) =></span> {</div><div class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">'Promise all'</span>);</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.time(<span class="string">'Promise then'</span>);</div><div class="line">timerPromisefy(<span class="number">1</span>).then(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="keyword">return</span> timerPromisefy(<span class="number">7</span>)</div><div class="line">}).then(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="keyword">return</span> timerPromisefy(<span class="number">10</span>)</div><div class="line">}).then(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="keyword">return</span> timerPromisefy(<span class="number">9</span>)</div><div class="line">}).then(<span class="function"><span class="params">()</span> =></span> {</div><div class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">'Promise then'</span>)</div><div class="line">});</div><div class="line"></div><div class="line"><span class="built_in">console</span>.time(<span class="string">'Promise race'</span>);</div><div class="line"><span class="built_in">Promise</span>.race([</div><div class="line"> timerPromisefy(<span class="number">1</span>),</div><div class="line"> timerPromisefy(<span class="number">7</span>),</div><div class="line"> timerPromisefy(<span class="number">10</span>),</div><div class="line"> timerPromisefy(<span class="number">9</span>)</div><div class="line">]).then(<span class="function"><span class="params">value</span> =></span> {</div><div class="line"> <span class="built_in">console</span>.timeEnd(<span class="string">'Promise race'</span>);</div><div class="line">});</div></pre></td></tr></table></figure>
<p><code>Promise.all()</code>方法返回一个<code>Promise</code>,当<code>iterable</code>参数中的 <em>promise</em> 并行执行,当所有 <em>promise</em> 都已经 <em>resolve</em> 了,返回 <em>resolved</em> 状态。当传递的 <em>promise</em> 包含一个 <em>reject</em> ,则返回 <em>rejected</em> 状态。<br>如果<code>Promise.all()</code>返回 <em>resolved</em> , 那么执行时间取决于执行最最慢的那个 <em>promise</em>;如果<code>Promise.all()</code>返回 <em>rejected</em> , 执行时间取决于第一个返回 <em>rejected</em> 的执行时间。</p>
<p><code>Promise.race()</code>方法返回一个<code>Promise</code>,当<code>iterable</code>参数中只要有一个 <em>promise</em> 状态被判定了,那么就返回该状态。<br>所以<code>Promise.race()</code>的执行时间取决于执行最快的那个 <em>promise</em>。</p>
<p><code>Promise.then()</code>方法的执行时间,是每个链式调用总时间之和。</p>
<blockquote>
<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></pre></td><td class="code"><pre><div class="line">Promise race: 2.3232421875ms</div><div class="line">Promise all: 3.675048828125ms</div><div class="line">Promise then: 31.32373046875ms</div></pre></td></tr></table></figure></p>
</blockquote>
]]></content>
<summary type="html">
<h2 id="什么是Promise"><a href="#什么是Promise" class="headerlink" title="什么是Promise"></a>什么是<strong>Promise</strong></h2><p><strong>Promise</strong>的核心理念是一个异步操作的结果,<strong>Promise</strong>包含两部分</p>
<ul>
<li><code>[[PromiseStates]]</code></li>
<li><code>[[PromiseValue]]</code></li>
</ul>
<p><strong>Promise</strong>状态三种可能:</p>
<ul>
<li><code>pending</code>: 悬而未决</li>
<li><code>resolved</code>: 决定</li>
<li><code>rejected</code>: 拒绝</li>
</ul>
<img src="/2017/12/07/Promise深入理解/state.png" alt="Promise状态" title="Promise状态">
</summary>
<category term="JavaScript" scheme="https://yeaseonzhang.github.io/tags/JavaScript/"/>
</entry>
<entry>
<title>CSS单位全解</title>
<link href="https://yeaseonzhang.github.io/2017/11/24/CSS%E5%8D%95%E4%BD%8D%E5%85%A8%E8%A7%A3/"/>
<id>https://yeaseonzhang.github.io/2017/11/24/CSS单位全解/</id>
<published>2017-11-24T13:33:07.000Z</published>
<updated>2017-11-23T16:47:07.962Z</updated>
<content type="html"><![CDATA[<h2 id="对于css单位的认识"><a href="#对于css单位的认识" class="headerlink" title="对于css单位的认识"></a>对于css单位的认识</h2><p>对于网页布局的单位,只知道<code>px</code>是仅仅不够的,还需要知道其他几个比较常见的单位,特别是css3推出的一些新的度量单位。</p>
<a id="more"></a>
<h2 id="em"><a href="#em" class="headerlink" title="em"></a>em</h2><p><code>em</code>是一种相对单位,它相对于父元素的字体大小。</p>
<p><code>em</code>常用于存在缩放需求时使用,比如在多行文本段落中,如果行高设置为<code>line-height: 18px</code>,如果文字的大小因为缩放发生改变,行高值是不会随之改变的,一直都是<code>18px</code>,如果将行高设置成一种相对值<code>line-height: 1.2em</code>,那么此时的行高值就会随着字体的大小改变而变化。</p>
<p>因为<code>em</code>是相对于父元素的字体大小,所以该单位存在明显的嵌套层级关系,浏览器默认的字体大小是<code>16px</code>,因此<code>1em = 16px</code>,需要注意的是<strong>chrome</strong>浏览器能够显示的最小字体是<code>12px</code>,当字体大小设置小于<code>12px</code>字体将按照<code>12px</code>显示。</p>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="MOowbV" data-default-tab="jjresult" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="em" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/MOowbV/" target="_blank" rel="external">em</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<h2 id="rem"><a href="#rem" class="headerlink" title="rem"></a>rem</h2><p><code>rem</code>(<strong>root em</strong>)是一种相对单位,和<code>em</code>不同点是<code>rem</code>相对于根元素<code>html</code>的字体大小。</p>
<p>利用这个特性,我们常常使用<code>rem</code>单位进行移动端页面的布局。</p>
<p><code>rem</code>布局的本质是等比缩放,一般是基于宽度。</p>
<img src="/2017/11/24/CSS单位全解/rem.png" alt="rem浏览器兼容性" title="rem浏览器兼容性">
<table>
<thead>
<tr>
<th>兼容性</th>
<th>iOS</th>
<th>Android</th>
</tr>
</thead>
<tbody>
<tr>
<td> rem</td>
<td>4.1+</td>
<td>2.1+</td>
</tr>
</tbody>
</table>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="YEQmjJ" data-default-tab="result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="rem" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/YEQmjJ/" target="_blank" rel="external">rem</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assetsi/embed/ei.js"></script>
<p>现在移动端设计稿的尺寸大多为以iPhone6为基准的<code>750px</code>,首先将页面划分为100份,每一份的宽度为<code>npx</code>, 设置<code>1rem = 10n</code>,所以以<code>750px</code>为基准的话,每份就是<code>7.5px</code>,<code>1rem</code>就对应<code>75px</code>。但这仅仅只能适配宽度为<code>750px</code>的设备,所以通过加载页面时动态计算设备的尺寸来,修改<code>html</code>的<code>font-size</code>值,就能实现页面缩放适配。</p>
<p>最简单设置rem基准值的方法。<br><figure class="highlight js"><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="built_in">document</span>.addEventListener(<span class="string">'DOMContentLoaded'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</div><div class="line"> <span class="keyword">var</span> rem = <span class="built_in">window</span>.innerWidth / <span class="number">10</span> + <span class="string">'px'</span>;</div><div class="line"> <span class="built_in">document</span>.getElementsByTagName(<span class="string">'html'</span>)[<span class="number">0</span>].style.fontSize = rem;</div><div class="line">})</div></pre></td></tr></table></figure></p>
<p>使用<strong>scss</strong>将<code>px</code>转换为<code>rem</code>值<br><figure class="highlight scss"><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">@function px2rem (<span class="variable">$px</span>) {</div><div class="line"> <span class="variable">$rem</span>: <span class="number">75px</span>;</div><div class="line"> @return (<span class="variable">$px</span> / <span class="variable">$rem</span>) + rem;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>也有人建议将设计稿宽度划分成100份,每一份就是一个<code>rem</code>单位,那么<code>750px</code>宽度的设计稿,对应的<code>html</code>的<code>font-size = 1rem = 7.5px</code>,方便兼容<code>vh/vw</code>单位。但是不建议这么做,你知道什么吗?</p>
<h2 id="vh-vw"><a href="#vh-vw" class="headerlink" title="vh/vw"></a>vh/vw</h2><p><code>vh/vw</code>单位类似于百分比单位不同之处在于<code>vh/vw</code>单位的布局不依赖于父级的宽高,而是相对于视口的宽高。<br><code>1vh</code>等于1%的视口高度,<code>1vw</code>等于1%的视口宽度。若视口宽度是<code>750px</code>,那么<code>1vw</code>就是<code>7.5px</code>。</p>
<img src="/2017/11/24/CSS单位全解/v-unit.png" alt="视口单位兼容性" title="视口单位兼容性">
<p>目前移动端高端机型对于视口单位基本全面支持。</p>
<table>
<thead>
<tr>
<th>兼容性</th>
<th>iOS</th>
<th>Android</th>
</tr>
</thead>
<tbody>
<tr>
<td> vw</td>
<td>6.1+</td>
<td>4.4+</td>
</tr>
</tbody>
</table>
<p></p><p data-height="705" data-theme-id="0" data-slug-hash="JOvLOy" data-default-tab="result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="v-unit" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/JOvLOy/" target="_blank" rel="external">v-unit</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p><strong>注</strong>:不同浏览器在获取视口的方法不同<br>IE9+、Firefox、Safari、Opera和Chrome均提供了4个属性<code>innerWidth</code>、<code>innerHeight</code>、<code>outerWidth</code>和<code>outerHeight</code>。</p>
<ul>
<li>IE9+、Safari和Firefox中,<code>outerWidth</code>和<code>outerHeight</code>返回浏览器窗口本身的尺寸,而<code>innerWidth</code>和<code>innerHeight</code>则表示该容器中页面视图区的大小(减去边框宽度)</li>
<li>Chrome中,<code>inner*</code>和<code>outer*</code>返回相同的值,即视口大小而非浏览器窗口的大小。</li>
<li>在IE、Firefox、Safari、Opera和Chrome中,都能通过<code>document.documentElement.clientWidth</code>和<code>document.documentElement.clientHeight</code>中保存了页面视口信息。</li>
</ul>
<p>获取页面视口大小<br><figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> pageWidth = <span class="built_in">window</span>.innerWidth,</div><div class="line"> pageHeight = <span class="built_in">window</span>.innerHeight;</div><div class="line"></div><div class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> pageWidth != <span class="string">'number'</span>) {</div><div class="line"> <span class="keyword">if</span> (<span class="built_in">document</span>.compatMode == <span class="string">'CSS1Compat'</span>) { <span class="comment">// 浏览器标准模式</span></div><div class="line"> pageWidth = <span class="built_in">document</span>.documentElement.clientWidth;</div><div class="line"> pageHeight = <span class="built_in">document</span>.documentElement.clientHeight;</div><div class="line"> } <span class="keyword">else</span> { <span class="comment">// IE6 混杂模式</span></div><div class="line"> pageWidth = <span class="built_in">document</span>.body.clientWidth;</div><div class="line"> pageHeight = <span class="built_in">document</span>.doby.clientHeight;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>其实,<code>vw</code>还可以和<code>rem</code>方案结合,这样就不需要js计算来设置<code>html</code>字体大小。<br><figure class="highlight css"><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="selector-tag">html</span> {</div><div class="line"> <span class="attribute">font-size</span>: <span class="number">1vw</span></div><div class="line">}</div><div class="line"><span class="selector-tag">p</span> {</div><div class="line"> <span class="attribute">width</span>: <span class="number">15rem</span>;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>往往一份设计稿为了兼容大屏设备,我们会采取限制布局的最大宽度。大于这个宽度的话页面居中并且,两边会留白。这个时候<code>vw</code>单位就无法满足我们的需求了。</p>
<h2 id="vmin-vmax"><a href="#vmin-vmax" class="headerlink" title="vmin/vmax"></a>vmin/vmax</h2><p><code>vmin</code>是指<code>vh</code>和<code>vw</code>中较小的那一个的大小,当然<code>vmax</code>就是<code>vh</code>和<code>vw</code>中较大的那一个。</p>
<p>例如,浏览器视口宽<code>1100px</code>、高<code>700px</code>,那么<code>1vmin = 7px; 1vmax = 11px</code>;如果浏览器视口宽<code>800px</code>,高<code>1080px</code>,那么<code>1vmin = 8px; 1vmax = 10.8px</code></p>
<p>很有意思的是,使用这个单位的时候我们并不关心宽高,而是按照大小来区分,所以在移动端中的应用会比较多。</p>
<figure class="highlight css"><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="selector-class">.box</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">100vmin</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">100vmin</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<img src="/2017/11/24/CSS单位全解/vmin.png" alt="vmin.png" title="">
<figure class="highlight css"><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="selector-class">.box</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">100vmax</span>;</div><div class="line"> <span class="attribute">width</span>: <span class="number">100vmax</span>;</div><div class="line">}</div></pre></td></tr></table></figure>
<img src="/2017/11/24/CSS单位全解/vmax.png" alt="vmax.png" title="">
<h2 id="ch-和-ex"><a href="#ch-和-ex" class="headerlink" title="ch 和 ex"></a>ch 和 ex</h2><p><code>ch</code>和<code>ex</code>单位都是基于当前字体的特定单位。</p>
<p><code>ch</code>单位,被定义为当前字体<code>0</code>字符的宽度。所以如果你使用的是等宽字体,那么你就可以直接定义一个盒子能够容纳多少个字符。</p>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="EbLLPQ" data-default-tab="result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="ch" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/EbLLPQ/" target="_blank" rel="external">ch</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p><code>ex</code>单位,被定义为当前字体<code>x</code>字符高度。这个单位通常用于排版微调,确保精确控制。</p>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="WXJJMR" data-default-tab="css,result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="ex" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/WXJJMR/" target="_blank" rel="external">ex</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<h2 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h2><ul>
<li><p><code>em</code>单位,还是老老实实作为字体/行高单位,如果用做布局使用,会牵一发而动全身,一个节点变化导致后代元素都需要重新计算</p>
</li>
<li><p><code>rem</code>单位,需要结合<code>js</code>脚本动态设置<code>html</code>字体大小,如果用户禁用了js(少数情况),这种时候我们可以选择<code><noscript>开启JavaScript,获得更高的用户体验</noscript></code>;第二个方案就是使用媒体查询,为主流尺寸的设备设置<code>html</code>字体大小</p>
</li>
<li><p><code>vh/vw/vmin/vmax</code>单位,对于设备系统浏览器要求比较高,如果不考虑兼容低版本浏览器,可以选择使用。当你选择使用<code>vw/vh</code>单位的时候,配合<code>calc</code>计算属性会更精确完成布局,例如<code>width: calc(50vw - 40px)</code></p>
</li>
<li><p><code>ch/ex</code>单位,使用的频率不高。如果使用的是等宽字体,<code>ch</code>单位可以用来布局,但是中文字体和英文字体等宽肯定是不一样宽的,所以还是不要考虑用来布局了。<code>ex</code>单位的应用场景,基本上使用<code>em</code>单位都能完成,所以也是一个可用可不用的单位。</p>
</li>
</ul>
<h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul>
<li><p><a href="https://webdesign.tutsplus.com/articles/7-css-units-you-might-not-know-about--cms-22573" target="_blank" rel="external">7 CSS Units You Might Not Know About</a></p>
</li>
<li><p><a href="https://www.w3.org/Style/Examples/007/units.zh_HK.html" target="_blank" rel="external">網頁樣式表 CSS提示以及技巧</a></p>
</li>
<li><a href="http://yanhaijing.com/css/2017/09/29/principle-of-rem-layout/" target="_blank" rel="external">Rem布局的原理解析</a></li>
</ul>
]]></content>
<summary type="html">
<h2 id="对于css单位的认识"><a href="#对于css单位的认识" class="headerlink" title="对于css单位的认识"></a>对于css单位的认识</h2><p>对于网页布局的单位,只知道<code>px</code>是仅仅不够的,还需要知道其他几个比较常见的单位,特别是css3推出的一些新的度量单位。</p>
</summary>
<category term="css" scheme="https://yeaseonzhang.github.io/tags/css/"/>
</entry>
<entry>
<title>前端跨域常用方法</title>
<link href="https://yeaseonzhang.github.io/2017/10/12/%E5%89%8D%E7%AB%AF%E8%B7%A8%E5%9F%9F%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95/"/>
<id>https://yeaseonzhang.github.io/2017/10/12/前端跨域常用方法/</id>
<published>2017-10-11T16:38:06.000Z</published>
<updated>2017-10-12T14:37:42.118Z</updated>
<content type="html"><![CDATA[<img src="/2017/10/12/前端跨域常用方法/security.png" alt="security.png" title="">
<p>在开发过程中经常会涉及跨域问题,解决跨域问题的方案也有很多种,接下来就来梳理一下前端跨域的常用方法。</p>
<h2 id="同源策略"><a href="#同源策略" class="headerlink" title="同源策略"></a>同源策略</h2><p>何为<strong>跨域</strong>,<strong>跨域</strong>是相对于同源而言。协议、域名和端口均相同,则为<strong>同源</strong>。<br>浏览器通过<strong>同源策略</strong>限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制,摘抄自<a href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy" target="_blank" rel="external">MDN</a>。</p>
<a id="more"></a>
<h2 id="常见解决方案"><a href="#常见解决方案" class="headerlink" title="常见解决方案"></a>常见解决方案</h2><h3 id="document-domain"><a href="#document-domain" class="headerlink" title="document.domain"></a>document.domain</h3><p>这种方案主要用于主域相同,子域不同的跨域情况。例如: <code>https://jdc.jd.com/</code> 和 <code>https://www.jd.com/</code>。</p>
<p>通过在<a href="https://www.jd.com/" target="_blank" rel="external">https://www.jd.com/</a>打开一个<a href="https://jdc.jd.com/" target="_blank" rel="external">https://jdc.jd.com/</a>,此时JDC的域名是<code>jdc.jd.com/</code>,通过控制台执行<code>document.domain = 'jd.com'</code>;。强制设置主域,实现同源。</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></pre></td><td class="code"><pre><div class="line"><span class="keyword">var</span> jdc = <span class="built_in">window</span>.open(<span class="string">'https://jdc.jd.com/'</span>);</div><div class="line"><span class="comment">// JDC 页面加载完成后执行</span></div><div class="line"><span class="keyword">var</span> divs = jdc.document.getElementsByTagName(<span class="string">'div'</span>);</div><div class="line"></div><div class="line">$(divs).css(<span class="string">'border'</span>, <span class="string">'1px solid red'</span>);</div></pre></td></tr></table></figure>
<p>通常的做法是通过<code>iframe</code>加载一个跨域页面资源。因为<code>window.open</code>这个方法在浏览器中会被当做谈广告禁止掉。</p>
<blockquote>
<p><a href="http://domain.com/index.html" target="_blank" rel="external">http://domain.com/index.html</a></p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">iframe</span> <span class="attr">id</span>=<span class="string">"sub"</span> <span class="attr">src</span>=<span class="string">"http://sub.domain.com/index.html"</span>></span><span class="tag"></<span class="name">iframe</span>></span></div><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> username = <span class="string">'yeseonzhang'</span>;</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p><a href="http://sub.domain.com/index.html" target="_blank" rel="external">http://sub.domain.com/index.html</a></p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="built_in">document</span>.domain = <span class="string">'domain.com'</span>;</div><div class="line"> <span class="built_in">console</span>.log(<span class="built_in">window</span>.parent.username);</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<h3 id="location-hash"><a href="#location-hash" class="headerlink" title="location.hash"></a>location.hash</h3><p>这种跨域方法主要是通过<strong>设置/监听</strong>url的hash部分,来实现跨域,同时需要借助第三个页面来进行辅助。</p>
<img src="/2017/10/12/前端跨域常用方法/location-hash.png" alt="location-hash.png" title="">
<p>上图就是三个页面的包含关系,以及<code>hash</code>的传递过程。</p>
<blockquote>
<p><a href="http://domain-a.com/a.html" target="_blank" rel="external">http://domain-a.com/a.html</a></p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">iframe</span> <span class="attr">id</span>=<span class="string">"iframe-b"</span> <span class="attr">src</span>=<span class="string">"http://domain-b.com/b.html"</span>></span><span class="tag"></<span class="name">iframe</span>></span></div><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> bPage = <span class="built_in">document</span>.getElementById(<span class="string">'iframe-b'</span>);</div><div class="line"></div><div class="line"> <span class="comment">/* step 1 */</span></div><div class="line"> bPage.src = bPage.src + <span class="string">'#user=yeaseonzhang'</span>;</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">cb</span> (<span class="params">res</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(res);</div><div class="line"> }</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p><a href="http://domain-b.com/b.html" target="_blank" rel="external">http://domain-b.com/b.html</a></p>
</blockquote>
<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"><span class="tag"><<span class="name">iframe</span> <span class="attr">id</span>=<span class="string">"iframe-c"</span> <span class="attr">src</span>=<span class="string">"http://domain-a.com/c.html"</span>></span><span class="tag"></<span class="name">iframe</span>></span></div><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> cPage = <span class="built_in">document</span>.getElementById(<span class="string">'iframe-c'</span>);</div><div class="line"></div><div class="line"> <span class="built_in">window</span>.onhashchange = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="comment">/* step 2 */</span></div><div class="line"> cPage.src = cPage.src + location.hash;</div><div class="line"> }</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p><a href="http://domain-a.com/c.html" target="_blank" rel="external">http://domain-a.com/c.html</a></p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="built_in">window</span>.onhashchange = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="comment">/* step 3 */</span></div><div class="line"> <span class="built_in">window</span>.parent.parent.cb(<span class="string">'success: '</span> + location.hash);</div><div class="line"> }</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<p>由于<strong>a页面</strong>和<strong>c页面</strong>是同域资源,所以<strong>c页面</strong>可以通过<code>window.parent.parent</code>访问<strong>a页面</strong>资源。</p>
<h3 id="window-name"><a href="#window-name" class="headerlink" title="window.name"></a>window.name</h3><p>这个方案类似<code>location.hash</code>,需要通过第三个页面进行辅助。<br><code>window.name</code>属性是用来获取/设置窗口的名称。需要注意的是,当前窗口的<code>window.name</code>并不会因为页面的重载和跳转而更改,所以可以利用这个特性将跨域的<code>window.name</code>通过重定向到同域页面进行读取。</p>
<img src="/2017/10/12/前端跨域常用方法/window-name.png" alt="window-name.png" title="">
<blockquote>
<p><a href="http://domain-a.com/a.html" target="_blank" rel="external">http://domain-a.com/a.html</a></p>
</blockquote>
<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"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> iframe = <span class="built_in">document</span>.createElement(<span class="string">'iframe'</span>);</div><div class="line"> <span class="comment">/* step 1 加载跨域页面 */</span></div><div class="line"> iframe.src = <span class="string">'http://domain-b.com/b.html'</span>;</div><div class="line"> <span class="keyword">var</span> domain = <span class="string">'diff'</span>;</div><div class="line"></div><div class="line"> <span class="comment">/* 监听iframe加载 */</span></div><div class="line"> iframe.onload = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</div><div class="line"> <span class="keyword">if</span> (<span class="string">'diff'</span> == domain) {</div><div class="line"> <span class="comment">/* step 2 重定向到同域页面 */</span></div><div class="line"> iframe.contentWindow.location = <span class="string">'http://www.domain-a.com/c.html'</span>;</div><div class="line"> domain = <span class="string">'same'</span>;</div><div class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="string">'same'</span> == domain) {</div><div class="line"> <span class="comment">/* 获取同域资源的window.name信息 */</span></div><div class="line"> cb(iframe.contentWindow.name);</div><div class="line"> <span class="comment">/* 清空数据 */</span></div><div class="line"> iframe.contentWindow.name = <span class="string">''</span>;</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">cb</span> (<span class="params">res</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="built_in">JSON</span>.parse(res));</div><div class="line"> }</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p><a href="http://domain-b.com/b.html" target="_blank" rel="external">http://domain-b.com/b.html</a></p>
</blockquote>
<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"><span class="tag"><<span class="name">scirpt</span>></span></div><div class="line"> /* 写入相关数据 */</div><div class="line"> var obj = {</div><div class="line"> username: 'yeaseonzhang'</div><div class="line"> }</div><div class="line"> window.name = JSON.stringify(obj);</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p><a href="http://domain-a.com/c.html" target="_blank" rel="external">http://domain-a.com/c.html</a></p>
</blockquote>
<p>同域<strong>c页面</strong>,可以是一个空页面,不需要进行任何操作。</p>
<h3 id="JSONP"><a href="#JSONP" class="headerlink" title="JSONP"></a>JSONP</h3><p><strong>JSONP</strong>(JSON with Padding)是<strong>JSON</strong>的一种使用方式。这种方式允许用户传递一个<code>callback</code>参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据。</p>
<p>众所周知,html页面中所有带有<code>src</code>属性的标签(<code><img></code>,<code><script></code>和<code>iframe</code>)都拥有跨域能力。所以最简单的实现方式就是动态加载JS。</p>
<blockquote>
<p>客户端</p>
</blockquote>
<figure class="highlight js"><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">todo</span>(<span class="params">data</span>)</span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'The author is: '</span>+ data.name);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="keyword">var</span> script = <span class="built_in">document</span>.createElement(<span class="string">'script'</span>);</div><div class="line"><span class="comment">/* callback参数,用来指定回调函数的名字。 */</span></div><div class="line">script.src = <span class="string">'http://www.yeaseonzhang.com/author?callback=todo'</span>;</div><div class="line"><span class="built_in">document</span>.body.appendChild(script);</div></pre></td></tr></table></figure>
<blockquote>
<p>服务端</p>
</blockquote>
<figure class="highlight plain"><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">/* 服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 */</div><div class="line">todo({"name": "yeaseonzhang"});</div></pre></td></tr></table></figure>
<p><code>todo()</code>函数会被作为全局函数来执行,只要定义了<code>todo()</code>函数,该函数就会被立即调用。</p>
<h3 id="postMessage"><a href="#postMessage" class="headerlink" title="postMessage"></a>postMessage</h3><p><code>window.postMessage</code>是HTML5中一个安全的,基于事件的消息API。</p>
<img src="/2017/10/12/前端跨域常用方法/postmessage.png" alt="postmessage.png" title="">
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">otherWindow.postMessage(message, targetOrigin, [transfer]);</div></pre></td></tr></table></figure>
<p><code>postMessage()</code>,方法包含三个参数:</p>
<ul>
<li><code>message</code>: 消息内容</li>
<li><code>targetOrigin</code>: 接受消息窗口的源,即”协议 + 域名 + 端口”。也可以设置为通配符<code>*</code>,向所有窗口发送</li>
<li><code>transfer</code>: 可选参数(布尔值),是一串和message 同时传递的<code>Transferable</code>对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。</li>
</ul>
<p><strong>发送者</strong>和<strong>接收者</strong>都可以通过<code>message</code>事件,监听对方的消息。<code>message</code>事件的事件对象<code>event</code>包含三个属性:</p>
<ul>
<li><code>event.source</code>: 发送消息的窗口对象的引用,可以用此在两个窗口建立双向通信。</li>
<li><code>event.origin</code>: 发送消息的URI</li>
<li><code>event.data</code>: 消息内容</li>
</ul>
<blockquote>
<p>发送者: <a href="http://domain-a.com/a.html" target="_blank" rel="external">http://domain-a.com/a.html</a></p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> newWindow = <span class="built_in">window</span>.open(<span class="string">'http://domain-b.com/b.html'</span>);</div><div class="line"> <span class="comment">/* 向b.html发送消息 */</span></div><div class="line"> newWindow.postMessage(<span class="string">'Hello'</span>, <span class="string">'http://domain-b.com/b.html'</span>);</div><div class="line"></div><div class="line"> <span class="comment">/* 双向通信,接收b.html的回复消息 */</span></div><div class="line"> <span class="keyword">var</span> onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="keyword">var</span> data = event.data;</div><div class="line"> <span class="keyword">var</span> origin = event.origin;</div><div class="line"> <span class="keyword">var</span> source = event.source;</div><div class="line"> <span class="keyword">if</span> (origin == <span class="string">'http://domain-b.com/b.html'</span>) {</div><div class="line"> <span class="built_in">console</span>.log(data); <span class="comment">//Nice to see you!</span></div><div class="line"> }</div><div class="line"> };</div><div class="line"> <span class="built_in">window</span>.addEventListener(<span class="string">'message'</span>, onmessage, <span class="literal">false</span>);</div><div class="line"><span class="xml"><span class="tag"></<span class="name">scirpt</span>></span></span></div></pre></td></tr></table></figure>
<blockquote>
<p>接收者:<a href="http://domain-b.com/b.html" target="_blank" rel="external">http://domain-b.com/b.html</a></p>
</blockquote>
<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"><span class="tag"><<span class="name">script</span>></span><span class="javascript"></span></div><div class="line"> <span class="keyword">var</span> onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="keyword">var</span> data = event.data;</div><div class="line"> <span class="keyword">var</span> origin = event.origin;</div><div class="line"> <span class="keyword">var</span> source = event.source;</div><div class="line"> <span class="keyword">if</span> (origin == <span class="string">'http://domain-a.com/a.html'</span>) {</div><div class="line"> <span class="built_in">console</span>.log(data); <span class="comment">//Hello</span></div><div class="line"> <span class="comment">/* 回复a.html的消息 */</span></div><div class="line"> source.postMessage(<span class="string">'Nice to see you!'</span>, <span class="string">'http://domain-a.com/a.html'</span>);</div><div class="line"> }</div><div class="line"> };</div><div class="line"> <span class="built_in">window</span>.addEventListener(<span class="string">'message'</span>, onmessage, <span class="literal">false</span>);</div><div class="line"><span class="tag"></<span class="name">script</span>></span></div></pre></td></tr></table></figure>
<h3 id="WebSocket"><a href="#WebSocket" class="headerlink" title="WebSocket"></a>WebSocket</h3><p><code>WebSocket</code>是一种HTML5的一种新的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案,详细介绍请访问<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket" target="_blank" rel="external">MDN</a>。</p>
<img src="/2017/10/12/前端跨域常用方法/websocket.png" alt="websocket.png" title="">
<figure class="highlight js"><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="comment">/* websocket协议为ws/wss, 类似http/https的区别 */</span></div><div class="line">wsUrl = <span class="string">'wss://127.0.0.1:8090/ws/'</span>;</div><div class="line"></div><div class="line"><span class="comment">/* 发送 */</span></div><div class="line">ws = <span class="keyword">new</span> WebSocket(wsUrl);</div><div class="line"></div><div class="line"><span class="comment">/* 连接成功建立时调用 */</span></div><div class="line">ws.onopen = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"websocket command onopen"</span>);</div><div class="line"> <span class="keyword">var</span> msg = {</div><div class="line"> <span class="attr">username</span>: <span class="string">'YeaseonZhang'</span></div><div class="line"> }</div><div class="line"> <span class="comment">/* 通过 send() 方法向服务端发送消息,参数必须为字符串 */</span></div><div class="line"> ws.send(<span class="built_in">JSON</span>.stringify(msg));</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* 服务端向客户端发送消息时调用 */</span></div><div class="line">ws.onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="comment">/* event.data包含了服务端发送过来的消息 */</span></div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"websocket command onmessage: "</span> + event.data);</div><div class="line"> <span class="keyword">if</span> (event.data === <span class="string">'success'</span>) {</div><div class="line"> <span class="comment">/* 通过 close() 方法断开websocket连接 */</span></div><div class="line"> ws.close();</div><div class="line"> }</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* 连接被关闭时调用 */</span></div><div class="line">ws.onclose = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"websocket command onclose: "</span> + event.data);</div><div class="line">};</div><div class="line"></div><div class="line"><span class="comment">/* 出现错误时调用 */</span></div><div class="line">ws.onerror = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>{</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">"websocket command onerror: "</span> + event.data);</div><div class="line">};</div></pre></td></tr></table></figure>
<p><code>WebSocket</code>的优势是除了可以实现跨域,还有就是可以保持长连接,而不需要通过轮询实现实时性。</p>
<h3 id="CORS"><a href="#CORS" class="headerlink" title="CORS"></a>CORS</h3><p><code>CORS</code>是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。</p>
<p>只需要后端同学支持就ok,前端不需要做很多额外工作(除了携带<code>cookie</code>)。</p>
<p>只要服务器返回的相应中包含头部信息<code>Access-Control-Allow-Origin: domain-name</code>,<code>domain-name</code>为允许跨域的域名,也可以设置成<code>*</code>,浏览器就会允许本次跨域请求。</p>
<h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>以上就是我所了解的跨域的解决方案,希望对你有所帮助。</p>
]]></content>
<summary type="html">
<img src="/2017/10/12/前端跨域常用方法/security.png" alt="security.png" title="">
<p>在开发过程中经常会涉及跨域问题,解决跨域问题的方案也有很多种,接下来就来梳理一下前端跨域的常用方法。</p>
<h2 id="同源策略"><a href="#同源策略" class="headerlink" title="同源策略"></a>同源策略</h2><p>何为<strong>跨域</strong>,<strong>跨域</strong>是相对于同源而言。协议、域名和端口均相同,则为<strong>同源</strong>。<br>浏览器通过<strong>同源策略</strong>限制从一个源加载的文档或脚本与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制,摘抄自<a href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy" target="_blank" rel="external">MDN</a>。</p>
</summary>
<category term="web安全" scheme="https://yeaseonzhang.github.io/tags/web%E5%AE%89%E5%85%A8/"/>
</entry>
<entry>
<title>2017前端面试题及答案总结</title>
<link href="https://yeaseonzhang.github.io/2017/09/17/2017%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%8A%E7%AD%94%E6%A1%88%E6%80%BB%E7%BB%93/"/>
<id>https://yeaseonzhang.github.io/2017/09/17/2017前端面试题及答案总结/</id>
<published>2017-09-17T13:42:57.000Z</published>
<updated>2017-09-25T15:10:53.071Z</updated>
<content type="html"><![CDATA[<p>“金三银四,金九银十”,用来形容求职最好的几个月。但是随着行业的饱和,初中级前端er就业形势不容乐观。</p>
<p>行业状态不可控,我们能做的当然只是让自己变得更加具有竞争力。</p>
<p>今年自己也用了几个月的时间来准备笔记面试,巩固基础知识。特此将自己在这个过程总结的题目分享出来,希望对于求职和准备求职的同学有所帮助。</p>
<a id="more"></a>
<h2 id="CSS"><a href="#CSS" class="headerlink" title="CSS"></a>CSS</h2><h3 id="列举不同的清除浮动的技巧"><a href="#列举不同的清除浮动的技巧" class="headerlink" title="列举不同的清除浮动的技巧"></a>列举不同的清除浮动的技巧</h3><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><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">/* 1.添加新元素 */</div><div class="line"><div class="outer"></div><div class="line"> <div class="div1"></div></div><div class="line"> <div class="div2"></div></div><div class="line"> <div class="div3"></div></div><div class="line"> <div class="clearfix"></div></div><div class="line"></div></div><div class="line">.clearfix {</div><div class="line"> clear: both;</div><div class="line">}</div><div class="line"></div><div class="line">/* 2.为父元素增加样式 */</div><div class="line">.clearfix {</div><div class="line"> overflow: auto;</div><div class="line"> zoom: 1; // 处理兼容性</div><div class="line">}</div><div class="line"></div><div class="line">/* 3.:after 伪元素方法 (作用于父元素) */</div><div class="line">.outer {</div><div class="line"> zoom: 1;</div><div class="line"> &:after {</div><div class="line"> display: block;</div><div class="line"> height: 0;</div><div class="line"> clear: both;</div><div class="line"> content: '.';</div><div class="line"> visibillity: hidden;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="一像素边框"><a href="#一像素边框" class="headerlink" title="一像素边框"></a>一像素边框</h3><p>使用<code>sass</code>语法。</p>
<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><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">/* 定义 */</div><div class="line">@mixin border-1px ($color) {</div><div class="line"> position: relative;</div><div class="line"> &:after {</div><div class="line"> display: block;</div><div class="line"> position: absolute;</div><div class="line"> left: 0;</div><div class="line"> bottom: 0;</div><div class="line"> width: 100%;</div><div class="line"> border-top: 1px solid $color;</div><div class="line"> context: '';</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">@media (-webkit-min-device-pixel-radio: 1.5), (min-device-pixel-radio: 1.5) {</div><div class="line"> border-1px {</div><div class="line"> &:after {</div><div class="line"> -webkit-transform: scaleY(0.7);</div><div class="line"> transform: scaleY(0.7);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">@media (-webkit-min-device-pixel-radio: 2), (min-device-pixel-radio: 2) {</div><div class="line"> border-1px {</div><div class="line"> &:after {</div><div class="line"> -webkit-transform: scaleY(0.5);</div><div class="line"> transform: scaleY(0.5);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">/* 使用方式 */</div><div class="line">@inclue border-1px(rgba(7, 17, 27, .1));</div></pre></td></tr></table></figure>
<h3 id="形成BFC-Block-Formatting-Context-的几种方式"><a href="#形成BFC-Block-Formatting-Context-的几种方式" class="headerlink" title="形成BFC(Block Formatting Context)的几种方式"></a>形成<strong>BFC</strong>(Block Formatting Context)的几种方式</h3><p>BFC全称”Block Formatting Context”, 中文为“块级格式化上下文”。BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素。</p>
<ul>
<li><code>float</code>为 <code>left|right</code></li>
<li><code>overflow</code>为 <code>hidden|auto|scroll</code></li>
<li><code>display</code>为 <code>table-cell|table-caption|inline-block</code></li>
<li><code>position</code>为 <code>absolute|fixed</code></li>
</ul>
<h3 id="布局"><a href="#布局" class="headerlink" title="布局"></a>布局</h3><ul>
<li><p><a href="https://yeaseonzhang.github.io/2017/07/05/CSS布局/"><strong>圣杯布局</strong>和<strong>双飞翼布局</strong></a></p>
</li>
<li><p>左定宽右自适应宽度,并且等高布局(最小高度200px)</p>
</li>
</ul>
<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><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">/* HTML */</div><div class="line"><div class="container"></div><div class="line"> <div class="left">Left silder</div></div><div class="line"> <div class="content">Main content</div></div><div class="line"></div></div><div class="line"></div><div class="line">/* CSS */</div><div class="line">.container {</div><div class="line"> overflow: hidden;</div><div class="line">}</div><div class="line"></div><div class="line">.left {</div><div class="line"> float: left;</div><div class="line"> width: 200px;</div><div class="line"> margin-bottom: -9999px;</div><div class="line"> padding-bottom: 9999px;</div><div class="line"> background-color: #eee;</div><div class="line">}</div><div class="line"></div><div class="line">.content {</div><div class="line"> margin-left: 200px;</div><div class="line"> margin-bottom: -9999px;</div><div class="line"> padding-bottom: 9999px;</div><div class="line"> background-color: #ccc;</div><div class="line">}</div><div class="line"></div><div class="line">.left, .content {</div><div class="line"> min-height: 200px;</div><div class="line"> height: auto !important;</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="JS"><a href="#JS" class="headerlink" title="JS"></a>JS</h2><h3 id="async与defer区别"><a href="#async与defer区别" class="headerlink" title="async与defer区别"></a><code>async</code>与<code>defer</code>区别</h3><p>异步(async) 脚本将在其加载完成后立即执行,而 延迟(defer) 脚本将等待 HTML 解析完成后,并按加载顺序执行。</p>
<h3 id="location-replace-与location-assign-区别"><a href="#location-replace-与location-assign-区别" class="headerlink" title="location.replace()与location.assign()区别"></a><code>location.replace()</code>与<code>location.assign()</code>区别</h3><p><code>location.replace()</code>的url不会出现在history中</p>
<h3 id="new操作符"><a href="#new操作符" class="headerlink" title="new操作符"></a><code>new</code>操作符</h3><ul>
<li>创建一个空对象,并且<code>this</code>变量引用该对象,同时还继承了 该函数的原型</li>
<li>属性和方法被加入到<code>this</code>引用的对象中</li>
<li>新创建的对象由<code>this</code>所引用,并且最后隐式的返回<code>this</code></li>
</ul>
<h3 id="AMD-CMD-CommonJS"><a href="#AMD-CMD-CommonJS" class="headerlink" title="AMD CMD CommonJS"></a>AMD CMD CommonJS</h3><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">/* AMD是RequireJS对模块化的定义</div><div class="line"> * CMD是seaJS对模块化的定义</div><div class="line"> * CommonJS是Node对模块化的规范</div><div class="line"> **/</div><div class="line"></div><div class="line">/* AMD 依赖关系前置 */</div><div class="line">define(['./a', './b'], function (a, b) {</div><div class="line"> a.something();</div><div class="line"> b.something();</div><div class="line">})</div><div class="line"></div><div class="line">/* CMD 按需加载,依赖就近 */</div><div class="line">define(function (require, exports, module) {</div><div class="line"> var a = require('./a');</div><div class="line"> a.something();</div><div class="line"></div><div class="line"> var b = require('./b');</div><div class="line"> b.something();</div><div class="line">})</div></pre></td></tr></table></figure>
<h4 id="DOM-操作"><a href="#DOM-操作" class="headerlink" title="DOM 操作"></a>DOM 操作</h4><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></pre></td><td class="code"><pre><div class="line">// 创建节点</div><div class="line">createDocumentFragment()</div><div class="line">createElement()</div><div class="line">createTextNode()</div><div class="line"></div><div class="line">// 添加 移除 替换 插入</div><div class="line">appendChild()</div><div class="line">removeChild()</div><div class="line">replaceChild()</div><div class="line">insertBefore()</div><div class="line"></div><div class="line">// 查找</div><div class="line">getElementsByTagName()</div><div class="line">getElementsByName()</div><div class="line">getElementsByClassName()</div><div class="line">getElementById()</div><div class="line">querySelector()</div><div class="line">querySelectorAll()</div></pre></td></tr></table></figure>
<h3 id="JS设置css样式的几种方式"><a href="#JS设置css样式的几种方式" class="headerlink" title="JS设置css样式的几种方式"></a>JS设置css样式的几种方式</h3><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></pre></td><td class="code"><pre><div class="line">/* 1.直接设置style属性 */</div><div class="line">element.style.height = '100px';</div><div class="line"></div><div class="line">/* 2.直接设置属性 */</div><div class="line">element.setAttribute('height', '100px');</div><div class="line"></div><div class="line">/* 3.使用setAttribute设置style属性 */</div><div class="line">element.setAttribute('style', 'height: 100px !important');</div><div class="line"></div><div class="line">/* 4.使用setProperty设置属性,通过第三个参数设置important */</div><div class="line">element.style.setProperty('height', '300px', 'important');</div><div class="line"></div><div class="line">/* 5.设置cssText */</div><div class="line">element.style.cssText += 'height: 100px !important';</div></pre></td></tr></table></figure>
<h3 id="阻止默认行为"><a href="#阻止默认行为" class="headerlink" title="阻止默认行为"></a>阻止默认行为</h3><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></pre></td><td class="code"><pre><div class="line">function stopDefault( e ) {</div><div class="line"> // 阻止默认浏览器动作(W3C)</div><div class="line"> if ( e && e.preventDefault ) {</div><div class="line"> e.preventDefault();</div><div class="line"> } else {</div><div class="line"> // IE中阻止函数器默认动作的方式</div><div class="line"> window.event.returnValue = false;</div><div class="line"> }</div><div class="line"> return false;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="阻止冒泡"><a href="#阻止冒泡" class="headerlink" title="阻止冒泡"></a>阻止冒泡</h3><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></pre></td><td class="code"><pre><div class="line">function stopBubble(e) {</div><div class="line"> // 如果提供了事件对象,则这是一个非IE浏览器</div><div class="line"> if ( e && e.stopPropagation ) {</div><div class="line"> // 因此它支持W3C的stopPropagation()方法</div><div class="line"> e.stopPropagation();</div><div class="line"> } else {</div><div class="line"> // 否则,我们需要使用IE的方式来取消事件冒泡</div><div class="line"> window.event.cancelBubble = true;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="Ajax交互过程"><a href="#Ajax交互过程" class="headerlink" title="Ajax交互过程"></a>Ajax交互过程</h3><ul>
<li>创建XMLHttpRequest对象,也就是创建一个异步调用对象.</li>
<li>创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.</li>
<li>设置响应HTTP请求状态变化的函数.</li>
<li>发送HTTP请求.</li>
<li>获取异步调用返回的数据.</li>
<li>使用JavaScript和DOM实现局部刷新.</li>
</ul>
<h3 id="考察知识点最广的JS面试题"><a href="#考察知识点最广的JS面试题" class="headerlink" title="考察知识点最广的JS面试题"></a>考察知识点最广的JS面试题</h3><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></pre></td><td class="code"><pre><div class="line">function Foo() {</div><div class="line"> getName = function () { alert(1); }</div><div class="line"> return this;</div><div class="line">}</div><div class="line">Foo.getName = function () { alert(2); }</div><div class="line">Foo.prototype.getName = function () { alert(3); }</div><div class="line">var getName = function () { alert(4); }</div><div class="line">function getName () { alert(5); }</div><div class="line"></div><div class="line">/* 写出输出 */</div><div class="line">Foo.getName();</div><div class="line">getName();</div><div class="line">Foo().getName();</div><div class="line">getName();</div><div class="line">new Foo.getName();</div><div class="line">new Foo().getName();</div><div class="line">new new Foo().getName();</div></pre></td></tr></table></figure>
<p>具体讲解参见<a href="http://www.cnblogs.com/xxcanghai/p/5189353.html" target="_blank" rel="external">一道常被人轻视的前端JS面试题</a></p>
<h3 id="JS数组深浅拷贝"><a href="#JS数组深浅拷贝" class="headerlink" title="JS数组深浅拷贝"></a>JS数组深浅拷贝</h3><ul>
<li><code>slice</code>实现</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = ['old', 1, true, null, undefined];</div><div class="line"></div><div class="line">var new_arr = arr.slice();</div><div class="line"></div><div class="line">new_arr[0] = 'new';</div><div class="line"></div><div class="line">console.log(arr) // ["old", 1, true, null, undefined]</div><div class="line">console.log(new_arr) // ["new", 1, true, null, undefined]</div></pre></td></tr></table></figure>
<ul>
<li><code>concat</code>实现</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = ['old', 1, true, null, undefined];</div><div class="line"></div><div class="line">var new_arr = arr.concat();</div><div class="line"></div><div class="line">new_arr[0] = 'new';</div><div class="line"></div><div class="line">console.log(arr) // ["old", 1, true, null, undefined]</div><div class="line">console.log(new_arr) // ["new", 1, true, null, undefined]</div></pre></td></tr></table></figure>
<p>以上两种方法只是浅拷贝,如果数组元素是基本类型,就会拷贝一份新的;但是如果数组元素是对象或者数组,就只会拷贝引用(类似指针),修改其中一个就会影响另外一个。</p>
<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></pre></td><td class="code"><pre><div class="line">var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];</div><div class="line"></div><div class="line">var new_arr = arr.concat();</div><div class="line"></div><div class="line">new_arr[0] = 'new';</div><div class="line">new_arr[3][0] = 'new1';</div><div class="line"></div><div class="line">console.log(arr) // ["old", 1, true, ['new1', 'old2'], {old: 1}]</div><div class="line">console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]</div></pre></td></tr></table></figure>
<ul>
<li><code>JSON.stringify</code>实现数组深拷贝</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];</div><div class="line"></div><div class="line">var new_arr = JSON.parse(JSON.stringify(arr));</div><div class="line"></div><div class="line">new_arr[0] = 'new';</div><div class="line">new_arr[3][0] = 'new1';</div><div class="line"></div><div class="line">console.log(arr) // ["old", 1, true, ['old1', 'old2'], {old: 1}]</div><div class="line">console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]</div></pre></td></tr></table></figure>
<p>简单粗暴,但是问题是不能拷贝函数,不推荐。</p>
<p>然后我们来手动实现深浅拷贝。</p>
<ul>
<li>浅拷贝</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var shallowCopy = function (obj) {</div><div class="line"> // 判断是否是数组或者对象</div><div class="line"> if (typeof obj !== 'object') {</div><div class="line"> return</div><div class="line"> }</div><div class="line"> var newObj = obj instanceof Array ? [] : {};</div><div class="line"> for (var key in obj) {</div><div class="line"> if (obj.hasOwnProperty(key)) {</div><div class="line"> newObj[key] = obj[key];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return newObj;</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>深拷贝</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var deepCopy = function (obj) {</div><div class="line"> if (typeof obj !== 'object') {</div><div class="line"> return</div><div class="line"> }</div><div class="line"> var newObj = obj instanceof Array ? [] : {};</div><div class="line"> for (var key in obj) {</div><div class="line"> if (obj.hasOwnProperty(key)) {</div><div class="line"> newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return newObj</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="数组去重"><a href="#数组去重" class="headerlink" title="数组去重"></a>数组去重</h3><ul>
<li><code>filter</code> + <code>indexOf</code></li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">function unique (arr) {</div><div class="line"> var res = arr.filter(function (item, index, array) {</div><div class="line"> return array.indexOf(item) === index;</div><div class="line"> })</div><div class="line"> return res;</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li><code>filter</code> + <code>sort</code></li>
</ul>
<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">function unique (arr) {</div><div class="line"> return arr.concat().sort().filter(function (item, index, array) {</div><div class="line"> return !index || item !== array[index - 1];</div><div class="line"> })</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li><code>ES6</code></li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">function uniqu3 (arr) {</div><div class="line"> return [... new Set(arr)];</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="找出数组中的最大值"><a href="#找出数组中的最大值" class="headerlink" title="找出数组中的最大值"></a>找出数组中的最大值</h3><ul>
<li><code>reduce</code></li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = [6, 4, 1, 8, 2, 11, 3];</div><div class="line"></div><div class="line">function max (prev, next) {</div><div class="line"> return Math.max(prev, next)</div><div class="line">}</div><div class="line"></div><div class="line">console.log(arr.reduce(max));</div></pre></td></tr></table></figure>
<ul>
<li><code>apply</code></li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = [6, 4, 1, 8, 2, 11, 3];</div><div class="line"></div><div class="line">console.log(Math.max.apply(null, arr));</div></pre></td></tr></table></figure>
<ul>
<li><code>ES6</code></li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var arr = [6, 4, 1, 8, 2, 11, 3];</div><div class="line"></div><div class="line">function max (arr) {</div><div class="line"> return Math.max(...arr);</div><div class="line">}</div><div class="line"></div><div class="line">console.log(max(arr));</div></pre></td></tr></table></figure>
<h3 id="打乱数组的方法"><a href="#打乱数组的方法" class="headerlink" title="打乱数组的方法"></a>打乱数组的方法</h3><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></pre></td><td class="code"><pre><div class="line">var arr = [];</div><div class="line">for (var i = 0; i < 100; i++) {</div><div class="line"> arr[i] = i;</div><div class="line">}</div><div class="line"></div><div class="line">arr.sort(function () {</div><div class="line"> return 0.5 - Math.random();</div><div class="line">});</div></pre></td></tr></table></figure>
<h3 id="数组扁平化"><a href="#数组扁平化" class="headerlink" title="数组扁平化"></a>数组扁平化</h3><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></pre></td><td class="code"><pre><div class="line">var arr = [1, [2, [3, 4]]];</div><div class="line"></div><div class="line">function flatten(arr) {</div><div class="line"></div><div class="line"> while (arr.some(item => Array.isArray(item))) {</div><div class="line"> arr = [].concat(...arr);</div><div class="line"> }</div><div class="line"></div><div class="line"> return arr;</div><div class="line">}</div><div class="line"></div><div class="line">console.log(flatten(arr))</div></pre></td></tr></table></figure>
<h3 id="排序"><a href="#排序" class="headerlink" title="排序"></a>排序</h3><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><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">// 冒泡</div><div class="line">function bubbleSort2(arr) {</div><div class="line"> var len = arr.length;</div><div class="line"> for (var i = 0; i <= len - 1; i++) {</div><div class="line"> for (var j = 0; j <= len - i; j++) {</div><div class="line"> if (arr[j + 1] < arr[j]) {</div><div class="line"> var temp;</div><div class="line"> temp = arr[j];</div><div class="line"> arr[j] = arr[j + 1];</div><div class="line"> arr[j + 1] = temp;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> return arr;</div><div class="line">}</div><div class="line"></div><div class="line">// 快速排序</div><div class="line">function quickSort(arr) {</div><div class="line"> if(arr.length == 0) {</div><div class="line"> return []; // 返回空数组</div><div class="line"> }</div><div class="line"></div><div class="line"> var cIndex = Math.floor(arr.length / 2);</div><div class="line"> var c = arr.splice(cIndex, 1);</div><div class="line"> var l = [];</div><div class="line"> var r = [];</div><div class="line"></div><div class="line"> for (var i = 0; i < arr.length; i++) {</div><div class="line"> if(arr[i] < c) {</div><div class="line"> l.push(arr[i]);</div><div class="line"> } else {</div><div class="line"> r.push(arr[i]);</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> return quickSort(l).concat(c, quickSort(r));</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="数字格式化-1234567890-gt-1-234-567-890"><a href="#数字格式化-1234567890-gt-1-234-567-890" class="headerlink" title="数字格式化 1234567890 -> 1,234,567,890"></a>数字格式化 <code>1234567890 -> 1,234,567,890</code></h3><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></pre></td><td class="code"><pre><div class="line">function formatNum (num) {</div><div class="line"> return num.replace(/\B(?=(\d{3})+(?!\d))/g, ',');</div><div class="line">}</div><div class="line">var num = '1234567890';</div><div class="line">var res = formatNum(num);</div><div class="line">console.log(res);</div></pre></td></tr></table></figure>
<h3 id="打乱数组的方法-1"><a href="#打乱数组的方法-1" class="headerlink" title="打乱数组的方法"></a>打乱数组的方法</h3><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></pre></td><td class="code"><pre><div class="line">var arr = [];</div><div class="line">for (var i = 0; i < 100; i++) {</div><div class="line"> arr[i] = i;</div><div class="line">}</div><div class="line"></div><div class="line">arr.sort(function () {</div><div class="line"> return 0.5 - Math.random();</div><div class="line">})</div></pre></td></tr></table></figure>
<h3 id="尾调用优化"><a href="#尾调用优化" class="headerlink" title="尾调用优化"></a>尾调用优化</h3><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><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">function factorial(n) {</div><div class="line"> if (n === 1) return 1;</div><div class="line"> return n * factorial(n-1);</div><div class="line">}</div><div class="line">factorial(5)</div><div class="line"></div><div class="line">/* 优化尾递归 */</div><div class="line">function factorial(n, total) {</div><div class="line"> if (n === 1) return total;</div><div class="line"> return factorial(n - 1, n * total);</div><div class="line">}</div><div class="line">factorial(5, 1)</div></pre></td></tr></table></figure></p>
<h3 id="柯里化"><a href="#柯里化" class="headerlink" title="柯里化"></a>柯里化</h3><p>实现<code>add(1,2)</code>和<code>add(1)(2)</code>均输出<code>3</code><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><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">function add () {</div><div class="line"> let sum = 0;</div><div class="line"> Array.prototype.forEach.call(arguments, function (item, index){</div><div class="line"> if (typeof item !== 'number') {</div><div class="line"> return false;</div><div class="line"> } else {</div><div class="line"> sum += item;</div><div class="line"> }</div><div class="line"> })</div><div class="line"> var tmp = function () {</div><div class="line"> Array.prototype.forEach.call(arguments, function (item, index){</div><div class="line"> if (typeof item !== 'number') {</div><div class="line"> return false;</div><div class="line"> } else {</div><div class="line"> sum += item;</div><div class="line"> }</div><div class="line"> })</div><div class="line"> return tmp;</div><div class="line"> }</div><div class="line"> tmp.toString = function () {</div><div class="line"> return sum</div><div class="line"> }</div><div class="line"> return tmp;</div><div class="line">}</div><div class="line">add(1, 2); // 3</div><div class="line">add(1)(2); // 3</div><div class="line">add(1, 2, 3)(1, 4)(2, 2)(1) // 16</div></pre></td></tr></table></figure></p>
<h3 id="ES8-新特性"><a href="#ES8-新特性" class="headerlink" title="ES8 新特性"></a>ES8 新特性</h3><ul>
<li>字符串填充</li>
</ul>
<figure class="highlight plain"><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">str.padStart(targetLength [, padString])</div><div class="line">str.padEnd(targetLength [, padString])</div></pre></td></tr></table></figure>
<ul>
<li><code>values</code>和<code>entries</code>函数</li>
</ul>
<figure class="highlight plain"><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">Object.values(obj)</div><div class="line">Object.entries(obj)</div></pre></td></tr></table></figure>
<ul>
<li><code>getOwnPropertyDescriptors</code>函数</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">Object.getOwnPropertyDescriptors(obj)</div></pre></td></tr></table></figure>
<ul>
<li>函数参数逗号结尾</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">function es8(var1, var2, var3,) {}</div></pre></td></tr></table></figure>
<ul>
<li>异步函数<br>由<code>async</code>关键词定义的函数声明了一个可以异步执行的函数,返回一个<code>AsyncFunction</code>类型的对象。</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">fucntion fetchTextByPromise () {</div><div class="line"> return new Promise(resolve => {</div><div class="line"> setTimeout(() => {</div><div class="line"> resolve('es8');</div><div class="line"> }, 2000);</div><div class="line"> });</div><div class="line">}</div><div class="line">async function sayHello () {</div><div class="line"> const externalFetchedText = await fetchTextByPromise();</div><div class="line"> console.log(`Hello, ${externalFetchedText}`);</div><div class="line">}</div><div class="line">sayHello();</div></pre></td></tr></table></figure>
<h3 id="数据类型判断"><a href="#数据类型判断" class="headerlink" title="数据类型判断"></a>数据类型判断</h3><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></pre></td><td class="code"><pre><div class="line">var class2type = {};</div><div class="line"></div><div class="line">'Boolean Number String Function Array Date RegExp Object Error Null Undefined'.split(' ').map((item, index) => {</div><div class="line"> class2type['[object ' + item + ']'] = item.toLowerCase();</div><div class="line">})</div><div class="line"></div><div class="line">function type (obj) {</div><div class="line"> return typeof obj === 'object' || typeof obj === 'function' ?</div><div class="line"> class2type[{}.toString.call(obj)] || 'object' : typeof obj;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="防抖"><a href="#防抖" class="headerlink" title="防抖"></a>防抖</h3><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><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">/*</div><div class="line"> * func:需要调用的函数</div><div class="line"> * wait: 防抖时间</div><div class="line"> * immediate:布尔值,是否立即执行</div><div class="line"> **/</div><div class="line"></div><div class="line">var debounce = function (func, wait, immediate) {</div><div class="line"> var timeout;</div><div class="line"> return function () {</div><div class="line"> var context = this;</div><div class="line"> var args = arguments;</div><div class="line"></div><div class="line"> if (timeout) clearTimeout(timeout);</div><div class="line"></div><div class="line"> if (immediate) { // 是否立即执行func</div><div class="line"> var callNow = !timeout;</div><div class="line"> timeout = setTimeout(function () {</div><div class="line"> timeout = null;</div><div class="line"> }, wait);</div><div class="line"></div><div class="line"> if (callNow) {</div><div class="line"> func.apply(context, args);</div><div class="line"> }</div><div class="line"> } else {</div><div class="line"> timeout = setTimeout(function () {</div><div class="line"> func.apply(context, args);</div><div class="line"> }, wait);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="简单的字符串模板"><a href="#简单的字符串模板" class="headerlink" title="简单的字符串模板"></a>简单的字符串模板</h3><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></pre></td><td class="code"><pre><div class="line">var TemplateEngine = function(tpl, data) {</div><div class="line"> var re = /<%([^%>]+)?%>/g, match;</div><div class="line"> while(match = re.exec(tpl)) {</div><div class="line"> tpl = tpl.replace(match[0], data[match[1]])</div><div class="line"> }</div><div class="line"> return tpl;</div><div class="line">}</div><div class="line"></div><div class="line">var template = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';</div><div class="line">console.log(TemplateEngine(template, {</div><div class="line"> name: "Yeaseon",</div><div class="line"> age: 24</div><div class="line">}));</div><div class="line"></div><div class="line">// '<p>Hello, my name is Yeaseon. I\'m 24 years old.</p>';</div></pre></td></tr></table></figure>
<h3 id="apply、call和bind"><a href="#apply、call和bind" class="headerlink" title="apply、call和bind"></a><code>apply</code>、<code>call</code>和<code>bind</code></h3><ul>
<li><code>apply</code>和<code>call</code></li>
</ul>
<p>在严格模式下,未指定环境对象而调用函数,则this 值不会转型为window。除非明确把函数添加到某个对象或者调用apply()或call(),否则this 值将是undefined。</p>
<p>在非严格模式下,call、apply的第一个参数传递为null或undefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window。</p>
<ul>
<li><code>apply</code>、<code>call</code>和<code>bind</code>比较</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">var obj = {</div><div class="line"> x: 81</div><div class="line">};</div><div class="line"></div><div class="line">var foo = {</div><div class="line"> getX: function () {</div><div class="line"> return this.x;</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">console.log(foo.getX.bind(obj)());</div><div class="line">console.log(foo.getX.apply(obj));</div><div class="line">console.log(foo.getX.call(obj));</div></pre></td></tr></table></figure>
<p>很明显,<code>bind</code>方法后面多了一对括号。也就是说,当你希望改变上下文环境之后并且立即执行,而是回调执行的时候(多用于事件监听器函数),使用<code>bind()</code>方法,而<code>apply/call</code>则会立即执行函数。</p>
<ul>
<li>定义一个 log 方法,让它可以代理 console.log 方法。</li>
</ul>
<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">function log(){</div><div class="line"> console.log.apply(console, arguments);</div><div class="line">};</div><div class="line">log(1); //1</div><div class="line">log(1,2); //1 2</div></pre></td></tr></table></figure>
<ul>
<li>给每一个 log 消息添加一个”(app)”的前辍,比如:</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">log("hello world"); //(app)hello world</div></pre></td></tr></table></figure>
<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">function log(){</div><div class="line"> var args = Array.prototype.slice.call(arguments);</div><div class="line"> args.unshift('(app)');</div><div class="line"> console.log.apply(console, args);</div><div class="line">};</div></pre></td></tr></table></figure>
<ul>
<li><code>apply</code>实现<code>bind</code></li>
</ul>
<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">function bind (fn, context) {</div><div class="line"> return function () {</div><div class="line"> return fn.apply(context, argument);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="创建对象"><a href="#创建对象" class="headerlink" title="创建对象"></a>创建对象</h3><ul>
<li>工厂模式</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">function createPerson(name, age, job){</div><div class="line"> var o = new Object();</div><div class="line"> o.name = name;</div><div class="line"> o.age = age;</div><div class="line"> o.job = job;</div><div class="line"> o.sayName = function(){</div><div class="line"> alert(this.name);</div><div class="line"> };</div><div class="line"> return o;</div><div class="line">}</div><div class="line">var person1 = createPerson("Nicholas", 29, "Software Engineer");</div><div class="line">var person2 = createPerson("Greg", 27, "Doctor");</div></pre></td></tr></table></figure>
<ul>
<li>构造函数模式</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">function Person(name, age, job){</div><div class="line"> this.name = name;</div><div class="line"> this.age = age;</div><div class="line"> this.job = job;</div><div class="line"> this.sayName = function(){</div><div class="line"> alert(this.name);</div><div class="line"> };</div><div class="line">}</div><div class="line">var person1 = new Person("Nicholas", 29, "Software Engineer");</div><div class="line">var person2 = new Person("Greg", 27, "Doctor");</div></pre></td></tr></table></figure>
<ul>
<li>原型模式</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">function Person(){</div><div class="line">}</div><div class="line">Person.prototype.name = "Nicholas";</div><div class="line">Person.prototype.age = 29;</div><div class="line">Person.prototype.job = "Software Engineer";</div><div class="line">Person.prototype.sayName = function(){</div><div class="line"> alert(this.name);</div><div class="line">};</div><div class="line">var person1 = new Person();</div><div class="line">person1.sayName(); //"Nicholas"</div></pre></td></tr></table></figure>
<ul>
<li>构造函数 + 原型模式</li>
</ul>
<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">function Person(name, age, job){</div><div class="line"> this.name = name;</div><div class="line"> this.age = age;</div><div class="line"> this.job = job;</div><div class="line"> this.friends = ["Shelby", "Court"];</div><div class="line">}</div><div class="line">Person.prototype = {</div><div class="line"> constructor : Person,</div><div class="line"> sayName : function(){</div><div class="line"> alert(this.name);</div><div class="line"> }</div><div class="line">}</div><div class="line">var person1 = new Person("Nicholas", 29, "Software Engineer");</div><div class="line">var person2 = new Person("Greg", 27, "Doctor");</div><div class="line">person1.friends.push("Van");</div><div class="line">alert(person1.friends); //"Shelby,Count,Van"</div><div class="line">alert(person2.friends); //"Shelby,Count"</div><div class="line">alert(person1.friends === person2.friends); //false</div><div class="line">alert(person1.sayName === person2.sayName); //true</div></pre></td></tr></table></figure>
<h3 id="JS实现Jquery的extend-方法"><a href="#JS实现Jquery的extend-方法" class="headerlink" title="JS实现Jquery的extend()方法"></a>JS实现Jquery的<code>extend()</code>方法</h3><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><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></pre></td><td class="code"><pre><div class="line">function extend() {</div><div class="line"> // 默认不进行深拷贝</div><div class="line"> var deep = false;</div><div class="line"> var name, options, src, copy, clone, copyIsArray;</div><div class="line"> var length = arguments.length;</div><div class="line"> // 记录要复制的对象的下标</div><div class="line"> var i = 1;</div><div class="line"> // 第一个参数不传布尔值的情况下,target 默认是第一个参数</div><div class="line"> var target = arguments[0] || {};</div><div class="line"> // 如果第一个参数是布尔值,第二个参数是 target</div><div class="line"> if (typeof target == 'boolean') {</div><div class="line"> deep = target;</div><div class="line"> target = arguments[i] || {};</div><div class="line"> i++;</div><div class="line"> }</div><div class="line"> // 如果target不是对象,我们是无法进行复制的,所以设为 {}</div><div class="line"> if (typeof target !== "object" && !isFunction(target)) {</div><div class="line"> target = {};</div><div class="line"> }</div><div class="line"></div><div class="line"> // 循环遍历要复制的对象们</div><div class="line"> for (; i < length; i++) {</div><div class="line"> // 获取当前对象</div><div class="line"> options = arguments[i];</div><div class="line"> // 要求不能为空 避免 extend(a,,b) 这种情况</div><div class="line"> if (options != null) {</div><div class="line"> for (name in options) {</div><div class="line"> // 目标属性值</div><div class="line"> src = target[name];</div><div class="line"> // 要复制的对象的属性值</div><div class="line"> copy = options[name];</div><div class="line"></div><div class="line"> // 解决循环引用</div><div class="line"> if (target === copy) {</div><div class="line"> continue;</div><div class="line"> }</div><div class="line"></div><div class="line"> // 要递归的对象必须是 plainObject 或者数组</div><div class="line"> if (deep && copy && (isPlainObject(copy) ||</div><div class="line"> (copyIsArray = Array.isArray(copy)))) {</div><div class="line"> // 要复制的对象属性值类型需要与目标属性值相同</div><div class="line"> if (copyIsArray) {</div><div class="line"> copyIsArray = false;</div><div class="line"> clone = src && Array.isArray(src) ? src : [];</div><div class="line"></div><div class="line"> } else {</div><div class="line"> clone = src && isPlainObject(src) ? src : {};</div><div class="line"> }</div><div class="line"></div><div class="line"> target[name] = extend(deep, clone, copy);</div><div class="line"></div><div class="line"> } else if (copy !== undefined) {</div><div class="line"> target[name] = copy;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> return target;</div><div class="line">};</div></pre></td></tr></table></figure>
<h3 id="自定义事件(通过观察者模式)"><a href="#自定义事件(通过观察者模式)" class="headerlink" title="自定义事件(通过观察者模式)"></a>自定义事件(通过观察者模式)</h3><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><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">function EventTarget () {</div><div class="line"> this.handlers = {};</div><div class="line">}</div><div class="line"></div><div class="line">EventTarget.prototype = {</div><div class="line"> constructor: EventTarget,</div><div class="line"> addHandler: function (type, handler) {</div><div class="line"> if (typeof this.handlers[type] == 'undefined') {</div><div class="line"> this.handlers[type] = [];</div><div class="line"> }</div><div class="line"> this.handlers[type].push(handler)</div><div class="line"> },</div><div class="line"> fire: function (event) {</div><div class="line"> if (!event.target) {</div><div class="line"> event.target = this;</div><div class="line"> }</div><div class="line"> if (this.handlers[event.type] instanceof Array) {</div><div class="line"> var handlers = this.handlers[event.type];</div><div class="line"> for (var i = 0, len = handlers.length; i < len; i++) {</div><div class="line"> handlers[i](event);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> },</div><div class="line"> removeHandler: function (type, handler) {</div><div class="line"> if (this.handlers[type] instanceof Array) {</div><div class="line"> var handlers = this.handlers[type];</div><div class="line"> for (var i = 0, len = handlers.length; i < len; i++) {</div><div class="line"> if (handlers[i] === handler) {</div><div class="line"> break;</div><div class="line"> }</div><div class="line"> }</div><div class="line"> handlers.splice(i, 1);</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h2 id="安全"><a href="#安全" class="headerlink" title="安全"></a>安全</h2><h3 id="跨域的几种方法"><a href="#跨域的几种方法" class="headerlink" title="跨域的几种方法"></a>跨域的几种方法</h3><ol>
<li>主域相同的跨域</li>
</ol>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">document.domain</div></pre></td></tr></table></figure>
<ol>
<li><p><code>window.postMessage</code></p>
</li>
<li><p><code>JSONP</code>跨域(只支持<code>GET</code>)</p>
</li>
</ol>
<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></pre></td><td class="code"><pre><div class="line">function todo(data){</div><div class="line"> console.log('The author is: '+ data.name);</div><div class="line">}</div><div class="line"></div><div class="line">var script = document.createElement('script');</div><div class="line">/* 向服务器www.yeaseonzhang.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字。 */</div><div class="line">script.src = 'http://www.yeaseonzhang.com/author?callback=todo';</div><div class="line">document.body.appendChild(script);</div><div class="line">/* 服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 */</div><div class="line">todo({"name": "fewjq"});</div><div class="line">/* 由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了todo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象。*/</div></pre></td></tr></table></figure>
<ol>
<li><code>websocket</code>跨域</li>
</ol>
<h3 id="XSS-和-CSRF"><a href="#XSS-和-CSRF" class="headerlink" title="XSS 和 CSRF"></a>XSS 和 CSRF</h3><ul>
<li><a href="http://blog.csdn.net/ghsau/article/details/17027893" target="_blank" rel="external">XSS</a></li>
<li><a href="http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html" target="_blank" rel="external">CSRF</a></li>
</ul>
<h2 id="性能"><a href="#性能" class="headerlink" title="性能"></a>性能</h2><h3 id="CSS-优化"><a href="#CSS-优化" class="headerlink" title="CSS 优化"></a>CSS 优化</h3><ul>
<li>正确的时机调用CSS</li>
<li>使用媒体查询标记<code><link></code>,选择性加载</li>
<li>减少css文件数量</li>
<li>压缩css代码</li>
</ul>
<h3 id="渲染"><a href="#渲染" class="headerlink" title="渲染"></a>渲染</h3><ul>
<li><a href="http://coolshell.cn/articles/9666.html" target="_blank" rel="external">浏览器渲染原理</a></li>
</ul>
]]></content>
<summary type="html">
<p>“金三银四,金九银十”,用来形容求职最好的几个月。但是随着行业的饱和,初中级前端er就业形势不容乐观。</p>
<p>行业状态不可控,我们能做的当然只是让自己变得更加具有竞争力。</p>
<p>今年自己也用了几个月的时间来准备笔记面试,巩固基础知识。特此将自己在这个过程总结的题目分享出来,希望对于求职和准备求职的同学有所帮助。</p>
</summary>
<category term="面试" scheme="https://yeaseonzhang.github.io/tags/%E9%9D%A2%E8%AF%95/"/>
</entry>
<entry>
<title>深入理解Flex属性</title>
<link href="https://yeaseonzhang.github.io/2017/07/05/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Flex%E5%B1%9E%E6%80%A7/"/>
<id>https://yeaseonzhang.github.io/2017/07/05/深入理解Flex属性/</id>
<published>2017-07-05T06:25:59.000Z</published>
<updated>2017-10-12T14:12:17.929Z</updated>
<content type="html"><![CDATA[<p>Flex 是 Flexible Box的缩写,意为“弹性布局”,可以简便、完整、响应式地实现各种页面布局。</p>
<p>Flex的出现就是为了解决传统布局的<code>display</code>属性 + <code>position</code>属性 + <code>float</code>属性的复杂性。</p>
<a id="more"></a>
<h2 id="浏览器对于Flex的支持性"><a href="#浏览器对于Flex的支持性" class="headerlink" title="浏览器对于Flex的支持性"></a>浏览器对于Flex的支持性</h2><img src="/2017/07/05/深入理解Flex属性/caniuse.png" alt="https://caniuse.com/" title="https://caniuse.com/">
<p>可以看到浏览器对于Flex布局的支持性已经很好了,所以我们可以放心大胆的用在我们项目中。</p>
<h2 id="flex-属性"><a href="#flex-属性" class="headerlink" title="flex 属性"></a>flex 属性</h2><p><code>flex: flex-grow | flex-shrink | flex-basis</code></p>
<p>flex属性包含三个值:<code>flex-grow</code>、<code>flex-shrink</code>和<code>flex-basis</code></p>
<ul>
<li><code>flex-grow</code>: 扩展比例</li>
<li><code>flex-shrink</code>: 收缩比例</li>
<li><code>flex-basis</code>: 伸缩基准值</li>
</ul>
<p>首先我们简单写一个flex布局的Demo</p>
<blockquote>
<p>HTML</p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"parent"</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"child_1"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"child_2"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"child_3"</span>></span><span class="tag"></<span class="name">div</span>></span></div><div class="line"><span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></table></figure>
<blockquote>
<p>CSS</p>
</blockquote>
<figure class="highlight css"><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="selector-class">.child_1</span>,</div><div class="line"><span class="selector-class">.child_2</span>,</div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">1</span>;</div><div class="line"> <span class="attribute">height</span>: <span class="number">200px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_1</span> {</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(255, 0, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_2</span> {</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 255, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 0, 255, .5);</div><div class="line">}</div></pre></td></tr></table></figure>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="yzqpeQ" data-default-tab="css,result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="Flex-1" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/yzqpeQ/" target="_blank" rel="external">Flex-1</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>设置父元素<code>display: flex</code>,其子元素就能使用flex布局,我们只是简单的为子元素使用了<code>flex: 1</code>就实现了三等分,而且会随着父元素的宽度变化而变化。这就是我们平时flex布局的简单用法,即各个子元素按照比例布局。</p>
<p><code>flex: 1</code>其实是<code>flex: 1 1 0%</code>的简写属性,即伸缩比例都是1。下面我们就分别理解下三个属性值对于布局的影响。</p>
<h2 id="flex-basis-属性"><a href="#flex-basis-属性" class="headerlink" title="flex-basis 属性"></a>flex-basis 属性</h2><p><code>flex-basis</code>属性是伸缩的基准值,这个属性也是我们计算最终宽度的决定性因素。</p>
<p>通过子元素<code>flex-basis</code>属性和与父元素(容器)宽度值进行比较,会出现两种情况(忽略相等的情况):</p>
<ul>
<li>子元素<code>flex-basis</code>属性和 < 父元素宽度</li>
<li>子元素<code>flex-basis</code>属性和 > 父元素宽度</li>
</ul>
<p>上面的两种情况就分别对应了<code>flex-grow</code>和<code>flex-shrink</code>属性生效的情况,也就是说当子元素的<code>flex-basis</code>属性宽度和小于父元素的宽度值时<code>flex-grow</code>生效,反之<code>flex-shrink</code>生效。</p>
<h2 id="flex-grow-属性"><a href="#flex-grow-属性" class="headerlink" title="flex-grow 属性"></a>flex-grow 属性</h2><p><code>flex-grow</code>属性是扩展比例,上面我们也谈到了当子元素的<code>flex-basis</code>总和小于父元素的宽度值时<code>flex-grow</code>生效。</p>
<p>现在我们就来改变CSS,满足这个前提条件。</p>
<blockquote>
<p>CSS</p>
</blockquote>
<figure class="highlight css"><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="selector-class">.parent</span> {</div><div class="line"> <span class="attribute">display</span>: flex;</div><div class="line"> <span class="attribute">width</span>: <span class="number">600px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_1</span>,</div><div class="line"><span class="selector-class">.child_2</span>,</div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="attribute">height</span>: <span class="number">200px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_1</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">1</span> <span class="number">0</span> <span class="number">150px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(255, 0, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_2</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">100px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 255, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">1</span> <span class="number">0</span> <span class="number">150px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 0, 255, .5);</div><div class="line">}</div></pre></td></tr></table></figure>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="NaBXpz" data-default-tab="css,result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="Flex-2" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/NaBXpz/" target="_blank" rel="external">Flex-2</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>此时,各个元素的<code>flex-basis</code>和为<code>(150 + 100 + 150) = 400px</code>, 小于父元素的<code>600px</code>,我们就来分别计算每个子元素的宽度值。<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></pre></td><td class="code"><pre><div class="line">可用空间 = 父元素width - 子元素flex-basis总和 => 600 - (150 + 100 + 150) = 200</div><div class="line"></div><div class="line">单位扩展空间 = 可用空间/子元素flex-grow总和 => 200/(1 + 0 + 1) = 100</div></pre></td></tr></table></figure></p>
<p>子元素的计算公式为<code>width = flex-basis + flex-grow * 单位扩展空间</code></p>
<p>所以<code>child_1</code>宽度为<code>(150 + 1 * 100) = 250px</code>, <code>child_2</code>宽度为<code>(100 + 0 * 100) = 100px</code>, <code>child_3</code> 同 <code>child_1</code>。</p>
<h2 id="flex-shrink-属性"><a href="#flex-shrink-属性" class="headerlink" title="flex-shrink 属性"></a>flex-shrink 属性</h2><p><code>flex-shrink</code> 属性是收缩比例,当子元素的<code>flex-basis</code>总和大于父元素的宽度值时<code>flex-grow</code>生效。</p>
<p>现在我们就修改CSS满足这个前提。</p>
<blockquote>
<p>CSS</p>
</blockquote>
<figure class="highlight css"><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="selector-class">.parent</span> {</div><div class="line"> <span class="attribute">display</span>: flex;</div><div class="line"> <span class="attribute">width</span>: <span class="number">600px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_1</span>,</div><div class="line"><span class="selector-class">.child_2</span>,</div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="comment">/*flex: 1;*/</span></div><div class="line"> <span class="attribute">height</span>: <span class="number">200px</span>;</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_1</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">1</span> <span class="number">400px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(255, 0, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_2</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">1</span> <span class="number">200px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 255, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line"><span class="selector-class">.child_3</span> {</div><div class="line"> <span class="attribute">flex</span>: <span class="number">0</span> <span class="number">2</span> <span class="number">400px</span>;</div><div class="line"> <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(0, 0, 255, .5);</div><div class="line">}</div></pre></td></tr></table></figure>
<p></p><p data-height="265" data-theme-id="0" data-slug-hash="ZXjvyN" data-default-tab="css,result" data-user="YeaseonZhang" data-embed-version="2" data-pen-title="Flex-3" class="codepen">See the Pen <a href="https://codepen.io/YeaseonZhang/pen/ZXjvyN/" target="_blank" rel="external">Flex-3</a> by YeaseonZhang (<a href="https://codepen.io/YeaseonZhang" target="_blank" rel="external">@YeaseonZhang</a>) on <a href="https://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
<p>当然啦,我们可以按照<code>flex-grow</code>的计算方法套用。</p>
<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></pre></td><td class="code"><pre><div class="line">溢出空间 = 父元素width - 子元素flex-basis总和 => 600 - (400 + 200 + 400) = -400</div><div class="line"></div><div class="line">单位收缩空间 = 溢出空间/子元素flex-shrink总和 => -400/(1 + 2 + 2) = -100</div></pre></td></tr></table></figure>
<p>子元素的计算公式为<code>width = flex-basis + flex-shrink * 单位收缩空间</code></p>
<p>所以<code>child_1</code>宽度为<code>(400 + 1 * (-100)) = 300px</code>, <code>child_2</code>宽度为<code>(200 + 1 * (-100)) = 100px</code>, <code>child_3</code> 同 <code>(400 + 2 * (-100)) = 200px</code>。</p>
<p>大功告成了?其实并没有实例情况并不是我们计算的那样<code>300px 100px 200px</code>,而是<code>285.72px 142.86px 171.42px</code>。</p>
<p>通过Google,发现了一种收缩因数的计算方法:<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">理想空间 = 子元素(flex-basis * flex-shrink)之和 => 400 * 1 + 200 * 1 + 400 * 2 = 1400</div><div class="line"></div><div class="line">溢出空间 = 父元素width - 子元素flex-basis总和 => 600 - (400 + 200 + 400) = -400</div><div class="line"></div><div class="line">收缩因数 = (flex-basis * flex-shrink) / 理想空间 => 400 / 1400 = 0.286; 200 / 1400 = 0.143; 800 / 1400 = 0.571</div></pre></td></tr></table></figure></p>
<p>分别为每个子元素计算了收缩因数就能计算我们子元素的实际宽度,子元素的计算公式<code>width = flex-basis + 收缩因数 * 溢出空间</code></p>
<p>所以<code>child_1</code>宽度为<code>400 + 0.286 * (-400) = 285.6</code>, <code>child_2</code>宽度为<code>200 + 0.143 * (-400) = 142.8</code>, <code>child_3</code>宽度为<code>400 + 0.571 * (-400) = 171.6</code></p>
<p>现在我们计算出的值与浏览器渲染出的值基本上是相同的,我们对于<code>flex</code>属性的了解已经不再是单单的比例计算了,希望本文对你有所帮助。</p>
]]></content>
<summary type="html">
<p>Flex 是 Flexible Box的缩写,意为“弹性布局”,可以简便、完整、响应式地实现各种页面布局。</p>
<p>Flex的出现就是为了解决传统布局的<code>display</code>属性 + <code>position</code>属性 + <code>float</code>属性的复杂性。</p>
</summary>
</entry>
<entry>
<title>CSS布局</title>
<link href="https://yeaseonzhang.github.io/2017/07/05/CSS%E5%B8%83%E5%B1%80/"/>
<id>https://yeaseonzhang.github.io/2017/07/05/CSS布局/</id>
<published>2017-07-05T03:05:06.000Z</published>
<updated>2017-07-23T15:04:40.249Z</updated>
<content type="html"><![CDATA[<p>由于最近工作比较饱和,也没有太多的心思去写博客。今天更新一篇,我们来谈谈圣杯布局和双飞翼布局。</p>
<a id="more"></a>
<h3 id="圣杯布局"><a href="#圣杯布局" class="headerlink" title="圣杯布局"></a>圣杯布局</h3><blockquote>
<p>HTML</p>
</blockquote>
<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></pre></td><td class="code"><pre><div class="line"><!DOCTYPE html></div><div class="line"><html lang="en"></div><div class="line"><head></div><div class="line"> <meta charset="UTF-8"></div><div class="line"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></div><div class="line"> <meta http-equiv="X-UA-Compatible" content="ie=edge"></div><div class="line"> <title>Holy Grail Layout</title></div><div class="line"> <link rel="stylesheet" href="./base.css"></div><div class="line"></head></div><div class="line"><body></div><div class="line"> <div class="container"></div><div class="line"> <div class="main"></div></div><div class="line"> <div class="sub"></div></div><div class="line"> <div class="extra"></div></div><div class="line"> </div></div><div class="line"></body></div><div class="line"></html></div></pre></td></tr></table></figure>
<blockquote>
<p>CSS</p>
</blockquote>
<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><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">body {</div><div class="line"> min-width: 600px;</div><div class="line">}</div><div class="line"></div><div class="line">.container {</div><div class="line"> padding-left: 210px;</div><div class="line"> padding-right: 190px;</div><div class="line">}</div><div class="line"></div><div class="line">.main {</div><div class="line"> float: left;</div><div class="line"> width: 100%;</div><div class="line"> height: 300px;</div><div class="line"> background-color: rgba(255, 0, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line">.sub {</div><div class="line"> position: relative;</div><div class="line"> left: -210px;</div><div class="line"> float: left;</div><div class="line"> width: 200px;</div><div class="line"> height: 300px;</div><div class="line"> margin-left: -100%;</div><div class="line"> background-color: rgba(0, 255, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line">.extra {</div><div class="line"> position: relative;</div><div class="line"> right: -190px;</div><div class="line"> float: left;</div><div class="line"> width: 180px;</div><div class="line"> height: 300px;</div><div class="line"> margin-left: -180px;</div><div class="line"> background-color: rgba(0, 0, 255, 0.5);</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="双飞翼布局"><a href="#双飞翼布局" class="headerlink" title="双飞翼布局"></a>双飞翼布局</h3><blockquote>
<p>HTML</p>
</blockquote>
<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><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><!DOCTYPE html></div><div class="line"><html lang="en"></div><div class="line"></div><div class="line"><head></div><div class="line"> <meta charset="UTF-8"></div><div class="line"> <meta name="viewport" content="width=device-width, initial-scale=1.0"></div><div class="line"> <meta http-equiv="X-UA-Compatible" content="ie=edge"></div><div class="line"> <title>Double Wing Layout</title></div><div class="line"> <link rel="stylesheet" href="./base.css"></div><div class="line"></head></div><div class="line"></div><div class="line"><body></div><div class="line"> <div class="main-wrapper"></div><div class="line"> <div class="main"></div></div><div class="line"> </div></div><div class="line"> <div class="sub"></div></div><div class="line"> <div class="extra"></div></div><div class="line"></body></div><div class="line"></div><div class="line"></html></div></pre></td></tr></table></figure>
<blockquote>
<p>CSS</p>
</blockquote>
<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><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">.main-wrapper {</div><div class="line"> float: left;</div><div class="line"> width: 100%;</div><div class="line">}</div><div class="line"></div><div class="line">.main {</div><div class="line"> height: 300px;</div><div class="line"> margin-left: 210px;</div><div class="line"> margin-right: 190px;</div><div class="line"> background-color: rgba(255, 0, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line">.sub {</div><div class="line"> float: left;</div><div class="line"> width: 200px;</div><div class="line"> height: 300px;</div><div class="line"> margin-left: -100%;</div><div class="line"> background-color: rgba(0, 255, 0, .5);</div><div class="line">}</div><div class="line"></div><div class="line">.extra {</div><div class="line"> float: left;</div><div class="line"> width: 180px;</div><div class="line"> height: 300px;</div><div class="line"> margin-left: -180px;</div><div class="line"> background-color: rgba(0, 0, 255, .5);</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>由于最近工作比较饱和,也没有太多的心思去写博客。今天更新一篇,我们来谈谈圣杯布局和双飞翼布局。</p>
</summary>
</entry>
<entry>
<title>CSS设计指南·读书笔记</title>
<link href="https://yeaseonzhang.github.io/2017/05/14/CSS%E8%AE%BE%E8%AE%A1%E6%8C%87%E5%8D%97%C2%B7%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
<id>https://yeaseonzhang.github.io/2017/05/14/CSS设计指南·读书笔记/</id>
<published>2017-05-14T05:30:08.000Z</published>
<updated>2017-06-24T16:56:26.140Z</updated>
<content type="html"><![CDATA[<img src="/2017/05/14/CSS设计指南·读书笔记/stylin_with_css.jpg" alt="CSS设计指南" title="CSS设计指南">
<p>前端开发中,JS很重要,但CSS也不能轻视,我们来一场CSS学习之旅。</p>
<a id="more"></a>
<h2 id="CSS-工作原理"><a href="#CSS-工作原理" class="headerlink" title="CSS 工作原理"></a>CSS 工作原理</h2><h3 id="特殊的上下文选择符"><a href="#特殊的上下文选择符" class="headerlink" title="特殊的上下文选择符"></a>特殊的上下文选择符</h3><h4 id="子选择符-gt"><a href="#子选择符-gt" class="headerlink" title="子选择符 >"></a>子选择符 ></h4><p><code>标签1 > 标签2</code></p>
<p><strong>标签2</strong>必须是<strong>标签1</strong>的子元素,反过来说,<strong>标签1</strong>是<strong>标签2</strong>的父元素。</p>
<h4 id="紧邻同胞选择符"><a href="#紧邻同胞选择符" class="headerlink" title="紧邻同胞选择符 +"></a>紧邻同胞选择符 +</h4><p><code>标签1 + 标签2</code></p>
<p><strong>标签2</strong>必须紧跟在其同胞<strong>标签1</strong>的后面。</p>
<h4 id="一般同胞选择符"><a href="#一般同胞选择符" class="headerlink" title="一般同胞选择符 ~"></a>一般同胞选择符 ~</h4><p><code>标签1 ~ 标签2</code></p>
<p><strong>标签2</strong>必须跟在其同胞<strong>标签1</strong>后面。</p>
<h4 id="通用选择符"><a href="#通用选择符" class="headerlink" title="通用选择符 *"></a>通用选择符 *</h4><p>通用选择符<code>*</code>是一个通配符,它匹配任何元素。不过,一般在使用<code>*</code>选择符时,都会同时使用另一个选择符,比如:<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></pre></td><td class="code"><pre><div class="line">p * {</div><div class="line"> color: red;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>这样只会把<code>p</code>包含的所有元素的文本变成红色。</p>
<p>还可以用它构成<strong>非子选择符</strong>,比如:<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></pre></td><td class="code"><pre><div class="line">section * a {</div><div class="line"> font-size: 14px;</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>所有<code>section</code>孙子元素<code>a</code>都会被选中,至于<code>a</code>的父元素是什么,没有关系。</p>
<h3 id="ID和类选择符"><a href="#ID和类选择符" class="headerlink" title="ID和类选择符"></a>ID和类选择符</h3><h4 id="ID-属性"><a href="#ID-属性" class="headerlink" title="ID 属性"></a>ID 属性</h4><p>用于页内导航ID<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></pre></td><td class="code"><pre><div class="line"><a href="#first">First title</a></div><div class="line"></div><div class="line"><h2 id="first">First title</h2></div></pre></td></tr></table></figure></p>
<p><code>href</code>属性以<code>#</code>开头,<code>#first</code>就是一个页面的锚点,会与使用了CSS选择符里面相同的<code>id="first"</code>元素做匹配,就会把页面定位到<code>h2#first</code>的位置,这也就是为什么CSS的<code>id</code>选择器在页面中只能使用一次。</p>
<h3 id="属性选择符"><a href="#属性选择符" class="headerlink" title="属性选择符"></a>属性选择符</h3><h4 id="属性名选择符"><a href="#属性名选择符" class="headerlink" title="属性名选择符"></a>属性名选择符</h4><p><code>标签名[属性名]</code></p>
<p>选择任何带有<code>属性名</code>的<code>标签名</code></p>
<h4 id="属性值选择符"><a href="#属性值选择符" class="headerlink" title="属性值选择符"></a>属性值选择符</h4><p><code>标签名[属性名='属性值']</code></p>
<p><strong>注</strong>:在HTML5中,<code>属性值</code>的引号可以不加,但是推荐添加。</p>
<h3 id="伪类"><a href="#伪类" class="headerlink" title="伪类"></a>伪类</h3><p>伪类这个叫法源自它们与类相似,但实际上没有类会附加到标记中的标签上。</p>
<ul>
<li><strong>UI伪类</strong>会在HTML元素处于某个状态时,为该元素应用CSS样式。</li>
<li><strong>结构化伪类</strong>会在标记中存在某个结构上的关系时,为相应元素应用CSS样式。</li>
</ul>
<h4 id="UI伪类"><a href="#UI伪类" class="headerlink" title="UI伪类"></a>UI伪类</h4><h5 id="链接伪类"><a href="#链接伪类" class="headerlink" title="链接伪类"></a>链接伪类</h5><ul>
<li>Link,未点击状态</li>
<li>Visited,点击过这个链接</li>
<li>Hover,鼠标悬停在这个链接上</li>
<li>Active,链接正在被点击(鼠标在元素上按下,还没有释放)</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">a:link { color: black; }</div><div class="line">a:visited { color: gray; }</div><div class="line">a:hover { text-decoration: none; }</div><div class="line">a:active { color: red; }</div></pre></td></tr></table></figure>
<p>按照<code>LoVe HA</code>的顺序使用它们,否则浏览器可能不会显示预期结果。</p>
<blockquote>
<p>一个冒号(<code>:</code>)表示伪类,两个冒号(<code>::</code>)表示CSS3新增伪类。</p>
</blockquote>
<h5 id="focus-伪类"><a href="#focus-伪类" class="headerlink" title=":focus 伪类"></a>:focus 伪类</h5><p><code>e:focus</code></p>
<blockquote>
<p>在后续例子中,e表示任何元素,不再以文字表示</p>
</blockquote>
<p>获得焦点时,<code>:focus</code>伪类生效<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">input:focus { border: 1px solid blue; }</div></pre></td></tr></table></figure></p>
<h5 id="target-伪类"><a href="#target-伪类" class="headerlink" title=":target 伪类"></a>:target 伪类</h5><p><code>e:target</code></p>
<p>如果用户点击一个指向页面中其他元素的链接,则那个元素就是<strong>target</strong>,可以用<code>:target</code>伪类选中它。</p>
<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></pre></td><td class="code"><pre><div class="line"><a href="#more_info">More Information</a></div><div class="line"></div><div class="line"><h2 id="more_info">This is the information you are looking for.</h2></div><div class="line"></div><div class="line">// CSS</div><div class="line">#more_info:target { background: #eee }</div></pre></td></tr></table></figure>
<p>当用户点击链接转向<strong>ID</strong>为<code>more_info</code>的元素时,为该元素添加<code>#eee</code>背景。</p>
<h4 id="结构化伪类"><a href="#结构化伪类" class="headerlink" title="结构化伪类"></a>结构化伪类</h4><h5 id="first-child-和-last-child"><a href="#first-child-和-last-child" class="headerlink" title=":first-child 和 :last-child"></a>:first-child 和 :last-child</h5><p><code>e:first-child</code><br><code>e:last-child</code></p>
<p><code>:first-child</code>代表一组同胞元素中的第一个元素,而<code>:last-child</code>代表最后一个。<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><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">// css</div><div class="line">ol.results li:first-child {</div><div class="line"> color:blue;</div><div class="line">}</div><div class="line"></div><div class="line">// html</div><div class="line"><ol class="results"></div><div class="line"> <li>My Fast Pony</li></div><div class="line"> <li>Steady Trotter</li></div><div class="line"> <li>Slow Ol' Nag</li></div><div class="line"></ol></div></pre></td></tr></table></figure></p>
<p>第一个<code><li></code>就会被选中,<strong>My Fast Pony</strong>就会变成蓝色。</p>
<h5 id="nth-child"><a href="#nth-child" class="headerlink" title=":nth-child"></a>:nth-child</h5><p><code>e:nth-child(n)</code></p>
<blockquote>
<p>n 表示一个数值(也可以是 odd 或 even)</p>
</blockquote>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">li:nth-child(3) {...}</div></pre></td></tr></table></figure>
<h3 id="伪元素"><a href="#伪元素" class="headerlink" title="伪元素"></a>伪元素</h3><p>伪元素就是文档中若有实无的元素。</p>
<h4 id="first-letter-伪元素"><a href="#first-letter-伪元素" class="headerlink" title="::first-letter 伪元素"></a>::first-letter 伪元素</h4><p><code>e::first-letter</code></p>
<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></pre></td><td class="code"><pre><div class="line">p::first-letter {</div><div class="line"> font-size: 300%;</div><div class="line">}</div></pre></td></tr></table></figure>
<p>上面的CSS样式就可以得到段落首字母放大的效果。</p>
<h4 id="first-line-伪元素"><a href="#first-line-伪元素" class="headerlink" title="::first-line 伪元素"></a>::first-line 伪元素</h4><p><code>e::first-line</code></p>
<p>可以选中文本段落的第一行。</p>
<h4 id="before-和-after-伪元素"><a href="#before-和-after-伪元素" class="headerlink" title="::before 和 ::after 伪元素"></a>::before 和 ::after 伪元素</h4><p><code>e::before</code><br><code>e::after</code></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><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"><p class="age">25</p></div><div class="line"></div><div class="line">// css</div><div class="line">p.age::before {</div><div class="line"> content: 'Age: ';</div><div class="line">}</div><div class="line">p.age::after {</div><div class="line"> content: ' years.';</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>就能得到结果:<br><code>Age: 25 years.</code></p>
<h3 id="层叠"><a href="#层叠" class="headerlink" title="层叠"></a>层叠</h3><h4 id="计算特指度"><a href="#计算特指度" class="headerlink" title="计算特指度"></a>计算特指度</h4><p>下面具体讲讲怎么计算选择符的特指度。首先,有一个简单的计分规则,即每个选择符都要按下面的“<strong>ICE</strong>”公式计算三个值:<br><code>I - C - E</code> (ID Class Element)</p>
<p>针对这个公式的计分方法如下:</p>
<ol>
<li>选择符中有一个ID,就在<strong>I</strong>的位置上加1</li>
<li>选择符中有一个类,就在<strong>C</strong>的位置上加1</li>
<li>选择符中有一个元素名,就在<strong>E</strong>的位置上加1</li>
<li>得到一个三位数</li>
</ol>
<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></pre></td><td class="code"><pre><div class="line">p 0-0-1 特指度=1</div><div class="line">p.largetext 0-1-1 特指度=11</div><div class="line">p#largetext 1-0-1 特指度=101</div><div class="line">body p#largetext 1-0-2 特指度=102</div><div class="line">body p#largetext ul.mylist 1-1-3 特指度=113</div><div class="line">body p#largetext ul.mylist li 1-1-4 特指度=114</div></pre></td></tr></table></figure>
<h3 id="规则声明"><a href="#规则声明" class="headerlink" title="规则声明"></a>规则声明</h3><h4 id="数字值"><a href="#数字值" class="headerlink" title="数字值"></a>数字值</h4><p><code>em</code> 和 <code>ex</code> 都是字体大小的单位,但在CSS中,它们作为长度单位适用于任何元素。</p>
<ul>
<li><code>em</code>,它表示一种字体中字母<strong>M</strong>的宽度,因此大小取决于字体</li>
<li><code>ex</code>,表示给定字体中字母<strong>x</strong>的高度,不包括字母上、下突出的部分</li>
</ul>
<h4 id="颜色值"><a href="#颜色值" class="headerlink" title="颜色值"></a>颜色值</h4><h5 id="颜色名"><a href="#颜色名" class="headerlink" title="颜色名"></a>颜色名</h5><ul>
<li>aqua 浅绿色</li>
<li>black 黑色</li>
<li>blue 蓝色</li>
<li>fuchsia 紫红色</li>
<li>gray 灰色</li>
<li>green 绿色</li>
<li>lime 黄绿色</li>
<li>maroon 褐红色</li>
<li>navy 深蓝色</li>
<li>olive 茶青色</li>
<li>purple 紫色</li>
<li>red 红色</li>
<li>sliver 银色</li>
<li>teal 青色</li>
<li>white 白色</li>
<li>yellow 黄色</li>
</ul>
<p>以上就是<strong>W3C</strong>定义了16个颜色的关键字。</p>
<h2 id="定位元素"><a href="#定位元素" class="headerlink" title="定位元素"></a>定位元素</h2><h3 id="盒子有多大"><a href="#盒子有多大" class="headerlink" title="盒子有多大"></a>盒子有多大</h3><p>盒模型结论一:没有(就是没有设置<code>width</code>的)宽度的元素始终会扩展到填满其父元素的宽度为止。添加水平边框、内边距和外边距,<br>会导致内容宽度减少,减少量等于水平边框、内边距和外边距的和。</p>
<p>盒模型结论二:为设定了宽度的盒子添加边框、内边距和外边距,会导致盒子扩展得更宽。实际上,盒子的<code>width</code>属性设定的只是盒子内容区的宽度,<br>而非盒子要占据的水平宽度。</p>
<p>CSS3新增的<strong>box-sizing</strong>属性,强制转换盒子模型。</p>
<h3 id="浮动与清除"><a href="#浮动与清除" class="headerlink" title="浮动与清除"></a>浮动与清除</h3><h4 id="围住浮动元素的三种方法"><a href="#围住浮动元素的三种方法" class="headerlink" title="围住浮动元素的三种方法"></a>围住浮动元素的三种方法</h4><ul>
<li>为父元素添加<code>overflow:hidden</code></li>
<li>同时浮动父元素<code>float: left/right</code></li>
<li>添加非浮动的清除元素或者给父元素添加<code>clearfix</code>类</li>
</ul>
<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></pre></td><td class="code"><pre><div class="line">// HTML</div><div class="line"><section class="clearfix"></div><div class="line"> <img src="images/rubber_duck.jpg"></div><div class="line"> <p>It's fun to float.</p></div><div class="line"></section></div><div class="line"><footer>Here is the footer element...</footer></div><div class="line"></div><div class="line">// CSS</div><div class="line">.clearfix:after {</div><div class="line"> content: '.';</div><div class="line"> display: block;</div><div class="line"> height: 0;</div><div class="line"> visibility:hidden;</div><div class="line"> clear:both;</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="背景"><a href="#背景" class="headerlink" title="背景"></a>背景</h3><h4 id="背景属性"><a href="#背景属性" class="headerlink" title="背景属性"></a>背景属性</h4><p>CSS规定的与背景相关的属性:</p>
<ul>
<li><code>background-color</code></li>
<li><code>background-image</code></li>
<li><code>background-repeat</code></li>
<li><code>background-position</code></li>
<li><code>background-size</code></li>
<li><code>background-attachment</code></li>
<li><code>background</code></li>
<li><code>background-clip</code></li>
<li><code>background-origin</code></li>
<li><code>background-break</code></li>
</ul>
<h4 id="背景渐变"><a href="#背景渐变" class="headerlink" title="背景渐变"></a>背景渐变</h4><h5 id="渐变点"><a href="#渐变点" class="headerlink" title="渐变点"></a>渐变点</h5><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><div class="line">6</div></pre></td><td class="code"><pre><div class="line">.gradient1 {</div><div class="line"> background:linear-gradient(#64d1dd, #fff 50%, #64d1dd);</div><div class="line">}</div><div class="line">.gradient2 {</div><div class="line"> background:linear-gradient(#e86a43 20%, #fff 50%, #e86a43 80%);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>第一个例子在50%处包含一个渐变点。注意,开始和结束位置如果没有声明,则默认为0% 和 100%。</p>
<blockquote>
<p>如果不是使用百分比或其他值声明渐变点的位置,则三种颜色会均匀分布于整个渐变,其实际位置是0%、50%和100%。</p>
</blockquote>
<h5 id="放射性渐变"><a href="#放射性渐变" class="headerlink" title="放射性渐变"></a>放射性渐变</h5><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></pre></td><td class="code"><pre><div class="line">.gradient1 {</div><div class="line"> background: -webkit-radial-gradient(#fff, #64d1dd, #70aa25);</div><div class="line">}</div><div class="line">.gradient2 {</div><div class="line"> background: -webkit-radial-gradient(circle, #fff, #64d1dd, #e86a43);</div><div class="line">}</div><div class="line">.gradient3 {</div><div class="line"> background: -webkit-radial-gradient(50px 30px, circle, #fff, #64d1dd, #4947ba);</div><div class="line">}</div></pre></td></tr></table></figure>
<p>三个三色放射性渐变。第一个是默认的填满图形渐变,第二个是圆形渐变,第三个是指定位置的圆形渐变</p>
<h2 id="字体和文本"><a href="#字体和文本" class="headerlink" title="字体和文本"></a>字体和文本</h2><h3 id="字体"><a href="#字体" class="headerlink" title="字体"></a>字体</h3><p>网页中的字体的三个来源:</p>
<ul>
<li>用户机器中安装的字体</li>
<li>保存在第三方网站上的字体</li>