案例——面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿)。

下面是一个简单的选项卡,也是我们常见的面向过程的创建形式。

 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 面向对象(二) —— 案例篇相关推荐

  1. Javascript面向对象二

    Javascript面向对象二 可以通过指定原型属性来对所有的对象指定属性, Object.prototype.name="zhangsan"; Object.prototype. ...

  2. javascript面向对象系列第一篇——构造函数和原型对象

    前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如何用构造函数和原型对象来创建对象 构造函数 构造函数是 ...

  3. JavaScript 面向对象游戏案例:贪吃蛇

    面向对象游戏案例:贪吃蛇 案例相关源码以上传到 GitHub :https://github.com/sunna1/snake 案例介绍 案例目标 游戏的目的是用来体会js高级语法的使用 不需要具备抽 ...

  4. JavaScript 面向对象(二)——案列篇

    看案例前可以先看看基础篇:JavaScript  面向对象(一)--基础篇 案例--面向对象的选项卡:把面向过程的程序一步步改成面向对象的形式,使其能够更加的通用(但是通用的东西,一般会比较臃肿). ...

  5. JavaScript 面向对象编程(二) —— 构造函数 / 原型 / 继承 / ES5 新增方法

    本篇为 JavaScript 进阶 ES6 系列笔记第二篇,将陆续更新后续内容.参考:JavaScript 进阶面向对象 ES6 :ECMAScript 6 入门 : Javascript 继承机制的 ...

  6. JavaScript进阶面向对象ES6整合篇

    整合篇整体内容比较多,详细点可以查询目录 文章目录 一.JavaScript面向对象 1.面向对象编程介绍 2.ES6中的类和对象 3.类的继承 4.案例:面向对象案例 二.构造函数和原型 1. 构造 ...

  7. JavaScript 时间戳(互相转换)(自定义格式)- 案例篇

    文章目录 JavaScript 时间戳(自定义格式)转换 - 案例(含代码) 一.时间戳(`s` 秒) 1. `转化顺序` · 说明: 2. 效果图: 3. 代码: 二.时间戳(`ms` 毫秒) 1. ...

  8. JavaScript 基础知识 - DOM篇(二)

    7. 节点操作 7.1 节点的属性 节点分类: 标签节点 文本节点 属性节点 注释节点 节点常用的属性: nodeType:节点的类型 nodeName:节点名称 nodeValue:节点值 常见的节 ...

  9. JavaScript 基础知识 - 入门篇(二)

    11. 函数 11.1 函数的基础知识 为什么会有函数? 在写代码的时候,有一些常用的代码需要书写很多次,如果直接复制粘贴的话,会造成大量的代码冗余: 函数可以封装一段重复的javascript代码, ...

最新文章

  1. day29Struts 类型转换和自定义类型转换,input视图
  2. Spring Cloud入门,看这篇就够了!
  3. 怎样求信号中的RMS值?
  4. 循序渐进之Maven(4) - 第一个SpringMVC项目
  5. 03-13 微信小程序自动化测试
  6. pandas知识点(汇总和计算描述统计)
  7. 用python导出pptx中每一页的标题
  8. ECS Linux 服务器解除ssh登陆后被锁定或暂停输入输出的终端
  9. 46多项式01——一元多项式和运算
  10. Maven下载JasperReports报错Could not find artifact com.lowagie:itext:pom:2.1.7.js6 in alimaven
  11. Flexbox 基础知识
  12. Privacy-Preserving Deep Learning via Additively Homomorphic Encryption
  13. 对拉勾网数据分析职位做数据分析
  14. 快速确定针式打印机故障部位方法
  15. 魔法少女 LJJ——线段树
  16. 嗖嗖~您有一份上云计划待查收
  17. PCIe系列专题之二:2.1 TLP的前世今生
  18. Android 使用SeekBar时动态显示进度且随SeekBar一起移动
  19. Jamie's Contact Groups ——(一对多)二分图多重最大匹配
  20. Web项目的页面跳转问题

热门文章

  1. Spark 实践——基于 Spark MLlib 和 YFCC 100M 数据集的景点推荐系统
  2. questasim的傻瓜式安装与仿真教程
  3. 【SpringBoot学习】39、SpringBoot 集成 wxJava 微信小程序:订单支付
  4. 代码管理工具:Git
  5. chrome如何手动同步?
  6. GetContactInfoUtils(一个获取手机联系人名称,电话,头像的工具类)
  7. 拼多多关键词搜索商品接口,拼多多关键词搜索列表接口,宝贝详情页接口,关键词取商品列表接口
  8. *6-1 CCF 2015-03-2 数字排序
  9. *4-2 CCF 2014-12-2 Z字形扫描
  10. CSS如何实现内凹角效果