??本人自學前端近半年,js達到熟練的水平,面向對象思想达吞、this指向有一定的了解,但是要用面向對象思想寫代碼就一臉懵逼了荒典,最近看到某課堂的視頻(里面廣告嫌疑酪劫,就不說是啥了),覺得講的很好寺董,因此想和大家分享一下覆糟,希望那些和我一樣有一定基礎但是不知道怎么寫的小伙伴也能愉快的寫代碼。
??我們以選項卡的實現(xiàn)為例螃征,先給出html的結構和樣式:
<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>
??我們先用過程式的編程思想來實現(xiàn)搪桂,然后將其改為面向對象思想的代碼。
window.onload=function(){
//獲取元素
var oParent=document.getElementById('div1');
var btns=oParent.getElementsByTagName('button');
var divs=oParent.getElementsByTagName('div');
//通過循環(huán)給每個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顯示
}
}
}
??對于小白盯滚,也就是和我一樣的人踢械,一般就是寫出上面的代碼。現(xiàn)在我們要用面向對象的思想來改寫魄藕,首先我們要對以上代碼進行變形内列,使其不要出現(xiàn)函數(shù)的嵌套(如onload函數(shù)中就存在嵌套函數(shù)),變量可以改為全局變量背率,所以講以上代碼做出如下改變:變量變?yōu)槿肿兞炕扒疲殖鰜硪粋€init()函數(shù)和change()函數(shù)。
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';
}
??根據(jù)以上代碼的變形寝姿,我們現(xiàn)在用面向對象思想來編寫代碼交排,創(chuàng)建構造函數(shù),添加屬性及方法饵筑。
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';
};
??將結構寫出來埃篓,復制改過的代碼,此時面向對象的思想已經(jīng)初現(xiàn)端倪了根资。最后一步就是添加this了架专,因此將每個屬性前面都添加this。
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指向的問題裤纹。讓我們一個一個來看委刘。首先構造函數(shù)中的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指向與函數(shù)的調用方式有關礁遣,因此作出如下改變斑芜。
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中祟霍,用匿名函數(shù)中采用This.change(this);方式來調用方法杏头。同時將this(指向當前點擊的btn)以參數(shù)形式傳入change()中,這樣一個面向對象思想的代碼就寫出來了沸呐。
??不知道大家看了會不會對大家有所幫助醇王,現(xiàn)在我用面向過程思想寫了一個拖拽的代碼,大家可以試著將其改為面向對象的代碼崭添,代碼如下寓娩,過程中會有幾個坑,一個就是this指向的問題滥朱,另外一個就是事件函數(shù)的問題(ev只能出現(xiàn)在事件函數(shù)中)根暑。最后跟大家分享一個小經(jīng)驗,事件和定時器很容易造成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>