-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
666 lines (334 loc) · 41 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
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
<head><meta name="generator" content="Hexo 3.8.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">
<title> Mooory-Site </title>
<link rel="icon" href="/images/favicon.png">
<link rel="stylesheet" href="/nayo.min.css">
</head>
<body>
<header class="header">
<nav class="header-inner">
<span class="iconfont icon-menu mobile-toggle"></span>
<div class="header-logo">
<a href="/">
<!--<img class="header-logo-img" src="/images/logo.png"/>-->首页
</a>
</div>
<div class="header-menu">
<a class="header-menu-link" id="header-menu-home" href="/">
<i class="iconfont icon-home">
</i></a>
<a class="header-menu-link" id="header-menu-archives" href="/archives">
<i class="iconfont icon-archives">
</i></a>
<a class="header-menu-link" id="header-menu-tags" href="/tags">
<i class="iconfont icon-tags">
</i></a>
<a class="header-menu-link" id="header-menu-about" href="/about">
<i class="iconfont icon-about">
</i></a>
<a class="header-menu-link" id="header-menu-search">
<i class="iconfont icon-search">
</i></a>
</div>
</nav>
</header>
<div class="container">
<div class="container-inner">
<div class="profile sildeUpMin">
<img class="avatar" src="/images/header.jpg">
<p class="author">Mooory</p>
</div>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2019/03/14/proxy/">proxy和reflect实现数据拦截处理</a>
<div class="article-meta">
<time>Mar 14, 2019</time>
</div>
</div>
<div class="typo article-excerpt">
<p>最近在面试时,遇到双向绑定的原理,我只了解脏检查和object.defineProperty进行数据挟持的方法。面试官问我还知道别的方法吗?(what?)不造啊</p>
<p>后来私下查了一下,es6的proxy可对数据进行一层“拦截”,同样能够实现对数据的一些操作:比如双向绑定。</p>
<h2 id="proxy"><a href="#proxy" class="headerlink" title="proxy"></a>proxy</h2><p>Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以是一种“元编程”,即对编程语言进行编程。</p>
<p>简单地理解,就是在目标对象之前假设一层“拦截”,外界对改对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤。基本就想字面意思:代理。<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(target, handler);</span><br></pre></td></tr></table></figure></p>
<p>其中,target、handler 均为对象,target 指目标对象(需要拦截的),handler 中定义拦截行为。</p>
<figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> obj = <span class="keyword">new</span> <span class="built_in">Proxy</span>({}, {</span><br><span class="line"> <span class="keyword">get</span>: function (target, key, receiver) {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`getting <span class="subst">${key}</span>!`</span>); <span class="comment">// es 6 新増的字符串拓展写法</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Reflect</span>.get(target, key, receiver);</span><br><span class="line"> },</span><br><span class="line"> <span class="keyword">set</span>: function (target, key, value, receiver) {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`setting <span class="subst">${key}</span>!`</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Reflect</span>.set(target, key, value, receiver);</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">obj.count = <span class="number">1</span></span><br><span class="line"><span class="comment">// setting count!</span></span><br><span class="line">++obj.count</span><br><span class="line"><span class="comment">// getting count!</span></span><br><span class="line"><span class="comment">// setting count!</span></span><br><span class="line"><span class="comment">// 2</span></span><br></pre></td></tr></table></figure>
<p>上面重新定义了属性的读取和设置,搭配Reflect一起使用。</p>
<p>注意,要使得Proxy起作用,必须针对Proxy实例(上例是proxy对象)进行操作,而不是针对目标对象(上例是空对象)进行操作。</p>
<p>Proxy 实例也可以作为其他对象的原型对象。<br><figure class="highlight js"><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> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>({}, {</span><br><span class="line"> <span class="keyword">get</span>: function(target, property) {</span><br><span class="line"> <span class="keyword">return</span> <span class="number">35</span>;</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> obj = <span class="built_in">Object</span>.create(proxy);</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> Object.create()方法接受两个参数:Object.create(obj,propertiesObject) ;</span></span><br><span class="line"><span class="comment"> obj:一个对象,应该是新创建的对象的原型。</span></span><br><span class="line"><span class="comment"> propertiesObject:可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()的第二个参数一样)。注意:该参数对象不能是 undefined,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">obj.time <span class="comment">// 35</span></span><br></pre></td></tr></table></figure></p>
<p>proxy对象是obj对象的原型,obj对象本身并没有time属性,所以根据原型链,会在proxy对象上读取该属性,导致被拦截。</p>
<p>拦截器上可以设置多个操作,如果没有设置,直接落在目标对象上,按原先的方法产生结果。</p>
<h3 id="操作"><a href="#操作" class="headerlink" title="操作"></a>操作</h3><ul>
<li>get(target, propKey, receiver):拦截对象属性的读取,比如proxy.foo和proxy[‘foo’]。</li>
<li>set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = v或proxy[‘foo’] = v,返回一个布尔值。</li>
<li>has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。</li>
<li>deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。</li>
<li>ownKeys(target):拦截Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for…in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。</li>
<li>getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。</li>
<li>defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。</li>
<li>preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。</li>
<li>getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。</li>
<li>isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。</li>
<li>setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。</li>
<li>apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…)。</li>
<li>construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(…args)。</li>
</ul>
<figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//get</span></span><br><span class="line"><span class="keyword">var</span> person = {</span><br><span class="line"> name: <span class="string">"张三"</span></span><br><span class="line">};</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(person, {</span><br><span class="line"> <span class="keyword">get</span>: function(target, property) {</span><br><span class="line"> <span class="keyword">if</span> (property <span class="keyword">in</span> target) {</span><br><span class="line"> <span class="keyword">return</span> target[property];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">ReferenceError</span>(<span class="string">"Property \""</span> + property + <span class="string">"\" does not exist."</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">proxy.name <span class="comment">// "张三"</span></span><br><span class="line">proxy.age <span class="comment">// 抛出一个错误</span></span><br></pre></td></tr></table></figure>
<h3 id="this问题"><a href="#this问题" class="headerlink" title="this问题"></a>this问题</h3><p>虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。<br><figure class="highlight js"><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="keyword">const</span> target = {</span><br><span class="line"> m: <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> === proxy);</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"><span class="keyword">const</span> handler = {};</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(target, handler);</span><br><span class="line"></span><br><span class="line">target.m() <span class="comment">// false</span></span><br><span class="line">proxy.m() <span class="comment">// true</span></span><br></pre></td></tr></table></figure></p>
<h2 id="reflect"><a href="#reflect" class="headerlink" title="reflect"></a>reflect</h2><p>Reflect对象的设计目的有这样几个。</p>
<p>(1) 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。<br><img src="/images/proxy_01.jpg"><br>(2) 修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。</p>
<figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 老写法</span></span><br><span class="line"><span class="keyword">try</span> {</span><br><span class="line"> <span class="built_in">Object</span>.defineProperty(target, property, attributes);</span><br><span class="line"> <span class="comment">// success</span></span><br><span class="line">} <span class="keyword">catch</span> (e) {</span><br><span class="line"> <span class="comment">// failure</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">if</span> (<span class="built_in">Reflect</span>.defineProperty(target, property, attributes)) {</span><br><span class="line"> <span class="comment">// success</span></span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// failure</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>(3) 让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。<br><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 老写法</span></span><br><span class="line"><span class="string">'assign'</span> <span class="keyword">in</span> <span class="built_in">Object</span> <span class="comment">// true</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 新写法</span></span><br><span class="line"><span class="built_in">Reflect</span>.has(<span class="built_in">Object</span>, <span class="string">'assign'</span>) <span class="comment">// true</span></span><br></pre></td></tr></table></figure></p>
<p>(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。</p>
<p>这就是前面使用的功能,使用reflect完成默认行为。保证原生行为能够正常执行。</p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2019/03/14/proxy/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2019/02/26/observer/">浅谈发布/订阅模式</a>
<div class="article-meta">
<time>Feb 26, 2019</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/js/">js</a>
</div>
</div>
<div class="typo article-excerpt">
<p>观察者模式时软件设计模式的一种。<br>在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。</p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2019/02/26/observer/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2019/01/17/常见排序算法的原理与实现/">常见排序算法的原理与实现</a>
<div class="article-meta">
<time>Jan 17, 2019</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/算法/">算法</a>
</div>
</div>
<div class="typo article-excerpt">
<h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>本文介绍了冒泡、选择、插入、归并、快速、堆排序等多种排序的原理、js实现和性能表现。希望能把排序算法发光发热!</p>
<ul>
<li>冒泡: 将数组相邻元素两两比较大小,一遍一遍把当前最大值(最小值)冒泡到最后。</li>
<li>选择: 通过数组循环,记录当前最小值(最大值)所在,再与第一个元素进行元素交换,依次类推。</li>
<li>插入: 对未排序数据中,从已排序序列中从后向前查询,找到相应的位置进行插入。</li>
<li>归并: 将数组拆分成n个一个元素的数组,再进行两两合并。从底层往上合并时,左右两边的数组都是排序好的,因此合并容易。</li>
<li>快排: 选择基准元素(一般是中间),所有小于基准的放在左边,大于基准的放在右边,重复直到结束。</li>
<li>堆排: 初始化堆后,将最后一个元素与堆顶元素交换后,最后元素移出堆排序序列中,再不断调整堆使满足堆的性质。</li>
</ul>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2019/01/17/常见排序算法的原理与实现/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2019/01/09/medianTwoArray/">求取两个排序数组的中位数</a>
<div class="article-meta">
<time>Jan 09, 2019</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/算法/">算法</a>
</div>
</div>
<div class="typo article-excerpt">
<p>##问题:</p>
<blockquote>
<p>给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 。<br>请找出这两个有序数组的中位数。要求算法的时间复杂度为 O(log (m+n)) 。<br>你可以假设 nums1 和 nums2 不同时为空。<br>示例 1:<br>nums1 = [1, 3]<br>nums2 = [2]<br>中位数是 2.0<br>示例 2:<br>nums1 = [1, 2]<br>nums2 = [3, 4]<br>中位数是 (2 + 3)/2 = 2.5</p>
</blockquote>
<p>##思考:<br>总体思考:<br>最主要的难点是算法复杂度的限制, log级别的时间复杂度我们自然想到二分法,每次取中间值,自然得出的是log2(n)级别的。<br>因为nums1和nums2是有序数组,我们对这两个数组分别在某一位置进行划分。</p>
<p>比如nums1数组设为A, 划分位置为 i :<br>left_A | right_A<br>A [0],A [1],…,A [i-1] | A [i],A [i + 1],…,A [m-1]<br>这样左边有 i 个元素,右边有( m - i )个元素。</p>
<p>nums2数组设为B,划分位置为 j :<br>left_B | right_B<br>B [0],B [1],…,B [j-1] | B [j],B [j + 1],…,B [n-1]<br>这样左边有 j 个元素,右边有( n - j )个元素。</p>
<p>把两个数组的左右两边分别混合,也就是left_A和left_B放一起,right_A和right_B放一起,得到中位数需要满足下面两个条件:</p>
<ol>
<li>左右数量相等(偶数:i + j = m - i + n -j )或者左边比右边大一个(奇数:i + j = m - i + n -j + 1)</li>
<li>max(left_A) 小于 min(right_B),而且max(left_B) 小于 min(right_A),因为left_A肯定小于right_A, left_B肯定小于right_B</li>
</ol>
<p>那么对于总长度为奇数,中位数 = max(left_A, left_B);对于总长度为偶数,中位数 = ( max(left_A, left_B) ,min(right_A,right_B) ) / 2</p>
<p>把上面两个条件进行整理:</p>
<ol>
<li>i = 0〜m,j = parseInt( (m + n + 1) / 2) - i (奇偶通用,阴影划分的为左边,其他为右边)<br><img src="https://upload-images.jianshu.io/upload_images/11352552-79f3071104811c90.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="总长度为奇数"><br><img src="https://upload-images.jianshu.io/upload_images/11352552-966deac16c1abb40.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="总长度为偶数"><br>所以n要大于等于m(n>=m),这样确保 j 是合法索引。</li>
<li>shortArray[ i -1] <= longArray[ j ],longArray[ j - 1 ] <= shortArray [ i ]</li>
</ol>
<p>##实现细节:</p>
<ol>
<li>先对nums1和nums2的长度进行判断,选择长的作为longArray, 短的作为shortArray</li>
<li>i 在 [ 0, m ]中进行取值,并根据二分法取中值,j = parseInt( (m + n + 1) / 2) - i </li>
<li>如果( j > 0 && i < m && longArray[j-1] > shortArray[i] ),说明shortArray [i]太小,i 应该继续增大,取值范围变为 [ i + 1, m ]</li>
<li>如果( i > 0 && j < n && shortArray[i-1] > longArray[j] ),说明shortArray [i]太大, i 应该减小,取值范围变为[0, i - 1]</li>
<li>以此循环,直到上面条件都不满足,说明要么取到边界了(i =0 , j=0 等情况),要么shortArray和longArray左边都取了值,要选出shortArray和longArray左边最大的值。</li>
</ol>
<ul>
<li>(i =0 情况下,左侧确定,左边最大值为longArray[j - 1] )<br><img src="https://upload-images.jianshu.io/upload_images/11352552-269f3f76f8ca7f7f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image.png"></li>
<li>(j = 0情况下,左侧确定,左侧最大值为shortArray[i - 1])<br><img src="/images/placeholder.png" alt="image.png" data-src="https://upload-images.jianshu.io/upload_images/11352552-eeb4360a82713bb5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" class="lazyload"></li>
<li>(其他情况,shortArray和longArray左边都取了值)<br><img src="/images/placeholder.png" alt="image.png" data-src="https://upload-images.jianshu.io/upload_images/11352552-bc42f88fec4e1c07.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" class="lazyload"></li>
</ul>
<ol start="6">
<li>对于总长度为奇数, 中位数 = max(left_A, left_B), 也就是第5步得到的值。如果是奇数,要再得到 minRight.</li>
</ol>
<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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> findMedianSortedArrays = <span class="function"><span class="keyword">function</span>(<span class="params">nums1, nums2</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> shortArray = [],longArray = [], m = nums1.length, n = nums2.length,</span><br><span class="line"> temp = <span class="number">0</span>, maxLeft = <span class="number">0</span>, minRight = <span class="number">0</span>;</span><br><span class="line"> <span class="comment">//保证 n >= m </span></span><br><span class="line"> <span class="keyword">if</span>(m > n) {</span><br><span class="line"> shortArray = nums2;</span><br><span class="line"> longArray = nums1;</span><br><span class="line"> temp = m;</span><br><span class="line"> m = n;</span><br><span class="line"> n = temp;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> shortArray = nums1;</span><br><span class="line"> longArray = nums2;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//假设shortArray取i个,longArray取parseInt((m+n+1)/2)-i个</span></span><br><span class="line"> <span class="keyword">var</span> imin = <span class="number">0</span>, imax = m, i, j;</span><br><span class="line"> <span class="keyword">do</span> {</span><br><span class="line"> i = <span class="built_in">parseInt</span>((imin + imax)/<span class="number">2</span>);</span><br><span class="line"> j = <span class="built_in">parseInt</span>((m + n + <span class="number">1</span>)/<span class="number">2</span> - i);</span><br><span class="line"> <span class="keyword">if</span>(j > <span class="number">0</span> && i < m && longArray[j<span class="number">-1</span>] > shortArray[i]) {</span><br><span class="line"> <span class="comment">// shortArray和longArray左右都取了值,且i值取小了</span></span><br><span class="line"> imin = i + <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>( i > <span class="number">0</span> && j < n && shortArray[i<span class="number">-1</span>] > longArray[j]) {</span><br><span class="line"> <span class="comment">// shortArray和longArray左右都取了值,且i值取大了</span></span><br><span class="line"> imax = i - <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 考虑边界情况</span></span><br><span class="line"> <span class="keyword">if</span>(i == <span class="number">0</span>) {</span><br><span class="line"> maxLeft = longArray[j - <span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span> (j == <span class="number">0</span> ) {</span><br><span class="line"> maxLeft = shortArray[i - <span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// i值不小不大, 也就是(shortArray[i-1] <= longArray[j] && longArray[j-1] <= shortArray[i])</span></span><br><span class="line"> maxLeft = <span class="built_in">Math</span>.max(shortArray[i - <span class="number">1</span>], longArray[j <span class="number">-1</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">while</span> (imin <= imax);</span><br><span class="line"> <span class="comment">//两数组相加个数是奇数,只要取中间值</span></span><br><span class="line"> <span class="keyword">if</span>( (m + n)%<span class="number">2</span> == <span class="number">1</span> ) <span class="keyword">return</span> maxLeft;</span><br><span class="line"> <span class="comment">//个数是偶数,必须左右两边中位数相加除以二</span></span><br><span class="line"> <span class="keyword">if</span>(i == m) {</span><br><span class="line"> minRight = longArray[j];</span><br><span class="line"> } <span class="keyword">else</span> <span class="keyword">if</span>(j == n){</span><br><span class="line"> minRight = shortArray[i];</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> minRight = <span class="built_in">Math</span>.min(shortArray[i], longArray[j]);</span><br><span class="line"> };</span><br><span class="line"> <span class="keyword">return</span> (maxLeft + minRight)/<span class="number">2</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2019/01/09/medianTwoArray/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/12/27/vuexAndRedux/">flux/redux/mobx/vuex相关解析</a>
<div class="article-meta">
<time>Dec 27, 2018</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/react/">react</a>
<a class="article-tag" href="/tags/vue/">vue</a>
</div>
</div>
<div class="typo article-excerpt">
<h1 id="状态管理是什么"><a href="#状态管理是什么" class="headerlink" title="状态管理是什么?"></a>状态管理是什么?</h1><p>在组件化开发的新前端发展史上,组件的发展提供了更好的编码效率,更好的代码阅读性,维护性,补充HTML5语义化标签的不足。前端承担了越来越多的任务,特别是做一个spa项目。然而我们父子组件沟通可以通过props和回调,但是在两个组件我们并不知道它们的调用关系的时候,如何进行沟通呢?<br>
</p></div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/12/27/vuexAndRedux/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/12/10/node/">node第一步!</a>
<div class="article-meta">
<time>Dec 10, 2018</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/node/">node</a>
</div>
</div>
<div class="typo article-excerpt">
<p>node在我们前端运用中频繁被提及,现在让我们来了解node是什么!</p>
<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。<br>作为异步驱动的 JavaScript 运行时,Node 被设计成可升级的网络应用。<br>Node 的用户不必担心死锁过程, 因为没有锁。Node 中几乎没有函数直接执行 I/O 操作,因此进程从不阻塞。由于没有任何阻塞,可伸缩系统在 Node 中开发是非常合理的。<br>
</p></div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/12/10/node/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/11/29/AddTwoNumbers/">两个数正序和逆序相加</a>
<div class="article-meta">
<time>Nov 29, 2018</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/算法/">算法</a>
</div>
</div>
<div class="typo article-excerpt">
<h1 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h1><p>本章将介绍两个数正序和逆序相加两种方法。</p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/11/29/AddTwoNumbers/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/11/16/webpack-common/">常见webpack的loaders和插件</a>
<div class="article-meta">
<time>Nov 16, 2018</time>
</div>
</div>
<div class="typo article-excerpt">
<p>本文将介绍一些常见webpack的loaders和插件,以供参考学习~<br>
</p></div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/11/16/webpack-common/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/11/11/webpack-theory/">webpack原理呀!</a>
<div class="article-meta">
<time>Nov 11, 2018</time>
</div>
</div>
<div class="typo article-excerpt">
<p>本文将简单介绍webpack相关的原理~</p>
<h2 id="webpack构建流程"><a href="#webpack构建流程" class="headerlink" title="webpack构建流程"></a>webpack构建流程</h2><ol>
<li>初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;</li>
<li>开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;</li>
<li>确定入口:根据配置中的 entry 找出所有的入口文件;</li>
<li>编译模块:从入口文件出发,调用所有配置的 Loader </li>
<li>对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;</li>
<li>完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;</li>
<li>输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;</li>
<li>输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。</li>
</ol>
<p>在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。</p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/11/11/webpack-theory/">Continue</a>
</div>
</article>
<article class="article">
<div class="article-header">
<a class="article-title" href="/2018/10/07/one-pix/">移动端高清适配方案</a>
<div class="article-meta">
<time>Oct 07, 2018</time>
<span class="iconfont icon-star"></span>
<a class="article-tag" href="/tags/css/">css</a>
</div>
</div>
<div class="typo article-excerpt">
<p>在移动端设置了边框为1px,为什么显示出来经常是模糊的呢?<br>这个涉及设备像素比的知识:<a href="https://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/" target="_blank" rel="noopener">https://www.zhangxinxu.com/wordpress/2012/08/window-devicepixelratio/</a><br>点击这个链接了解更多。</p>
</div>
<div class="article-bottom">
<a class="article-readmore" href="/2018/10/07/one-pix/">Continue</a>
</div>
</article>
<nav class="paginator">
<span class="page-number"> Page <strong>1</strong>, Total <strong>28</strong> . </span>
<a class="next" href="/page/2/">
Next
<i class="iconfont icon-right"></i>
</a>
</nav>
</div>
</div>
<a id="page-backTop">
<span>
<i class="iconfont icon-backtotop"></i>
</span>
</a>
<div class="search-container sildeUpMin">
<div class="search-header">
<input type="text" placeholder="Typing Something here." id="search-input" class="search-input">
<span class="search-cancel">
<i class="iconfont icon-cancel">
</i></span>
</div>
<div id="search-result" class="search-result"></div>
</div>
<div class="mobile-menu">
<img class="mobile-menu-icon lazyload" src="/images/placeholder.png" data-src="/images/favicon.png">
<a class="mobile-menu-link" href="/">Home
</a>
<a class="mobile-menu-link" href="/archives">Archives
</a>
<a class="mobile-menu-link" href="/tags">Tags
</a>
<a class="mobile-menu-link" href="/about">About
</a>
<a class="mobile-menu-link mobile-menu-search" href="#">Search </a>
</div>
<footer id="footer">
<div class="footer-copyright">
©
2017-
2019
Mooory
<br>
Theme Nayo
</div>
</footer>
Theme Nayo
<script src="/nayo.bundle.js"></script>
</body>
</html>