利用这个类可以保存方法的的实参,函数以后备用。在实例生成时会产生一个序列号用来标识是否来自undo或者redo的调用,从而避免存入缓存栈。
在浏览器中用调试工具看调用结果
View Code
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6 <title>javascript</title>
7 </head>
8
9 <body>
10 <input type="button" value=" - " id="a" /> <input type="button" value=" + " id="b" />
11
12 <input type="button" value=" - " id="c" /> <input type="button" value=" + " id="d" />
13 <script type="text/javascript">
14 /*function a() {
15 Do([].slice.call(arguments));
16 }
17 function Do() {
18 var temp = (arguments[0]),indicator = arguments.callee;
19 indicator.stack = [];
20 indicator.stack[0] = temp;
21 }
22 a({c:1,b:2}, 123, function(arg) {
23 return arg+1;
24 });
25 function dir() {
26 console.log(arguments[0]);
27 }
28 dir(Do.stack[0][2](3));*/
29
30 function MemoryDo(step){
31
32 var indicator,that,fn,slice,args;
33 (
34 indicator=arguments.callee,
35 slice=[].slice
36 )
37 if(!(this instanceof indicator)){return new indicator(step);}
38
39 indicator.keys={};
40 that=this;
41 this.stack=[];
42 this.index=0;
43
44
45 fn = indicator.prototype;
46 fn.constructor = indicator;
47
48 fn.is=function(o){
49 return ({}).toString.call(o).slice(8, -1);
50 }
51 fn.slice=function(o,index){
52 return slice.call(o,index || 0);
53 }
54 fn.setIndex=function(number){
55 if(number<0 || this.is(this.index)!=='Number'){return};
56 this.index=number;
57 }
58 fn.getIndex=function(){
59 return this.is(this.index)==='Number' ? this.index : null;
60 }
61 fn.sign=function(){
62 return ('abcdefghijk'[Math.random().toFixed(1) * 10]+this.randomNumber(10000,10000000));
63 }
64 fn.randomNumber=function(a,b){
65 return Math.round(Math.random()*b+a);
66 }
67 fn.dataBuffer=function(){
68 var temp,socureCall=arguments.callee.caller,flag=arguments[0][arguments[0].length-1],data;
69 if (socureCall.arguments.length !== arguments[0].length || indicator.keys[flag]==='used') return;
70
71 data=this.stack;
72 if(data.length===this.step){data.shift()};
73
74 temp=data[data.length]=[];
75 temp[temp.length]=(this.slice(arguments[0],0)).concat(this.sn);
76 temp[temp.length]=arguments.callee.caller;
77
78 indicator.keys[this.sn]='used';
79
80 this.index=this.stack.length;
81 }
82 fn.redo=function(){
83 //var data=indicator.stack[indicator.stack.length-1];
84 //console.log(data);
85 if(this.index===this.stack.length){
86 this.re=-1;return;
87 }else{
88 this.re=1;
89 this.virtualDo(this.index+=1);
90 }
91
92 }
93 fn.undo=function(){
94 //var data=indicator.stack[indicator.stack.length-1];
95 //console.log(data);
96
97 if(this.index===0){
98 return;
99 }else{
100 this.un=1;
101 this.virtualDo(this.index-=1);
102 }
103
104 }
105 fn.virtualDo=function(){
106 var data=this.stack,i=0,len=this.index,temp;
107 for(;i<len;){
108 temp=data[i++];
109 temp[1].apply(undefined,temp[0]);
110 }
111 }
112
113
114 this.step=this.is(step)==='Number'? step : 10;
115 this.sn=this.sign();
116
117 }
118
119
120 var a=MemoryDo(4);
121 var b=MemoryDo(2);
122 function doIt(o,fn){
123 a.dataBuffer(arguments);
124
125 fn(arguments);
126 b.dataBuffer(arguments);
127 }
128 doIt({a:1,b:2,c:3},function(a){
129 console.dir(a);
130 });
131 doIt({b:2,c:3},function(a){
132 console.dir(a);
133 });
134 doIt({c:3},function(a){
135 console.dir(a);
136 });
137 doIt({d:4},function(a){
138 console.dir(a);
139 });
140 document.getElementById('a').onclick=function(){
141 a.undo();
142 }
143 document.getElementById('b').onclick=function(){
144 a.redo();
145 }
146 document.getElementById('c').onclick=function(){
147 b.undo();
148 }
149 document.getElementById('d').onclick=function(){
150 b.redo();
151 }
152 </script>
153 </body>
154 </html>