面向对象小结
2015-10-09 21:03
911 查看
面向对象之构造函数
结构:function 构造函数() { this.属性 = valve } 构造函数.prototype.方法 = function() { } var 对象1 = new 构造函数(); 对象1.方法(); eg : function Person() { this.name = 'bob'; } Person.prototype.sayName = function() { alert(this.name) } var p1 = new Person(); alert(p1.name); // bob p1.sayName(); //bob tips : 当`new`去调用一个函数,函数中的`this`就是`new`创建出来的对象,而且函数的返回值就是`this`,也就是对象(隐式返回)
如何改写面向对象的选项卡
原则:先写出普通的方法,再改成面向对象的写法。
1、普通的方法
(1)尽量不要出现函数嵌套函数
(2)可以有全局变量
(3)把onload中不是赋值的语句放到单独函数中。
2、改成面向对象
(1)全局变量就是属性
(2)函数就是方法
(3)onload中创建对象
(4)改this指向问题,尽量让this指向对象
eg: <body> <input type="button" value="选项1" class="active"> <input type="button" value="选项2"> <input type="button" value="选项3"> <div class="box1" style="display:block">内容一</div> <div class="box2">内容二</div> <div class="box3">内容三</div> </body> /*面向对象写法*/ window.onload = function(){ var t1=new Tab('tab1'); t1.init(); t1.autoPlay(2000); var t2=new Tab('tab2'); //新弄的一个 t2.init(); t2.autoPlay(1000); } function Tab(id) { this.oTaba=document.getElementById(id); this.aInp=this.oTaba.getElementsByTagName('input'); this.aDiv=this.oTaba.getElementsByTagName('div'); this.iNow=0; } Tab.prototype.init = function() { var This=this; for (var i = 0; i < this.aInp.length; i++) { this.aInp[i].index=i; this.aInp[i].onclick=function() { console.log(this) This.change(this); }; }; } Tab.prototype.change = function(obj) { for (var i = 0; i < this.aInp.length; i++) { this.aInp[i].className=''; this.aDiv[i].className=''; }; obj.className='active'; this.aDiv[obj.index].className='active'; }; Tab.prototype.autoPlay = function (time){ var This=this; setInterval(function(){ This.iNow++; if (This.iNow == This.aInp.length) { This.iNow=0; }; for (var i = 0; i < This.aInp.length; i++) { This.aInp[i].className=''; This.aDiv[i].className=''; }; This.aInp[This.iNow].className='active'; This.aDiv[This.iNow].className='active'; },time) }
包装对象
1、系统对象也是基于原型prototype的程序
2、基本类型都有自己对应的包装对象 : String 、 Number、 Boolean(除了null 和 undefined)
var str = 'abc'; str.charAt(0); //基本类型会找到对应的包装对象,包装对象把所有的属性和方法给了基本类型,然后包装对象消失
原型链
1 、实例对象与原型之间的链接,叫做原型链。最外层是Object.prototype2、proto(原型链,隐式连接) ,先找普通方法,再找原型。最后找最外层
3、Object对象类型时原型链的最外层
面向对象的一些属性和方法
1、hasOwnPrototype(); 看是不是自身下面的属性和方法,不会查找原型下面的属性和方法2、constructor : 查看对象的构造函数。
function Person() { } Person.prototype.name = 'Bob'; Person.prototype.age = 100; Person.prototype.constructor = Person //自动生成,不要手动添加 var p1 = new Person(); alert( p1.constructor ) //function Person() {} /** tips :写成对象字面量时 指向问题 **/ function Person() { } Person.prototype = { name : 'Bob', age : 100 } var p1 = new Person(); alert( p1.constructor ) //function Object() {[native code]} 解决办法 :手动修改指向 Person.prototype = { constructor : Person, name : 'Bob', age 1629e : 100 }
3、for in
找不到系统自带的属性,比如constructor,自己写constructor也找不到
4、instanceof : 运算符,对象与构造函数在原型链上是否有联系,任何对象instanceof Object 都是true
5、toString : Object上的方法,也可用作类型的判断(最靠谱);系统对象下面都是自带的,写在构造函数prototype下的,自己写的都是通过原型链找Object下面的(Object.prototype)
var arr = []; alert( Object.prototype.toString.call(arr) ) // '[object Array]'
继承
概念 : 在原有对象的基础上,略作修改,得到一个新的对象,并且不影响原有对象常用的继承方式:
属性的继承 : call方法的继承 :for in (浅复制与深复制)
function Person (name,age) { this.name = name; this.age = age; } Person.prototype.sayName = function () { alert(this.name) } Person.prototype.sayAge = function () { alert(this.age) } function Start (name, age, job) { Person.call(this,name,age); //属性继承 this.job = job; } extend(Start.prototype,Person.prototype); //方法继承,浅复制 Start.prototype.sayJob = function () { alert(this.job); } function extend (obj1,obj2) { for (var attr in obj2) { obj1[attr] = obj2[attr] } } var s1 = new Start('黄晓明',20,'stat'); s1.sayAge(); s1.sayJob(); var p1 = new Person('小球',100); alert(p1.name);
继承的其他方式
1、类式继承 : 利用构造函数继承的方式类 : js是没用类概念的,把构造函数看做是类
子构造函数.prototype = new 父构造函数 //继承的属性和方法
存在的问题 : ,
(1)constructor的指向问题 (需手动指向)
(2)实例1 的属性方法修改会影响 实例2 (想想原型链的查找 , 属性和方法分开继承)
function Person1(name) { this.name = name; this.job = 'worker'; } Person1.prototype.sayName = function() { alert(this.name); } Person1.prototype.sayJob = function() { alert(this.job); } function Person2(name,age) { Person1.call(this,name,age); //继承属性 this.age = age; this.job = 'student'; } /** 下面四行重点,前三行继承方法,第四行解决指向问题 **/ var F = function(){}; F.prototype = Person1.prototype; Person2.prototype = new F(); Person2.prototype.constructor = Person2; Person2.prototype.sayAge = function() { alert(this.age); } var p1 = new Person2('小强','255'); alert(p1.name); p1.sayName(); p1.sayAge();
2、原型继承 : 借助原型来实现对象继承对象
function Person() { this.name = 'bob'; this.job = 'worker'; } Person.prototype.sayName = function() { alert(this.name); } Person.prototype.sayJob = function() { alert(this.job); } var p2 = cloneObj(Person); p2.name = 'xiaohua'; p2.age = 289; p2.sayName(); function cloneObj(obj) { var F = function(){}; F.prototype = obj.prototype; return new F(); }
组件开发
组件开发 : 多组对象,像兄弟之间的关系,代码复用(UI组件,功能组件)默认参数 : 写在构造函数中,普通方法
配置参数 : 写在参数中
//组件开发弹出框 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> * {margin: 0;padding: 0} .loading1 {border: 1px solid #000;position: absolute;left: 0;top: 0;z-index: 10} .loading1 p {width: 100%;height: 40px;background: #0cf} .loading1 p .close {float: right;} #mark {width: 100%; height: 100%; position: absolute; left: 0; top: 0; background: rgba(0,0,0,.4);} </style> <script type="text/javascript"> window.onload = function() { var aInp = document.getElementsByTagName('input'); aInp[0].onclick = function() { var l1 = new Load(); l1.init({ iNow : 1, drag : true }) } aInp[1].onclick = function() { var l2 = new Load(); l2.init({ iNow : 2, w : '100', h : '400', dir : 'right', title : '广告' }); } aInp[2].onclick = function() { var l3 = new Load(); l3.init({ iNow : 3, title : '推广', mark : true }) } } function Load() { this.obj = null; this.mark = null; this.disX = 0; this.disY = 0; this.settings = { w : '300', h : '300', dir : 'center', title : '登陆', mark : false, toDown : function(){}, toMove : function(){}, toUp : function(){} } } Load.prototype.json = {}; // 处理多次点击多次添加的问题 Load.prototype.init = function(opt) { var This = this; extend(this.settings , opt); if (this.json[opt.iNow] == undefined) { this.json[opt.iNow] = true; } if (this.json[opt.iNow]) { this.cresteData(); this.json[opt.iNow] = false; }; } Load.prototype.cresteData = function() { this.obj = document.createElement('div'); this.obj.className = 'loading1'; this.obj.innerHTML = '<p><span>登陆</span><span class="close">X</span></p>'; document.body.appendChild(this.obj); this.fnMark(); this.setData(); this.drag(); this.fnClose(); } Load.prototype.setData = function() { var oTitle = this.obj.getElementsByTagName('span')[0]; this.obj.style.width = this.settings.w + 'px'; this.obj.style.height = this.settings.h + 'px'; oTitle.innerHTML = this.settings.title; if ( this.settings.dir == 'center' ) { this.obj.style.left = ( viewWidth() - this.obj.offsetWidth )/2 + 'px'; this.obj.style.top = ( viewHeight() - this.obj.offsetHeight )/2 + 'px'; }else if ( this.settings.dir == 'right' ) { this.obj.style.left = ( viewWidth() - this.obj.offsetWidth ) + 'px'; this.obj.style.top = ( viewHeight() - this.obj.offsetHeight ) + 'px'; } } Load.prototype.fnClose = function() { var This = this; var oClose = this.obj.getElementsByTagName('span')[1]; oClose.onclick = function (){ document.body.removeChild( This.obj ); This.json[This.settings.iNow] = true; console.log( This.settings ) if ( This.settings.mark ) { document.body.removeChild( This.mark ); }; } } Load.prototype.fnMark = function() { if (this.settings.mark == true ) { this.mark = document.createElement('div'); this.mark.id = 'mark'; document.body.appendChild(this.mark) }; } Load.prototype.drag = function (){ var This = this; if (this.settings.drag) { this.obj.onmousedown = function(ev) { var ev = ev || window.event; This.fnDown(ev); // This.settings.toDown(); return false; } }; } Load.prototype.fnDown = function(ev) { var This=this; this.disX = ev.clientX - this.obj.offsetLeft; this.disY = ev.clientY - this.obj.offsetTop; document.onmousemove = function(ev) { var ev = ev || window.event; This.fnMove(ev); // This.default.toMove(); } document.onmouseup = function(ev) { var ev = ev || window.event; This.fnUp(); // This.default.toUp(); } } Load.prototype.fnMove = function(ev) { var iLeft = ev.clientX - this.disX; var iTop = ev.clientY - this.disY; if (iLeft < 0) { iLeft = 0; }else if (iLeft > viewWidth()-this.obj.offsetWidth) { iLeft = viewWidth()-this.obj.offsetWidth; } this.obj.style.left = iLeft + 'px'; this.obj.style.top = iTop + 'px'; } Load.prototype.fnUp = function() { document.onmousemove = null; document.onmouseup = null; } function extend (obj1,obj2) { for(var attr in obj2){ obj1[attr] = obj2[attr] } } function viewWidth() { return document.documentElement.clientWidth; } function viewHeight() { return document.documentElement.clientHeight; } </script> </head> <body> <input type="button" value="1" /> <input type="button" value="2" /> <input type="button" value="3" /> <!-- <div class="loading1"> <p><span>登陆</span><span class="close">X</span></p> </div> --> <!-- <div id="mark"></div> --> </body> </html>
//组件开发选项卡 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> #tab1,#tab2,#tab3 {width: 300px;height: 300px;} #tab1 div,#tab2 div,#tab3 div {width: 300px;height: 200px;border: 1px solid #000;display: none;} input {width: 60px;height: 30px;} .active {background: red} </style> <script type="text/javascript"> window.onload = function() { var t1 = new Tab(); t1.init({ id : 'tab1', events : 'onclick' }); var t2 = new Tab(); t2.init({ id : 'tab2', events : 'onmouseover' }) t2.delay(); var t3 = new Tab(); t3.init({ id : 'tab3', events : 'onmouseover' }); t3.setIndex(1); } function Tab() { this.obj = null; this.aBtn = null; this.aBox = null; this.timer = null; this.settings = { events : 'onclick' } } Tab.prototype.init = function(opt) { extend(this.settings,opt) this.obj = document.getElementById(opt['id']); this.aBtn = this.obj.getElementsByTagName('input'); this.aBox = this.obj.getElementsByTagName('div'); this.change(); } Tab.prototype.change = function() { var This = this; for (var i = 0; i < This.aBtn.length; i++) { This.aBtn[i].index = i; This.aBtn[i][This.settings.events] = function() { var _this = This; for (var i = 0; i < _this.aBtn.length; i++) { _this.aBtn[i].className = ''; _this.aBox[i].style.display = 'none'; }; this.className = 'active'; _this.aBox[ this.index ].style.display = 'block'; } }; } Tab.prototype.delay = function() { var This = this; for (var i = 0; i < this.aBtn.length; i++) { this.aBtn[i].index = i; this.aBtn[i].onmouseout = function() { clearTimeout(This.timer); } this.aBtn[i][this.settings.events] = function() { var _index = this.index; This.timer = setTimeout(function(){ toDelay(_index) },200) } } function toDelay(index) { for (var i = 0; i < This.aBtn.length; i++) { This.aBtn[i].className = ''; This.aBox[i].style.display = 'none'; }; This.aBtn[index].className = 'active'; This.aBox[index ].style.display = 'block'; } } Tab.prototype.setIndex = function(index) { for (var i = 0; i < this.aBtn.length; i++) { this.aBtn[i].className = ''; this.aBox[i].style.display = 'none' }; this.aBtn[index].className = 'active'; this.aBox[index].style.display = 'block' } function extend(obj1,obj2) { for(var attr in obj2) { obj1[attr] = obj2[attr] } } </script> </head> <body> <div id="tab1"> <input type="button" value="1" class="active" /> <input type="button" value="2" /> <input type="button" value="3" /> <div style="display: block;">111111111</div> <div>22222222</div> <div>33333333</div> </div> <div id="tab2"> <input type="button" value="1" class="active" /> <input type="button" value="2" /> <input type="button" value="3" /> <div style="display: block;">111111111</div> <div>22222222</div> <div>33333333</div> </div> <div id="tab3"> <input type="button" value="1" class="active" /> <input type="button" value="2" /> <input type="button" value="3" /> <div style="display: block;">111111111</div> <div>22222222</div> <div>33333333</div> </div> </body> </html>
自定义事件 :
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript"> window.onload = function () { var oDiv = document.getElementById('div1'); var oSpan = document.getElementById('span1'); bindEvent(oDiv,'click',function(){ alert(1) }); bindEvent(oDiv,'click',function(){ alert(2) }); bindEvent(oSpan,'show',function(){ alert(3) }); bindEvent(oSpan,'show',function(){ alert(4) }); bindEvent(oSpan,'hide',function(){ oSpan.style.background = 'red'; }); fireEvenet(oSpan,'hide') function bindEvent(obj,events,fn) { //不完善,比如this指向 // obj :图书馆的楼层 // events :图书的分类(书架) // fn :一本书 obj.listener = obj.listener || {}; obj.listener[events] = obj.listener[events] || []; obj.listener[events].push(fn); if (obj.addEventListener) { obj.addEventListener(events,fn,false) }else{ obj.attachEvent('on'+events,fn) } } function fireEvenet(obj,events) { //主动触发函数 for (var i = 0; i < obj.listener[events].length; i++) { console.log(obj.listener[events]) obj.listener[events][i](); }; } } </script> </head> <body> <div id="div1">div</div> <span id="span1">span</span> </body> </html>
相关文章推荐
- PostgreSQL教程(三):表的继承和分区表详解
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#中面向对象编程机制之多态学习笔记
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- 浅析Ruby中继承和消息的相关知识
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- C#面向对象特征的具体实现及作用详解
- C# 面向对象的基本原则
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- 浅谈对c# 面向对象的理解
- C++中拷贝构造函数的应用详解
- C++实现不能被继承的类实例分析
- Ruby面向对象编程详解
- 构造函数不能声明为虚函数的原因及分析
- 深入讲解C++中的构造函数
- C++类成员构造函数和析构函数顺序示例详细讲解
- c++基础语法:构造函数与析构函数
- Python3 面向对象概述