本人自学前端近半年,js达到熟练的水平,面向对象思想、this指向有必定的了解,可是要用面向对象思想写代码就一脸懵逼了,最近看到某课堂的视频(里面广告嫌疑,就不说是啥了),以为讲的很好,所以想和你们分享一下,但愿那些和我同样有必定基础可是不知道怎么写的小伙伴也能愉快的写代码。
咱们以选项卡的实现为例,先给出html的结构和样式:javascript
<style type="text/css"> #div1 div{ width: 200px; height:200px; border: 1px #000 solid; display: none; } .active{ background: red; } </style> <body> <div id="div1"> <button class="active">1</button> <button>2</button> <button>3</button> <div style="display: block;">111</div> <div>222</div> <div>333</div> </div> </body>
咱们先用过程式的编程思想来实现,而后将其改成面向对象思想的代码。css
window.onload=function(){ //获取元素 var oParent=document.getElementById('div1'); var btns=oParent.getElementsByTagName('button'); var divs=oParent.getElementsByTagName('div'); //经过循环给每一个btn添加点击事件 for (var i = 0; i < btns.length; i++) { btns[i].index=i;//存储当前btn的下标 btns[i].onclick=function(){ for (var i = 0; i < btns.length; i++) { btns[i].className=''; divs[i].style.display='none'; } this.className='active'; divs[this.index].style.display='block';//让对应当前btn的div显示 } } }
对于小白,也就是和我同样的人,通常就是写出上面的代码。如今咱们要用面向对象的思想来改写,首先咱们要对以上代码进行变形,使其不要出现函数的嵌套(如onload函数中就存在嵌套函数),变量能够改成全局变量,因此讲以上代码作出以下改变:变量变为全局变量,分出来一个init()函数和change()函数。html
var oParent,btns,divs; window.onload=function(){ oParent=document.getElementById('div1'); btns=oParent.getElementsByTagName('button'); divs=oParent.getElementsByTagName('div'); init(); }; function init(){ for (var i = 0; i < btns.length; i++) { btns[i].index=i; btns[i].onclick=change; } } function change(){ for (var i = 0; i < btns.length; i++) { btns[i].className=''; divs[i].style.display='none'; } this.className='active'; divs[this.index].style.display='block'; }
根据以上代码的变形,咱们如今用面向对象思想来编写代码,建立构造函数,添加属性及方法。前端
window.onload=function(){ var t1=new Tab(); t1.init(); }; function Tab(){ oParent=document.getElementById('div1'); btns=oParent.getElementsByTagName('button'); divs=oParent.getElementsByTagName('div'); } Tab.prototype.init=function(){ for (var i = 0; i < this.btns.length; i++) { btns[i].index=i; btns[i].onclick=change; } } Tab.prototype.change=function() { for (var i = 0; i < this.btns.length; i++) { btns[i].className=''; divs[i].style.display='none'; } className='active'; divs[btn.index].style.display='block'; };
将结构写出来,复制改过的代码,此时面向对象的思想已经初现端倪了。最后一步就是添加this了,所以将每一个属性前面都添加this。java
window.onload=function(){ var t1=new Tab(); t1.init(); }; function Tab(){ this.oParent=document.getElementById('div1'); this.btns=this.oParent.getElementsByTagName('button'); this.divs=this.oParent.getElementsByTagName('div'); } Tab.prototype.init=function(){ for (var i = 0; i < this.btns.length; i++) { this.btns[i].index=i; this.btns[i].onclick=change(); } } Tab.prototype.change=function() { for (var i = 0; i < this.btns.length; i++) { this.btns[i].className=''; this.divs[i].style.display='none'; } this.className='active'; this.divs[this.index].style.display='block'; };
以上代码就完成了吗?答案是否认的。为何?仍是由于this指向的问题。让咱们一个一个来看。首先构造函数中的this,因为是用new关键字,所以this指向t1,没问题。init()方法,因为调用方式是t1.init(),this指向也为t1,没问题。那问题确定是在change()方法中了,首先看看其调用形式this.btns[i].onclick=change();其this指向为this.btns[i],即当前点击的按钮,所以在change()内部,this.btns[i],this.divs[i]都不存在,由于btns和divs是t1的属性,其余的this如this.className指向是正确的,所以咱们要改变this指向,通常都是将this指向改成指向对象,即t1。怎么改this指向?this指向与函数的调用方式有关,所以做出以下改变。编程
Tab.prototype.init=function(){ var This=this; for (var i = 0; i < this.btns.length; i++) { this.btns[i].index=i; this.btns[i].onclick=function(){ This.change(this); } } } Tab.prototype.change=function(btn) { for (var i = 0; i < this.btns.length; i++) { this.btns[i].className=''; this.divs[i].style.display='none'; } btn.className='active'; this.divs[btn.index].style.display='block'; };
首先在init()中,将this存在变量This中,用匿名函数中采用This.change(this);方式来调用方法。同时将this(指向当前点击的btn)以参数形式传入change()中,这样一个面向对象思想的代码就写出来了。函数
不知道你们看了会不会对你们有所帮助,如今我用面向过程思想写了一个拖拽的代码,你们能够试着将其改成面向对象的代码,代码以下,过程当中会有几个坑,一个就是this指向的问题,另一个就是事件函数的问题(ev只能出如今事件函数中)。最后跟你们分享一个小经验,事件和定时器很容易形成this指向的问题,所以在面向对象编程过程当中要特别注意。this
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>drag</title> <style type="text/css"> #div1{ width: 100px; height: 100px; background: red; position: absolute; } </style> <script type="text/javascript"> window.onload=function(){ var oDiv=document.getElementById('div1'); var disX=0; var disY=0; oDiv.onmousedown=function(ev){ var ev=ev || window.event; disX=ev.clientX-oDiv.offsetLeft; disY=ev.clientY-oDiv.offsetTop; document.onmousemove=function(ev){ var ev=ev || window.event; oDiv.style.left=ev.clientX-disX+'px'; oDiv.style.top=ev.clientY-disY+'px'; }; document.onmouseup=function(){ document.onmousemove=null; document.onmouseup=null; } return false; } } </script> </head> <body> <div id='div1'></div> </body> </html>