代理模式1

"Hello World, Hello Blog"

Posted by wudimingwo on December 15, 2018

1.png 2.png image.png 想快递? 像中介? image.png

邓哥的例子

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
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
        <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
        <title>dddd</title>
        <style type="text/css">
            
        </style>
    </head>
    <body>
         <button id="btn">click</button>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
        <script type="text/javascript">
          
              
              var mrDeng = {
                sendFlower : function (target) {
                	var flower = 'sunflower';
                	target.receiveFlower(flower);
                }
              };
              
              
              
              //代理
              var cstProxy = {
                proxyFlower : function (target) {
                  this.listenMood(target,function () {
                    mrDeng.sendFlower(target);
                  })
                },
                // 关键是监听心情(状态)
                listenMood: function (target, cb) {
                	var timer = setInterval(function () {
                		if (target.mood) {
                			cb();
                			clearInterval(timer);
                		}
                	},300);
                }
                
              }
              用的是setInterval,不停监听某个状态,
              一旦成功,就执行回调.保证成功率.
              
              这应该算是监听数据了吧?
              
              // godness
              var godness = {
                mood : null,
                receiveFlower : function () {
                  // true good false bad
                  this.mood ? console.log('ok') : console.log('get out');
                },
                changeMood : function () {
                	this.mood = Math.random() > 0.5;
                },
                createMood : function () {
                	var self = this;
                self.changeMood();
                	setInterval(function () {
                		self.changeMood();
                		
                	},400);
                }
              }
              
              godness.createMood();
              cstProxy.proxyFlower(godness);
              
        </script>
    </body>
</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
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
        <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
        <title>dddd</title>
        <style type="text/css">
            div{
              display: inline-block;
              border: 1px solid #CCCCCC;
            }
            div img{
              width: 200px;
              height: 100px;
            }
        </style>
    </head>
    <body>
        <div id="app"></div>
        <script type="text/javascript">
            var MyImage = function (id) {
            	var oImg = new Image();
            	this.setSrc = function (src) {
            		oImg.src = src;
            	}
            	document.getElementById(id).appendChild(oImg);
            }
              
            
            //代理
            var ProxyImage = (function () {
              var oMyImg = new MyImage('app');
//            oMyImg.setSrc('./img/1.jpg');
            	
            	var oNewImage = new Image();// 这是用来代理的.代理发送请求加载资源.
            	
            	// 用来监控
            	oNewImage.onload = function () {
            		oMyImg.setSrc(oNewImage.src);//加载完成时,替换过来.
            	}
            	return function (src) {
                oMyImg.setSrc('./img/1.jpg');// 这是占位图,本地图
              	oNewImage.src = src;
            	}
            	
            })();
            var url = 'http://s9.knowsky.com/bizhi/l/20090808/200910296%20%2841%29.jpg';
            ProxyImage(url);
        </script>
    </body>
</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
闭包版本
var aaaaa = (function () {
            	var lastTime = 0;
            	return function () {
            	  if (new Date().getTime() - lastTime > 1000) {
            	    console.log('aaa');
                  lastTime = new Date().getTime();
            	}
            	}
            })()
btn.onclick = aaaaa;
函数工厂版本
function debounce (fun) {
            	var lastTime = 0;
            	return function () {
            		if (new Date().getTime() - lastTime > 1000) {
            			lastTime = new Date().getTime();
            			return fun.apply(this,arguments);

            		}
            	};
            }
            
            function aaa () {
            	console.log('aaa');
            }
            var aaaa = debounce(aaa);
            
            btn.onclick = aaaa;
返回对象版本
function Debounce (fun) {
            	var lastTime = 0;
            	this.debounce = function () {
            		if (new Date().getTime() - lastTime > 1000) {
            		  lastTime = new Date().getTime();
            			return fun.apply(this,arguments);
            		}
            	};
            }
            
            function aaa () {
              console.log('aaa');
            }
            var a = new Debounce(aaa);
            
            btn.onclick = a.debounce;
不过这样似乎没什么意思?
比起直接定义在一个对象上,lastTime 成了私有变量?

