JavaScript 面向对象(二) —— 案例篇
案例——面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿)。
下面是一个简单的选项卡,也是我们常见的面向过程的创建形式。
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 #tabBox input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 #tabBox .active { 10 background: #E9D4D4; 11 } 12 #tabBox div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <script> 24 window.οnlοad=function(){ 25 var tabBox = document.getElementById('tabBox'); 26 var tabBtn = tabBox.getElementsByTagName('input'); 27 var tabDiv = tabBox.getElementsByTagName('div'); 28 29 for(var i=0;i<tabBtn.length;i++){ 30 tabBtn[i].index = i; 31 tabBtn[i].onclick = function (){ 32 for(var j=0;j<tabBtn.length;j++){ 33 tabBtn[j].className=''; 34 tabDiv[j].style.display='none'; 35 } 36 this.className='active'; 37 tabDiv[this.index].style.display='block'; 38 }; 39 } 40 }; 41 </script> 42 </head> 43 44 <body> 45 <div id="tabBox"> 46 <input type="button" value="游戏" class="active" /> 47 <input type="button" value="旅行" /> 48 <input type="button" value="音乐" /> 49 <div style="display:block;">GTA5、孤岛惊魂</div> 50 <div>澳大利亚、西藏</div> 51 <div>暗里着迷、一生有你</div> 52 </div> 53 </body> 54 </html>
效果:
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面来一步步改成面向对象的形式。
1.首先将嵌套的函数拿到window.onload外面,不能有函数嵌套,可以有全局变量。如下:所有的改写最终效果都不变。
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 #tabBox input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 #tabBox .active { 10 background: #E9D4D4; 11 } 12 #tabBox div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <script> 24 //将在嵌套函数里的变量提取到全局中 25 var tabBtn = null; 26 var tabDiv = null; 27 28 window.onload = function(){ 29 var tabBox = document.getElementById('tabBox'); 30 tabBtn = tabBox.getElementsByTagName('input'); 31 tabDiv = tabBox.getElementsByTagName('div'); 32 33 for(var i=0;i<tabBtn.length;i++){ 34 tabBtn[i].index = i; 35 //此处调用函数即可 36 tabBtn[i].onclick = clickBtn; 37 } 38 }; 39 40 //将嵌套函数提取到全局中 41 function clickBtn(){ 42 for(var j=0;j<tabBtn.length;j++){ 43 tabBtn[j].className=''; 44 tabDiv[j].style.display='none'; 45 } 46 this.className='active'; 47 tabDiv[this.index].style.display='block'; 48 }; 49 50 </script> 51 </head> 52 53 <body> 54 <div id="tabBox"> 55 <input type="button" value="游戏" class="active" /> 56 <input type="button" value="旅行" /> 57 <input type="button" value="音乐" /> 58 <div style="display:block;">GTA5、孤岛惊魂</div> 59 <div>澳大利亚、西藏</div> 60 <div>暗里着迷、一生有你</div> 61 </div> 62 </body> 63 </html>
2.将全局的变量变为对象的属性,全局的函数变为对象的方法;将window.onload里的代码提取到一个构造函数里面,在window.onload里创建对象即可;(下面的代码执行起来是有问题的)。
这里必须注意:在构造函数Tab里的this跟之前this所代表的是不同的(此处是通过new来创建对象的);在上面的示例中,this指的是调用者;在构造函数里,this指向的是var tab = new Tab() ,即tab这个对象,注意是对象。
说一下这段代码的问题:我们在Tab的原型上添加clickBtn方法后,clickBtn方法里的this本应该是指向var tab = new Tab()的,但是我们在第44行将clickBtn添加给了this.tabBtn[i],即input按钮,clickBtn的所属由Tab对象变成了input按钮(第49行)。
clickBtn的所属变成input按钮后,那么clickBtn里的this指向按钮,那再来看clickBtn里的代码,this.tabBtn、this.tabDiv,input按钮里有这两个属性吗?没有,所以会出错!
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 #tabBox input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 #tabBox .active { 10 background: #E9D4D4; 11 } 12 #tabBox div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <script> 24 25 window.onload = function(){ 26 var tab = new Tab("tabBox"); 27 } 28 29 /** 30 * 将之前window.onload里的代码提到一个构造函数里 31 * [可以将这个Tab构造函数想象成一个Tab类] 32 * @param {Object} id:选项卡id以参数的形式传入 33 */ 34 function Tab(id){ 35 var tabBox = document.getElementById(id); 36 //将之前的全局变量变为对象的属性 37 this.tabBtn = tabBox.getElementsByTagName('input'); 38 this.tabDiv = tabBox.getElementsByTagName('div'); 39 40 for(var i=0;i<this.tabBtn.length;i++){ 41 this.tabBtn[i].index = i; 42 43 //此处这种方式调用函数,已经将clickBtn的所属变成this.tabBtn[i] 44 this.tabBtn[i].onclick = this.clickBtn; 45 } 46 }; 47 //将之前的全局函数添加到构造函数的原型里,作为对象的一个方法 48 Tab.prototype.clickBtn = function(){ 49 alert(this); //HTMLInputElement 50 for(var j=0;j<this.tabBtn.length;j++){ 51 this.tabBtn[j].className=''; 52 this.tabDiv[j].style.display='none'; 53 } 54 this.className='active'; 55 this.tabDiv[this.index].style.display='block'; 56 }; 57 58 </script> 59 </head> 60 61 <body> 62 <div id="tabBox"> 63 <input type="button" value="游戏" class="active" /> 64 <input type="button" value="旅行" /> 65 <input type="button" value="音乐" /> 66 <div style="display:block;">GTA5、孤岛惊魂</div> 67 <div>澳大利亚、西藏</div> 68 <div>暗里着迷、一生有你</div> 69 </div> 70 </body> 71 </html>
将clickBtn赋给input按钮后,方法内的this也指向了input按钮:执行第49行代码的效果
3.将clickBtn的调用放在一个函数里,这样就不会改变clickBtn的所属了。
看第41-47行,注意在function里需要用到外部保存的变量_this。再看第52行,此时弹出的是一个Object,说明clickBtn的所属关系没变,还是Tab对象。
但是还有另一个问题,此时clickBtn里的this指向对象,那么看第57、58行中this.className、this.index,此处的this指的是tab对象,那么对象中有这两个属性吗?没有,还会出错!
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 #tabBox input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 #tabBox .active { 10 background: #E9D4D4; 11 } 12 #tabBox div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <script> 24 25 window.onload = function(){ 26 var tab = new Tab("tabBox"); 27 } 28 29 /** 30 * 选项卡 31 * @param {Object} id:选项卡id 32 */ 33 function Tab(id){ 34 var tabBox = document.getElementById(id); 35 36 this.tabBtn = tabBox.getElementsByTagName('input'); 37 this.tabDiv = tabBox.getElementsByTagName('div'); 38 39 for(var i=0;i<this.tabBtn.length;i++){ 40 this.tabBtn[i].index = i; 41 //将this保存成一个变量,就可以在下面代码中调用对象的方法了 42 var _this = this; 43 //此处这种方式调用函数,就不会改变clickBtn方法的所属关系 44 this.tabBtn[i].onclick = function(){ 45 //注意此处不能直接使用this,this指向this.tabBtn[i] 46 _this.clickBtn(); 47 }; 48 } 49 }; 50 //点击选项卡按钮 51 Tab.prototype.clickBtn = function(){ 52 alert(this); //Object 53 for(var j=0;j<this.tabBtn.length;j++){ 54 this.tabBtn[j].className=''; 55 this.tabDiv[j].style.display='none'; 56 } 57 this.className='active'; 58 this.tabDiv[this.index].style.display='block'; 59 }; 60 61 </script> 62 </head> 63 64 <body> 65 <div id="tabBox"> 66 <input type="button" value="游戏" class="active" /> 67 <input type="button" value="旅行" /> 68 <input type="button" value="音乐" /> 69 <div style="display:block;">GTA5、孤岛惊魂</div> 70 <div>澳大利亚、西藏</div> 71 <div>暗里着迷、一生有你</div> 72 </div> 73 </body> 74 </html>
4. 以参数的形式将点击的按钮传入clickBtn中,看第44行代码,以及54,55行代码
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 #tabBox input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 #tabBox .active { 10 background: #E9D4D4; 11 } 12 #tabBox div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <script> 24 25 window.onload = function(){ 26 var tab = new Tab("tabBox"); 27 } 28 29 /** 30 * 选项卡 31 * @param {Object} id:选项卡id 32 */ 33 function Tab(id){ 34 var tabBox = document.getElementById(id); 35 36 this.tabBtn = tabBox.getElementsByTagName('input'); 37 this.tabDiv = tabBox.getElementsByTagName('div'); 38 39 for(var i=0;i<this.tabBtn.length;i++){ 40 this.tabBtn[i].index = i; 41 var _this = this; 42 this.tabBtn[i].onclick = function(){ 43 //注意参数this代表的是this.tabBtn[i],即input按钮 44 _this.clickBtn(this); 45 }; 46 } 47 }; 48 //将点击的按钮以参数的形式传入 49 Tab.prototype.clickBtn = function(btn){ 50 for(var j=0;j<this.tabBtn.length;j++){ 51 this.tabBtn[j].className=''; 52 this.tabDiv[j].style.display='none'; 53 } 54 btn.className='active'; 55 this.tabDiv[btn.index].style.display='block'; 56 }; 57 58 </script> 59 </head> 60 61 <body> 62 <div id="tabBox"> 63 <input type="button" value="游戏" class="active" /> 64 <input type="button" value="旅行" /> 65 <input type="button" value="音乐" /> 66 <div style="display:block;">GTA5、孤岛惊魂</div> 67 <div>澳大利亚、西藏</div> 68 <div>暗里着迷、一生有你</div> 69 </div> 70 </body> 71 </html>
5.最终版 —— 将代码提取到一个单独的js文件中,在用的时候引入即可。一般花大时间去写一个面向对象的程序,就是为了能够复用,以及方便的使用。
tab.js
1 /**2 * 选项卡3 * @param {Object} id 选项卡id4 */5 function Tab(id){6 var tabBox = document.getElementById(id);7 this.tabBtn = tabBox.getElementsByTagName('input');8 this.tabDiv = tabBox.getElementsByTagName('div');9 10 for(var i=0;i<this.tabBtn.length;i++){ 11 this.tabBtn[i].index = i; 12 var _this = this; 13 this.tabBtn[i].onclick = function(){ 14 _this.clickBtn(this); 15 }; 16 } 17 }; 18 /** 19 * 为Tab原型添加点击选项卡方法 20 * @param {Object} btn 点击的按钮 21 */ 22 Tab.prototype.clickBtn = function(btn){ 23 for(var j=0;j<this.tabBtn.length;j++){ 24 this.tabBtn[j].className=''; 25 this.tabDiv[j].style.display='none'; 26 } 27 btn.className='active'; 28 this.tabDiv[btn.index].style.display='block'; 29 };
使用:tab.html 可以看到使用的时候,就可以很简单的创建两个选项卡出来了。
1 <!DOCTYPE html>2 <html>3 <head>4 <style>5 .tab input {6 background: #F6F3F3;7 border: 1px solid #FF0000;8 }9 .tab .active { 10 background: #E9D4D4; 11 } 12 .tab div { 13 width:300px; 14 height:250px; 15 display:none; 16 padding: 10px; 17 background: #E9D4D4; 18 border: 1px solid #FF0000; 19 } 20 </style> 21 <meta charset="utf-8" /> 22 <title>选项卡</title> 23 <!-- 引入tab.js --> 24 <script type="text/javascript" src="../js/tab.js" ></script> 25 <script> 26 27 window.onload = function(){ 28 var tab1 = new Tab("tabBox1"); 29 30 var tab2 = new Tab("tabBox2"); 31 } 32 33 </script> 34 </head> 35 36 <body> 37 <div class="tab" id="tabBox1"> 38 <input type="button" value="游戏" class="active" /> 39 <input type="button" value="旅行" /> 40 <input type="button" value="音乐" /> 41 <div style="display:block;">GTA5、孤岛惊魂</div> 42 <div>澳大利亚、西藏</div> 43 <div>暗里着迷、一生有你</div> 44 </div> 45 <br /> 46 <div class="tab" id="tabBox2"> 47 <input type="button" value="技术" class="active" /> 48 <input type="button" value="工具" /> 49 <input type="button" value="网站" /> 50 <div style="display:block;">Java、Spring</div> 51 <div>Eclipse、HBuilder</div> 52 <div>博客园、CSD</div> 53 </div> 54 </body> 55 </html>
效果:
看的有点晕吧,一定要好好理解JS面向对象中的this。js中面向对象大部分时候出问题就是出在this的处理上,需要注意。
面向过程:简洁、美观、容易维护;
面向对象:容易出错、混乱、难以维护;面向对象相对面向过程来说,写代码的时候麻烦些,但是用起来很方便,面向过程则相反。
开发面向对象的程序需要有一个好的面向对象的思维,即将具体对象抽象成一个构造函数的过程。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来简单总结一下JS面向对象中的this,this一般会在两种情况下出问题,一是使用定时器、二是事件,从上面的例子中也可以看出来。注意下面的说法是在构造函数里哦,其它情况下,this指向的是调用者。
可以看到效果没有将姓名显示出来,其实看到这里原因应该很清楚了,就是第14行代码中this.name,此处的this指向谁?指向window,因为setInterval是属于window的。
1 <!DOCTYPE html>2 <html>3 <meta charset="UTF-8" />4 <head>5 <script>6 7 function Person(name){8 this.name = name;9 //定时器 10 setInterval(this.showName, 3000); 11 } 12 Person.prototype.showName = function(){ 13 alert(this); //window 14 alert("姓名:"+this.name); 15 } 16 17 var p1 = new Person("jiangzhou"); 18 19 </script> 20 </head> 21 </html>
效果:
解决办法:上面例子中已经列出来了,就是用一个function将要执行的代码包起来,使其所属关系不会发生变化,注意function里调用方法时使用的是外部变量'_this'。事件的处理在上面的例子中已经说明了。
1 <!DOCTYPE html>2 <html>3 <meta charset="UTF-8" />4 <head>5 <script>6 7 function Person(name){8 this.name = name;9 10 var _this = this; 11 12 setInterval(function(){ 13 _this.showName(); 14 }, 3000); 15 } 16 Person.prototype.showName = function(){ 17 alert(this); //[Object Object] 18 alert("姓名:"+this.name); //姓名:jianghzou 19 } 20 21 var p1 = new Person("jiangzhou"); 22 23 </script> 24 </head> 25 </html>
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再附上一个案例 —— 拖拽
原始的面向过程代码:
1 <!DOCTYPE html>2 <html>3 <head>4 <meta charset="UTF-8">5 <style>6 #box {7 width: 100px; 8 height: 100px; 9 background: blue; 10 position: absolute; 11 } 12 </style> 13 <title>拖拽</title> 14 <script> 15 var oBox=null; 16 var disX=0; 17 var disY=0; 18 19 window.οnlοad=function(){ 20 oBox=document.getElementById('box'); 21 22 oBox.οnmοusedοwn=fnDown; 23 }; 24 //鼠标按下事件 25 function fnDown(ev){ 26 var oEvent = ev||event; 27 disX = oEvent.clientX - oBox.offsetLeft; 28 disY = oEvent.clientY - oBox.offsetTop; 29 30 document.onmousemove = fnMove; 31 document.onmouseup = fnUp; 32 } 33 //鼠标移动事件 34 function fnMove(ev){ 35 var oEvent=ev||event; 36 37 oBox.style.left = oEvent.clientX - disX + 'px'; 38 oBox.style.top = oEvent.clientY - disY + 'px'; 39 } 40 //鼠标抬起事件 41 function fnUp(){ 42 document.onmousemove = null; 43 document.onmouseup = null; 44 } 45 </script> 46 </head> 47 48 <body> 49 <div id="box"></div> 50 </body> 51 </html>
下面是面向对象的代码
drag.js
1 /**2 * 拖拽3 * @param {Object} id div的id4 */5 function Drag(id){6 this.oBox = document.getElementById(id);7 this.disX = 0;8 this.disY = 0;9 10 var _this = this; 11 12 this.oBox.onmousedown = function(){ 13 _this.fnDown(); 14 } 15 } 16 //鼠标按下 17 Drag.prototype.fnDown = function(ev){ 18 var oEvent = ev || event; 19 20 this.disX = oEvent.clientX - this.oBox.offsetLeft; 21 this.disY = oEvent.clientY - this.oBox.offsetTop; 22 23 var _this = this; 24 25 document.onmousemove = function(){ 26 _this.fnMove(); 27 }; 28 document.onmouseup = function(){ 29 _this.fnUp(); 30 }; 31 } 32 //鼠标移动 33 Drag.prototype.fnMove = function(ev){ 34 var oEvent= ev || event; 35 36 this.oBox.style.left = oEvent.clientX - this.disX + 'px'; 37 this.oBox.style.top = oEvent.clientY - this.disY + 'px'; 38 } 39 //鼠标抬起 40 Drag.prototype.fnUp = function(){ 41 document.onmousemove = null; 42 document.onmouseup = null; 43 }
drag.html
1 <!DOCTYPE html>2 <html>3 <head>4 <meta charset="UTF-8">5 <style>6 div {7 position: absolute;8 }9 </style> 10 <title>拖拽</title> 11 <script type="text/javascript" src="../js/drag.js" ></script> 12 <script> 13 window.onload = function(){ 14 var drag1 = new Drag("box1"); 15 16 var drag1 = new Drag("box2"); 17 }; 18 </script> 19 </head> 20 21 <body> 22 <div id="box1" style="background: red;width: 200px;height: 200px;"></div> 23 24 <div id="box2" style="background: blue;width: 100px;height: 300px;"></div> 25 </body> 26 </html>
效果:
转载于:https://www.cnblogs.com/zhangrui09/p/8507462.html
JavaScript 面向对象(二) —— 案例篇相关推荐
- Javascript面向对象二
Javascript面向对象二 可以通过指定原型属性来对所有的对象指定属性, Object.prototype.name="zhangsan"; Object.prototype. ...
- javascript面向对象系列第一篇——构造函数和原型对象
前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是 ...
- JavaScript 面向对象游戏案例:贪吃蛇
面向对象游戏案例:贪吃蛇 案例相关源码以上传到 GitHub :https://github.com/sunna1/snake 案例介绍 案例目标 游戏的目的是用来体会js高级语法的使用 不需要具备抽 ...
- JavaScript 面向对象(二)——案列篇
看案例前可以先看看基础篇:JavaScript 面向对象(一)--基础篇 案例--面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿). ...
- JavaScript 面向对象编程(二) —— 构造函数 / 原型 / 继承 / ES5 新增方法
本篇为 JavaScript 进阶 ES6 系列笔记第二篇,将陆续更新后续内容.参考:JavaScript 进阶面向对象 ES6 :ECMAScript 6 入门 : Javascript 继承机制的 ...
- JavaScript进阶面向对象ES6整合篇
整合篇整体内容比较多,详细点可以查询目录 文章目录 一.JavaScript面向对象 1.面向对象编程介绍 2.ES6中的类和对象 3.类的继承 4.案例:面向对象案例 二.构造函数和原型 1. 构造 ...
- JavaScript 时间戳(互相转换)(自定义格式)- 案例篇
文章目录 JavaScript 时间戳(自定义格式)转换 - 案例(含代码) 一.时间戳(`s` 秒) 1. `转化顺序` · 说明: 2. 效果图: 3. 代码: 二.时间戳(`ms` 毫秒) 1. ...
- JavaScript 基础知识 - DOM篇(二)
7. 节点操作 7.1 节点的属性 节点分类: 标签节点 文本节点 属性节点 注释节点 节点常用的属性: nodeType:节点的类型 nodeName:节点名称 nodeValue:节点值 常见的节 ...
- JavaScript 基础知识 - 入门篇(二)
11. 函数 11.1 函数的基础知识 为什么会有函数? 在写代码的时候,有一些常用的代码需要书写很多次,如果直接复制粘贴的话,会造成大量的代码冗余: 函数可以封装一段重复的javascript代码, ...
最新文章
- day29Struts 类型转换和自定义类型转换,input视图
- Spring Cloud入门,看这篇就够了!
- 怎样求信号中的RMS值?
- 循序渐进之Maven(4) - 第一个SpringMVC项目
- 03-13 微信小程序自动化测试
- pandas知识点(汇总和计算描述统计)
- 用python导出pptx中每一页的标题
- ECS Linux 服务器解除ssh登陆后被锁定或暂停输入输出的终端
- 46多项式01——一元多项式和运算
- Maven下载JasperReports报错Could not find artifact com.lowagie:itext:pom:2.1.7.js6 in alimaven
- Flexbox 基础知识
- Privacy-Preserving Deep Learning via Additively Homomorphic Encryption
- 对拉勾网数据分析职位做数据分析
- 快速确定针式打印机故障部位方法
- 魔法少女 LJJ——线段树
- 嗖嗖~您有一份上云计划待查收
- PCIe系列专题之二:2.1 TLP的前世今生
- Android 使用SeekBar时动态显示进度且随SeekBar一起移动
- Jamie's Contact Groups ——(一对多)二分图多重最大匹配
- Web项目的页面跳转问题
热门文章
- Spark 实践——基于 Spark MLlib 和 YFCC 100M 数据集的景点推荐系统
- questasim的傻瓜式安装与仿真教程
- 【SpringBoot学习】39、SpringBoot 集成 wxJava 微信小程序:订单支付
- 代码管理工具:Git
- chrome如何手动同步?
- GetContactInfoUtils(一个获取手机联系人名称,电话,头像的工具类)
- 拼多多关键词搜索商品接口,拼多多关键词搜索列表接口,宝贝详情页接口,关键词取商品列表接口
- *6-1 CCF 2015-03-2 数字排序
- *4-2 CCF 2014-12-2 Z字形扫描
- CSS如何实现内凹角效果