本人自學前端近半年,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>