作业1.0图片懒加载多个图片加载?

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
   var div = [].slice.call(document.getElementsByTagName('div'));
            var MyImage = function (dom) {
                var oImg = new Image();
                this.setSrc = function (src) {
                    oImg.src = src;
                }
                dom.appendChild(oImg);
            }
            
            function ProxyImage (dom) {
            	var oMyImg = new MyImage(dom);
            	var newImage = new Image();
            	
            	newImage.onload = function () {
            		oMyImg.setSrc(newImage.src);
            	}
            	
            	this.proxy = function (src) {
            		oMyImg.setSrc('./img/1.jpg');
            		newImage.src = src;
            	}
            }
            
            var appSrc = new ProxyImage(div[0]);
            var url = 'http://s9.knowsky.com/bizhi/l/20090808/200910296%20%2841%29.jpg';
//          ProxyImage(url);
            btn.onclick = function () {
              appSrc.proxy(url);
            }

这写的啥玩意..
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
过了几天我自己又跟着印象又写了一次,
我发现了一个差别.
我总盯着数据, 我定义一个函数,想返回的是数据.
而我看陈老师的代码, 他定义一个函数,想返回的是一个放置数据的对象,容器.
这就是面向对象的编程思维的具体表现之一?
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
        <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
        <title>dddd</title>
        <style type="text/css">
            .wrapper div{
              width: 300px;
              height: 150px;
            }
            .wrapper img{
              width: 100%;
              height: 100%;
            }
        </style>
    </head>
    <body>
         <div class="wrapper">
           <div class="item1"></div>
           <div class="item2"></div>
           <div class="item3"></div>
           <div class="item4"></div>
           <div class="item5"></div>
           <div class="item6"></div>
           <div class="item7"></div>
           <div class="item8"></div>
           <div class="item9"></div>
           <div class="item10"></div>
         </div>
        <script type="text/javascript">
            // 批量懒加载
            // 假设 item1 和 url 是配对的
            var arr = [
              {class : "item1", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item2", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item3", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item4", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item5", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item6", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item7", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item8", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item8", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"},
              {class : "item10", url : "http://pic.pptbz.com/201506/2015070581208537.JPG"}
            ]
          
            // 获取元素, 
            var wrapper = document.getElementsByClassName("wrapper")[0];
            // 渲染图片
            function myImg (url,dom) {
            	var img = new Image();
            	img.src = url;
            	console.log(dom);
            	dom.appendChild(img);
            	return img;
            }
            // 懒加载
            function lazyload (arr) {
              if (!Array.isArray(arr)) {
              	arr = [{class : arguments[1], url : arr}];
              }
              var len = arr.length;
              
              for(var i = 0; i < len ; i++) {
                (function (i) {
                var ele = document.getElementsByClassName(arr[i].class)[0];
                var img = myImg("img/1.jpg",ele);
                var newImg = new Image();
              	newImg.onload = function () {
              	  img.src = arr[i].url;
                }
              	 setTimeout(function () {
              	   console.log(arr[i]);
              	   newImg.src = arr[i].url;
              	},1000);
                })(i);
            	}
            }
            var url = "http://pic.pptbz.com/201506/2015070581208537.JPG";
            console.log(wrapper);
            lazyload(arr);
        </script>
    </body>
</html>

作业2.0 事件累积?

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
先写一波事件点击改变属性的操作.
写得时候感觉写得挺溜的,
写完之后发现可读性很差,毫无维护性,扩展性可言..
通篇也没有用到什么面相对象的东西.
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
        <meta http-equiv="X-UA-Compatible" content="ie=edge"/>
        <title>dddd</title>
        <style type="text/css">
            div{
              position: absolute;
              left: 100px;
              top: 100px;
              height: 100px;
              width: 100px;
              font-size: 18px;
              border: 1px solid black;
            }
        </style>
    </head>
    <body>
         <div>duyi</div>
         <span>up</span>
         <button>width up</button>
         <button>height up</button>
         <button>fontSize up</button>
         <button>right</button>
         <button>bottom</button>
         <br />
         <span>down</span>
         <button>width down</button>
         <button>height down</button>
         <button>fontSize down</button>
         <button>left</button>
         <button>top</button>
        <script type="text/javascript">
            // 我希望点击,发生相应的改变
            var div = document.getElementsByTagName('div')[0];
            var buttonArray = document.getElementsByTagName('button');
            function up (div,prop) {
            	div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) + 10 + 'px';
            }
            function returnUpAndDown (div,flag) {
            	return function (prop) {
            	  if(flag == 'up'){
              		return function () {
                  	div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) + 10 + 'px';
              		}
            	  }else if(flag == 'down'){
            	    return function () {
                    div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) - 10 + 'px';
                  }
            	  }else{
            	    throw error;
            	  }
            	}
            }
            var fatherUp = returnUpAndDown(div,'up');
            var fatherDown = returnUpAndDown(div,'down');
            var arr = ['width','height','fontSize','left','top'];
            
            var newArrUp = arr.map(function (item,index) {
            	return fatherUp(item);
            });
            var newArrDown = arr.map(function (item,index) {
              return fatherDown(item);
            });
            var ArrUpAndDown = newArrUp.concat(newArrDown);
            ArrUpAndDown.forEach(function (item,index) {
            	buttonArray[index].onclick = function () {
            		item();
            	}
            })
            
            
        </script>
    </body>
