Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
912 lines (665 loc) · 57.4 KB
/
Copy pathindex.html
File metadata and controls
912 lines (665 loc) · 57.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" >
<title>LuoxlStayReal</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="description">
<meta property="og:type" content="website">
<meta property="og:title" content="LuoxlStayReal">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="LuoxlStayReal">
<meta property="og:description">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="LuoxlStayReal">
<meta name="twitter:description">
<link rel="alternative" href="/atom.xml" title="LuoxlStayReal" type="application/atom+xml">
<link rel="icon" href="/favicon.png">
<link rel="stylesheet" href="/css/style.css" type="text/css">
</head>
<body>
<div id="container">
<div class="left-col">
<div class="overlay"></div>
<div class="intrude-less">
<header id="header" class="inner">
<a href="/" class="profilepic">
<img lazy-src="/img/portrait.png" class="js-avatar">
</a>
<hgroup>
<h1 class="header-author"><a href="/">Luoxl</a></h1>
</hgroup>
<div class="switch-btn">
<div class="icon">
<div class="icon-ctn">
<div class="icon-wrap icon-house" data-idx="0">
<div class="birdhouse"></div>
<div class="birdhouse_holes"></div>
</div>
<div class="icon-wrap icon-ribbon hide" data-idx="1">
<div class="ribbon"></div>
</div>
<div class="icon-wrap icon-link hide" data-idx="2">
<div class="loopback_l"></div>
<div class="loopback_r"></div>
</div>
<div class="icon-wrap icon-me hide" data-idx="3">
<div class="user"></div>
<div class="shoulder"></div>
</div>
</div>
</div>
<div class="tips-box hide">
<div class="tips-arrow"></div>
<ul class="tips-inner">
<li>菜单</li>
<li>標籤</li>
<li>友情链接</li>
<li>關於</li>
</ul>
</div>
</div>
<div class="switch-area">
<div class="switch-wrap">
<section class="switch-part switch-part1">
<nav class="header-menu">
<ul>
<li><a href="/">主页</a></li>
<li><a href="/archives">所有文章</a></li>
</ul>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="/#" title="github">github</a>
<a class="weibo" target="_blank" href="/#" title="weibo">weibo</a>
<a class="rss" target="_blank" href="/#" title="rss">rss</a>
<a class="zhihu" target="_blank" href="/#" title="zhihu">zhihu</a>
</div>
</nav>
</section>
<section class="switch-part switch-part2">
<div class="widget tagcloud" id="js-tagcloud">
<a href="/tags/CSS-JavaScript/" style="font-size: 10px;">CSS JavaScript</a> <a href="/tags/HTTP/" style="font-size: 10px;">HTTP</a> <a href="/tags/JavaScript-异步/" style="font-size: 10px;">JavaScript 异步</a> <a href="/tags/JavaScript-设计模式/" style="font-size: 10px;">JavaScript 设计模式</a> <a href="/tags/简单算法-动态规划-递归/" style="font-size: 10px;">简单算法 动态规划 递归</a>
</div>
</section>
<section class="switch-part switch-part3">
<div id="js-friends">
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">奥巴马的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">卡卡的美丽传说</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">本泽马的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">吉格斯的博客</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">习大大大不同</a>
<a target="_blank" class="main-nav-link switch-friends-link" href="http://localhost:4000/">托蒂的博客</a>
</div>
</section>
<section class="switch-part switch-part4">
<div id="js-aboutme">我是谁,我从哪里来,我到哪里去?我就是我,是颜色不一样的吃货…</div>
</section>
</div>
</div>
</header>
</div>
</div>
<div class="mid-col">
<nav id="mobile-nav">
<div class="overlay">
<div class="slider-trigger"></div>
<h1 class="header-author js-mobile-header hide">Luoxl</h1>
</div>
<div class="intrude-less">
<header id="header" class="inner">
<div class="profilepic">
<img lazy-src="/img/portrait.png" class="js-avatar">
</div>
<hgroup>
<h1 class="header-author">Luoxl</h1>
</hgroup>
<nav class="header-menu">
<ul>
<li><a href="/">主页</a></li>
<li><a href="/archives">所有文章</a></li>
<div class="clearfix"></div>
</ul>
</nav>
<nav class="header-nav">
<div class="social">
<a class="github" target="_blank" href="/#" title="github">github</a>
<a class="weibo" target="_blank" href="/#" title="weibo">weibo</a>
<a class="rss" target="_blank" href="/#" title="rss">rss</a>
<a class="zhihu" target="_blank" href="/#" title="zhihu">zhihu</a>
</div>
</nav>
</header>
</div>
</nav>
<div class="body-wrap">
<article id="post-多行省略" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2017/11/21/多行省略/" class="article-date">
<time datetime="2017-11-21T13:44:57.000Z" itemprop="datePublished">2017-11-21</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2017/11/21/多行省略/">CSS ellipsis</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="单行省略">单行省略</h1><p>单行省略的问题一般采用统一的解决方法————css样式<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">overflow</span>:<span class="value"> hidden</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">text-overflow</span>:<span class="value"> ellipsis</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">white-space</span>:<span class="value"> nowrap</span></span>;</span><br></pre></td></tr></table></figure></p>
<p>该方法没有兼容性问题。且对于中英文均显示正常。</p>
<h1 id="多行省略">多行省略</h1><h2 id="CSS方式">CSS方式</h2><h3 id="webkit内核实现多行省略">webkit内核实现多行省略</h3><p>多行省略在webkit内核中可以使用如下样式(超过三行省略):<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">display</span>:<span class="value"> -webkit-box</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">-webkit-box-orient</span>:<span class="value"> vertical</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">-webkit-line-clamp</span>:<span class="value"> <span class="number">3</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">overflow</span>:<span class="value"> hidden</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">text-overflow</span>:<span class="value"> ellipsis</span></span>;</span><br></pre></td></tr></table></figure></p>
<p>除去浏览器的兼容性问题,在纯字母的情况下需要特殊处理,加上:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">word-break</span>:<span class="value"> break-all</span></span>;</span><br></pre></td></tr></table></figure></p>
<h3 id="float方式">float方式</h3><p>该方法的缺点很明显: ‘…’总是不一定能够遮盖住整个字符,会出现字符显示不完整的视觉效果。</p>
<h3 id="before&after方式">before&after方式</h3><p>该类设置为:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">font-size</span>:<span class="value"> <span class="number">1em</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">line-height</span>:<span class="value"> <span class="number">1.5em</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">max-height</span>:<span class="value"> <span class="number">3em</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">overflow</span>:<span class="value"> hidden</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">position</span>:<span class="value"> relative</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">margin-bottom</span>:<span class="value"> <span class="number">20px</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">word-break</span>:<span class="value"> break-all</span></span>;</span><br></pre></td></tr></table></figure></p>
<p>其中max-height设置为两倍的line-height<br>将before设置为:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">content</span>:<span class="value"> <span class="string">'...'</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">position</span>:<span class="value"> absolute</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">right</span>:<span class="value"> <span class="number">0px</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">bottom</span>:<span class="value"> <span class="number">0px</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">background-color</span>:<span class="value"> <span class="hexcolor">#cec</span></span></span>;</span><br></pre></td></tr></table></figure></p>
<p>after设置为:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="rule"><span class="attribute">content</span>:<span class="value"> <span class="string">''</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">width</span>:<span class="value"> <span class="number">0.72em</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">height</span>:<span class="value"> <span class="number">1.2em</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">position</span>:<span class="value"> absolute</span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">right</span>:<span class="value"><span class="number">0px</span></span></span>;</span><br><span class="line"><span class="rule"><span class="attribute">background-color</span>:<span class="value"> <span class="hexcolor">#cec</span></span></span>;</span><br></pre></td></tr></table></figure></p>
<p>其中<code>background-color</code>设置为文字背景色;after的<code>width</code>设置为当前文字大小时,’…’的宽度。</p>
<p>该方法的设计理念是:当文字高度没有超过2行,使用after的空白内容盖住’…’。当超过时,则显示before伪元素的内容。<br>after只设置left不设置bottom,则其总是在元素的最下面,而不是父元素的最下面。<br>该方法与float方法有一样的缺点。<br>相对于float方法的优点是没有固定元素的高度。</p>
<p><strong>CSS的实现方式在<a href="https://codepen.io/luoxlStayReal/pen/mqxred" target="_blank" rel="external">该codepen</a>中可以对比效果。</strong></p>
<h2 id="JavaScript方式">JavaScript方式</h2><p>JS的实现方法对比<code>Clamp.js</code>和<code>TextOverflowClamp.js</code>这两种。<br><strong>这两种在<a href="https://codepen.io/luoxlStayReal/pen/EbLaVL" target="_blank" rel="external">该codepen</a>中可以对比效果。</strong><code>Clamp.js</code>的效果更优秀。</p>
<ul>
<li><code>TextOverflowClamp.js</code>将文字按照宽度进行切分,将每行内容放入<code>span</code>标签插入该节点。最后一行使用单行省略的css样式进行处理。</li>
<li><code>Clamp.js</code>方法根据不同浏览器进行适配。在支持<code>webkitLineClamp</code>属性的内核中,使用css多行省略的方式(<code>Clamp.js</code>允许禁用原生的css多行省略样式)。在其他浏览器中,根据总长度将显示内容剪裁为<code>content+...</code>。</li>
</ul>
<h3 id="Clamp-js">Clamp.js</h3><ul>
<li>优点:适配性和扩展性很强。</li>
<li>缺点:一个字符一个字符的减少,判断是否超出高度,貌似没有必要。参考sort方式分情况进行二分法减少可以提升其效率。</li>
</ul>
<h3 id="JS方法缺点">JS方法缺点</h3><ul>
<li>不能适配屏幕缩放。需要监听屏幕改变重新计算显示字符。</li>
</ul>
<h1 id="结语">结语</h1><ul>
<li>Javascript方式没有视觉缺陷和兼容性问题,在使用’…’作为省略符号的时候,采用该方法最为妥当。</li>
<li>CSS样式可通过修改’…’省略的方式来改善视觉上的影响。比如渐变等。</li>
</ul>
<p>CSS有毒zZ</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/CSS-JavaScript/">CSS JavaScript</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-日记型博客" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/08/14/日记型博客/" class="article-date">
<time datetime="2016-08-14T12:08:26.000Z" itemprop="datePublished">2016-08-14</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/08/14/日记型博客/">日记型博客</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>使用performance.timing来测速的时候遇到了一些问题。引出了一些相关的问题,在此作为整理。</p>
<h1 id="console">console</h1><p><strong>背景</strong>:测试performance的loadEventEnd-start的时候,总是为负值(此时还没loadEventEnd,值为0)。使用了console.log输出看结果,console出来的对象里不减后结果不为负值。当时还以为console自带类似setTimeout般的异步功能,后发现输出pt(performance.timing).loadEventEnd的确为0。</p>
<p><strong>原因</strong>:console输出一个对象的时候不会直接展示出来,而是折叠的,当点击展开的时候才去把这个对象的数据“拉”出来展示,由于对象的值后面改变了,所以显示的是最终的。如果执行到这一句停顿的话,会发现输出的就是当时的timing值。</p>
<p><strong>结论</strong>:还是debugger调试靠谱。</p>
<h1 id="如何可靠的取到loadEventEnd的值,测出onload所用的时间">如何可靠的取到loadEventEnd的值,测出onload所用的时间</h1><p><strong>背景</strong>:测速的时候需要测onload的时间,但执行这段js的时候可能loadEventEnd还没有触发。</p>
<p><strong>原因</strong>:onload事件表示当前的js,html,css等资源已经加载完毕,但执行到计算onload时间的时候,可能js还没“加载”完毕。</p>
<p><strong>实验</strong>:考虑到异步的存在,加载完毕这个词真的Real模糊。<br>测试环境为window 8, Chrome 52.0.2743.116 m</p>
<ul>
<li><p><strong>天真的直接在测速的地方加上setTimeout</strong><br><br>搭了个静态页面测了测没问题。(考虑了内置js,外联js的情况)<br>天真的第一段测试入口页面代码如下:<br><img src="/image/日记型博客/code.png" alt="html"><br>一测,加setTimeout有效。结果如下:<br><img src="/image/日记型博客/result1.png" alt="html"></p>
</li>
<li><p><strong>外联js请求很慢才到达</strong><br><br>毕竟现网环境和静态页面差很多,不能这么随意确定方案。如果js很晚才来,setTimeout还会等它吗?测试代码在node环境下,请求到js的时候延迟5秒再返回。和第一段测试代码一样的html。结果竟然也一样。后面的代码都在等前面的请求到了再执行。</p>
</li>
<li><p><strong>setTimeout一定比onload晚?貌似不一定的样子</strong><br><br>加setTimeout只能把当前任务丢到“下一个”执行栈,并不能保证此时就onload完了?<br>在延迟5秒返回js的基础上,给script分别加上了async和defer属性。<br>加上defer的结果如下:<br><img src="/image/日记型博客/defer.jpg" alt="html"><br>inline代码的setTimeout都比onload提前触发。js还是按序在onload前触发的。<br>加上async结果(此时只设置了s1晚5秒返回,s2立刻返回):<br><img src="/image/日记型博客/async.jpg" alt="html"><br>js都在onload前触发,s2代码和setTimeout都在onload前执行完毕。<br>同时加defer和async的表现与async一样。</p>
</li>
</ul>
<p><strong>结论</strong>:只在setTimeout里测onload时间不靠谱。应该监听onload事件,在里面setTimeout输出load时间。</p>
<h1 id="异步和任务队列">异步和任务队列</h1><p><strong>背景</strong>:说起js异步的方法,比较常见的有回调,Promise,setTimeout,Pub/Sub。Promise和setTimeout“据说是可以进入异步队列”的方法,因此在测performance的时候也尝试了用promise。但是结果总是0。</p>
<p><strong>实验</strong>:代码和结果如下:<br><img src="/image/日记型博客/promise&setTimeout.png" alt="html"><br><img src="/image/日记型博客/pResult.png" alt="html"></p>
<p><strong>问题</strong>:都是异步,怎么有差距?我联想到了node里的nextTick,setImmediate的某些区别,难道是放在当前任务队列末尾,下一个队列开头或者下一个队列末尾的区别?</p>
<p><strong>结论1</strong>:算上node,优先级为:process.nextTick > promise.then > setTimeout > setImmediate。</p>
<p><strong>结论2</strong>:任务队列有区别。</p>
<ul>
<li><strong>macro-task</strong>:script整体代码, setTimeout, setInterval, setImmediate, I/O, UI rendering, dispatch click</li>
<li><strong>micro-task</strong>:process.nextTick, Promises(浏览器原生), Object.observe, MutationObserver<br>上面是两种异步队列的分类。在挂起任务时,JS引擎会将所有任务按照类别分到这两种队列中。(上面提到的一些东西还没仔细研究。但setTimeout和Promise的关系还是看出来了。)<br>(1)首先在macrotask队列(也叫task queue 是不是很耳熟)取出第一个任务。<br>(2)1 执行完毕后取出micro-task的所有任务顺序执行。<br>(3)之后再取<strong>一个</strong>macrotask的任务。(回到1, 循环至没有任务)<br>当某种任务队列是空的就跳过,还是执行本类型任务的下一个。</li>
</ul>
<p>#遗留问题<br>onload是怎么触发的呢? 目前认为是最后一个js的macro-task执行栈空了触发的。</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/JavaScript-异步/">JavaScript 异步</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-回文子序列" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/04/04/回文子序列/" class="article-date">
<time datetime="2016-04-04T13:28:22.000Z" itemprop="datePublished">2016-04-04</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/04/04/回文子序列/">回文子序列</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>在此记录一道腾讯笔试的编程题。这题乍一看觉得是用动态规划,但是并没有做出来,最后是用递归解的。递归的思想更容易但是时间复杂度很高,所以我估计这题最后提交上去会超时ORZ。接下来回顾这道题,并再举别的和此题类似的例子~~~</p>
<h1 id="题目描述">题目描述</h1><p>给一个字符串,找出它的最长的回文子序列的长度。例如,如果给定的序列是“BBABCBCAB”,则输出应该是7,“BABCBAB”是在它的最长回文子序列。 “BBBBB”和“BBCBB”也都是该字符串的回文子序列,但不是最长的。</p>
<p>当时的题目写的不是这样直白,好像是说一个字符串可以删除任意个字符,求删除后字符串是回文字符串的最大长度。当时就觉着直接求所有子串,然后从长到短来依次判断是否是回文串,如果是则直接return长度。但是这种穷举法显然太弱了。接下来先用递归方法来求解吧(虽然时间复杂度高,但是代码好写…)。</p>
<h1 id="递归解法">递归解法</h1><h2 id="思路">思路</h2><p>给定一个字符串,从两边开始对比(当然从两边,因为谁也不嫌长,而且是子序列,不要求连在一起),假设此时左右下标分别为i和j。</p>
<ul>
<li>如果str[i]==str[j],则len+1,然后递归str(i+1,j-1)。</li>
<li>如果str[i]!=str[j],则分别递归str(i+1,j)和str(i,j-1),取两者的较大值。</li>
</ul>
<h2 id="代码">代码</h2><pre><code class="java"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">longest</span><span class="params">(String s)</span> </span>{
<span class="keyword">if</span>(s.length() <= <span class="number">1</span>) <span class="keyword">return</span> s.length();
<span class="keyword">if</span>(s.charAt(<span class="number">0</span>) == s.charAt(s.length()-<span class="number">1</span>)){
<span class="keyword">return</span> longest(s.substring(<span class="number">1</span>, s.length()-<span class="number">1</span>))+<span class="number">2</span>;
}
<span class="keyword">int</span> a = longest(s.substring(<span class="number">1</span>, s.length()));
<span class="keyword">int</span> b = longest(s.substring(<span class="number">0</span>, s.length()-<span class="number">1</span>));
<span class="keyword">return</span> Math.max(a, b);
}
</code></pre>
<h1 id="DP解法">DP解法</h1><h2 id="思路-1">思路</h2><p>dp[i][j]存放字符串str中从CharAt(i)到CharAt(j)的最长回文子序列长度。</p>
<ul>
<li>如果str[i]==str[j],dp[i][j]=dp[i+1][j-1]+1。</li>
<li>如果str[i]!=str[j],dp[i][j]=max(dp[i+1][j],dp[i][j-1])。</li>
</ul>
<p>然而,递归表达式写出来了,还要考虑初始条件及入口。</p>
<ul>
<li>初始条件: dp[i][i]=1。</li>
<li>入口:由前面给出的DP表达式可以看出来,在求解dp[i][j]时,要已经得到dp[i+1][j-1],dp[i+1][j],dp[i][j-1]这三个变量。</li>
</ul>
<p>从矩阵的角度来看这个dp二维数组。首先,肯定是j>i,即我们用的是该矩阵的右上半角。其次,初始化时,dp[i][i]=1表示该矩阵的对角线上的数字都为1。再看入口条件,dp[i+1][j-1],dp[i+1][j],dp[i][j-1]都在dp[i][j]的右下角。分析完了,可以感受到如何构造这个dp数组了吧~</p>
<p>由下列矩阵可知,在给问好处赋值的时候,X和+处应该已经有值。因此,我们应该从对角线开始,依次向右上角给矩阵赋值。<br><img src="/image/回文子序列/递归求解.png" alt="递归求解"><br>下图显示地描述了这个过程(假设此时str=”abca”)<br><img src="/image/回文子序列/dp示例.png" alt="dp示例"></p>
<h2 id="代码-1">代码</h2><pre><code class="java"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">int</span> <span class="title">longest</span><span class="params">(String s)</span> </span>{
<span class="keyword">int</span> n = s.length();
<span class="keyword">int</span>[][] dp = <span class="keyword">new</span> <span class="keyword">int</span>[n][n];
<span class="keyword">int</span> tmp;
<span class="keyword">char</span>[] str = s.toCharArray();
<span class="comment">//初始化</span>
<span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>; i<=n-<span class="number">1</span>; i++){
dp[i][i] = <span class="number">1</span>;
}
<span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">1</span>; i<=n-<span class="number">1</span>; i++){
tmp = <span class="number">0</span>;
<span class="comment">//考虑 str[j, j+i] 由j到j+i的串</span>
<span class="keyword">for</span>(<span class="keyword">int</span> j=<span class="number">0</span>; j+i<=n-<span class="number">1</span>; j++){
<span class="comment">//如果首尾相同</span>
<span class="keyword">if</span>(str[j] == str[j+i]){
tmp = dp[j+<span class="number">1</span>][j+i-<span class="number">1</span>] + <span class="number">2</span>;
}<span class="keyword">else</span>{
tmp = Math.max(dp[j+<span class="number">1</span>][j+i],dp[j][j+i-<span class="number">1</span>]);
}
dp[j][j+i] = tmp;
}
}
<span class="comment">//返回串 str[0][n-1] 的结果</span>
<span class="keyword">return</span> dp[<span class="number">0</span>][n-<span class="number">1</span>];
}
</code></pre>
<h1 id="类似解法——最长公共子序列">类似解法——最长公共子序列</h1><h2 id="题目描述-1">题目描述</h2><p>两个字符串Str1和Str2,求两个字符串的公共子序列(顺序不可打乱)的长度。比如”abcdef”和”ccaf”的最长公共子序列为”cf”,长度为2。</p>
<h2 id="思路-2">思路</h2><p>我们可以感受到这题可以用dp[i][j]保存str1(0,i)和str2(0,j)的最长公共子序列。(此处不写s.toCharArray或者charAt,意思就是这样)</p>
<ul>
<li>当str1[i]==str2[j]时,dp[i][j]=dp[i-1][j-1]+1</li>
<li>当str1[i]!=str2[j]时,dp[i][j]=max(dp[i-1][j],dp[i][j-1])<br>在矩阵上表示为从矩阵的左上角求解到右下角。一般来说我们需要初始化dp[0][<em>]与dp[</em>][0],但也可以加一行一列赋值为0再直接进入dp过程。</li>
</ul>
<p>dp赋值图如下:<br><img src="/image/回文子序列/最长子序列dp.png" alt="最长子序列dp"></p>
<h1 id="文章最后">文章最后</h1><p>动态规划用处很大,这两个问题还分别有最长回文子串和最长公共子串,与上面解法几乎一样。但最长回文子串有个Manacher的解法,能在O(n)的复杂度得到结果。算法很妙,在此不做解释了。可以移步<a href="https://segmentfault.com/a/1190000003914228" target="_blank" rel="external">这里</a>查看详细解法。</p>
<p>明天晚上就是微软上机测试了,感受到了少壮不努力,老大徒伤悲…… 也不知道刷的90道leetcode够不够ORZ,加油吧~</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/简单算法-动态规划-递归/">简单算法 动态规划 递归</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-HTTP-1-2-对比" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/04/01/HTTP-1-2-对比/" class="article-date">
<time datetime="2016-04-01T09:12:07.000Z" itemprop="datePublished">2016-04-01</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/04/01/HTTP-1-2-对比/">HTTP 1-2 对比</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<p>超文本传输协议是一种应用层的协议。它是一种基于请求/响应的无状态的协议。</p>
<h1 id="http1-0_v-s_http1-1">http1.0 v.s http1.1</h1><h2 id="进化的原因">进化的原因</h2><p>由于每个站点每天会有很多用户的请求,为了提高系统效率,HTTP1.0规定浏览器与服务器只保持短暂的链接,浏览器每次请求都要新建立一个TCP链接,该链接在请求完成后断开,服务器不跟踪也不记录过去的请求。</p>
<p>由于网页变得复杂,这样频繁新建和断开链接的操作对性能造成影响。比如,当一个网页里包含了很多src时,对每个src都需要建立关闭链接的操作,太费事。因此,HTTP1.1出现了,它支持持久连接,在一个TCP上传送多个HTTP请求和响应(但其实现代浏览器通常最多6-8个HTTP/1.1的链接限制,后面会谈到HTTP2)。一个包含多个Src的网页可以在一次建立连接中传输。它还允许客户端不用等待上一次请求结果返回,就可以发出下一次请求,但服务器端必须按照接收到客户端请求的先后顺序依次回送响应结果,以保证客户端能够区分出每次请求的响应内容,这样也显著地减少了整个下载过程所需要的时间。</p>
<h2 id="不同之处">不同之处</h2><p>HTTP1.1的绝大部分内容都和性能有关,比如减少连接建立次数,减少传输数据量。下面例举几个主要的改变:</p>
<ul>
<li><p><strong>持久连接</strong></p>
<p> HTTP1.1支持持久连接(persistent connection),并且默认使用。为了实现这个功能肯定需要新加入字段来实现。比如:Connection 请求头的值为Keep-Alive 时,客户端通知服务器返回本次请求结果后保持连接;Connection 请求头的值为close 时,客户端通知服务器返回本次请求结果后关闭连接。 </p>
</li>
<li><p><strong>Host域</strong></p>
<p> HTTP1.0中没有加入host域,它认为每台服务器都绑定唯一一个IP地址(可能是因为没有一个IP要配置多个虚拟web站点的需要吧),它在建立TCP连接的时候指定了IP地址,这个IP地址上只有一个host。随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed web servers),他们共享一个IP地址,因此需要host来区分。HTTP1.1中浏览器可以使用主机头名来明确表示要访问服务器上的哪个WEB站点,这才实现了在一台WEB服务器上可以在同一个IP地址和端口号上使用不同的主机名来创建多个虚拟WEB站点。</p>
<p> HTTP1.1中如果没有Host头域会报400错误,但支持空的host域。</p>
</li>
<li><p><strong>Transfer-Encoding</strong></p>
<p> HTTP1.1支持chunked transfer。<br> HTTP消息中可以包含任意长度的实体,通常它们使用Content-Length来给出消息结束标志。但是,对于很多动态产生的响应,只能通过缓冲完整的消息来判断消息的大小,但这样做会加大延迟。</p>
<p> HTTP/1.1中引入了Chunked transfer-coding来解决上面这个问题,发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。</p>
<p> 在HTTP/1.0中,有一个Content-MD5的头域,要计算这个头域需要发送方缓冲完整个消息后才能进行。而HTTP/1.1中,采用chunked分块传递的消息在最后一个块(零长度)结束之后会再传递一个拖尾(trailer),它包含一个或多个头域,这些头域是发送方在传递完所有块之后再计算出值的。发送方会在消息中包含一个Trailer头域告诉接收方这个拖尾的存在。</p>
</li>
<li><p><strong>Range/Content-Range</strong></p>
<p> 当客户端已经有内容的一部分,为了节省带宽,可以只向服务器请求一部分。</p>
<p> HTTP/1.1中在请求消息中引入了range头域,它允许只请求资源的某个部分。在响应消息中Content-Range头域声明了返回的这部分对象的偏移值和长度。如果服务器相应地返回了对象所请求范围的内容,则响应码为206(Partial Content),它可以防止Cache将响应误以为是完整的一个对象。(2XX代表请求成功)</p>
</li>
<li><p><strong>100-continue</strong></p>
<p> 如果请求中包含很多内容,但不确定服务器是否能够接收该请求(是否有权限)。因此,客户端事先发送一个只带头域的请求,如果服务器因为权限拒绝了请求,就回送响应码401(Unauthorized);如果服务器接收此请求就回送响应码100,客户端就可以继续发送带实体的完整请求了。</p>
<p> 客户端在Request头部中包Expect: 100-continue。Server看到之后呢如果回100 (Continue) 这个状态代码,客户端就继续发requestbody。</p>
</li>
<li><p><strong>Cache</strong></p>
<p> HTTP1.0使用Expire头域来判断资源是否过期。通过If-Modified-Since头域向服务器验证资源的Last-Modefied头域是否有更新,源服务器可能返回304(Not Modified),则表明该对象仍有效;也可能返回200(OK)替换请求的Cache对象。此外,HTTP/1.0中还定义了Pragma:no-cache头域,客户端使用该头域说明请求资源不能从cache中获取,而必须回源获取。</p>
<p> 我们可以发现HTTP1.0有几处不足:当资源在秒级别内进行更改,而Modefied时间只精确到秒级别,其实资源更改了但是时间上显示不出来;有时候资源变成过期对象,但是与服务器资源相同,其实没有必下载新的资源。</p>
<p> HTTP1.1针对这几处不足进行改进。</p>
<ul>
<li>引入ETag头域用于重激活机制,它的值entity tag可以用来唯一的描述一个资源。请求消息中可以使用If-None-Match头域来匹配资源的entity tag是否有变化。</li>
<li><p>当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。</p>
<p>HTTP1.1加入Cache-control,对缓存进行控制。</p>
</li>
</ul>
</li>
<li><p><strong>其他</strong></p>
<p> request方法新添加了options,put,delete,trace,connect</p>
<p> 新添加了一些状态码,包括206和100</p>
</li>
</ul>
<h1 id="HTTP/2">HTTP/2</h1><p>于2015年2月28日定稿。多数headers与1.1一样,可以向下兼容。</p>
<blockquote>
<p>HTTP/2 is a replacement for how HTTP is expressed “on the wire.” It is not a ground-up rewrite of the protocol; HTTP methods, status codes and semantics are the same, and it should be possible to use the same APIs as HTTP/1.x (possibly with some small additions) to represent the protocol.</p>
<p>The focus of the protocol is on performance; specifically, end-user perceived latency, network and server resource usage. One major goal is to allow the use of a single connection from browsers to a Web site.</p>
</blockquote>
<p>HTTP的详细内容可以参考本文下方的链接。在此仅简单总结相对HTTP1.1的优点:</p>
<ul>
<li><p>多路复用 multiplexing</p>
<p> <img src="/image/HTTP-1-2-对比/多路复用.png" alt="多路复用"> 如图所示可以同时发送多个请求</p>
</li>
<li>二进制,方便运输和解析。(1.1是文本协议)</li>
<li><p>服务推送 Server Push</p>
<p> <img src="/image/HTTP-1-2-对比/2.png" alt="http1.1"> <img src="/image/HTTP-1-2-对比/3.png" alt="http2"><br> 上图来自文章后面的一个视频。<br> 相当于发了一个HTML文档内的所有资源。优点是可以缓存,缺点是如果客户端缓存了则白白浪费了资源。于是,看下一条</p>
</li>
<li><p>服务器提示 Server Hints</p>
<p> 服务器提示可以先于客户端检测到将要请求的资源,提前通知客户端,服务器不发送所有资源的实体,它只发送资源的 URL。客户端接到提示后进一步验证之前的缓存,如果发现需要这些资源,则正式发起请求。服务器提示对 HTTP/2 来说兴许不是最新的,但非常值得在这里顺便一提,因为它没有上文提到的服务器推送冗余的缺点。</p>
</li>
</ul>
<h1 id="相关资料">相关资料</h1><h2 id="五分钟短片简介HTTP2-0:">五分钟短片简介HTTP2.0:</h2><div class="video-container"><iframe src="//www.youtube.com/embed/https://youtu.be/fJ0C4zN5uOQ" frameborder="0" allowfullscreen></iframe></div>
<p>如果看不了,地址为:<a href="https://youtu.be/fJ0C4zN5uOQ" target="_blank" rel="external">https://youtu.be/fJ0C4zN5uOQ</a></p>
<h2 id="http1_v-s_http2">http1 v.s http2</h2><p><a href="http://www.blogjava.net/yongboy/archive/2015/03/17/423531.html" target="_blank" rel="external">http://www.blogjava.net/yongboy/archive/2015/03/17/423531.html</a><br><a href="http://www.w3ctech.com/topic/862" target="_blank" rel="external">http://www.w3ctech.com/topic/862</a><br><a href="http://www.alloyteam.com/2015/03/http2-0-di-qi-miao-ri-chang/" target="_blank" rel="external">http://www.alloyteam.com/2015/03/http2-0-di-qi-miao-ri-chang/</a> 这个讲得不枯燥~ 很赞</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/HTTP/">HTTP</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
<article id="post-JQuery对象" class="article article-type-post" itemscope itemprop="blogPost">
<div class="article-meta">
<a href="/2016/03/31/JQuery对象/" class="article-date">
<time datetime="2016-03-31T12:16:07.000Z" itemprop="datePublished">2016-03-31</time>
</a>
</div>
<div class="article-inner">
<input type="hidden" class="isFancy" />
<header class="article-header">
<h1 itemprop="name">
<a class="article-title" href="/2016/03/31/JQuery对象/">JQuery对象</a>
</h1>
</header>
<div class="article-entry" itemprop="articleBody">
<h1 id="第一映像">第一映像</h1><p>在日常编程中可以感觉到,jQuery使程序变得精简。显然,jQuery对象与DOM对象是有区别的。因为jQuery对象能够操作DOM对象,我们知道jQuery对象中肯定包含DOM对象。\$(“p”).get(0).innerHTML可以获得第一个p元素的innerHTML,\$(“p”).get(0)取到的是一个DOM元素,不再是jQuery对象。jQuery的函数操作大多返回一个jQuery对象,当判断一个元素前面有没有别的元素时,使用pre()是否为undefined是无法判断的,因为就算没有元素,也会返回一个空的jQuery对象[object Object],因此需要用pre().get(0)是否为undefined来判断前面是否还有元素。讲到这里有了个明确的概念:<strong>jQuery对象包含了DOM对象,并在jQuery对象中封装了各种对DOM对象进行操作的函数</strong>。</p>
<h1 id="代码演变">代码演变</h1><h2 id="一个简单的dom操作">一个简单的dom操作</h2><p>首先,从一个很简单的功能开始说。一个按钮inp,点击一次,隐藏块div1。结构代码如下:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="title">div</span> <span class="attribute">id</span>=<span class="value">"div1"</span>></span><span class="tag"></<span class="title">div</span>></span></span><br><span class="line"><span class="tag"><<span class="title">input</span> <span class="attribute">type</span>=<span class="value">"button"</span> <span class="attribute">value</span>=<span class="value">"点击"</span> <span class="attribute">id</span>=<span class="value">"inp"</span>></span></span><br></pre></td></tr></table></figure></p>
<p>我们可能会这样写代码:</p>
<pre><code class="javascript"><span class="keyword">var</span> div=<span class="built_in">document</span>.getElementById(<span class="string">"div1"</span>);
<span class="keyword">var</span> btn=<span class="built_in">document</span>.getElementById(<span class="string">"div1"</span>);
btn.onclick=functioin(){
div.style.display=<span class="string">"none"</span>;
}
</code></pre>
<p>想偷懒的程序员们希望能够少写点getElementById这样长的句子,因此决定把得到dom元素的方法封装起来以便调用。</p>
<pre><code class="javascript"><span class="keyword">var</span> F=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="built_in">document</span>.getElementById(id);
};
<span class="keyword">var</span> i=F(<span class="string">"inp"</span>);
<span class="keyword">var</span> d=F(<span class="string">"div1"</span>);
i.onclick=<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{
d.style.display=<span class="string">"none"</span>;
};
</code></pre>
<h2 id="面向对象的设计">面向对象的设计</h2><p>如果再想在F后链式实现.click()和.hide(),则需要使用构造函数。</p>
<pre><code class="javascript"><span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">return</span> <span class="keyword">this</span>.getElementById(id);
};
F.prototype.getElementById = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">this</span>.ele = <span class="built_in">document</span>.getElementById(id);
<span class="keyword">return</span> <span class="keyword">this</span>;
};
<span class="keyword">var</span> i=<span class="keyword">new</span> F(<span class="string">"inp"</span>);
<span class="keyword">var</span> d=<span class="keyword">new</span> F(<span class="string">"div1"</span>);
i.ele.onclick=<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{
d.ele.style.display=<span class="string">"none"</span>;
};
</code></pre>
<p>实现封装。将new F封装到\$中 将onclick和hide写为F的原型函数。</p>
<pre><code class="javascript"><span class="keyword">var</span> F = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">return</span> <span class="keyword">this</span>.getElementById(id);
};
F.prototype.getElementById = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">this</span>.ele = <span class="built_in">document</span>.getElementById(id);
<span class="keyword">return</span> <span class="keyword">this</span>;
};
F.prototype.click = <span class="function"><span class="keyword">function</span>(<span class="params">fn</span>) </span>{
<span class="keyword">this</span>.ele.onclick=fn;
};
F.prototype.hide = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
<span class="keyword">this</span>.ele.style.display=<span class="string">"none"</span>;
};
<span class="keyword">var</span> $=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="keyword">new</span> F(id);
}
<span class="keyword">var</span> i=$(<span class="string">"inp"</span>);
<span class="keyword">var</span> d=$(<span class="string">"div1"</span>);
i.click(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{
d.hide();
});
</code></pre>
<p>这一步已经实现了\$(“”).click()和.hide()的功能。然而内部还是和jQuery原生颇有不同。</p>
<h2 id="向jQuery格式靠近">向jQuery格式靠近</h2><p>jQuery中添加函数是使用\$.fn。因此,可以将F.prototype换成\$.fn试试:</p>
<pre><code class="javascript"><span class="keyword">var</span> $=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="keyword">new</span> $.fn(id);
}
$.fn = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">return</span> <span class="keyword">this</span>.getElementById(id);
};
$.fn.prototype.getElementById = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">this</span>.ele = <span class="built_in">document</span>.getElementById(id);
<span class="keyword">return</span> <span class="keyword">this</span>;
};
$.fn.prototype.click = <span class="function"><span class="keyword">function</span>(<span class="params">fn</span>) </span>{
<span class="keyword">this</span>.ele.onclick=fn;
};
$.fn.prototype.hide = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
<span class="keyword">this</span>.ele.style.display=<span class="string">"none"</span>;
};
</code></pre>
<p>由于并没有\$.fn这样的变量,因此\$.fn是\$上的一个属性,将\$的定义提前。<br>考虑到\$可以取得一堆node,且get(i)为第i个DOM元素。因此,直接将ele赋值到this[i]中。</p>
<pre><code class="javascript"><span class="keyword">var</span> $=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="keyword">new</span> $.fn(id);
}
$.fn = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="keyword">return</span> <span class="keyword">this</span>.init(id);
};
$.fn.prototype.init = <span class="function"><span class="keyword">function</span>(<span class="params">selector,context</span>) </span>{<span class="comment">//querySelectorAll ie8+</span>
<span class="keyword">var</span> nodes=(context || <span class="built_in">document</span>).querySelectorAll(selector);
<span class="keyword">this</span>.length=nodes.length;
<span class="built_in">console</span>.log(nodes.length);
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i]=nodes[i];
}
<span class="keyword">return</span> <span class="keyword">this</span>;<span class="comment">//返回当前作用域,init只是在当前作用域上添加了nodes(真正可操作的dom元素)</span>
};
$.fn.prototype.click = <span class="function"><span class="keyword">function</span>(<span class="params">fn</span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].onclick=fn;
}
};
$.fn.prototype.hide = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].style.display=<span class="string">"none"</span>;
}
};
</code></pre>
<p>jQuery中添加函数应该是直接\$.fn.newFun这种形式,prototype应该被隐藏。因此,直接将\$.fn.prototype用$.fn1替代。new \$.fn(id)则可替换为new \$.fn1.init(id)。由于改变构造函数会改变对象的<strong>prototype</strong>导致返回的对象找不到click和hide函数,因此需要将\$.fn1.init.prototype设为\$.fn.prototype,也即是\$.fn1。</p>
<pre><code class="javascript"><span class="keyword">var</span> $=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="keyword">new</span> $.fn1.init(id);
}
$.fn = <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{
<span class="comment">// return this.init(id);</span>
};
$.fn1=$.fn.prototype;
$.fn1.init = <span class="function"><span class="keyword">function</span>(<span class="params">selector,context</span>) </span>{
<span class="keyword">var</span> nodes=(context || <span class="built_in">document</span>).querySelectorAll(selector);
<span class="keyword">this</span>.length=nodes.length;
<span class="built_in">console</span>.log(nodes.length);
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i]=nodes[i];
}
<span class="keyword">return</span> <span class="keyword">this</span>;
};
<span class="comment">// 这样才能new $.fn1.init的对象能够有hide click函数</span>
$.fn1.init.prototype=$.fn1;
$.fn1.click = <span class="function"><span class="keyword">function</span>(<span class="params">fn</span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].onclick=fn;
}
};
$.fn1.hide = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].style.display=<span class="string">"none"</span>;
}
};
<span class="keyword">var</span> i=$(<span class="string">"#inp"</span>);
<span class="keyword">var</span> d=$(<span class="string">"#div1"</span>);
i.click(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{
d.hide();
});
</code></pre>
<p>用\$.fn替换\$.fn.prototype也是一样的,不知道怎么觉得用对象替换该对象的prototype有点奇怪,但其实是一样的,只是为了区分留下来的\$.fn因此多替换了一步。可以看到\$.fn 函数已经没有作用的,是个空函数,为了体现jQuery的精简,\$.fn1=\$.fn.prototype 设为一个空函数的prototype与设为函数$的prototype没有区别。<br>最后将\$.fn替换\$.fn1,删除\$.fn,设置\$.fn1=\$.prototype ,大功告成。</p>
<pre><code class="javascript"><span class="keyword">var</span> $=<span class="function"><span class="keyword">function</span>(<span class="params">id</span>)</span>{
<span class="keyword">return</span> <span class="keyword">new</span> $.fn.init(id);
}
$.fn=$.prototype;
$.fn.init = <span class="function"><span class="keyword">function</span>(<span class="params">selector,context</span>) </span>{<span class="comment">//querySelectorAll ie8以上支持</span>
<span class="keyword">var</span> nodes=(context || <span class="built_in">document</span>).querySelectorAll(selector);
<span class="keyword">this</span>.length=nodes.length;
<span class="built_in">console</span>.log(nodes.length);
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i]=nodes[i];
}
<span class="keyword">return</span> <span class="keyword">this</span>;<span class="comment">//返回当前作用域,init只是在当前作用域上添加了nodes(真正可操作的dom元素)</span>
};
<span class="comment">// 这样才能new $.fn1.init的对象能够有hide click函数</span>
$.fn.init.prototype=$.fn;
$.fn.click = <span class="function"><span class="keyword">function</span>(<span class="params">fn</span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].onclick=fn;
}
};
$.fn.hide = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{
<span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">0</span>;i<<span class="keyword">this</span>.length;++i){
<span class="keyword">this</span>[i].style.display=<span class="string">"none"</span>;
}
};
<span class="keyword">var</span> i=$(<span class="string">"#inp"</span>);
<span class="keyword">var</span> d=$(<span class="string">"#div1"</span>);
i.click(<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{
d.hide();
});
</code></pre>
<h1 id="结束语">结束语</h1><p>jQuery设计的很好,值得学习。说到底也是利用原型继承实现面向对象开发的思想。第一次写博客~~ 哈哈哈<br>加油~~!</p>
</div>
<div class="article-info article-info-index">
<div class="article-tag tagcloud">
<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/JavaScript-设计模式/">JavaScript 设计模式</a></li></ul>
</div>
<div class="clearfix"></div>
</div>
</div>
</article>
</div>
<footer id="footer">
<div class="outer">
<div id="footer-info">
<div class="footer-left">
© 2017 Luoxl
</div>
<div class="footer-right">
<a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/litten/hexo-theme-yilia" target="_blank">Yilia</a> by Litten
</div>
</div>
</div>
</footer>
</div>
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css" type="text/css">
<script>
var yiliaConfig = {
fancybox: true,
mathjax: true,
animate: true,
isHome: true,
isPost: false,
isArchive: false,
isTag: false,
isCategory: false,
open_in_new: false
}
</script>
<script src="http://7.url.cn/edu/jslib/comb/require-2.1.6,jquery-1.9.1.min.js" type="text/javascript"></script>
<script src="/js/main.js" type="text/javascript"></script>
<!-- mathjax config similar to math.stackexchange -->
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
processEscapes: true
}
});
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
}
});
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Queue(function() {
var all = MathJax.Hub.getAllJax(), i;
for(i=0; i < all.length; i += 1) {
all[i].SourceElement().parentNode.className += ' has-jax';
}
});
</script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<div id="totop" style="position:fixed;bottom:50px;right:50px;cursor: pointer;">
<a title="���ض���"><img src="/img/scrollup.png"/></a>
</div>
<script src="/js/totop.js"></script>
</div>
</body>
</html>