收藏的js学习小例子
1.js模拟java里的Map
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
function Map(){ var obj = {} ; this.put = function(key , value){ obj[key] = value ; } this.size = function(){ var count = 0 ; for(var attr in obj){ count++; } return count ; } this.get = function(key){ if(obj[key] || obj[key] === 0 || obj[key] === false){ return obj[key]; } else { return null; } } this.remove = function(key){ if(obj[key] || obj[key] === 0 || obj[key] === false){ delete obj[key]; } } this.eachMap = function(fn){ for(var attr in obj){ fn(attr, obj[attr]); } } } var m = new Map(); m.put('01' , 'abc'); m.put('02' , false) ; m.put('03' , true); m.put('04' , new Date()); m.eachMap(function(key , value){ alert(key +" :"+ value); });
2.去除数组重复项
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
var arr = [2,1,2,10,2,3,5,5,1,10,13]; // js对象的特性 : 在js对象中 key 是永远不会重复的 // 1 把数组转成一个js的对象 // 2 把数组中的值,变成js对象当中的key // 3 把这个对象 再还原成数组 // 把数组转成对象 function toObject(arr){ var obj = {} ; // 私有的对象 var j ; for(var i=0 , j= arr.length ; i<j; i++){ obj[arr[i]] = true ; } return obj ; } // 把这个对象转成数组 function keys(obj){ var arr = [] ; // 私有对象 for(var attr in obj){ if(obj.hasOwnProperty(attr)){ arr.push(attr); } } return arr ; } //综合的方法 去掉数组中的重复项 function uniq(newarr){ return keys(toObject(newarr)); } alert(uniq(arr));
3.继承案例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<script type=text/javascript> var __extends = this.__extends || function (sub, sup) { for (var p in sup) if (sup.hasOwnProperty(p)) sub[p] = sup[p];//继承父类自身属性 function __() { this.constructor = sub; } __.prototype = sup.prototype; sub.prototype = new __(); alert(sub.prototype.constructor); }; function extend(sub,sup){ var F=new Function();//创建一个空函数 F.prototype=sup.prototype;//空函数原型指向父类原型 sub.prototype=new F(); sub.prototype.constructor = sub; sub.superClass =sup.prototype;//保持父类原型 //判断父类原型对象的构造器 if(sup.prototype.constructor==Object.prototype.constructor){ //如果简单原型覆盖 则手动添加 sup.prototype.constructor=sup; } } function Person(name,age){ this.name=name; this.age=age; } Person.ff='sssc'; Person.prototype={ sayName : function(){ alert("对对") } } function Boy(name ,age,sex){ //或者 Boy.superClass.constructor.call(this,name,age) Person.call(this,name,age); this.sex=sex; } //Boy.prototype=new Person(); __extends(Boy,Person);//继承 var b=new Boy('对对',23,'男'); alert(b.name); alert(b.age); alert(b.sex); b.sayName(); alert(Boy.prototype.constructor.ff);//输出父类自身属性 </script>
4.链式编程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*** * //简单的链式编程 * var person={ run:function(){ alert("跑"); return this; }, jump:function(){ alert("跳"); return this; }, sleep:function(){ alert("睡"); return this; } } person.run().jump().sleep(); */ (function(window,undefined){ //定义私有_$方法 function _$(arguments){ //正则表达式匹配id选择器 var idselector=/^#\w+$/; this.dom //此属性接收所得到的元素. if(idselector.test(arguments[0])){ this.dom=document.getElementById(arguments[0].substring(1)); }else{ throw Error (' arguments is error'); } }; //在Function上扩展一个可以实现链式编程的方法 Function.prototype.method=function(methodName,fn){ this.prototype[methodName]=fn; return this; }; _$.prototype={ constructor:_$, addEvent:function(type,fn){ if (window.addEventListener) { //ff this.dom.addEventListener(type, fn); } else if (window.attachEvent) {//ie this.dom.attachEvent("on"+type,fn); } return this; }, setStyle:function(property,val){ this.dom.style[property]=val; return this; } }; window.$=_$; _$.onReady=function(fn){ //1.实例化出来_$对象 真正的注册到window上 window.$=function (){ return new _$(arguments); } ; //2.执行代码 fn(); //3.实现链式编程 _$.method('addEvent',function(){ alert('111'); return this; }).method('setStyle',function(){ alert('222'); return this; }); _$.prototype.addEvent().setStyle(); } })(window) ; $.onReady(function(){ $("#inp").addEvent("dblclick",function(){ alert("双击"); }).setStyle("backgroundColor","red"); }); </script>
5.组合模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>组合模式</title> <script type=text/javascript> /*** * * 公司- * 部门1 * 人员1 * 人员2 * 人员3 * 部门2 * 人员4 * 人员5 * 人员6 */ /*** * * 普通方式实现 */ var Org =function(name){ this.name=name; this.depts=[]; } Org.prototype={ constructor:Org, addDepts:function(child){ this.depts.push(child); return this; }, getDepts:function(){ return this.depts; } } var Dept=function(name){ this.name=name; this.persons=[]; }; Dept.prototype={ constructor:Dept, addPersons:function(child){ this.persons.push(child); return this; }, getPersons:function(){ return this.persons; } }; var Person=function(name){ this.name=name; } Person.prototype={ constructor:Person, work:function(){ document.write(this.name+'工作,'); } } var p1=new Person('人员1') var p2=new Person('人员2') var p3=new Person('人员3') var p4=new Person('人员4') var p5=new Person('人员5') var p6=new Person('人员6') var dept1=new Dept('部门1'); dept1.addPersons(p1).addPersons(p2).addPersons(p3); var dept2=new Dept('部门2'); dept2.addPersons(p4).addPersons(p5).addPersons(p6); var org =new Org('yjq'); org.addDepts(dept1).addDepts(dept2); //循环工作 for(var i=0,depts= org.getDepts();i<depts.length;i++){ var dept=depts[i]; for(var j=0,persons=dept.getPersons();j<persons.length;j++){ if(persons[j].name ==='人员4'){ //persons[j].work(); } } } //可维护性差 /*** * 组合模式方式实现 * * 场景: * 1.存在一批组织成某种层次体系的对象 * 2.希望对这批对象或其中的一部分对象实施一个操作 * * 特点: * 1.组合模式中只有两种类型对象:组合对象,叶子对象 * 2.这两中类型都实现同一批接口 * 3.一般我们会在组合对象中调用其他方法并隐式调用'下级对象'的方法(递归) */ var Composite=function(name){ this.name=name; this.type='Composite';//说明对象类型 this.children=[]; }; Composite.prototype={ constructor:Composite, addChild:function(child){ this.children.push(child); return this; }, getChild:function(name){ //接收叶子对象 var elements=[]; //判断对象是否为Leaf类型的,是则添加到数组,否则继续递归 var pushLeaf=function(item){ if(item.type=='Composite'){ item.children.forEach(arguments.callee); }else if(item.type==='Leaf'){ elements.push(item); } }; //根据name 让指定name下所有的类型为Leaf的对象执行 if(name&& this.name!==name){ this.children.forEach(function(item){ //如果传递的name是2级节点名称 if(item.name===name&&item.type==='Composite'){ item.children.forEach(pushLeaf); } //如果name是3级,4级.....节点 if(item.name!==name&&item.type==='Composite'){ item.children.forEach(arguments.callee); } //如果传递的name是叶子节点的时候 if(item.name===name&&item.type==='Leaf'){ elements.push(item); } }); }else{//不传递name 则是整个公司leaf this.children.forEach(pushLeaf); } //返回 return elements; }, work:function(name){ //获取leaf类型对象节点 var leafObjects=this.getChild(name); for(var i=0;i<leafObjects.length;i++){ leafObjects[i].work(); } } } var Leaf=function(name){ this.name=name; this.type='Leaf';//说明对象类型 } Leaf.prototype={ constructor:Leaf, addChild:function(child){ throw new Error('error'); }, getChild:function(name){ if(this.name=name){ return this; } return null; }, work:function(){ document.write(this.name+'工作,'); } } var _p1=new Leaf('人员1'); var _p2=new Leaf('人员2'); var _p3=new Leaf('人员3'); var _p4=new Leaf('人员4'); var _p5=new Leaf('人员5'); var _p6=new Leaf('人员6'); var _p7=new Leaf('人员7'); var _p8=new Leaf('人员8'); var _p9=new Leaf('人员9'); var _p10=new Leaf('人员10'); var _p11=new Leaf('人员11'); var _p12=new Leaf('人员12'); var _dept1=new Composite('部门1'); _dept1.addChild(_p1).addChild(_p2).addChild(_p3); var _dept2=new Composite('部门2'); _dept2.addChild(_p4).addChild(_p5).addChild(_p6); var _dept3=new Composite('部门3'); _dept3.addChild(_p7).addChild(_p8).addChild(_p9); var _dept4=new Composite('部门4'); _dept4.addChild(_p10).addChild(_p11).addChild(_p12); var org1 =new Composite('公司1'); org1.addChild(_dept1).addChild(_dept2); var org2 =new Composite('公司2'); org2.addChild(_dept3).addChild(_dept4); var org =new Composite('公司'); org.addChild(org1).addChild(org2); org.work('公司1'); </script> </head> <body> </body> </html>
6.装饰者模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>装饰者模式</title> <script type=text/javascript> /*** * 装饰者(decorator)模式 * 作用:为对象添加新特性; * 实现: * 1.实现同样的接口(具有相同的方法) * 2.需要有子类 * 3.子类需要接收父类的的引用 * 简单的说就是:需要装饰的类(父类)把它的引用传递给装饰类(子类)让装饰类装饰 */ var Car =function(car){ //为了让子类继承(让子类多一个父类的引用) this.car=car; }; Car.prototype={ constructor:Car, getPrice:function(){ return 1000; }, assemble:function(){ alert('car'); } }; //新需求:加车灯 需要加钱(方法改变) var LightDecorator=function(car){ //原始对象 Car.call(this,car);//借用构造函数继承 } LightDecorator.prototype=new Car();//原型继承 LightDecorator.prototype={ constructor:LightDecorator, //重写父类方法 getPrice:function(){ return this.car.getPrice()+11; //继承过来的car 有父类的引用 加钱11 }, assemble:function(){ alert('LightCar'); } } //需要加其他的 var OtherDecorator=function(car){ //原始对象 Car.call(this,car);//借用构造函数继承 } OtherDecorator.prototype=new Car();//原型继承 OtherDecorator.prototype={ constructor:OtherDecorator, //重写父类方法 getPrice:function(){ return this.car.getPrice()+1; //继承过来的car 有父类的引用 加钱1 }, assemble:function(){ alert('OtherCat'); } } var car =new Car(); alert(car.getPrice()); car.assemble(); car =new LightDecorator(car); alert(car.getPrice()); car.assemble(); car =new OtherDecorator(car); alert(car.getPrice()); car.assemble(); //返回一个当前时间的字符串表示形式 function getDate() { return new Date().toString(); } function upperCaseDecorator(fn){ return function(){ return fn.apply(this,arguments).toUpperCase(); } } alert(getDate()); alert(upperCaseDecorator(getDate)()); </script> </head> <body> </body> </html>
7.桥接模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>桥接模式</title> <script type="text/javascript"> /** * 桥接模式:主要是把抽象和实现分离,使它们完全独立 */ var PublicClass= function(){ //私有化变量 var privateMethod =function(){ alert('do something....'); } //可单元测试 privateMethod(); //通过特权函数去访问这个私有的独立单元 this.bridgeMethod=function(){ return privateMethod(); } }; var p = new PublicClass(); p.bridgeMethod(); </script> </head> <body> </body> </html>
8.观察者模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>观察者模式</title> <script type=text/javascript> /** * 观察者模式:对程序中的某一个对象的进行实时的观察,当该对象状态发生改变的时候 进行通知 * 观察者、被观察者 * 案例:订报纸 (报社:发布者、订阅者) */ //发布者(被观察者) var Publish=function(name){ this.name=name; this.subscribers=[];//接受所以的订阅者(每一个元素是函数的类型fn)数组 }; //Publish类的实例对象去发布消息的方法 Publish.prototype.deliver=function(news){ var publish=this; this.subscribers.forEach(function(fn){ fn(news,publish);//把消息发给一个订阅者 }); return this;//链式编程 } //具体的一个订阅者去订阅报纸的方法 Function.prototype.subscribe=function(publish){ var sub =this;//取得具体订阅者这个人 //some方法:循环遍历数组的每一个元素,执行一个函数,如果其中有一个返回true,那么整天返回true var alreadyExists =publish.subscribers.some(function(item){ return item===sub; }); //如果当前出版社里不存在这个人,则将其加入其中 if(!alreadyExists){ publish.subscribers.push(this); } return this;//链式编程 } //具体的一个订阅者去取消订阅报纸的方法 Function.prototype.unsubscribe=function(publish){ var sub=this;//具体的这个人 //filter:过滤函数,循环遍历数组的每一个元素,执行一个函数如果不匹配,则删除该元素 publish.subscribers=publish.subscribers.filter(function(itme){ return item!==sub; }); return this;//链式编程 } window.onload=function(){ //实例化发布者对象(报社对象、被观察者) var pub1=new Publish('报社1'); var pub2=new Publish('报社2'); var pub3=new Publish('报社3'); //观察者(订阅者) var sub1 = function(news){ document.getElementById('sub1').innerHTML+=arguments[1].name+':'+news+'/n'; }; var sub2 = function(news){ document.getElementById('sub2').innerHTML+=arguments[1].name+':'+news+'/n'; }; //执行订阅的方法 sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3); sub2.subscribe(pub1).subscribe(pub2); //事件绑定 YJQ.EventHelper.addHandler(document.getElementById('pub1'),'click',function(){ pub1.deliver(document.getElementById('text1').value); }); YJQ.EventHelper.addHandler(document.getElementById('pub2'),'click',function(){ pub2.deliver(document.getElementById('text2').value); }); YJQ.EventHelper.addHandler(document.getElementById('pub3'),'click',function(){ pub3.deliver(document.getElementById('text3').value); }); } </script> </head> <body> <input id="pub1" type="button" value="报社1"/><input id="text1" value=""/><br/> <input id="pub2" type="button" value="报社2"/><input id="text2" value=""/><br/> <input id="pub3" type="button" value="报社3"/><input id="text3" value=""/><br/> <textarea id="sub1" rows="5" cols="30"></textarea> <textarea id="sub2" rows="5" cols="30"></textarea> </body> <script type=text/javascript> var YJQ={}; YJQ.EventHelper={ addHandler:function(element,type,handler){ if(element.addEventListener){ //FF element.addEventListener(type,handler,false); }else if(element.attachEvent){//IE element.attachEvent('on'+type,handler); } }, removeHandler:function(element,type,handler){ if(element.addEventListener){ //FF element.removeEventListener(type,handler,false); }else if(element.attachEvent){//IE element.detachEvent('on'+type,handler); } } } </script> </html>
9.代理模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>代理模式</title> <script type=text/javascript> /** * 代理模式(proxy):代理也是对象,它的目的就是为了节制(控制)对本体对象的访问 * 代理对象和另一个对象(实体对象)实现的是同样的接口,实际上工作还是实体在做 */ var Book=function(id,title,author){ this.id=id; this.title=title; this.author=author; }; //图书馆(本体对象,实例化图书馆需要消耗很多的资源) var Library=function(books){ this.books=books; } Library.prototype={ constructor:Library, addbook:function(book){ this.books[book.id]=book; }, findbook:function(id){ if(this.books[id]){ return this.books[id]; } return null; }, checkoutbook:function(id){ return this.findbook(id); }, returnbook:function(book){ this.books[book.id]=book; } } //图书馆的代理对象 var LibraryProxy=function(books){ this.books=books; this.libray=null;//定义一个空对象 } LibraryProxy.prototype={ constructor:LibraryProxy, //初始化Library initializeLibrary:function(){ if(this.libray==null){ this.libray=new Library(this.books); } }, addbook:function(book){ this.initializeLibrary(); this.libray.books[book.id]=book; }, findbook:function(id){ this.initializeLibrary(); if(this.libray.books[id]){ return this.libray.books[id]; } return null; }, checkoutbook:function(id){ this.initializeLibrary(); return this.libray.findbook(id); }, returnbook:function(book){ this.initializeLibrary(); this.libray.books[book.id]=book; } } var proxy=new LibraryProxy({ '1':new Book('1','c#','y'), '2':new Book('2','js','z'), }); alert(proxy.findbook('1').title);//c# </script> </head> <body> </body> </html>
10.单例模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>单例模式</title> <script type=text/javascript> //单例模式(singliton) //1.简单单例 var Singliton={ name:'yjq', age:'23', sayHello:function(){ alert('hello'); } }; alert(Singliton.name); Singliton.sayHello(); //另一个作用 :划分命令空间 //2.借用闭包创建单例:闭包主要的目的 保护数据 //命名空间 var YJQ ={}; YJQ.Singleton=(function(){ //添加自己的私有成员 var name = 'yjq'; var age ='23'; //把块级作用域里的执行结果赋值给单体对象 return { name:name, age:age, sayHello:function(){ alert('hello'); } }; })(); alert(YJQ.Singleton.name); YJQ.Singleton.sayHello(); //3.惰性单例(常用) var Ext={}; Ext.Base=(function(){ //私有变量 控制返回的单例对象 var uniqInstance; //undefined //需要一个构造器 init初始化单例对象的方法 function init(){ //私有成员变量 var name = 'yjq'; var age = '23'; var sayHello = function(){ alert('hello'); } return { name: name, age: age, sayHello: sayHello } } return { getInstance :function(){ if(!uniqInstance){//如果不存在 创建单例对象 uniqInstance = init(); } return uniqInstance; } }; })(); Ext.Base.getInstance().sayHello(); //4.分支单例(判断程序的分支)(常用) var def =true; Ext.More =(function(){ var objA ={}; //ff var objB ={}; //ie return (def)?ojbA:ojbB; })(); </script> </head> <body> </body> </html>