</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
刚开始这么想的,用debounce
var debounce = (function () {
              // 让每个函数拥有同一个 timer
              var timer = null;
              return function (fun,delay) {
                var delay = delay || 1000;
                return function () {
                  var self = this;
                  var args = arguments;
                  timer = setTimeout(function () {
                    fun.apply(self,args);
                  },delay);
                }
              }
            })();
          ... 此部分与上面相同
            var newArrUp = arr.map(function (item,index) {
            	return debounce(fatherUp(item));
            });
            var newArrDown = arr.map(function (item,index) {
              return debounce(fatherDown(item));
            });
            ...此部分与上面相同

我的思路是,首先要实现延迟,自然想到debounce 防抖
要互相之间影响,所以让他们拥有同一个timer,
结果,后一个操作会取消前一个操作,
也就是说,
我们需要每次操作的时候,把不同的函数操作,放进一个函数里,然后延迟执行?

事件累积作业2.0版本

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
我们让每个button点击事件都绑定同一个函数,
每个点击事件会传一个参数,来决定要改变哪个属性.
但会有延迟.
        <script type="text/javascript">
          var debounce = (function () {
              // 让每个函数拥有同一个 timer
              var timer = null;
              return function (fun,delay) {
                var delay = delay || 1000;
                return function () {
                  var self = this;
                  var args = arguments;
                  timer = setTimeout(function () {
                    fun.apply(self,args);
                  },delay);
                }
              }
            })();
            // 我希望点击,发生相应的改变
            var div = document.getElementsByTagName('div')[0];
            var buttonArray =[].slice.call(document.getElementsByTagName('button'));
            buttonArray.forEach(function (item,index) {
            	item.index = index;
            })
            function up (div,prop) {
            	div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) + 10 + 'px';
            }
            function returnUpAndDown (div,flag) {
            	return function (prop) {
            	  if(flag == 'up'){
              		return function () {
                  	div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) + 10 + 'px';
              		}
            	  }else if(flag == 'down'){
            	    return function () {
                    div.style[prop] = parseFloat(window.getComputedStyle(div,null)[prop]) - 10 + 'px';
                  }
            	  }else{
            	    throw error;
            	  }
            	}
            }
            var fatherUp = returnUpAndDown(div,'up');
            var fatherDown = returnUpAndDown(div,'down');
            var arr = ['width','height','fontSize','left','top','width','height','fontSize','left','top'];
            // 有个函数,每次点击都会点击这个函数,并且传一个参数给他,要他执行哪个,
            // 这个参数应该是个唯一标识.
            function proxy () {
            	var index = this.index;
            	console.log(arr[index]);
            	if (index < 5) {
            		this.style[arr[index]] = fatherUp([arr[index]])();
            	}else{
            		this.style[arr[index]] = fatherDown([arr[index]])();
            	}
            }
            
            buttonArray.forEach(function (item,index) {
            	buttonArray[index].onclick = proxy;
            })
            
            
            // 我们希望,就跟防抖一样,有个延迟作用.
            // 关键是让不同函数,拥有同一个timer?
            // 最简单的是闭包
            
            
            
        </script>
    </body>
