-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
3882 lines (2662 loc) · 902 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>YongSir | 专业程序员伪装者</title>
<meta name="author" content="13hoop">
<meta id="viewport" name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta property="og:site_name" content="YongSir"/>
<meta property="og:image" content="/favicon.ico"/>
<link href="/favicon.ico" rel="icon">
<link rel="alternate" href="/atom.xml" title="YongSir" type="application/atom+xml">
<link rel="stylesheet" href="/css/style.css" media="screen" type="text/css">
</head>
<body>
<div class="blog">
<div class="content">
<header>
<div class="site-branding">
<h1 class="site-title">
<a href="/">YongSir</a>
</h1>
<p class="site-description">专业程序员伪装者</p>
</div>
<nav class="site-navigation">
<ul>
<li><a href="/">主页</a></li>
<li><a href="/archives">归档</a></li>
</ul>
</nav>
</header>
<main class="site-main posts-loop">
<article>
<h3 class="article-title"><a href="/2017/12/24/小朋友的编程5/"><span>小朋友的编程5</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/12/24/小朋友的编程5/" rel="bookmark">
<time class="entry-date published" datetime="2017-12-24T03:01:43.000Z">
2017-12-24
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>这一篇仍然是视频部分的补充资料,主要就是介绍javaScript的</p>
<h3 id="关于js代码"><a href="#关于js代码" class="headerlink" title="关于js代码"></a>关于js代码</h3><p>通过前边的知识,我们知道写在网页中<code>script</code>标签中的内容,就是javaScript代码,我们以前还提到过, javascript 是一种接近人类自然语言的高级编程语言。所以在网页中一个必然的事实就是,凡是看到<script>便签之间包含的东西,那么它就是js代码,而js代码在现代的网页中是无处不在的,我们随意的找一些现实中的例子,比如baidu,如果我们使用开发者工具打开–还记得怎样操作吗?(想一想快捷键–F12),你就会发现大量的script标签,就像这样:<br><img src="https://wx3.sinaimg.cn/mw1024/006mou3Bgy1flhma9ana2j31hu0y8nb7.jpg" alt="JS代码在网页中无处不在,比如baidu"></p>
<p>但是我们为什么需要js代码呢?</p>
<p>因为本身html是死的,它是什么样就在你写完它的那一刻就固定了,比如一个标题元素<code><title>标题一</title></code>一开始就固定了永远是标题一,一个数字为100,那么它就会是一直是100,像这样一经创建再也不改变的现象,通常用<code>静态</code>这个词来概括。但现实中的网页却不是这样,大多数时候网页是可以进行各种各样的交互的。比如在我们上次视频中的那个按钮–也就是<code><button></code>,我们点击了它会触发一定的事件,我们视频中就是让它计算最终结果并显示结果,再比如你去优酷看视屏的时候,你要去点击播放按钮才会开始播放,以及在玩游戏时你常常会通过键盘让角色运动,而让它干点儿什么通常就是靠js来帮助实现的。</p>
<p>换一个更通俗的例子,还记得我们前边的机器人吗,我们通过html这样的元素组成了机器人的头,身体等各个部位,而js就相当于给机器人添加了各种行动和思想,让机器人可以动动胳膊抬抬腿之类的行动,这就是为什么我的网页中需要js。因为它会让原本死的元素由静态变为<code>动态</code>,从而变得可以被人们点击,滚动,缩放(<em>缩放网页,你可以试试按下键盘中的Cril键,同时滚动鼠标中间的滚轮</em>)等等交互行为。</p>
<p>好了,现在停下来我们总结一下:<br>我们会知道,通常的网页都是可以交互的,有的有可以点击的按钮,有的有可以放大的图片,大部分网页还能随着鼠标的滑动而滚动…等等这些行为,都是依靠js来实现的。</p>
<p>那么我们就来看看JS的具体内容,他到底有什么魔力呢?我们重新回顾一下上次视屏中的js代码:</p>
<p><code>// 表示注释,就是用来说明你在干什么的,使用时系统会忽略掉代//的行,所以这其实是给人看的,计算机是不管的</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 说明: element</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 上边的右侧代码是元素,它是网页的基本组成部分,这些都是 W3C 规定好了的,所以不是重点,重点是下边的代码</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 这里用到的数学公式: 速度v * 时间t = 路程s</span></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// ------------------</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 编程就是把复杂的事情,一步一步分解</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 目标: 创建一个网页,可以输入v和t,点击按钮,计算路程s,并显示结果</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 1> 创建一个网页,可以有输入v和t的元素 --- 已完成,并且不需要你掌握,知道了就行</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 2> 要能拿到v和t元素: 分别找到t/v input元素</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 3> a 点击按钮(事件)</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// b 拿到现在的v/t的值</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// c 计算</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// d 拿到resultElm</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// e 修改innerText</span></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 步骤2> 分别找到t/v input元素, 通过id去找到的 -- 规定好了的方法</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> speedElm = <span class="built_in">document</span>.getElementById(<span class="string">"speed"</span>)</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> timeElm = <span class="built_in">document</span>.getElementById(<span class="string">"time"</span>)</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distanceElm = <span class="built_in">document</span>.getElementById(<span class="string">"distance"</span>)</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 步骤3></span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// a 指定点击事件 -- 也是规定好了的, 通过onClick="anXiale()"</span></span></span><br><span class="line"><span class="javascript"> <span class="function"><span class="keyword">function</span> <span class="title">anXiale</span>(<span class="params"></span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="comment">// b 拿到现在的v/t的值</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> speedValue = speedElm.value</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> timeValue = timeElm.value</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distanceValue = distanceElm.value</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// c 带入公式 s = v * t ????</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distance = speedValue * timeValue</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// d 拿到resultElm</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> resultElm = <span class="built_in">document</span>.getElementById(<span class="string">"result"</span>)</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// e 将结果显示到 resultElm元素 -- 规定好了的</span></span></span><br><span class="line"><span class="javascript"> resultElm.innerText =<span class="string">": "</span> + distance</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure>
<p>首先,你肯定总是见到<code>var</code>这个单词,var是一种简写,他的全称是variable【变量】,再直白一点儿就是可以改变的量,比如在计算一个正方形的面积时,我们带入公式 <code>S(面积) = a(边长) * a(边长)</code>,不同的a就会有不同的S, a和S都是可以改变的,因此它们都是变量,而有的量比如 圆的面积计算中 <code>S = 2 * π * (r * r)</code>,其中的r跟S都是可以改变的是变量,而 2 和 π 都是固定的,所以我们称呼它们是<strong>常量</strong>而不是<strong>变量</strong>,对,就是这么的直白。</p>
<p>恭喜你,因为变量几乎就是网页可以变化的全部秘密,正是由于js中变量的存在,所以网页才可以动起来,所以变量的作用就像是提线木偶的线,一旦拉扯那些控制线,木偶就会做动作。</p>
<p><img src="https://wx1.sinaimg.cn/mw690/006mou3Bly1fmrmq9xxorj30tl0xcmz4.jpg" alt=""></p>
<p>其次,上边代码中还有一些符号,有计算符号 + * 还有 = ,他们的意思就是他们本身的意思,只需要注意的是 =, 在编程中并不叫等号,而是赋值符号,它表示<em>将右侧的数值或者变量 赋值给 右侧的变量</em>,好吧看起来的确有一些相等的意思,暂时这样理解也是没问题的。</p>
<p>还有,这样的语句 <code>function anXiale() {}</code>, 这个我们称之为函数,它是最小的功能单元,我们来具体看看:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数定义: 括号里数,我们叫他参数,没有参数就不写</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> 函数名(参数名1, 参数2...) </span>{</span><br><span class="line"> <span class="comment">// 函数具体怎么作实在这里,我们称之为 函数实现</span></span><br><span class="line"> <span class="keyword">return</span> 返回数值 <span class="comment">// 有的函数有,有的没有</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数调用,就是</span></span><br><span class="line">函数名(参数名<span class="number">1</span>, 参数<span class="number">2.</span>..)</span><br></pre></td></tr></table></figure></p>
<p>比如,我们刚刚提到的计算正方形的面积,如果写成函数的话并使用一下就是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 函数定义</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">squareArea</span>(<span class="params">a</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> a * a</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 首先声明面积变量S</span></span><br><span class="line"><span class="keyword">var</span> S</span><br><span class="line"><span class="comment">// 然后调用函数,参数</span></span><br><span class="line">S = squareArea(<span class="number">5</span>)</span><br><span class="line"><span class="comment">// 输出结果</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"面积是"</span> + S)</span><br></pre></td></tr></table></figure></p>
<p>运行一下结果就是,点击<a href="http://js.jirengu.com/hosoqekase/2/edit">这里</a>去看代码:<br><img src="https://wx4.sinaimg.cn/mw690/006mou3Bly1fmrnfz8hgoj30ri0dstaf.jpg" alt=""></p>
<p>所以呢,函数就是一种操作,它会有输入然后执行某种操作,在比如我们使用<code>console.log("面积是" + S)</code>来输出结果到控制台,其实这也是一个函数,你看不到它的实现是因为 <code>浏览器</code>已经默默的帮你实现了,你直接使用就可以了,还有比如<code>document.getElementById("speed")</code>这样的函数调用,其实我说这都是规定好的,就是因为它们跟<code>console()</code>一样,都由浏览器帮我们实现好了,所以浏览器跟系统,其实又点儿想你的爸爸妈妈,他们已经帮你准备好了所有的物质基础,你只需要负责好好学习跟快乐成长就可以了 :)</p>
<p>好了,读到这里我希望在回过去看看我们上次的视频中的代码,是不是了解更多一些了呢,是不是觉得我说的那句你们基本已经学会了编程了,其实真的不是在骗你们…</p>
<p>所以,总结一下,<code>网页 = html元素 + js</code>,html是网页这个机器人的组成零件,js是可以让机器人动起来的电能和大脑。</p>
<p>另外,这里我举了一个计算面积的例子,你能不能参照着,想想如何去完成一个计算器呢?<br>我想最起码我们要有4个函数对应 加减乘除 4个基本操作对吧?还要有数据输入的html元素?对,还有呢…?</p>
<p>好了,下期视屏中我们一起试试吧G_G</p>
</script></p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/11/14/小朋友的编程-五/"><span>小朋友的编程-五</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/11/14/小朋友的编程-五/" rel="bookmark">
<time class="entry-date published" datetime="2017-11-14T06:58:04.000Z">
2017-11-14
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>这一篇仍然是视频部分的补充资料,主要就是介绍javaScript的</p>
<h3 id="关于js代码"><a href="#关于js代码" class="headerlink" title="关于js代码"></a>关于js代码</h3><p>通过前边的知识,我们知道写在网页中<code>script</code>标签中的内容,就是javaScript代码,我们以前还提到过, javascript 是一种接近人类自然语言的高级编程语言。所以在网页中一个必然的事实就是,凡是看到<code><script></code>标签之间包含的东西,那么它就是js代码,而js代码在现代的网页中是无处不在的,我们随意的找一些现实中的例子,比如baidu,如果我们使用开发者工具打开–还记得怎样操作吗?(想一想快捷键–F12),你就会发现大量的script标签,就像这样:<br><img src="https://wx3.sinaimg.cn/mw1024/006mou3Bgy1flhma9ana2j31hu0y8nb7.jpg" alt="JS代码在网页中无处不在,比如baidu"></p>
<p>但是我们为什么需要js代码呢?</p>
<p>因为本身html是死的,它是什么样就在你写完它的那一刻就固定了,比如一个标题元素<code><title>标题一</title></code>一开始就固定了永远是标题一,一个数字为100,那么它就会是一直是100,像这样一经创建再也不改变的现象,通常用<code>静态</code>这个词来概括。但现实中的网页却不是这样,大多数时候网页是可以进行各种各样的交互的。比如在我们上次视频中的那个按钮–也就是<code><button></code>,我们点击了它会触发一定的事件,我们视频中就是让它计算最终结果并显示结果,再比如你去优酷看视屏的时候,你要去点击播放按钮才会开始播放,以及在玩游戏时你常常会通过键盘让角色运动,而让它干点儿什么通常就是靠js来帮助实现的。</p>
<p>换一个更通俗的例子,还记得我们前边的机器人吗,我们通过html这样的元素组成了机器人的头,身体等各个部位,而js就相当于给机器人添加了各种行动和思想,让机器人可以动动胳膊抬抬腿之类的行动,这就是为什么我的网页中需要js。因为它会让原本死的元素由静态变为<code>动态</code>,从而变得可以被人们点击,滚动,缩放(<em>缩放网页,你可以试试按下键盘中的Cril键,同时滚动鼠标中间的滚轮</em>)等等交互行为。</p>
<p>好了,现在停下来我们总结一下:<br>我们会知道,通常的网页都是可以交互的,有的有可以点击的按钮,有的有可以放大的图片,大部分网页还能随着鼠标的滑动而滚动…等等这些行为,都是依靠js来实现的。</p>
<p>那么我们就来看看JS的具体内容,他到底有什么魔力呢?我们重新回顾一下上次视屏中的js代码: </p>
<p><code>// 表示注释,就是用来说明你在干什么的,使用时系统会忽略掉代//的行,所以这其实是给人看的,计算机是不管的</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span>></span><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 说明: element</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 上边的右侧代码是元素,它是网页的基本组成部分,这些都是 W3C 规定好了的,所以不是重点,重点是下边的代码</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 这里用到的数学公式: 速度v * 时间t = 路程s</span></span></span><br><span class="line"><span class="undefined"> </span></span><br><span class="line"><span class="javascript"> <span class="comment">// ------------------</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 编程就是把复杂的事情,一步一步分解</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 目标: 创建一个网页,可以输入v和t,点击按钮,计算路程s,并显示结果</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 1> 创建一个网页,可以有输入v和t的元素 --- 已完成,并且不需要你掌握,知道了就行</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 2> 要能拿到v和t元素: 分别找到t/v input元素 </span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 3> a 点击按钮(事件)</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// b 拿到现在的v/t的值</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// c 计算</span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// d 拿到resultElm </span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// e 修改innerText</span></span></span><br><span class="line"><span class="undefined"> </span></span><br><span class="line"><span class="undefined"> </span></span><br><span class="line"><span class="javascript"> <span class="comment">// 步骤2> 分别找到t/v input元素, 通过id去找到的 -- 规定好了的方法</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> speedElm = <span class="built_in">document</span>.getElementById(<span class="string">"speed"</span>)</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> timeElm = <span class="built_in">document</span>.getElementById(<span class="string">"time"</span>)</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distanceElm = <span class="built_in">document</span>.getElementById(<span class="string">"distance"</span>)</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// 步骤3> </span></span></span><br><span class="line"><span class="javascript"> <span class="comment">// a 指定点击事件 -- 也是规定好了的, 通过onClick="anXiale()"</span></span></span><br><span class="line"><span class="javascript"> <span class="function"><span class="keyword">function</span> <span class="title">anXiale</span>(<span class="params"></span>) </span>{</span></span><br><span class="line"><span class="javascript"> <span class="comment">// b 拿到现在的v/t的值</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> speedValue = speedElm.value</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> timeValue = timeElm.value</span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distanceValue = distanceElm.value</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// c 带入公式 s = v * t ????</span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> distance = speedValue * timeValue </span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="javascript"> <span class="comment">// d 拿到resultElm </span></span></span><br><span class="line"><span class="javascript"> <span class="keyword">var</span> resultElm = <span class="built_in">document</span>.getElementById(<span class="string">"result"</span>) </span></span><br><span class="line"><span class="undefined"> </span></span><br><span class="line"><span class="javascript"> <span class="comment">// e 将结果显示到 resultElm元素 -- 规定好了的</span></span></span><br><span class="line"><span class="javascript"> resultElm.innerText =<span class="string">": "</span> + distance</span></span><br><span class="line"><span class="undefined"> }</span></span><br><span class="line"><span class="undefined"> </span></span><br><span class="line"><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure>
<p>首先,你肯定总是见到<code>var</code>这个单词,var是一种简写,他的全称是variable【变量】,再直白一点儿就是可以改变的量,比如在计算一个正方形的面积时,我们带入公式 <code>S(面积) = a(边长) * a(边长)</code>,不同的a就会有不同的S, a和S都是可以改变的,因此它们都是变量,而有的量比如 圆的面积计算中 <code>S = 2 * π * (r * r)</code>,其中的r跟S都是可以改变的是变量,而 2 和 π 都是固定的,所以我们称呼它们是<strong>常量</strong>而不是<strong>变量</strong>,对,就是这么的直白。</p>
<p>恭喜你,因为变量几乎就是网页可以变化的全部秘密,正是由于js中变量的存在,所以网页才可以动起来,所以变量的作用就像是提线木偶的线,一旦拉扯那些控制线,木偶就会做动作。</p>
<p><img src="https://wx1.sinaimg.cn/mw690/006mou3Bly1fmrmq9xxorj30tl0xcmz4.jpg" alt=""></p>
<p>其次,上边代码中还有一些符号,有计算符号 + * 还有 = ,他们的意思就是他们本身的意思,只需要注意的是 =, 在编程中并不叫等号,而是赋值符号,它表示<em>将右侧的数值或者变量 赋值给 右侧的变量</em>,好吧看起来的确有一些相等的意思,暂时这样理解也是没问题的。</p>
<p>还有,这样的语句 <code>function anXiale() {}</code>, 这个我们称之为函数,它是最小的功能单元,我们来具体看看:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 函数定义: 括号里数,我们叫他参数,没有参数就不写</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> 函数名(参数名1, 参数2...) </span>{</span><br><span class="line"> <span class="comment">// 函数具体怎么作实在这里,我们称之为 函数实现</span></span><br><span class="line"> <span class="keyword">return</span> 返回数值 <span class="comment">// 有的函数有,有的没有</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 函数调用,就是</span></span><br><span class="line">函数名(参数名<span class="number">1</span>, 参数<span class="number">2.</span>..)</span><br></pre></td></tr></table></figure></p>
<p>比如,我们刚刚提到的计算正方形的面积,如果写成函数的话并使用一下就是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">// 函数定义</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">squareArea</span>(<span class="params">a</span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> a * a</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 首先声明面积变量S</span></span><br><span class="line"><span class="keyword">var</span> S</span><br><span class="line"><span class="comment">// 然后调用函数,参数</span></span><br><span class="line">S = squareArea(<span class="number">5</span>) </span><br><span class="line"><span class="comment">// 输出结果</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">"面积是"</span> + S)</span><br></pre></td></tr></table></figure></p>
<p>运行一下结果就是,点击<a href="http://js.jirengu.com/hosoqekase/2/edit" target="_blank" rel="noopener">这里</a>去看代码:<br><img src="https://wx4.sinaimg.cn/mw690/006mou3Bly1fmrnfz8hgoj30ri0dstaf.jpg" alt=""></p>
<p>所以呢,函数就是一种操作,它会有输入然后执行某种操作,在比如我们使用<code>console.log("面积是" + S)</code>来输出结果到控制台,其实这也是一个函数,你看不到它的实现是因为 <code>浏览器</code>已经默默的帮你实现了,你直接使用就可以了,还有比如<code>document.getElementById("speed")</code>这样的函数调用,其实我说这都是规定好的,就是因为它们跟<code>console()</code>一样,都由浏览器帮我们实现好了,所以浏览器跟系统,其实又点儿想你的爸爸妈妈,他们已经帮你准备好了所有的物质基础,你只需要负责好好学习跟快乐成长就可以了 :)</p>
<p>好了,读到这里我希望在回过去看看我们上次的视频中的代码,是不是了解更多一些了呢,是不是觉得我说的那句你们基本已经学会了编程了,其实真的不是在骗你们… </p>
<p>所以,总结一下,<code>网页 = html元素 + js</code>,html是网页这个机器人的组成零件,js是可以让机器人动起来的电能和大脑。</p>
<p>另外,这里我举了一个计算面积的例子,你能不能参照着,想想如何去完成一个计算器呢?<br>我想最起码我们要有4个函数对应 加减乘除 4个基本操作对吧?还要有数据输入的html元素?对,还有呢…?</p>
<p>好了,下期视屏中我们一起试试吧</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/10/31/小朋友的编程-四/"><span>小朋友的编程-四</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/10/31/小朋友的编程-四/" rel="bookmark">
<time class="entry-date published" datetime="2017-10-31T11:57:48.000Z">
2017-10-31
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>通过前边的铺垫,我们基本上对编程有了一些了解,简短的来说,编程就是通过编程语言,给机器预设一些指令代码,让机器能够按照一定的步骤完成我们需要的功能。<br>然后通过视频介绍我们知道了网页的秘密,所有的网页本质上都是代码,而且是一种叫<code>html</code>的代码,这篇文章,会介绍一些在视频中提到的专用词汇。</p>
<h3 id="首先是关于网页"><a href="#首先是关于网页" class="headerlink" title="首先是关于网页"></a>首先是关于网页</h3><p>一个网页就是一个<code>html</code>格式的文件,如果你尝试把一个网站保存下来的话,它的后缀就是<code>文件名.html</code>,我相信你肯定知道<code>txt</code>格式, 也见过<code>mp3</code>,<code>mp4</code>,<code>exe</code>等。<br><img src="http://wx3.sinaimg.cn/mw1024/006mou3Bly1fl2w0f6vkpj30i80pe40t.jpg" alt="常见文件格式例子"></p>
<p>如果你电脑里的文件是没有后缀的话,那就是系统并没有设置显示文件后缀,可以参考这里去试试<a href="https://jingyan.baidu.com/article/5d368d1e31ed903f60c057c6.html" target="_blank" rel="noopener">https://jingyan.baidu.com/article/5d368d1e31ed903f60c057c6.html</a></p>
<p>一般来说,<strong><code>格式</code>是代表着一种数据的组织方式,也指示着文件的用途</strong>。我套用个生活中的例子,需要帮助时,当你看到一个穿警服的人,即便你并不认识也从来没见过他,你也会知道他是警察,有困难就去找他帮忙。<strong>警服</strong>在这里就表示了对方警察的身份和职能,其实格式也有类似的意思,它会代表文件的某种特定的用途。比如<code>mp4</code>是要拿视屏播放器才能打开的,因为它是一种视屏文件格式,<code>mp3</code>是音乐要用音乐播放器放,<code>txt</code>文本格式可以用记事本打开,同理我们这里的<code>html</code>,它就是代表网页,是需要用浏览器来打开的。</p>
<p>事实上,浏览器是能够认识<code>html</code>中的代码,进而把这些代码渲染成漂亮的网页便于人们使用,毕竟只有专业认识才认识代码,而普通人上网只需要看到浏览器处理后的网页的样子就可以了。</p>
<p>– 好了,恭喜你,你了解到一个叫做<strong>文件格式</strong>的新知识了</p>
<p><code>html</code>是有一定规则的,还记得在<a href="http://js.jirengu.com" target="_blank" rel="noopener">js.jirengu.com</a>这个在线练习网站中,打开差不多是这样的:<br><img src="http://wx4.sinaimg.cn/mw1024/006mou3Bly1fl1prp26wlj31ae0s0wgt.jpg" alt="这是代开网页的样子"></p>
<p>刚进入时,左侧它就会自动给出一部分写好了的代码,我把它复制到下面:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE html></span></span><br><span class="line"><span class="tag"><<span class="name">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"utf-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>JS Bin<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure></p>
<p>视屏中并没有详细说明这些东西,但你可能也发现了一些规律,比如大部分代码都好像是这样的一种形式:<code><单词> 有的可能还有其他东西 </单词></code>, 或者简单一点儿像 <code><单词></code>,总之是由<strong>一个或者几个尖括号和单词</strong>组成的结构,这种结构我们称之为网页中的一个<code>元素</code>[element: 元素,单元之意]。元素就像是零件,将他们组合起来就是一个网页了,事实上,你看到的所有网页都是由各种各样的元素组合起来的,就好比扣子,拉链和布料这些基本材料,可以做成各种各样的衣服那样,(这是你小姨举的例子 (^_^)v</p>
<p>– 好了,恭喜你,你又知道了: 网页是由各种各样的元素组成的</p>
<p>除此之外,上边提到的结构中还有单词我们没有说到,这些单词不是乱写的,而是由一个叫<strong>万维网联盟(缩写W3C)</strong>的国际组织规定好了的,它们是能被各种浏览器都认识的特定单词,也称之为<code>标签</code>, 所以基本上: </p>
<blockquote>
<p><strong>元素</strong> = <strong><code><标签名> 可能有内容 </标签名></code> 或者 <code><标签名></code></strong></p>
</blockquote>
<p>所以我们现在就来找找,上述的代码中有哪些标签呢?<br>有一个html标签,一个head标签,一个body标签,meta跟title也都是标签,这里说明一下,第一句<code><!DOCTYPE html></code>是个例外,它的作用是告诉浏览器下面的 HTML 是用什么版本编写的,方便浏览器认识代码用的,你可以把它理解为一种固定不变的步骤。</p>
<p>我们知道了术语之后,再回头看看上边的代码,其实基本上就是一个大的html元素,有2个子元素是 <strong>头(head)元素</strong> 跟 <strong>体(body)元素</strong>,而头元素中又嵌套了 <strong>meta元素</strong>(<em>这里的meta里边的charset我们称之为的属性</em>)和 <strong>title元素</strong>, 而我们通常就会在 主体(body)元素 中利用各种标签,进行代码的编写,从而达到我们想要的网页效果,这也是我们视频中步骤一部分的内容。如果我用图表示一下,就是这样:<br><img src="http://wx1.sinaimg.cn/large/006mou3Bly1fl2ygc4zs7j30ci09pmxq.jpg" alt=""></p>
<p>就像机器人拥有各种各样的零件一样,网页中w3c规定的标签目前有150多个之多,常见的还有比如视频中我们用到的 <code><div> (表示区域), <button>(表示按钮), <img>(表示图片), <input>(表示输入框), <script>(表示js代码)</code>等等,以后我们还会逐渐见到其他元素,不过不要慌,这些标签都不用你去记忆,用到时去搜索查查,知道它是怎么回事儿就够了。</p>
<h3 id="关于js代码"><a href="#关于js代码" class="headerlink" title="关于js代码"></a>关于js代码</h3><p>…待续</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/10/04/小朋友的编程-三/"><span>小朋友的编程-三</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/10/04/小朋友的编程-三/" rel="bookmark">
<time class="entry-date published" datetime="2017-10-04T01:14:27.000Z">
2017-10-04
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>上两次阅读部分的意味更加浓厚一些,都是些很细小的知识,这篇文章我们将试着尝试一些更加实际的体验,去直观感受一下什么是编程,当然前半段会有一部分编程语言发展历史的介绍,耐心看完啦。</p>
<p>你已经知道了编程就是跟机器交互的过程,而我们告诉机器该怎么做,靠的是一种叫做编程语言的工具。你还知道机器内部所有的信息其实都是各种数字电路的信号,我们习惯使用<code>0</code>和<code>1</code>来代表数字信号,换言之机器能认识的其实只有0101,这种机器能<strong>直接</strong> <em>认识和执行的由一系列01010</em> 组成的东西我们称之为<code>机器语言</code>。</p>
<p>事实上最原始的编程,就是科学家们利用0101的组合去一步一步指示机器去完成功能的,但是只用0101又一个很大的问题,那就是虽然机器明白了,人却不懂了。具体来说如科学家A编的程序可能只有A自己知道,科学家B是无论如何都看不懂的,就算是对A自己,过了一段时间之后可能也都忘了当时是怎样编程了的。如果都是像0101这般不直观不友好的机器语言,项目就不可能让更多的人参与,机器所能完成的工作也就不可能像我们今天这样多姿多彩。怎么办呢?如果我们有一种人类能看懂而机器又能认识的语言就好了,可惜不行,因为我们前边提到了<strong>机器能也只能</strong>认识0101这样的<code>机器语言</code>,于是科学家从人类的实际生活中受到启发,生活中比如你想跟一个法国的小朋友交流,你会中文而她只会法语,你就会想着找个翻译就解决了你们的语言问题,于是科学家们就约定了一个总体原则,那就是所有的编程语言都最终可以被翻译成机器能认识的<code>机器语言</code>,这样就解决了上述问题。</p>
<p>按照上述的发展历程,在<code>机器语言</code>之上,一种更友好的编程语言被发明出来,那就是<code>汇编语言</code>,真实的汇编语言长得是这个样子的:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">.section .data</span><br><span class="line">#数据段,定义以ascii编码的字符串“hello, xiao ze qiu!\n”,并以output来表示内存的起始地址</span><br><span class="line"> output:</span><br><span class="line"> .ascii "hello, xiao ze qiu!\n"</span><br><span class="line">.section .text</span><br><span class="line">.global _start</span><br><span class="line">#程序以_start:开始运行</span><br><span class="line">_start:</span><br><span class="line">#调用write系统,eax为4表示write,ebx表示要写入的文件描述符,</span><br><span class="line">#1表示标准输出,也就是终端,ecx表示字符串开头的内存地址,edx表示长度</span><br><span class="line"> movl $4,%eax</span><br><span class="line"> movl $1,%ebx</span><br><span class="line"> movl $output,%ecx</span><br><span class="line"> movl $12,%edx</span><br><span class="line"> int $0x80</span><br><span class="line">#调用退出系统,1表示退出,0为正常退出,这里和c语言main函数的返回值应该是一个意思</span><br><span class="line"> movl $1,%eax</span><br><span class="line"> movl $0,%ebx</span><br><span class="line"> int $0x80</span><br></pre></td></tr></table></figure></p>
<p>你是不是有些蒙了,看起来好难好复杂的样子啊!其实上述程序干的事情很简答,只是在屏幕上跟你打个招呼而已 – “hello, xiao ze qiu!”,但是写起来却要那么长一串,所以在这里要心疼一下早编程的前辈们��,这个例子就暴漏了<code>汇编语言</code>的弱点,那就是虽然总算比0101有好一些,但实在是太麻烦了,难道编程语言就不能像我们平时说话那样,表达明确又简单吗?</p>
<p>其实是可以的,那就是人们终于在受不了汇编之后,又发明了很多种更接近人类语言的编程语言,我们统称它们为<code>高级编程语言</code>,它们有很多很多,据统计有250多种并且还在不断的被发明出来,因为它们各自要解决的问题和使用领域的不同,根据不用的设计理念就有了如此多的数量,但肯定都比汇编简单太多太多,比如上述打招呼如果用<code>C语言</code>来实现就是:<br><figure class="highlight c"><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="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> <span class="built_in">printf</span>(<span class="string">"hello, xiao ze qiu!"</span>); <span class="comment">// print 就是打印的意思,printf指的是打印之后自动换行而已</span></span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>是不是简单了很多也好懂了很多:-), 其实还有更简单比如有一门叫<code>JavaScript</code>的语言中只需要一句话:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">console</span>.log(<span class="string">"hello, xiao ze qiu!"</span>) <span class="comment">// console 就是控制台,就是windows系统上那个命令行的黑框框的东西,你自己先在电脑上试试,看能不能找到</span></span><br></pre></td></tr></table></figure></p>
<p>如果还是觉得麻烦,还有最简单的,比如在一门叫<code>Python</code>的编程语言中就是:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="string">"hello, xiao ze qiu!"</span>)</span><br></pre></td></tr></table></figure></p>
<p>是不是很简单,这样的对人友好的<code>高级编程语言</code>很接近于我们日常使用的语言,于是跟机器交流就变得容易多了,这才促进了整个计算机科学的发展。</p>
<p>所以我们稍稍总结一下,编程语言的发展基本上是这样的: <code>机器语言</code> ~> <code>汇编语言</code> ~> <code>高级语言</code>, 我们通常意义的编程就是,利用接近人类自然语言的<code>高级语言</code>给机器规定动作。</p>
<hr>
<p>下面就开始思考一个个具体的问题,让我们对生活中习以为常的逻辑行为做一些具体的仔细的整理。<br>不防就从对现实生活中模仿开始,比如我们知道周一到周五是上课时间,而周六日是休息不上课的,就这样简单的一句话,当我们试着把每个过程说清楚,用代码的方式就像是这样:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">首先是一个日期</span><br><span class="line">然后把它转化成星期</span><br><span class="line">如果是在周一到周五,那么正常上课</span><br><span class="line">如果是周六或者周日,那么不用上课</span><br></pre></td></tr></table></figure></p>
<p>这里边蕴含着一种<strong>选择结构</strong>,如果把它画成逻辑流程图,会更直观一些:<br><img src="http://wx3.sinaimg.cn/mw1024/006mou3Bgy1fk8hcqy9yuj30m80py0v8.jpg" alt=""></p>
<p>生活中还有其他的逻辑流程,比如再考虑这样一个例子,考试的时候你需要把全部的题做完才能交卷,这样的逻辑图是怎样的呢?我可以画出来是这样的:<br><img src="http://wx1.sinaimg.cn/mw1024/006mou3Bgy1fk8if79yy7j30s40sqwhk.jpg" alt=""><br>跟第一种不同的是这里边不光有<strong>选择结构</strong>还附带的有<strong>循环结构</strong>的逻辑,所谓循环逻辑就是直到满足一定的条件才会退出循环,否则就会一直执行的一种结构</p>
<p>事实上还有一种<strong>顺序结构</strong>就是按顺序一步一步来,上述的每个箭头都代表从这一步到下一步的顺序执行,它是最符合我们人类直觉最自然的结构,所以不必额外提出来。</p>
<p>现在,如果你能仔细在思考一下,就会发现这个世界上所有的事情,都最终可以用上边这3种基本逻辑结构通过组合来实现,有的是选择分支多一些,有的是循环多一些,比如我们让上边考试的例子在具体一些,那就加上考试是有时间的因素,一个考试的完整流程可能是这样的,先说代码:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">开始</span><br><span class="line">开始做题,并开始计时</span><br><span class="line">如果时间到了就必须交卷,退出</span><br><span class="line">如果时间没到,就把所有题做完,退出</span><br></pre></td></tr></table></figure></p>
<p>这里边的时间逻辑是最主要的,只要时间到了就必须交卷,不管做没有做完,还有另一种情况是时间没走完但做完了也可以交卷,文字不容易说明,不防也化成逻辑流程图:<br><img src="http://wx1.sinaimg.cn/mw1024/006mou3Bgy1fk8kdl1zv1j30o00sm77l.jpg" alt=""><br>注意图中有2条不一样的线,红色的表示同时进行,因为一开始计时就代表着可以开始做题;另外一条蓝色的线,代表每次做题都会去检测时间是否到了,如果到了就马上交卷,如果没到就继续计时和做题,基本就是2个并行分支一个计时,一个检测是否做完,在每个分支内部又是选择和循环的组合。所以这就是编程全部秘密,编程就是<strong>将某个功能,按照基本步骤进行逻辑划分,拆成一个一个简单的<code>顺序</code>或者<code>选择</code>或者<code>循环</code>的结构,从而最终达到某种确定的结果</strong>。</p>
<p>当然这里我们是通过文字和流程图实现的,实际的计算机编程中,我们只需要把上述,改为使用计算机能理解的编程语言实现了而已,所以只要你学会了将一个复杂过程一步一步的逻辑分解,就可以说已经学会了编程,这么一看,其实你已经无意识的使用了很多年的编程,只是你不知道罢了,所以编程不是什么神秘的事,相反它之非常平常。</p>
<p>那具体是怎样把这些逻辑通过编程语言来实现呢?其实我们只需要借助一点点数学就可以了,比如我下边简单的列举几个,看看你自己能不能看出来它是属于什么结构的:</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 一个 = 就是普通的等号," == " 这个才表示 比较数值</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// -------------- 1 --------------</span></span><br><span class="line"><span class="keyword">var</span> x = <span class="number">0</span> <span class="comment">// 不要管前边的var,你可以把x当成方程中的自变量一样,下边还有几个简单的单词,你应该可以自己查到的,试试吧</span></span><br><span class="line"><span class="keyword">if</span> (x == <span class="number">0</span>) {</span><br><span class="line"> <span class="comment">// 情况1之下做点儿什么 </span></span><br><span class="line">}<span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 情况2之下做点儿什么 </span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// -------------- 2 --------------</span></span><br><span class="line"><span class="keyword">var</span> x = <span class="number">10</span></span><br><span class="line"><span class="keyword">while</span>(x > <span class="number">5</span>) { <span class="comment">// while 单词表示 当什么什么时候</span></span><br><span class="line"> <span class="comment">// 做点儿什么,比如输出x</span></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">" >> "</span> + x)</span><br><span class="line"> x = x - <span class="number">1</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// -------------- 3 --------------</span></span><br><span class="line"><span class="comment">// x-- 是 x = x-1 的一种简写</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">var</span> x = <span class="number">10</span>; x > <span class="number">5</span>; x--) {</span><br><span class="line"> <span class="comment">// 做点儿什么,比如输出x</span></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">" -- "</span> + x)</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>1很简单,就是个只有2个分支的选择结构,我们称之为 <code>if-else语句</code><br>2通过单词也能大概猜到是个循环结构,我们称之为 <code>while语句</code><br>3呢,其实3也是一种循环结构,这种语句在编程中称之为 <code>for语句</code>, 它只是比2中的 <code>while语句</code> 写起来更简单一些罢了, 2和3都表示一种循环结构,它们的执行结果如图<br><img src="http://wx3.sinaimg.cn/large/006mou3Bgy1fk8m7ig8fdj31kw0ftq7z.jpg" alt=""></p>
<p>好了,这次只是让你简单的认识一下编程,至于各种语句应该怎么写,将在后续慢慢去了解,现在你只要能够知道<code>顺序/选择/循环</code>这3种结构,并学会把生活中的事情分解成一步一步的上述3种结构就可以了</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/09/18/小朋友的编程-二/"><span>小朋友的编程二</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/09/18/小朋友的编程-二/" rel="bookmark">
<time class="entry-date published" datetime="2017-09-18T01:39:27.000Z">
2017-09-18
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h3 id="一切都是数字和电路"><a href="#一切都是数字和电路" class="headerlink" title="一切都是数字和电路"></a>一切都是数字和电路</h3><p>我们上一次大致对电脑以及编程的概念有了一些了解,编程就像是跟机器说话,告诉机器按照我们设计的流程去完成工作,而电脑 = 电子元件 + 程序 = 硬件 + 软件。 这一节就在具体说说为什么电脑除了需要硬件之外还需要软件。</p>
<p>这还得从电路开始说起,我跟你提到过电路可以分为2类。一种叫<code>数字电路</code>,它出现的比较晚是个小弟,它的大哥是一个叫<code>模拟电路</code>的家伙,这家伙从人类认识和使用电以来,基本都是它,比如作为能源供应驱动电机,灯泡等等。</p>
<p>我还提到过,电不光是一种能量,还可以是一种信息,所以模拟电路和数字电路的区别,最根本的来说就是2者电路中的信号不一样,一个电路板如果它里面的信号是数字信号,那它就是数字电路,否则就是模拟电路。</p>
<p>简单的来说,随处可见的自然信号都模拟信号,比如声音信号,灯光等等,模拟信号的特点就是在时间上和取值上都是连续的不间断的,如果在你学过的数轴上,随意画出来就是一条连续不间断的曲线,就是一个典型而自然的模拟信号。</p>
<p>数字信号就不一样了,在时间上和取值上都是不连续的。这些说起来有些难以理解,但是通过图就看出来的:<br><img src="http://wx3.sinaimg.cn/mw1024/006mou3Bgy1fjtkw1x0w0g30b607xdfq.gif" alt=""></p>
<p>这是很简单的图,还有更复杂一些的,你能不能判断那些是模拟的那些是数字的呢?<br><img src="http://wx1.sinaimg.cn/mw1024/006mou3Bgy1fjtlemadohj31040ywq7n.jpg" alt=""></p>
<p>其实关键就是看信号图是否连续,如果没有间断那就是模拟的,如果是一个一个柱子一样的东西那就是数字的。</p>
<p>既然模拟信号又自然应用的又早,那为什么现在主流都是数字信号呢?</p>
<p>其实,再上图中你就能猜出一些,原因很多,但最关键的是数字信号简单,规律性强,简单就意味着用电量少,有规律就意味着处理很传输方便,所以数字电路可以做到很小很强,我们接着图:</p>
<p><img src="http://wx2.sinaimg.cn/mw1024/006mou3Bgy1fjtluehv9pj30ri0drgnh.jpg" alt=""><br>上图左侧是早期的计算机,硬件主要都是模拟电路,而右侧你就很熟悉了,就是普通的家用电脑,前者有几个屋子大小而后者桌上就能放,相对于体积差异它们的功能强弱才是更让人惊奇的,后者计算能力比前者要强<strong>好几百万倍</strong>都不止,即便你的手机的处理能力,也要比屋子一样的老电脑强很多很多。这就是为什么现在数字电路被广泛的使用在各个领域,电脑就是其中最典型的存在。</p>
<hr>
<p>了解了这些之后,我们再回到主题,电脑 = 硬件 + 软件,其中硬件指的是数字电路,那么软件呢?</p>
<p>其实还是好回到数字也是信息的那个例子,回顾一下吧:<br>比如我给定一个标准电压5v,如果比5小的电压我们称之为低电压,我们用0表示,比它高就是高电压,我们用1表示。同时我们还规定,如果高电压就代表天气晴朗适合出门玩,低电压为雨天不能出门,文字描述对应到表格就是:</p>
<table>
<thead>
<tr>
<th style="text-align:center">大于5V</th>
<th style="text-align:center">1</th>
<th style="text-align:center">天气晴朗</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">小于5V</td>
<td style="text-align:center">0</td>
<td style="text-align:center">阴雨天气</td>
</tr>
</tbody>
</table>
<p>那么如果给出的是<code>1</code>,你一看自然就知道了:噢,今天天清气朗,是可以出去游玩,<code>0</code>的话就正好相反。上述就通过把<code>电压</code>转化成了数字信号<code>0或1</code>(这一步是硬件在发挥作用),从而来0表示阴雨并让1表示晴天(这个规定谁代表谁就属于软件的工作),他们共同作用就完成了表示天气的好坏的功能。</p>
<p>让我们在扩展一下,如果科学家发现了一种材料,它做成的电路能根据天气的好坏而发生变化,雨天低于5v,晴天就高于5v,这时候我们把这种材料做的电路放到院子里,你只用在屏幕前去看显示0或者1,就知道了天气,不用自己出去看,并且整个过程是自动化的,也就是说一旦已你第一次布置好了之后,就再也不用去干预了,你就拥有了一个能自动告诉你天气的智能设备了。</p>
<p>这就是软件+硬件之所以厉害的原因,它们配合起来就是自动的,智能的。</p>
<p>看起来也不是太难,是吧</p>
<p>总结一下,通过这篇文章,你对软件和硬件多了解了一些:</p>
<ul>
<li>电脑里的硬件基本都是数字电路,它们可以处理数字信号</li>
<li>数字信号不是0就是1,电脑中的一切本质上都是0和1,不管是图片视屏还是游戏</li>
<li>软件的作用就是为了支持和解释硬件的,它规定01代表了什么</li>
</ul>
<p>这还是一篇概念性的材料,看过有个印象就行了,能了解到电脑中的一切都是0101很重要,因为它就是电脑工作的基本机制。预告一下:下周,我们就要开始试试最简单的编程了。</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/09/16/小朋友的编程-一/"><span>小朋友的编程(一)</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/09/16/小朋友的编程-一/" rel="bookmark">
<time class="entry-date published" datetime="2017-09-16T09:56:27.000Z">
2017-09-16
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h2 id="第0章-引子"><a href="#第0章-引子" class="headerlink" title="第0章 引子"></a>第0章 引子</h2><p>你一定对电脑和手机的使用非常熟悉,这些事情你几乎天天在做:</p>
<ul>
<li>打开电脑,屏幕亮起,等待一小段时间(或许你知道这是在启动系统),直到出现桌面</li>
<li>点击游戏图标,进入游戏就可以开心的玩游戏了</li>
<li>点击QQ,输入密码和账号,点击好友图像,就能在弹出的对话框中通过打字、语音或者视屏跟好友聊天了</li>
<li>到超市买东西,打开手机扫一扫就完成了付款</li>
<li>再回忆一个找动画片的例子: 打开浏览器,输入www.baidu.com就到了百度的首页,通过百度找到自己喜欢的动画片,比如“火影忍者”,在搜索结果中找到土豆网,点击它,等页面加载结束就可以看到动画片了 </li>
</ul>
<p>上述你一定非常熟练,对吧</p>
<p>但是你没有好奇过这一切是怎么发生的,它们背后的原理是什么呢?电脑究竟有什么魔力让它能帮你找到自己想要的信息?如果你学会了背后的东西,是不是就能自己去做自己的游戏,自己的QQ呢?</p>
<p>其实是可以的,在你轻描淡写的动动鼠标就完成的背后,是由大量杰出的科学家和工程师们的辛勤工作的成果,它们利用电子技术、信息网络技术和软件工程让这一切变得如此易用和普通。</p>
<hr>
<p>那么一开始,我们就先聊聊电脑,你认为电脑是什么呢?什么才算是电脑呢?看看下边几张图吧,你猜猜图中哪些是电脑:</p>
<p><img src="http://wx3.sinaimg.cn/mw1024/006mou3Bly1fjlldwt2hfj30ia0iajud.jpg" alt="猜猜看这里边那些是电脑?"></p>
<p>其实上边的都是电脑,家用台式机和笔记本很常见,但第一图的工业小型机和第四图的超级计算机就不常见了,其实远远不止这些,电脑的范围比你想象的还要广泛,比如你用的手机,每辆汽车上都有管理刹车和空调的汽车电脑,去银行取钱用到的ATM,去超市付款时收银员操作的收银机,甚至小到你玩的遥控玩具车,厨房里的电磁炉微波炉等等都可以称之为电脑,那么我们可以这样约定一下,我们所说的电脑是这样一种机器:<strong>能够<code>自动化</code>的实现某种或多种功能的<code>电子设备</code></strong>,它们都可以称为电子计算机,也就是我们口语化的电脑。</p>
<p>是不是没想到原来电脑有那么多小兄弟,你的周围除了那个四四方方的带有屏幕的机器外,还有那么多设备其实都是电脑,那你在想想,除了上边我提到的之外,还有没有其他的东西也可叫做电脑呢?你可以按照我们刚才约定的那个定义去估计,试一试吧</p>
<p>然后我们在将注意力放到刚刚的定义上,定义里有2个关键字,一个是<code>电子设备</code>,一个是<code>自动化</code>。怎样理解呢,你可以把电脑想象成一个完整健康的人,一个人首先是有肉体躯干的,其次他还是有思想有智力的,类似的,组成电脑的各种电子器件就相当于肉体躯干,而软件就是电脑的思想智力,如果一个人只有躯干没有意识,那他就是植物人,对电脑也是一样的,如果一堆没有软件调控的硬件,也不能完成我们需要的功能。所以一个完整的电子计算机(健康的人) = 电子元件(肉体) + 程序(思想意识),更通俗一些的说法是电脑 = 硬件 + 软件</p>
<p>所谓编程就是编写软件的行为,是一种给器件赋予灵魂,让硬件组织起来共同完成某种功能的行为。换一个角度说来,或许更容易理解一些:我们说话用的是普通话,你跟你姥姥说话用的是山东话,你小姨跟她的学生交流需要英语,我们人类之间的交流是需要语言交流的,同样的道理,如果想让那一堆冰冷的电子器件一起干一件什么件事的话,就需要跟机器交流。跟机器交流就是<code>编程</code>,我们用来跟机器交流的语言就是<code>编程语言</code>。所以本质上编程就是<code>通过编程语言,编写出机器能识别和执行的程序,让机器遵照先前编写好了的程序,达到完成某种功能的过程</code>。</p>
<p>所以简单的说编程就是告诉机器去干什么的过程</p>
<p>希望你通过上面的文字,能对软件,硬件,编程的概念有一个大概的印象,并且能对电脑的认识有所扩展一些就算达到目的了</p>
<p>给你留一个可选的小任务:上边的图片中有个叫<code>神威</code>的家伙,看起来很霸气,你能不能自己动手查一查它究竟有何特殊之处呢?</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/08/29/我的机器学习之概述/"><span>我的机器学习之概述</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/08/29/我的机器学习之概述/" rel="bookmark">
<time class="entry-date published" datetime="2017-08-29T04:52:15.000Z">
2017-08-29
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><ul>
<li>是什么?<br>通俗来讲就是利用已有数据,得到某种模型,并利用其预测未来的计算机方法,跟模式识别,统计学习,数据挖掘,计算机视觉,语音识别,和NPL等领略息息相关,是一门交叉学科。一般可认为数据挖掘等同于机器学习,只是其数据来源不仅仅来源于结构化数据,还包括图像,音频等。下面的说法也常常被默许:<br>模式识别最初来源于来源于工业界,后来扩展到语言,图像等等<br>数据挖掘 = 机器学习 + 数据库<br>自然语言处理 = 文本处理+机器学习<br>计算机视觉=图像处理+机器学习<br>语音识别=语音处理+机器学习</li>
</ul>
<p>核心的学习问题的定义:针对某类任务T的,可以用P来衡量性能,如果P可根据经验E来自我完善,则称之为该计算机程序从经验E中学习。 而机器学习这么学科就是让机器进行学习的学科,其最原始的定义由Tom Mitchell等提出:<br>从样本集<code>S(z, {xkk, y, ykk})</code>学习/估计一个假设<code>f(x)</code>,使得<code>f(x)</code>是问题世界模型<code>F(x)</code>的一个近似</p>
<ul>
<li>常见术语罗列,基本很容易理解<br><code>f = aX + bY + cZ + ...</code></li>
</ul>
<p>数据集: 所有可能取到的变量<br>示例/样本<br>属性/特征: a,b,c等<br>属性空间/样本空间/输入空间X:由全部属性而成的空间,如上述a,b,c为坐标轴形成的空间,每个点可以是一个样本<br>特征向量: 属性空间中的坐标向量<br>训练集<br>训练样本<br>假设<br>标记:关于示例结果的信息,如年龄20~35称之为适龄青年,适龄青年就是一个标记<br>样例:拥有标记的示例,会组成标记空间/输出空间<br>分类:对于离散型任务的别称<br>回归:预测结果是连续值的问题的统称<br>特征清洗相关: 采样,归一/离散化,降维,特征提取等<br>损失函数: 用以度量结果和预期的不同</p>
<ul>
<li>适用领域</li>
</ul>
<p>收集数据 -> </p>
<ul>
<li>机器学习算法分类</li>
</ul>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/26/js组件化演进探讨-Commom-js-AMD-CMD规范/"><span>js组件化演进探讨-Commom.js/AMD/CMD规范</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/26/js组件化演进探讨-Commom-js-AMD-CMD规范/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-26T09:45:15.000Z">
2017-04-26
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h3 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h3><p>在早先在的组件化演化一文中,通过对组件封装的一步一步推演,最终得到了一个集API权限管理,节省命名空间,以及调用方便的方式,但仍然没有解决所有的问题,比如模块依赖管理,而这是模块化演进到可用级别的必要条件</p>
<p>如果不是把工作重点转移到公司前端的工作上,无论如何都不会想到前端为了处理<code>命名空间冲突+组件加载及依赖管控+API接口权限管理</code>,这种绝大多数语言几乎天然拥有的能力,而为此付出了多少,在Java一个package,C++中一个import module 在前端的工作中确实在是大费周折,本质原因就是js原本是被设计成一门脚本语言,设计者也没有料到web会发展成今天这样复杂和多样,而只是以函数作为作用域标准,如果不加处理项目稍大,命名空间的管理和组件的依赖就是灾难级别的,所以modeul化是必然并还将继续发展,正如:</p>
<blockquote>
<p>规范形成的过程是痛苦的,前端的先驱在刀耕火种、茹毛饮血的阶段开始,发展到现在初具规模</p>
</blockquote>
<h3 id="模块化"><a href="#模块化?" class="headerlink" title="模块化?"></a>模块化?</h3><p>道理都说了,那就从代码来直观的展示一下模块化的历程,以下每一个<code>🔜</code>表示一种演进:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo1</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="comment">// do something</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo2</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="comment">// do something</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 🔜 函数 => 类</span></span><br><span class="line"><span class="keyword">var</span> Module = {</span><br><span class="line"> var1: <span class="number">1</span>,</span><br><span class="line"> var2: <span class="number">2</span>,</span><br><span class="line"> foo1: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ <span class="comment">/* do something */</span> },</span><br><span class="line"> foo2: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ <span class="comment">/* do something */</span> }</span><br><span class="line">}</span><br><span class="line">Module.foo2(); </span><br><span class="line">Module.var2 = <span class="number">100</span>; <span class="comment">// 无权限控制</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 🔜 类 => 借助立即执行函数</span></span><br><span class="line"><span class="keyword">var</span> myModule = (<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> var1 = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">var</span> var2 = <span class="number">2</span>;</span><br><span class="line"> foo1: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ <span class="comment">/* do something */</span> },</span><br><span class="line"> foo2: <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{ <span class="comment">/* do something */</span> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> fn1: foo1,</span><br><span class="line"> fn2: foo2</span><br><span class="line"> };</span><br><span class="line">})();</span><br><span class="line">myModule.foo1()</span><br></pre></td></tr></table></figure></p>
<p>很容易看出利用立即执行函数的好处,在以上的基础上随着服务器端NodeJS的兴起,终于推出了第一个模块化的js规范 – <code>CommonJS</code></p>
<h3 id="服务器端的commonjs"><a href="#服务器端的CommonJS" class="headerlink" title="服务器端的CommonJS"></a>服务器端的CommonJS</h3><p>具体来说就是3个基本规范:<br>1 作用域:单独文件,单独作用域,除非是Global的<br>2 输出:指定<code>module.exports</code>为唯一出口<br>3 依赖:通过<code>require</code>加载模块<br>于是上述demo套用这个规范以后就是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// --- Tony.js中 ---</span></span><br><span class="line"><span class="keyword">var</span> name = <span class="string">'Tony Stark'</span></span><br><span class="line">fucntion sayName() {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'Iron man is'</span> + name)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="built_in">module</span>.exports = {</span><br><span class="line"> run: sayName</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// --- Other file ---</span></span><br><span class="line"><span class="keyword">var</span> tonyModule = <span class="built_in">require</span>(<span class="string">'./Tony.js'</span>) <span class="comment">// 同步,并且相对路径时js需省略</span></span><br><span class="line">tonyModule.sayName()</span><br></pre></td></tr></table></figure></p>
<p>如果完全将<code>CommonJS</code>移植到浏览器,那么<code>require</code>同步加载势必会影响体验,但不同步呢依赖件的管理就不那么容易了,这个问题偏向的不同导致了2中浏览器端的模块化标准:<code>AMD</code>和<code>CMD</code></p>
<h3 id="amd-和-cmd"><a href="#AMD-和-CMD" class="headerlink" title="AMD 和 CMD"></a>AMD 和 CMD</h3><p>但是万变不离其宗,不管是谁都需要解决<code>模块定义,输出和输入(加载)</code>这3个问题</p>
<ul>
<li><code>AMD(Asynchronous Module Definition)</code>: 通过<code>RequireJS</code>库,实现了浏览器端异步模块定义,具体来说:</li>
</ul>
<p>1 模块定义和输出:使用全局函数<code>define(id?, dependencies?, factory/exportValue)</code>定义模块,其中的最后一个参数<code>factory/exportValue</code>为输出,可以是一个对象的值,更多的是初始化工厂方法<br>2 异步输入/加载: <code>require([dependency, ...], function() {})</code>函数,会自动异步加载依赖项,直到加载完成才执行对应操作</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">script</span> <span class="attr">data-main</span>=<span class="string">"js/app.js"</span> <span class="attr">src</span>=<span class="string">"lib/require.js"</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br></pre></td></tr></table></figure>
<p>页面上只出现一个<code><script data-main="js/app.js" src="js/require.js"></script></code>即可,这里的<code>data-main</code>是require的入口路径有的类似于<code>main()</code>函数一样,requirejs使用它来启动脚本的自动加载过程,这样就可以组织一个典型的页面结构:<br><img src="\img\js组件001.png" alt="Site页面组织结构"></p>
<p>然后使用时借助<code>require([dependency, ...], function() {})</code>函数<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">requirejs.config({</span><br><span class="line"> baseUrl: <span class="string">'js/lib'</span>,</span><br><span class="line"> paths: {</span><br><span class="line"> app: <span class="string">'../app'</span></span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">requirejs([<span class="string">'jquery'</span>, <span class="string">'canvas'</span>, <span class="string">'app/sub'</span>], <span class="function"><span class="keyword">function</span> (<span class="params">$, canvas, sub</span>) </span>{</span><br><span class="line"> <span class="comment">//using jQuery, canvas and the app/sub here</span></span><br><span class="line">});</span><br></pre></td></tr></table></figure></p>
<p>这就是<code>AMD</code>规则</p>
<ul>
<li><code>CMD(Common Module Definition)</code>: 以<code>SeaJS</code>为基础,国内发展出来的通用模块加载规则,其定义和输入输出如下<code>define(id?, [dependency...], function(require, exports, module) { });</code>,一个简单的例子:<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Tony.js</span></span><br><span class="line">define(<span class="function"><span class="keyword">function</span>(<span class="params">require, exports, modules</span>)) </span>{</span><br><span class="line"> <span class="keyword">var</span> $ = <span class="built_in">require</span>(<span class="string">'jQurey.2.1.js'</span>) <span class="comment">// 假设tony需要使用jQurey</span></span><br><span class="line"> <span class="keyword">var</span> name = <span class="string">'Tony Stark'</span></span><br><span class="line"> fucntion sayName() {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'Iron man is'</span> + name)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="built_in">module</span>.exports = sayName <span class="comment">// 输出</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// ----- Other file ------</span></span><br><span class="line"><span class="keyword">var</span> sayName = <span class="built_in">require</span>(<span class="string">'lib/Tony.js'</span>)</span><br><span class="line"><span class="keyword">var</span> ironMan = <span class="keyword">new</span> Tony()</span><br><span class="line">ironMan.sayName()</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>可看出更commondJS更相似,推崇一个文件一个模块,推崇就近加载,也就是用到就去加载</p>
<p>关于这两个的区别网上可以搜出一堆文章,简单总结一下</p>
<ul>
<li>最明显就是:在模块定义时,对依赖模块的执行时机处理不同(注意不是加载的时机或者方式不同)<blockquote>
<p>AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块<br>CMD推崇就近依赖,只有在用到某个模块的时候再去require<br>这种区别各有优劣,只是语法上的差距,而且就现在阶段来说,requireJS和SeaJS都支持对方的写法,所以写法的差距都不在具有区分度</p>
</blockquote>
</li>
</ul>
<p>很多人说requireJS是异步加载模块,SeaJS是同步加载模块,这么理解实际上是不准确的,其实加载模块都是异步的,只不过AMD依赖前置,js可以方便知道依赖模块是谁,立即加载,而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块,这也是很多人诟病CMD的一点,牺牲性能来带来开发的便利性,但实际上解析模块用的时间短到可以忽略</p>
<p>同样都是异步加载模块,AMD在加载模块完成后就会执行该模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,<code>哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行</code><br>CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样<code>模块的执行顺序和书写顺序是完全一致的</code></p>
<h3 id="组合兼容式"><a href="#组合兼容式" class="headerlink" title="组合兼容式"></a>组合兼容式</h3><p>CMD 和 AMD 最初从在写法上就能区分,但是现在逐渐都兼容对方的写法,虽然对于学习来说不免会带来一些困惑,但对于实际项目的便利性确是实实在在的,其实兼容起来很容易,对于AMD/CMD检测<code>define</code>,对于CommonJS检查<code>module.export</code>,实现起来大致如下:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">(<span class="function"><span class="keyword">function</span> (<span class="params">name, definition, context</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">module</span> != <span class="string">'undefined'</span> && <span class="built_in">module</span>.exports) {</span><br><span class="line"> <span class="comment">// 在 CMD 规范下 (node)</span></span><br><span class="line"> <span class="built_in">module</span>.exports = definition();</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> context[<span class="string">'define'</span>] == <span class="string">'function'</span> && (context[<span class="string">'define'</span>][<span class="string">'amd'</span>] || context[<span class="string">'define'</span>][<span class="string">'cmd'</span>]) ) {</span><br><span class="line"> <span class="comment">//在 AMD 规范下(RequireJS) 或者 CMD 规范下(SeaJS)</span></span><br><span class="line"> define(definition);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">//在浏览器环境下</span></span><br><span class="line"> context[name] = definition();</span><br><span class="line"> }</span><br><span class="line">})(<span class="string">'sample'</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> sample = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"><span class="meta"> "use strict"</span>;</span><br><span class="line"> <span class="keyword">var</span> a = <span class="number">1</span>;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">inc</span>(<span class="params"></span>)</span>{</span><br><span class="line"> a++;</span><br><span class="line"> }</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">get</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">return</span> a;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> inc: inc,</span><br><span class="line"> get: get</span><br><span class="line"> }</span><br><span class="line"> })();</span><br><span class="line"> <span class="keyword">return</span> sample;</span><br><span class="line">}, <span class="keyword">this</span>);</span><br></pre></td></tr></table></figure></p>
<p>这样就实现了写法兼容,想怎么写都行了</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/16/js拾遗之面向对象/"><span>js拾遗之面向对象</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/16/js拾遗之面向对象/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-16T07:46:43.000Z">
2017-04-16
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>js作为一门松散的语言,如果有严格<code>class_base</code>面向对象语言的经验,如java,C#的,经常会有WTF的感受,不是说好了面向对象吗,怎么类不是类,继承不好好继承,多态到混乱的感觉,也写了不短时间的js,最感慨的就是:<code>前端程序员们,竟然使用一门如此简陋的语言创造了如此异彩纷呈的互联网世界</code>,这比js本身更WTF,不信去那个著名的诡异js的网站测测,看能做对几个题💔。好了不在吐槽引战了,本篇就来彻底说说js中的面向对象</p>
<p>在说明之前,特别需要指出的是,不要因为对js这种<code>prototype_base</code>不了解,就按照java等的标准去有色的去看js,殊不知从面向对象这个层面上来说,只要满足对操作和消息的封装,不管是<code>class_base</code>还是<code>prototype_base</code>,即便实现方式差异巨大,但无疑都是最纯正的面向对象</p>
<p>在js中它本身并没有明确的类的概念,这是最让很多人WTF的地方,面向对象居然没有类,但是如果从OOP的本意出发,只要可以用引用类型抽象出具有相同特性的结构,对操作和消息进行黑盒实现,那么就是面向对象,js中这个封装结构就是<code>Object对象</code>,在<code>ECMA-262</code>中这样给<code>对象</code>定义:<code>无序属性的集合就是对象,其属性可以包含基本值,对象和函数</code>,所以看起来就是一组没有特定顺序的键值对集合。对象的每个属性或者方法都有一个名字,而每个名字都会有映射的值。所以从另一角度来说,ECMAScript的对象就是<code>散列表</code>–一组键值对,值可以是基本值或函数。当然想所有的面向对象语言一样,对象是基于引用类型创建的</p>
<h3 id="从属性说起"><a href="#从属性说起" class="headerlink" title="从属性说起"></a>从属性说起</h3><p>回顾一下对象的创建:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Object实例创建</span></span><br><span class="line"><span class="keyword">var</span> person = <span class="keyword">new</span> <span class="built_in">Object</span>()</span><br><span class="line">person.name = <span class="string">'Tony stark'</span></span><br><span class="line">person.age = <span class="number">42</span></span><br><span class="line">person.job = <span class="string">'Iron man'</span></span><br><span class="line">person.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 更加常见的 字面量 形式</span></span><br><span class="line"><span class="keyword">var</span> person = {</span><br><span class="line"> name: <span class="string">'Tony'</span>,</span><br><span class="line"> age: <span class="number">42</span>,</span><br><span class="line"> job: <span class="string">'Iron man'</span></span><br><span class="line"> sayName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>当创建一个对象的时候,除了我们所定义的属性,对象本身还有为实现JavaScript引擎,还有<code>为属性规定其特征的内部属性</code>,也称之为<code>特征属性</code>,通常这些内部值是不能访问的,为了区分将其规范到2对方括号中,而特征属性可分为2种:<br>1 表征数据的特征属性<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[[Configurable]] <span class="comment">// 表示能否通过delete删除属性,能否修改,默认为true</span></span><br><span class="line">[[Enmuerable]] <span class="comment">// 表示是否可通过 for-in 遍历属性,默认为true</span></span><br><span class="line">[[Writable]] <span class="comment">// 可写的</span></span><br><span class="line">[[value]] <span class="comment">// 就是具体的属性数据值</span></span><br></pre></td></tr></table></figure></p>
<p>以上这种<code>属性的属性</code>,大家都能嗅出<code>权限控制</code>的味道来,实时就是如此,并且js提供了<code>Object.defineProperty()</code>方法来控制,如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> person = {}</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(person, <span class="string">"job"</span>, {</span><br><span class="line"> configurable: <span class="literal">false</span>,</span><br><span class="line"> value: <span class="string">"Iron man"</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="keyword">delete</span> person.job</span><br><span class="line">alert(person.job) <span class="comment">// Iron man</span></span><br></pre></td></tr></table></figure></p>
<p>事实以上在严格模式之下,是会抛出异常的,这就是<code>特征属性</code>对属性数值的规范,并且一旦规定<code>configurable: false</code>,无法使用<code>Objcet.defineProperty()</code>方法修改除<code>writable</code>之外的任何特征,在使用中尤其重要的一点是,<code>Object.defineProperty()方法,如果不指定,会默认设置enumerable,configurable,writable为false的</code>,即便没有人真的用这个方法来创建属性,这一点也要足够审慎</p>
<p>2 访问器特指属性<br>这一种特征属性不包含数值,只包含了一对儿<code>setter 和 getter</code>,更具体一些就是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[[Configurable]] <span class="comment">// 表示能否通过delete删除属性,能否修改,默认为true</span></span><br><span class="line">[[Enmuerable]] <span class="comment">// 表示是否可通过 for-in 遍历属性,默认为true</span></span><br><span class="line">[[Get]] <span class="comment">// 默认值是undefined</span></span><br><span class="line">[[<span class="built_in">Set</span>]] <span class="comment">// 默认值是undefined</span></span><br></pre></td></tr></table></figure></p>
<p>对于访问器属性,也只能通过<code>Object.defineProperty()/defineProperties()</code>设置,用法就不多说了,绝大多数就是用以设置一些对象默认的值<br>而对于一个已有属性的特征属性,可以通过<code>Object.getOwnPropertyDescriptor()</code>得到</p>
<h3 id="对象创建和扩展"><a href="#对象创建和扩展" class="headerlink" title="对象创建和扩展"></a>对象创建和扩展</h3><p>看完了属性,让我们注意力转回到对象的创建上,毕竟我们的开发就是在频繁的创建或者扩展对象,先直接看代码:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 工厂模式创建</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createPerson</span>(<span class="params">name, age, job</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> obj = {</span><br><span class="line"> name: <span class="string">'Tony'</span>,</span><br><span class="line"> age: <span class="number">42</span>,</span><br><span class="line"> job: <span class="string">'Iron man'</span></span><br><span class="line"> sayName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> obj</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 构造函数创建</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, job</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.name= name; </span><br><span class="line"> <span class="keyword">this</span>.age= age;</span><br><span class="line"> <span class="keyword">this</span>.job= job;</span><br><span class="line"> <span class="keyword">this</span>.sayName= <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line"> };</span><br><span class="line">}</span><br><span class="line"><span class="keyword">var</span> tony = <span class="keyword">new</span> Person(<span class="string">'tony'</span>, <span class="number">29</span>, <span class="string">'Iron man'</span>)</span><br></pre></td></tr></table></figure></p>
<p>第一种方式很好理解,但一个突出的问题是,我们虽然创建了对象,但并不显示的知道对象的类型,这是不能接受的;而第二种方式,显然很明确,并且使用了 new 操作符,new实际上包含了:<code>创建对象 -> 构造函数作用域赋给创建的对象 -> 执行构造函数 -> 返回新对象</code>的完整过程</p>
<p>然后集中到构造函数中,向Java等靠拢,习惯性的大写,但它之中并没有显示的创建对象的操作,更没有直接把属性值赋给this对象,也没有return, 这是因为 new操作符都做了</p>
<p>对于一个对象,构造函数本身,就对应于<code>constructor</code>属性,可以这样验证:<br><figure class="highlight javascript"><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="keyword">var</span> p1 = <span class="keyword">new</span> Person(<span class="string">'p1'</span>, <span class="number">12</span>, xxx)</span><br><span class="line"><span class="keyword">var</span> p2 = <span class="keyword">new</span> Perosn(<span class="string">'p2'</span>, <span class="number">22</span>, yyy)</span><br><span class="line">p1.constructor == p2.constructor == Person <span class="comment">// true</span></span><br></pre></td></tr></table></figure></p>
<p>但使用构造函数并不是没有缺陷,如上述的p1和p2, 其<code>sayName</code>由于是函数,我们知道本身也是对象,所以各自实例花了自己的Function,换个角度会更明白一些:<br><code>this.sayName: new Function('alert(this.name)')</code></p>
<p>可见p1和p2的sayName的值,的确是各自分别地实现化了,那么问题随之而来:<br>第一:上述很明显不是我们通常意义上所理解的面向对象,虽然不排除有现实需求<br>第二:更严重的是在使用中,会导致不同的作用域链和标识符解析,出现了同名函数实际上不相等的事儿,eg:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">p1.sayName == p2.sayName <span class="comment">// false</span></span><br></pre></td></tr></table></figure></p>
<p>解决方式就是避免每个实例都创建,所以使用this对象单独绑定函数就行,like this:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 构造函数创建</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, job</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.name= name; </span><br><span class="line"> <span class="keyword">this</span>.age= age;</span><br><span class="line"> <span class="keyword">this</span>.job= job;</span><br><span class="line"> <span class="keyword">this</span>.sayName= sayName;</span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">sayName</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>这明显是一种妥协的处理方式,为了让各个实例共享单独的函数对象,把函数放到了全局,且不说有很多的函数,造成全局命名是灾难,但是<code>alert</code>中的<code>this</code>只表示Person,从语义上就不脱,所以我们需要救助于<code>原型模式</code></p>
<h3 id="使用原型模式创建和扩展对象"><a href="#使用原型模式创建和扩展对象" class="headerlink" title="使用原型模式创建和扩展对象"></a>使用原型模式创建和扩展对象</h3><p>接着上述,如果使用原型模式,我们这样创建对象:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>) </span>{}</span><br><span class="line">Person.prototype.name = <span class="string">'tony'</span></span><br><span class="line">Person.prototype.age = <span class="number">29</span> </span><br><span class="line">Person.prototype.job = <span class="string">'Iron man'</span></span><br><span class="line">Person.prototype.sayName= <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> p1 = <span class="keyword">new</span> Person()</span><br><span class="line"><span class="keyword">var</span> p2 = <span class="keyword">new</span> Person()</span><br><span class="line">p1.sayName == p2.sayName <span class="comment">// true</span></span><br></pre></td></tr></table></figure></p>
<p>这样所有的实例都会共享属性和方法了,同时注意到构造函数中什么也没有,但它是怎么做到的呢?这就涉及到ECMAScript中原型对象的性质 </p>
<p>涉及到js中对象的结构,那就使用<code>console.dir(obj)</code>查看一下,下图分别是使用最普通的<code>字面量创建</code>,<code>构造函数</code>以及<code>原型模式</code>的对象结构:<br><img src="/img/jsOOp002.png" alt="比较各种方式的不同之处"></p>
<p>可见: </p>
<ul>
<li>任何时候,只要创建一个新对象,那么该对象就会有一个自动的<code>prototype</code>属性,这一句<code>__proto__:Object</code>告诉我们,这是一个指向<code>对象的原型对象</code>的指针 – 该对象包含了所有实例共享的属性和方法</li>
<li>创建的对象本身的属性可以是从原型对象获取,也可以由自己创建,通过上图属性出现在不同的层能明显的看到</li>
<li>㊙️特别注意,<code>原型对象</code>中才存在<code>constructor</code>属性,它会指向对象的构造函数。上图可见,它默认会指向Object,但一旦自定义了构造函数,就指向构造函数本身,但不管怎样,构造函数是实例本身没有的,只有实例的原型对象才有</li>
</ul>
<p><img src="/img/jsOOP001.png" alt="第三种原型模式结构示意图:注意实例与构造函数间并不直接连接,而是通过原型对象实现连接"></p>
<p>更加直接一些,我们可以通过<code>isPrototypeOf()</code>方法来确定对象之间是否是同一个原型对象,通过<code>getPrototypeOf()</code>来回去<code>原型对象</code>的属性值比如:<br><figure class="highlight javascript"><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">Person.prototype.isPrototypwOf(p1) <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> personProtoObj = <span class="built_in">Object</span>.getPrototypeOf(preson)</span><br><span class="line"><span class="built_in">console</span>.log(personProtoObj == Person.prototype) <span class="comment">// true</span></span><br><span class="line">personProtoObj.name <span class="comment">// 'tony'</span></span><br></pre></td></tr></table></figure></p>
<p>我们可以拿到了原型对象及其<code>name</code>属性值,从实例角度来说,获取一个属性,首先从本身的属性中去查找,如果本身没有,就去原型对象中查找,这就解释了按上述方法,不管有多少实例,最终都会向上追溯到同一个原型对象的相同属性,这就实现了共享</p>
<p>更进一步,如果实例拥有一个相同的属性,那么会怎样呢?使用<code>hasOwnProperty()</code>会检测属性是否存在于当前实例,如:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> p3 = <span class="keyword">new</span> Person()</span><br><span class="line">p3.name = <span class="string">'hulk'</span></span><br><span class="line"></span><br><span class="line">p3.hasOwnProperty(<span class="string">'name'</span>) <span class="comment">// true</span></span><br><span class="line">p1.hasOwnProperty(<span class="string">'name'</span>) <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(p3.name) <span class="comment">// 'hulk'</span></span><br><span class="line"><span class="built_in">console</span>.log(p1.name) <span class="comment">// 'tony'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 当delete之后</span></span><br><span class="line"><span class="keyword">delete</span> p3.name</span><br><span class="line">p3.hasOwnProperty(<span class="string">'name'</span>) <span class="comment">// fasle</span></span><br><span class="line"><span class="built_in">console</span>.log(p2.name) <span class="comment">// 'tony' -- 重新找到原型中的属性值</span></span><br></pre></td></tr></table></figure></p>
<p>同名属性如果自有,就而不会去影响原型的属性,也就是上述<code>没有,才上溯到原型</code>的原则。此外对于<code>for - in</code>循环,也只会在实例本身中去循环而不会去管原型中的属性</p>
<p>上边的写法很麻烦,不妨把各个属性用字面量组合写到一起:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>) </span>{}</span><br><span class="line">Person.prototype = {</span><br><span class="line"> name: <span class="string">'tony'</span>,</span><br><span class="line"> age: <span class="number">42</span>,</span><br><span class="line"> job: <span class="string">'Iron man'</span></span><br><span class="line"> sayName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> stark = <span class="keyword">new</span> Person()</span><br></pre></td></tr></table></figure></p>
<p>使用字面量把各个属性写到一起,如果输出stark的结构的话,还是能看到不同之处,如图:<br><img src="\img\jsOOP003.png" alt="比较之"></p>
<p>可见比较两者,可看出这种字面量写在一起时,其原型对象并没有<code>contructor</code>,而是完全重写了一个新的原型对象,这个重写也切断了实例和原本<code>prototype.constructor</code>之间的连接关系,这是最大的不同之处,解决方式就是显示的添加一个<code>constrictor</code>并让其指向对象本身,这里就是在重写的原型中添加:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Person.prototype = {</span><br><span class="line"> ...</span><br><span class="line"> <span class="keyword">constructor</span>: Person</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>好吧,那到底该如何使用构造函数构造对象呢?一句话来说的就是,<code>要共享的原型之,不共享的构造之</code>,eg:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Man</span>(<span class="params">name, age, job, wife</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name</span><br><span class="line"> <span class="keyword">this</span>.age = age</span><br><span class="line"> <span class="keyword">this</span>.job = job</span><br><span class="line"> <span class="keyword">this</span>.wife = wife</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">Man.prototype = {</span><br><span class="line"> <span class="keyword">constructor</span>: Person,</span><br><span class="line"> sex: male,</span><br><span class="line"> sayName: function() {</span><br><span class="line"> alert(<span class="keyword">this</span>.name)</span><br><span class="line"> }</span><br><span class="line"> eat: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> alert(<span class="keyword">this</span>.name + <span class="string">'is eatring!'</span>)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> tony = Man(<span class="string">'tony'</span>, <span class="number">42</span>, <span class="string">'Iron man'</span>, <span class="string">'xxx'</span>)</span><br><span class="line"><span class="keyword">var</span> hulk = Man(<span class="string">'hulk'</span>, <span class="number">32</span>, <span class="string">'Hulk and scientist'</span>, <span class="string">'yyy'</span>)</span><br></pre></td></tr></table></figure></p>
<p>如上所示,tony和hulk的名字,工作,老婆是不能共享的,那就放到构造函数中,而都作为男性,性别是一样的,都能报出自己的名字,都能吃饭,所以这些共享的放到原型对象中</p>
<p>综上所属,可看出<code>通过原型对象,js实现了各实例属性的共享</code>,这就是原型对象的秘密</p>
<h3 id="js对象的继承"><a href="#js对象的继承" class="headerlink" title="js对象的继承"></a>js对象的继承</h3><p>通过上述,所有的对象都有原型对象的指针,并且原型对象本身也有一个原型对象,都是来自于Objcet这个基本对象,大致能猜到继承的影子了,对于Java等OO语言,继承可以有2种:接口继承和实现继承,接口只继承方法签名儿实现继承则继承实际方法,在js中是没有接口集成的,只有实现继承,如前边的揣测,使用过原型对象组成的链条来实现的</p>
<ul>
<li>基本的原型链式继承<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> SuperType = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.property = <span class="string">"super"</span></span><br><span class="line">}</span><br><span class="line">SuperType.prototype.getSuperValue = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.property</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> SubType = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.subProperty = <span class="string">"sub"</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">/* 后代对象的原型是父对象的实例 */</span></span><br><span class="line">SubType.prototype = <span class="keyword">new</span> SuperType()</span><br><span class="line">SubType.prototype.getSubproperty = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">this</span>.subProperty</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> father = <span class="keyword">new</span> SuperType()</span><br><span class="line"><span class="keyword">var</span> son = <span class="keyword">new</span> SubType()</span><br><span class="line"><span class="built_in">console</span>.log(instance.getSuperValue()) <span class="comment">// 'super'</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(father)</span><br><span class="line"><span class="built_in">console</span>.dir(son)</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>最关键的一句就是<code>SubType.prototype = new SuperType()</code>,也就是重写子对象的原型对象让<code>后代对象的原型对象 = 父对象的实例</code>,由此实例的属性和实例能找的它原型的属性,就都可以让子对象顺着它的原型对象而收缩到,从效果上就实现继承,如上述代码他们的继承图就是:<br><img src="/img.jsOOP004.png" alt=""></p>
<p>很显然,这样单纯的让原型对象==父对象的实例以后,回引出一下几个问题:<br>1 如果需要为向子对象的原型对象中添加新方法,是不能写成字面量的形式的。因为这样一来就等同于重现了实例对象,会覆盖掉最初的原型对象,自然链接父对象的原型链会被切断,而失去继承的效果,这一点是尤其需要注意的<br>2 基于同样的道理当子对象为他的原型添加属性,这个属性会被共享到所有的子对象实例,所以不应该把子对象的构造函数留空<br>3 此外还有一个问题是,再也无法单独为超对象的构造函数传递参数,因为这势必会影响到继承自他的子对象<br>所以单纯使用原型链只能算是粗暴的继承</p>
<ul>
<li>伪经典继承(也称组合继承 combination inheritance)<br>这的将构造函数 + 原型链组合的一种方式,其思路是:原型链实现对原型对象的继承,而实例属性的继承通过构造函数实现,如此便是:<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SuperType</span>(<span class="params">name</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.name = name</span><br><span class="line"> <span class="keyword">this</span>.colors = [<span class="string">'red'</span>, <span class="string">'green'</span>, <span class="string">'bule`]</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string">SuperType.prototype.sayName = function() {</span></span><br><span class="line"><span class="string"> alert(this.name)</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">var SubType = function(name, age) {</span></span><br><span class="line"><span class="string"> // 继承父对象的实例属性</span></span><br><span class="line"><span class="string"> Supertype.call(this, arguments)</span></span><br><span class="line"><span class="string"> this.age = age</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string">// 继承父对象的原型属性 </span></span><br><span class="line"><span class="string">SubType.prototype = new SuperType()</span></span><br><span class="line"><span class="string">// 可以选择纠正一下构造函数</span></span><br><span class="line"><span class="string"><!--SubType.prototype.constructor = SubType--></span></span><br><span class="line"><span class="string">SubType.prototype.sayAge = function() {</span></span><br><span class="line"><span class="string"> alert(this.age)</span></span><br><span class="line"><span class="string">}</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">var son1 = new SubType('</span>son1<span class="string">', 22)</span></span><br><span class="line"><span class="string">son1.colors.push('</span>yellow<span class="string">')</span></span><br><span class="line"><span class="string">son1.sayName() // son1</span></span><br><span class="line"><span class="string">son1.sayAge() // 22</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">var sonOther = new SubType('</span>other<span class="string">', 44)</span></span><br><span class="line"><span class="string">console.log(sonOther.colors) // ['</span>red<span class="string">', '</span>green<span class="string">', '</span>bule<span class="string">`]</span></span><br><span class="line"><span class="string">sonOther.sayName() // other</span></span><br><span class="line"><span class="string">sonOther.sayAge() // 44</span></span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>看图更加清晰一些:<br><img src="/img/jsOOP005.png" alt="为纠正构造函数结构图"></p>
<p>由于父对象的实例属性,在子对象的构造函数中完成继承,所以等同于子实例属性的创建和覆盖,同时只属于子实例实例如age不在被共享,而共享的只是来自于父实例的属性,这解释了<code>son1.colors 和 sonOther.colors</code>的不同;来自于父类原型的属性及方法以及被继承。可见没有了上面只使用原型链的问题,但这样就完美了吗?</p>
<p>上述这就用js实现了java类一样的继承了,但在js中绝大多数时候,是不需要这样完全模拟类的继承的,并且并不完美:至少SuperType就被调用了2次,一次在构造函数中,一次在链接原型链时,所以还需要改进</p>
<p>这就是js更常见的继承了,它并不模拟类的实现,虽然看起来不够模版化,数据耦合性很高,但却是见的比较多的,使用extendObj简单的封装了一下<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> extendObj = <span class="function"><span class="keyword">function</span>(<span class="params">superObj</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> obj = <span class="keyword">new</span> <span class="built_in">Object</span>(superObj.prototype)</span><br><span class="line"> obj.constructor = obj</span><br><span class="line"> <span class="keyword">return</span> obj</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> fa = {</span><br><span class="line"> name: <span class="string">'老王'</span>,</span><br><span class="line"> surname: <span class="string">'王'</span>,</span><br><span class="line"> familyName: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.surname)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="built_in">console</span>.log(fa.familyName())</span><br><span class="line"><span class="built_in">console</span>.dir(fa)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 不使用构造函数,不模拟类</span></span><br><span class="line"><span class="keyword">var</span> sequela1 = extendObj(fa)</span><br><span class="line">sequela1.name = <span class="string">'小王'</span></span><br><span class="line">sequela1.course = <span class="string">'数学'</span></span><br><span class="line">sequela1.projectWork = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="keyword">this</span>.course)</span><br><span class="line">}</span><br><span class="line"><span class="built_in">console</span>.dir(sequela1)</span><br><span class="line"><span class="built_in">console</span>.log(sequela1.projectWork())</span><br></pre></td></tr></table></figure></p>
<p>综上,就是js的继承,可见js即便他现在使用很广泛,也还有很多脚本化的身影,继承写起来并不入java等的容易,但也的确实现了继承,何况能理解到另一种形式的OOP,也很助于理解其他OOP语言</p>
<p>附上一个测试的demo代码:</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/12/vim拾遗之其实可以不用插件的/"><span>vim拾遗之其实可以不用插件的</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/12/vim拾遗之其实可以不用插件的/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-12T10:32:56.000Z">
2017-04-12
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>向所有刚接触到VIM的新手一样,笔者曾几何时也把vim搞的花里胡哨,美其名曰vim-ide,折腾了tons of plugins,直到vim被弄得越来越臃肿,直到遇到了浩哥,看到大哥信手纯vim在我面前完成了所有的那些,我原本只能借助插件完成的功能,一时惊愕不已: 原来这些VIM全都是自有的,这篇的目的并不是让大家告别插件,彻底的不用,而是结合笔者自己的使用经验,多给一钟选项罢了,好了开始吧</p>
<h3 id="vim下的文件跳转和查找"><a href="#vim下的文件跳转和查找" class="headerlink" title="vim下的文件跳转和查找"></a>vim下的文件跳转和查找</h3><p>不知道大家是否注意到过vim的设置选项中,是有一些默认的值得,比如<code>:set path?</code>,多半会输出这样一个结果:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">path=.,/usr/include,,</span><br></pre></td></tr></table></figure></p>
<p>通过path这个名称,大致也能猜到这是vim有关文件查找的路径,后边的就是指几个默认当前目录下,所以不出意外的话我们的查找应该以当前目录层级的相对路径,可是很可能你并不明确当前目录下的文件,这时候使用<code>:find *</code>通配的去查找着当前路径下的文件,可以使用tab跳转,但是如果<code>:set wildmenu</code>的话,找起来就更方便了,画风是这样的<br><img src="/img/vim-wildmenu.png" alt="wildmenu画风展示"></p>
<p>然后enter,就进入到了想要的文件,这就是实现了简单的文件查找和变更,如果此时先要回到原来的文件,可以通过<code>:ls</code>命令,他会罗列出当前vim缓存所有的未关闭的文件,like this:<br><img src="/img/vim-ls.png" alt="vim下的ls"><br>比如这里我想回到vim拾遗的文章,输入:<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">:b vi</span><br></pre></td></tr></table></figure></p>
<p>我甚至都不用tab出完整的文件名,直接enter就回到了原来的文件,当然你也可以语义化为back<br> vi…</p>
<h3 id="vim自己的自动补全"><a href="#vim自己的自动补全" class="headerlink" title="vim自己的自动补全"></a>vim自己的自动补全</h3><p>用vim敲代码几乎都或多或少听过<code>YouCompleteMe</code>这个插件的大名,它几乎支持每种语言,让代码写起来更容易,但实际上,vim本身就提供了这样的功能,那就是一系列的<code>Cr + n</code>的命令,下面列举如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">" 当前文件匹配</span><br><span class="line">Cr x + Cr n " next </span><br><span class="line">Cr x + Cr p " pre </span><br><span class="line"></span><br><span class="line">" 文件夹匹配</span><br><span class="line">Cr x + Cr F 再配合 n/p </span><br><span class="line">" tag匹配</span><br><span class="line">Cr x + Cr ]</span><br></pre></td></tr></table></figure></p>
<p><img src="/img/vim-autoCFile.png" alt="文件名自动补全"><br>谁用谁知道,是的我已经听到有人吐槽这个原生<code>OnmiComplete</code>很若,但是对多数人来说的确够用了,如果实在想做到想IDE一样索引API,那还需要<code>CTags</code>,对我来说完全目前还用不上,自带的足以,以后有机会在补上Ctags 及 JSTags 根vim配合的自动补全吧</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/10/Hbase面面观/"><span>Hbase面面观</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/10/Hbase面面观/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-10T08:29:12.000Z">
2017-04-10
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h3 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h3><p>大数据处理和存储框架Hadoop,除了最重要的<code>HDFS和MapReduce/Spark计算框架</code>之外,还需要很多辅助组件,比如需要分布式协调系统<code>zookeeper</code>来做热备,维护元数据命名空间, Sqoop作数据导入导出等等。这些都是从整个系统上的工具,而作为数据持久化的存储系统的<code>HDFS</code>,自然也发展出了很多自己的辅助组件,其中<code>HBase</code>无疑是最耀眼的</p>
<h3 id="是什么"><a href="#是什么?" class="headerlink" title="是什么?"></a>是什么?</h3><p>简单的,<code>HBase</code>是一种类数据库的存储层工具,其用于组织和管理结构化数据的存储,由于需要服务<code>HDFS</code>,自然它也是分布式的,并且是一种 <strong>列式的分布数据库</strong> ,最早由Goolge的BigTable论文中提出。虽然依托于HDFS很容易让人想起另一个结构数据工具<code>Hive</code>,但二者的区别和设计目的是不同的,在生态中的所处位置也不一样,这一点在<code>Hive初探</code>文章中有所探讨,总体来说,Hive是MepReduce层的工具,而Hbase是在结构化存储层,直接连接hdfs,还有诸如:</p>
<ul>
<li>Hive并不适用于实时数据查询处理,而这是HBase的强项</li>
<li>Hive部署不依托Zookeeper,而HBase需要</li>
<li>Hive的交互有SQL,而HBase不直接提供 </li>
</ul>
<p>相对于Hive的比较,更有趣的是HBase根传统数据库,比如mySQL这样的行式数据库的不同</p>
<p>HBase解决了那些HDFS的问题呢?HDFS本身就拥有良好的容错和扩展性,常常被扩展到上百节点,但仍然存在着作为文件系统,相较于结构化存储系统固有的天然劣势:如果我们只关心文件中的一部分数据,想对部分数据进行操作,文件系统只能通过对整个文件进行扫描来实现,所以HDFS:</p>
<ul>
<li>不支持数据查找</li>
<li>不适合增量式数据处理</li>
<li>不支持数据更新</li>
</ul>
<p>如果是单纯的离线存储也就罢了,但现实往往有实时性的需求,所以才有了HBase对HDFS的补充,HBase可以支持:<code>插入/删除/查询</code>等单条/部分数据的操作,便于高效过滤和读写数据</p>
<p>也正是由于其设计目的限制,让HBase拥有了一些跟传统数据库完全不同的实现,这就是列式无模式稀疏的数据组织方式。</p>
<h3 id="列式-因吹死停"><a href="#列式?-🤔因吹死停" class="headerlink" title="列式? 🤔因吹死停"></a>列式? 🤔因吹死停</h3><p> 先来看看一组数据,如果是在传统RDBMS中如mySQL是这样存储的:<br>| id | name | nickName | password | time |<br>| :–: | :——: | :——: | :——: |:——: |<br>| 001 | zhangsan | zzss | p11zzz | 20161212 |<br>| 002 | lisi | lsls | 333lll | 20161213 |</p>
<p>每一行的是一个完整数据单元,每一列对应于都是一个具体数据。但是在没有建立索引的情况下,读取整行,在遍历查找数据,会付出巨大IO;而索引和视图的建立,付出的IO和性能也不容忽视;最重要的是为满足多样的查询需求,数据库要不可避免的大量扩大膨胀,才能满足性能需求。而这些问题HBase是怎样处理的呢,如果上述数据在HBase中是怎样存储的呢?</p>
<h3 id="数据模型"><a href="#数据模型" class="headerlink" title="数据模型"></a>数据模型</h3><table style="border: 1px solid #9a9a9a"><br> <tr><br> <th>RowKey</th><br> <th>Value (CF Qualifier Version)</th><br> </tr><br> <tr><br> <td rowspan="2">001</td><br> <td>name{“real”: “zhangshan”, “nick” : “zzss” }</td><br> </tr><br> <tr><br> <td>info{“pwd” : “333lll”}</td><br> </tr><br> <tr><br> <td rowspan="2">001</td><br> <td>name{“real”: “lishi”, “nick” : “lsls” }</td><br> </tr><br> <tr><br> <td>info{“pwd” : “333lll”}</td><br> </tr><br></table>
<table>
<thead>
<tr>
<th style="text-align:center">RowKey</th>
<th style="text-align:center">CF:Column-Key</th>
<th style="text-align:center">Timestamp</th>
<th style="text-align:center">CellValue</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:center">name:real</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">zhangsan</td>
</tr>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:center">name:nick</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">zzss</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:center">name:real</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">lishi</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:center">name:nick</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">lsls</td>
</tr>
<tr>
<td style="text-align:center">001</td>
<td style="text-align:center">info:pwd</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">p11zzz</td>
</tr>
<tr>
<td style="text-align:center">002</td>
<td style="text-align:center">info:pwd</td>
<td style="text-align:center">123456789</td>
<td style="text-align:center">333lll</td>
</tr>
</tbody>
</table>
<p>上述是一个一种物理存储的形式,不太容易看明白,如果表述为逻辑存储形式:</p>
<p>从上述的物理和逻辑排布中,能看出在HBase中:<br>只有一中索引标识那就是<code>RowKey</code>,</p>
<p>传统行数据库的问题 </p>
<h3 id="构架为什么能做到实时"><a href="#构架,为什么能做到实时?" class="headerlink" title="构架,为什么能做到实时?"></a>构架,为什么能做到实时?</h3><ul>
<li>预写入日志:<code>WALs</code></li>
</ul>
<h3 id="hdfs的物理目录结构"><a href="#HDFS的物理目录结构" class="headerlink" title="HDFS的物理目录结构"></a>HDFS的物理目录结构</h3><p>在Hbase的设置文件中,具体设置:<br><code><name>hbase.rootdir</name></code></p>
<h3 id="常见操作"><a href="#常见操作" class="headerlink" title="常见操作"></a>常见操作</h3><ul>
<li><p>2种方式</p>
<ul>
<li>JDBC API</li>
<li>CLI</li>
</ul>
</li>
<li><p>读hdfs</p>
</li>
<li>增</li>
<li>删</li>
<li>查</li>
<li>改</li>
<li>写hdfs</li>
</ul>
<h3 id="核心使用"><a href="#核心使用" class="headerlink" title="核心使用"></a>核心使用</h3><ul>
<li>热点问题:客户点直接访问集群少数节点,导致节点机器超载,性能下降甚至region不可用,从而影响同RegionServer下的其他region</li>
<li>rowKey的设计</li>
<li>窄表和宽表</li>
<li>负载均衡</li>
</ul>
<h3 id="一个案例"><a href="#一个案例" class="headerlink" title="一个案例"></a>一个案例</h3>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/09/jQuery拾遗之动画/"><span>jQuery拾遗之动画</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/09/jQuery拾遗之动画/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-09T14:19:40.000Z">
2017-04-09
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<p>jQuery中提供了一些常用的动画,拜强势的PM和UX所赐,在他们威逼利诱之下也让我逐渐熟悉了jQuery动画的某些用法。</p>
<p>在具体说之前,不妨先来猜测一下,如果让我自己造一个专门的Animation的轮子,我想至少要满足一下功能:<br>1 简单的常用动画,要足够简单–如hide,show,toggle…<br>2 能对简单的动画进行组合,组合出比较复杂的动画,并且对整个动画执行的各个关键帧,要能控制和截断动画等操作<br>3 需要一个代完整参数的仿射变换的函数,就像cocoa中的<code>CGAffineTransform</code>一样:<br><figure class="highlight swift"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">CGAffineTransform</span> </span>{</span><br><span class="line"> <span class="type">CGFloat</span> a, b, <span class="built_in">c</span>, d;</span><br><span class="line"> <span class="type">CGFloat</span> tx, ty;</span><br><span class="line">};</span><br></pre></td></tr></table></figure></p>
<p>并且要映射成<code>CSS</code> </p>
<p>如果上述这些基本需求能满足,那么基本上这个地球上存在的能想到的动画都基本能实现,具体实现上由于帧动画和组合动画的要求,自然需要一个统一的动画队列,甚至是动画缓存池,要以对各个动画生命周期的控制</p>
<p>事实上jQuery设计者们都不是吃素的,他们为其提供了远超上以上需求的动画API,只是很多时候我们没有去仔细研究罢了</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">
</div>
</div>
</article>
<article>
<h3 class="article-title"><a href="/2017/04/06/js组件化演进探讨-从简单的封装说起/"><span>js组件化演进探讨-从简单的封装说起</span></a></h3>
<div class="article-top-meta">
<span class="posted-on">
<a href="/2017/04/06/js组件化演进探讨-从简单的封装说起/" rel="bookmark">
<time class="entry-date published" datetime="2017-04-06T01:22:41.000Z">
2017-04-06
</time>
</a>
</span>
</div>
<div class="article-content">
<div class="entry">
<h3 id="先从一个slideshow的封装说去"><a href="#先从一个slideShow的封装说去" class="headerlink" title="先从一个slideShow的封装说去"></a>先从一个slideShow的封装说去</h3><p>在前端虽说已经有了一些很成熟的UI库,但是对于我这个有过客户端开发经验的人总是忍不住会对一些常见的组建进行自以为是的封装,总想着向MFC,Cocoa那样完全组件化的开发,特别是针对于UI层级,但是考虑到前端的特殊性,这两种封装思路有时候并不经相同,所以想借着一个轮播slide的Demo,浅显的梳理一下。</p>
<p>直接从最关键的接口设计入手:于客户端封装相比,前端的组件可以全部js化,也可以html实现,更多的是二者兼而有之,而客户端平台往往只需要管理好接口API权限和参数,没有这种选择性的问题,比如在本例中,可以这样:<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="name">script</span> <span class="attr">scr</span>=<span class="string">'slideShow.js'</span>></span><span class="undefined"></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">'slideShow'</span>></span><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure></p>
<p>仅仅通过一个div借助js来实现,至于轮播的图像数据,以及其他元素全部通过js来添加,看起来很美妙:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">$.fn.slide = <span class="function"><span class="keyword">function</span>(<span class="params">opt</span>) </span>{</span><br><span class="line"> <span class="comment">// 创建5个img</span></span><br><span class="line"> <span class="comment">// img设置样式,src等等</span></span><br><span class="line"> <span class="comment">// img包裹个几层</span></span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建一个指示器 </span></span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建next/pre btn等等</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用</span></span><br><span class="line">$(<span class="string">'.slideShow'</span>).slide({</span><br><span class="line"> width: <span class="number">300</span>px;</span><br><span class="line"> height: <span class="number">200</span>px;</span><br><span class="line"> numOfCell: <span class="number">5</span>;</span><br><span class="line"> auto: <span class="literal">true</span>;</span><br><span class="line"> ...</span><br><span class="line">})</span><br></pre></td></tr></table></figure></p>
<p>也可在更多html的基础上,如:<br><figure class="highlight html"><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="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">'banner slideShow'</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">'picCell'</span> <span class="attr">scr</span>=<span class="string">'http://001.png'</span>></span><span class="tag"></<span class="name">img</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">'picCell'</span> <span class="attr">scr</span>=<span class="string">'http://001.png'</span>></span><span class="tag"></<span class="name">img</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">'picCell'</span> <span class="attr">scr</span>=<span class="string">'http://001.png'</span>></span><span class="tag"></<span class="name">img</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">'picCell'</span> <span class="attr">scr</span>=<span class="string">'http://001.png'</span>></span><span class="tag"></<span class="name">img</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">img</span> <span class="attr">class</span>=<span class="string">'picCell'</span> <span class="attr">scr</span>=<span class="string">'http://001.png'</span>></span><span class="tag"></<span class="name">img</span>></span></span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure></p>
<p>这一种明显给了更多的html内容,特别是img元素样式的单独分类,让变动更加直接,看起来也还不错,为了方便使用jQuery,具体例子的gits:<a href="https://github.com/13hoop/sliderShow/blob/master/index.html" target="_blank" rel="noopener">https://github.com/13hoop/sliderShow/blob/master/index.html</a></p>
<figure class="highlight javascript"><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="comment">// 调用方式</span></span><br><span class="line">$(<span class="string">'.banner'</span>).slides({</span><br><span class="line"> width: <span class="number">480</span>,</span><br><span class="line"> height: <span class="number">360</span>,</span><br><span class="line"> auto: <span class="literal">true</span></span><br><span class="line">})</span><br></pre></td></tr></table></figure>
<p>以上2中共同之处都是直接封装的<code>$.fn</code>上,这样调用时通过<code>$('.banner')</code>调用,看起来的确是很方便,但遗憾的是直接从是对<code>jQuery</code>的扩展,但一下子让所有的页面都具有了sliderShow,太过粗暴的硬塞给所有依赖jQuery的文件,很多时候是没有必要的</p>
<h3 id="困惑"><a href="#困惑-😖" class="headerlink" title="困惑 😖"></a>困惑 😖</h3><p>我自己第一个很困惑的问题是<code>对于样式在封装中的处理</code>:<br>是用js创建样式,还是不使用?如果全部用js会不会引入其他问题,比如有2个同样的控件,同样的样式要js创建2遍,性能如何?如果按照web规范,<code>结构是结构,样式是样式</code>,那对于基本不变的样式如在移动端页面,岂不是不能做到开箱即用?在纠结以一段时间之后,很可悲的发现与其这样瞎想,不如直接动手试试,尝试几次之后,不得不接受这样的结论:没有一个一劳永逸的准则,具体控件具体实现?🤔,完全是废话根没说一样😂,看来这个问题只能探讨到这儿了</p>
<p>接着说封装形式,前边是封装到<code>jQuery的fn</code>上,如果借助js模拟类的形式呢?:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 创建实例</span></span><br><span class="line"><span class="keyword">new</span> Banner($(<span class="string">'.banner'</span>), <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">// Banner`类`</span></span><br><span class="line"><span class="keyword">var</span> Banner = <span class="function"><span class="keyword">function</span>(<span class="params">$target, callback</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.$target = $target</span><br><span class="line"> <span class="keyword">this</span>.callback = callback</span><br><span class="line"> <span class="keyword">this</span>.init()</span><br><span class="line"> <span class="keyword">this</span>.bind()</span><br><span class="line">}</span><br><span class="line">Banner.prototype.init = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// 创建5个img</span></span><br><span class="line"> <span class="comment">// img设置样式,src等等</span></span><br><span class="line"> <span class="comment">// img包裹个几层</span></span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建一个指示器 </span></span><br><span class="line"> ...</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 创建next/pre btn等等</span></span><br><span class="line">}</span><br><span class="line">Banner.prototype.bind = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">// 事件 here</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
<p>很方便简洁的代码组织形式,自己偶尔写写简单基本都是按这个套路的,比如一个懒加载的图片墙,采用类型的封装之后就是:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Explode = <span class="function"><span class="keyword">function</span> (<span class="params">$target, callback</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.$target = $target</span><br><span class="line"> <span class="keyword">this</span>.callback = callback</span><br><span class="line"> <span class="keyword">this</span>.check()</span><br><span class="line"> <span class="keyword">this</span>.bind()</span><br><span class="line">}</span><br><span class="line">Explode.prototype.bind = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _this = <span class="keyword">this</span></span><br><span class="line"> <span class="keyword">var</span> clock <span class="comment">// 模拟网络延伸</span></span><br><span class="line"> $(<span class="built_in">window</span>).on(<span class="string">'scroll'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (clock) {</span><br><span class="line"> clearTimeout(clock)</span><br><span class="line"> }</span><br><span class="line"> clock = setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'hello'</span>)</span><br><span class="line"> _this.check()</span><br><span class="line"> }, <span class="number">100</span>)</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line">Explode.prototype.isVisible = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> height_win = $(<span class="built_in">window</span>).height()</span><br><span class="line"> <span class="keyword">var</span> scrolled = $(<span class="built_in">window</span>).scrollTop()</span><br><span class="line"> <span class="keyword">var</span> height = <span class="keyword">this</span>.$target.height()</span><br><span class="line"> <span class="keyword">var</span> offTop = <span class="keyword">this</span>.$target.offset().top</span><br><span class="line"> <span class="keyword">if</span> (height_win + scrolled >= offTop && offTop + height >scrolled) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">Explode.prototype.check = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">this</span>.isVisible(<span class="keyword">this</span>.$target)) {</span><br><span class="line"> <span class="keyword">this</span>.callback(<span class="keyword">this</span>.$target)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">$(<span class="string">'.container img'</span>).each(<span class="function"><span class="keyword">function</span> (<span class="params">k, img</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> $value = $(img)</span><br><span class="line"> <span class="keyword">new</span> Explode($value, <span class="function"><span class="keyword">function</span> (<span class="params">$target</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> url = $value.attr(<span class="string">'data-src'</span>)</span><br><span class="line"> <span class="keyword">if</span> ($value.hasClass(<span class="string">'loaded'</span>)) <span class="keyword">return</span></span><br><span class="line"> <span class="built_in">console</span>.log(k + <span class="string">'~~~'</span>)</span><br><span class="line"> $value.attr(<span class="string">'src'</span>, url)</span><br><span class="line"> $value.addClass(<span class="string">'loaded'</span>)</span><br><span class="line"> })</span><br><span class="line">})</span><br></pre></td></tr></table></figure></p>
<h3 id="最好的方式"><a href="#最好的方式" class="headerlink" title="最好的方式"></a>最好的方式</h3><p>但缺陷还是有的,最明显的就是没有实现权限管理,暴漏了太多,不妨再来一次:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> Explode =(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _Explode = <span class="function"><span class="keyword">function</span> (<span class="params">$target, callback</span>) </span>{</span><br><span class="line"> <span class="keyword">this</span>.$target = $target</span><br><span class="line"> <span class="keyword">this</span>.callback = callback</span><br><span class="line"> <span class="keyword">this</span>.check()</span><br><span class="line"> <span class="keyword">this</span>.bind()</span><br><span class="line"> }</span><br><span class="line"> _Explode.prototype.bind = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> _this = <span class="keyword">this</span></span><br><span class="line"> <span class="keyword">var</span> clock <span class="comment">// 模拟网络延伸</span></span><br><span class="line"> $(<span class="built_in">window</span>).on(<span class="string">'scroll'</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (clock) {</span><br><span class="line"> clearTimeout(clock)</span><br><span class="line"> }</span><br><span class="line"> clock = setTimeout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'hello'</span>)</span><br><span class="line"> _this.check()</span><br><span class="line"> }, <span class="number">100</span>)</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"> _Explode.prototype.isVisible = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> height_win = $(<span class="built_in">window</span>).height()</span><br><span class="line"> <span class="keyword">var</span> scrolled = $(<span class="built_in">window</span>).scrollTop()</span><br><span class="line"> <span class="keyword">var</span> height = <span class="keyword">this</span>.$target.height()</span><br><span class="line"> <span class="keyword">var</span> offTop = <span class="keyword">this</span>.$target.offset().top</span><br><span class="line"> <span class="keyword">if</span> (height_win + scrolled >= offTop && offTop + height > scrolled) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> _Explode.prototype.check = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.isVisible(<span class="keyword">this</span>.$target)) {</span><br><span class="line"> <span class="keyword">this</span>.callback(<span class="keyword">this</span>.$target)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> init: <span class="function"><span class="keyword">function</span>(<span class="params">targets, callback</span>) </span>{</span><br><span class="line"> $(targets).each(<span class="function"><span class="keyword">function</span>(<span class="params">idx , target</span>)</span>{</span><br><span class="line"> <span class="keyword">new</span> _Explode($(target), callback) </span><br><span class="line"> })</span><br><span class="line"> },</span><br><span class="line"> <span class="comment">// once: function(targets, callback) {</span></span><br><span class="line"> <span class="comment">// $(targets).each(function(idx , target){</span></span><br><span class="line"> <span class="comment">// new _Explode($(target), callback) </span></span><br><span class="line"> <span class="comment">// })</span></span><br><span class="line"> <span class="comment">// }</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">})()</span><br><span class="line"></span><br><span class="line">Explode.init($(<span class="string">'.container img'</span>), <span class="function"><span class="keyword">function</span>(<span class="params">$elNode</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> url = $elNode.attr(<span class="string">'data-src'</span>)</span><br><span class="line"> <span class="keyword">if</span> ($elNode.hasClass(<span class="string">'loaded'</span>)) <span class="keyword">return</span></span><br><span class="line"> $elNode.attr(<span class="string">'src'</span>, url)</span><br><span class="line"> $elNode.addClass(<span class="string">'loaded'</span>)</span><br><span class="line">})</span><br></pre></td></tr></table></figure></p>
<p>通过一个匿名函数,实现对<code>_Explode</code>代码的封装,同时借助<code>return</code>返回需要对外开放的方法,即添加了权限开放管理,又节省了命名空间,还在调用上获得得了便利,这才是比较容易接受的好方法</p>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p>扯了这么多,总是觉得单单控件的实现并没有怎样的难度,在前端反倒是对这些空间站的管理才是令人头大的,好在现在的套路基本被摸索出来了,那就是模块化js的开发规则,上述的最后一种方式,其实已经有一些模块化的影子了,但并不能很好的处理组建的依赖问题,而这些将在模块化js中一并解决,具体会在<code>js模块化管理的探索</code>后续文章中讨论</p>
</div>
</div>
<div class="article-footer">
<div class="article-meta pull-left">