什么是面向对象编程(oop)?用对象的思想去写代码,就是面向对象编程。
面向对象编程的特点
抽象:抓住核心问题
封装:只能通过对象来访问方法
继承:从已有对象上继承出新的对象
多态:多对象的不同形态
对象的组成
属性:对象下面的变量叫做对象的属性
方法:对象下面的函数叫做对象的方法
1 2 3 4 5 | var arr = [];
arr.number = 10;
};
arr.test();
|
登录后复制
创建一个对象
1 2 | var obj= new Object();
obj.showName();
|
登录后复制
如果需要创建两个或多个对象
1 2 3 | var obj1= new Object();
obj1.showName();
obj2.showName();
|
登录后复制
使用Object函数或对象字面量都可以创建面向对象,但需要创建多个对象时,会产生大量的重复代码,可通过工厂方式来解决这个问题
工厂方式 -------------------- 面向对象中的封装函数
1 2 3 4 5 6 7 8 | obj.name = name;
obj.showName = function (){
alert( this.name );
}; return obj;
} var p1 = createPerson( '小明' );
p1.showName(); var p2 = createPerson( '小强' );
p2.showName();
|
登录后复制
创建对象用工厂方式来实现,可以传递参数,由于创建对象都是使用Object的原生构造函数来实现的,因此无法识别对象类型
构造函数模式 -------------------- 给一个对象添加方法
1 2 3 4 5 | alert(this.name);
}
} var p1= new CreatePerson( '小明' );
p2.showName();
|
登录后复制
使用自定义的构造函数,定义对象类型的属性和方法,与工厂方式的区别:
没有显式的创建对象
直接将属性和方法赋给this对象
没有return语句
上面例子中:CreatePerson构造函数生成的两个对象p1与p2都是CreatePerson的实例
虽然构造函数解决了上面工厂方式的问题,但是它一样存在缺点,就是在创建对象时,每个对象都有一套自己的方法,每定义一个函数都实例化了一个对象
例如:
1 2 3 4 5 | function CreatePerson(name){ this.name = name;this.showName = function (){
alert( this.name );
};
} var p1 = new CreatePerson( '小明' );
|
登录后复制
测试例子中的p1.showName与p2.showName是否会相等,弹出的结果是false,说明p1和p2实例都包含一个不同的showName实例
再来举几个例子:
1 2 3 4 | var a = [1,2,3]; var b = [1,2,3];
alert( a == b );
alert(b);
|
登录后复制
1 2 | var a = [1,2,3]; var b = a;b.push(4);
alert(b);
|
登录后复制
1 2 3 | var a = [1,2,3]; var b = a;
b = [1,2,3,4];
alert(b);
|
登录后复制
对比上面的几个例子,不难看出基本类型和对象类型的区别了,对象类型的赋值不仅是值的复制,也是引用的传递;提到了对象的引用应该很清楚上述p1.showName==p2.showName为何会返回结果是false
原型模式(prototype) -------------------- 给一类对象添加方法
原型(prototype):重写对象下面公用的属性或方法,让公用的属性或方法在内存中只存在一份(提高性能),也就是说所有在原型对象中创建的属性或方法都直接被所有对象实例共享。
原型:类比css中的class
普通方法:类比css中的style
1 2 3 4 5 6 7 8 | var arr = [1,2,3,4,5]; var arr2 = [2,2,2,2,2];
Array.prototype.sum = function (){
result += this[i];
} return result;
};
alert( arr.sum() );
|
登录后复制
原型优先级:如果在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,该属性将会屏蔽原型中的那个属性
例子1:
1 2 3 4 5 | var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number);
|
登录后复制
例子2:
1 2 | Array.prototype.a=12;
alert(arr.a);
|
登录后复制
工厂方式之原型
1 2 3 4 5 6 7 | function CreatePerson(name){
}
CreatePerson.prototype.showName= function (){
} var p1= new CreatePerson( '小明' );
p1.showName(); var p2= new CreatePerson( '小强' );
p2.showName();
alert( p1.showName== p2.showName);
|
登录后复制
由上述例子中:p1.showName== p2.showName弹出的结果是true,可见原型解决了构造函数中“每定义一个函数都实例化了一个对象”的问题
原型的运用
选项卡实例:
1 2 3 4 5 6 7 8 9 10 11 | <!DOCTYPE html><html><head lang= "en" ><meta charset= "UTF-8" ><title>选项卡</title><style>#div1 div{width:400px;height:300px;border:1px solid #ccc;overflow: hidden;display: none;margin: 15px 0;}#div1 input{color: #fff;width:100px;height:40px;background: darkseagreen;border:none;font-size: 14px;letter-spacing: 5px;}#div1 p{font-size: 20px;line-height: 24px;text-align: center;color:darkgreen;}#div1 .title{padding: 0;font-weight: bold;}#div1 .active{background:sandybrown;color:#fff;}</style><script>window.onload= function (){ var oDiv=document.getElementById( 'div1' ); var aInput=oDiv.getElementsByTagName( 'input' ); var aDiv=oDiv.getElementsByTagName( 'div' ); var i=0; for (i=0;i<aInput.length;i++){
aInput[i].index=i;
aInput[i].onmousemove= function (){ for ( var i=0;i<aInput.length;i++){
aInput[i].className= '' ;
aDiv[i].style.display= 'none' ;
}
aInput[this.index].className= 'active' ;
aDiv[this.index].style.display= 'block' ;
}
}
}</script></head><body><div id= "div1" ><input class = "active" type= "button" value= "五言律诗" ><input type= "button" value= "七言律诗" ><input type= "button" value= "五言绝句" ><input type= "button" value= "七言绝句" ><div style= "display: block;" ><p class = "title" >落 花</p><p class = "author" >李商隐</p><p>高阁客竟去,小园花乱飞。</p><p>参差连曲陌,迢递送斜晖。</p><p>肠断未忍扫,眼穿仍欲归。</p><p>芳心向春尽,所得是沾衣。</p></div><div><p class = "title" >蜀 相</p><p class = "author" >杜甫</p><p>丞相祠堂何处寻,锦官城外柏森森。</p><p>映阶碧草自春色,隔叶黄鹂空好音。</p><p>三顾频烦天下计,两朝开济老臣心。</p><p>出师未捷身先死,长使英雄泪满襟。</p></div><div><p class = "title" >八阵图</p><p class = "author" >杜甫</p><p>功盖三分国,名成八阵图。</p><p>江流石不转,遗恨失吞吴。</p></div><div><p class = "title" >泊秦淮</p><p class = "author" >杜牧</p><p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p><p>商女不知亡国恨,隔江犹唱后庭花。</p></div></div></body></html>
|
登录后复制
效果(鼠标经过按钮时选项卡切换):
面向对象选项卡:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPE html><html><head lang= "en" ><meta charset= "UTF-8" ><title>选项卡</title><style>#div1 div,#div2 div{width:400px;height:300px;border:1px solid #ccc;overflow: hidden;display: none;margin: 15px 0;}#div1 input,#div2 input{color: #fff;width:100px;height:40px;background: darkseagreen;border:none;font-size: 14px;letter-spacing: 5px;}#div1 p,#div2 p{font-size: 20px;line-height: 24px;text-align: center;color:darkgreen;}#div1 .title,#div2 .title{padding: 0;font-weight: bold;}#div1 .active,#div2 .active{background:sandybrown;color:#fff;}</style><script>window.onload= function (){ var t1= new TabSwitch( 'div1' );
t1. switch (); var t2= new TabSwitch( 'div2' );
t2.autoPlay(); } function TabSwitch(id){this.oDiv=document.getElementById(id);this.aInput=this.oDiv.getElementsByTagName( 'input' );this.aDiv=this.oDiv.getElementsByTagName( 'div' );this.iNow=0;//自定义属性}
TabSwitch.prototype. switch = function (){
This.tab(this);
}
}
TabSwitch.prototype.tab= function (obj){
}this.aInput[obj.index].className= 'active' ;this.aDiv[obj.index].style.display= 'block' ;
}
setInterval( function (){ if (This.iNow==This.aInput.length-1){
This.iNow=0;
} else {
This.iNow++;
} for ( var i=0;i<This.aInput.length;i++){
This.aInput[i].className= '' ;
This.aDiv[i].style.display= 'none' ;
}
This.aInput[This.iNow].className= 'active' ;
This.aDiv[This.iNow].style.display= 'block' ;
},1000);
}</script></head><body><div id= "div1" ><input class = "active" type= "button" value= "五言律诗" ><input type= "button" value= "七言律诗" ><input type= "button" value= "五言绝句" ><input type= "button" value= "七言绝句" ><div style= "display: block;" ><p class = "title" >落 花</p><p class = "author" >李商隐</p><p>高阁客竟去,小园花乱飞。</p><p>参差连曲陌,迢递送斜晖。</p><p>肠断未忍扫,眼穿仍欲归。</p><p>芳心向春尽,所得是沾衣。</p></div><div><p class = "title" >蜀 相</p><p class = "author" >杜甫</p><p>丞相祠堂何处寻,锦官城外柏森森。</p><p>映阶碧草自春色,隔叶黄鹂空好音。</p><p>三顾频烦天下计,两朝开济老臣心。</p><p>出师未捷身先死,长使英雄泪满襟。</p></div><div><p class = "title" >八阵图</p><p class = "author" >杜甫</p><p>功盖三分国,名成八阵图。</p><p>江流石不转,遗恨失吞吴。</p></div><div><p class = "title" >泊秦淮</p><p class = "author" >杜牧</p><p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p><p>商女不知亡国恨,隔江犹唱后庭花。</p></div></div><div id= "div2" ><input class = "active" type= "button" value= "五言律诗" ><input type= "button" value= "七言律诗" ><input type= "button" value= "五言绝句" ><input type= "button" value= "七言绝句" ><div style= "display: block;" ><p class = "title" >落 花</p><p class = "author" >李商隐</p><p>高阁客竟去,小园花乱飞。</p><p>参差连曲陌,迢递送斜晖。</p><p>肠断未忍扫,眼穿仍欲归。</p><p>芳心向春尽,所得是沾衣。</p></div><div><p class = "title" >蜀 相</p><p class = "author" >杜甫</p><p>丞相祠堂何处寻,锦官城外柏森森。</p><p>映阶碧草自春色,隔叶黄鹂空好音。</p><p>三顾频烦天下计,两朝开济老臣心。</p><p>出师未捷身先死,长使英雄泪满襟。</p></div><div><p class = "title" >八阵图</p><p class = "author" >杜甫</p><p>功盖三分国,名成八阵图。</p><p>江流石不转,遗恨失吞吴。</p></div><div><p class = "title" >泊秦淮</p><p class = "author" >杜牧</p><p>烟笼寒水月笼沙,夜泊秦淮近酒家。</p><p>商女不知亡国恨,隔江犹唱后庭花。</p></div></div></body></html>
|
登录后复制
效果(第二个选项卡加了一个自动切换功能):
面向对象中this的问题
一般会出现问题的情况有两种:
例子1:
1 2 3 4 5 6 7 | setInterval( function (){
},1000);
}
Aaa.prototype.show= function (){
alert(this.a);
} var obj= new Aaa();
|
登录后复制
例子2:
1 2 3 | <!DOCTYPE html><html><head lang= "en" ><meta charset= "UTF-8" ><title>面向对象中this的问题-----事件</title><script> function Bbb(){ var _this=this;this.b=5;
document.getElementById( 'btn1' ).onclick= function (){
}}
|
登录后复制
1 2 | Bbb.prototype.show= function (){ alert(this.b); } window.onload= function (){ var p2= new Bbb();
}</script></head><body><input id= "btn1" type= "button" value= "按钮" ></body></html>
|
登录后复制
上面两个是分别对定时器和事件中this问题的解决方法,即将指向对象的this保存到了_this中,在嵌套函数中调用对象的方法或属性时用 _this.属性 或 _this.方法
再来个实例:
拖拽效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <!DOCTYPE html><html><head lang= "en" ><meta charset= "UTF-8" ><title>最初写的拖拽效果</title>
<style> #div1{ width:100px; height:100px; background: red; position: absolute; }
</style><script>window.onload= function (){ var oDiv=document.getElementById( 'div1' );
oDiv.onmousedown= function (ev){ var oEvent=ev||event; var disX=0; var disY=0; var disX=oEvent.clientX-oDiv.offsetLeft; var disY=oEvent.clientY-oDiv.offsetTop;
document.onmousemove= function (ev){ var oEvent=ev||event;
oDiv.style.left=oEvent.clientX-disX+ 'px' ;
oDiv.style.top=oEvent.clientY-disY+ 'px' ;
};
document.onmouseup= function (){
document.onmousemove=null;
document.onmouseup=null;
}; return false;
}
}</script></head><body><div id= "div1" ></div></body></html>
|
登录后复制
面向对象的拖拽
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!DOCTYPE html><html><head lang= "en" ><meta charset= "UTF-8" ><title>面向对象写的拖拽效果</title><style>#div1{width:100px;height:100px;background: red;position: absolute;}</style><script>window.onload= function (){ var p= new Darg( 'div1' );
p.init();
} function Darg(id){this.oDiv=document.getElementById(id);
Darg.prototype.init= function (){
This.fnDown(oEvent); return false;
}
}
Darg.prototype.fnDown= function (ev){
document.onmousemove= function (ev){ var oEvent=ev||event;
This.fnMove(oEvent);
};
document.onmouseup= function (){
This.fnUp();
};
}
Darg.prototype.fnMove= function (ev){
}
Darg.prototype.fnUp= function (){
document.onmouseup=null;
}</script></head><body><div id= "div1" ></div></body></html>
|
登录后复制
以上就是什么是面向对象编程(OOP)?面向对象编程的特点的详细内容,更多请关注php中文网其它相关文章!