</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
下面的这种写法,虽然实现的功能,但我看不出哪里有代理模式的意思?
下面的这种写法,给我的第一个启示是,先整理好数据,比什么都重要..
        <script type="text/javascript">
            // 我希望点击,发生相应的改变
            var div = document.getElementsByTagName('div')[0];
            var buttonArray =[].slice.call(document.getElementsByTagName('button'));
            buttonArray.forEach(function (item,index) {
            	item.index = index;
            })
            // 有个函数,每次点击都会点击这个函数,并且传一个参数给他,要他执行哪个,
            // 这个参数应该是个唯一标识.
            var timer = null;// timer 和 obj 这两个餐宿可以放进proxy闭包里?
            var obj = {
              width : parseInt(window.getComputedStyle(div,null).width),
              height : parseInt(window.getComputedStyle(div,null).height),
              left : parseInt(window.getComputedStyle(div,null).left),
              top : parseInt(window.getComputedStyle(div,null).top),
              fontSize : parseInt(window.getComputedStyle(div,null).fontSize)
            };
            function proxy () {
            	var index = this.index;
            	var prop = arr[index];
            	if (index < 5) {
            		obj[prop] += 10;
            	}else{
            		obj[prop] -= 10;
            	}
            	clearInterval(timer);
            	timer = setTimeout(function () {
            		for(var key in obj) {
            		  div.style[key] = obj[key] + 'px';
            		}
            	},1000);
            	console.log(obj);
            	
            }
            
            buttonArray.forEach(function (item,index) {
            	buttonArray[index].onclick = proxy;
            })
  
            
        </script>

第二种思路 累积函数

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
把函数放进一个大函数里? 
事件绑定在这个大函数(代理函数?)上.
每次事件触发时,
把相应的函数放进某个数组里.
重复点击,则重复放进数组里?
大函数有延时作用.
一旦超过事件,则遍历数组,执行里面的函数?

<script type="text/javascript">
            // 我希望点击,发生相应的改变
            var div = document.getElementsByTagName('div')[0];
            var buttonArray =[].slice.call(document.getElementsByTagName('button'));
            buttonArray.forEach(function (item,index) {
            	item.index = index;
            })
            // 创建10 个函数
            function getStyle (prop) {
            	return parseInt(window.getComputedStyle(div,null)[prop]);
            }
            
            function change (prop,flag) {
              if (flag == 'up') {
                div.style[prop] = getStyle(prop) + 10 + 'px'; 
              }else{
                div.style[prop] = getStyle(prop) - 10 + 'px'; 
              }
            }
            
            
            var proxy = (function () {
              var timer = null;
              var obj = {
                0 : ['width','up'],
                1 : ['height','up'],
                2 : ['fontSize','up'],
                3 : ['left','up'],
                4 : ['top','up'],
                5 : ['width','down'],
                6 : ['height','down'],
                7 : ['fontSize','down'],
                8 : ['left','down'],
                9 : ['top','down']
              };
              var arr = [];
              
              return function () {
                var index = this.index;
              	arr.push(function () {
              		change(obj[index][0],obj[index][1]);
              	});
              	clearInterval(timer);
              	timer = setInterval(function () {
              		arr.forEach(function (item,index) {
              			item();
              		});
              		arr = [];
              	},1000);
            	
              }
            	
            })();
            buttonArray.forEach(function (item,index) {
            	item.onclick = proxy;
            })
            
        </script>

原谅我里面很多地方写得很烂,
但这里的重点是,
这里的累积是,累积了要执行的函数.
放在了一个数组里.
以前在哪里见过,终于用上一回.