1、什么是面向对象编程?
用对象的思想去写代码,就是面向对象编程(OOP)。
2、面向对象编程(OOP)的特点
封装、继承、多态。
3、对象的组成
方法(行为、操作)——函数:过程、动态的(对象下面的函数)
属性——变量:状态、静态的(对象下面的变量)
4、创建对象的模式
通常情况下,我们在创建一个对象时会采用下列方式:
var obj = new Object(); //创建了一个空的对象
obj.name = '小明'; //属性
obj.showName = function(){ //方法
alert(this.name);
};
obj.showName();
上面创建代码的方式叫做对象字面量。对象字面量虽然可以创建对象,但是在创建多个对象时会产生代码的大量重复问题:
var obj = new Object(); //创建了一个空的对象
obj.name = '小明'; //属性
obj.showName = function(){ //方法
alert(this.name);
};
obj.showName();
var obj2 = new Object(); //创建了第二个空的对象
obj2 .name = '小强'; //属性
obj2 .showName = function(){ //方法
alert(this.name);
};
obj2 .showName();
为了解决上面的问题,可以封装一个函数,利用传参的方式创建多个对象:
function createPerson(name){
//1.原料
var obj = new Object();
//2.加工
obj.name = name;
obj.showName = function(){
alert( this.name );
};
//3.出场
return obj;
}
var p1 = createPerson('小明');
p1.showName();
var p2 = createPerson('小强');
p2.showName();
上面的封装函数即创建对象的另一种模式:工厂模式,工厂模式解决了代码重复的问题,但是还存在另一个问题,那就是p1和p2之间没有内在的联系,不能反映出它们是同一个原型对象的实例。将工厂模式创建出来的对象和系统对象(如:var arr = new Array() )作对比,可以发现两者有两点不同:一是函数名称首字母大写,二是new一个在函数内部,一个在函数外部,将上面的封装函数首字母大写,并将new提出来,则得到以下模式:
function CreatePerson(name){
this.name = name;
this.showName = function(){
alert( this.name );
};
}
var p1 = new CreatePerson('小明'); //new后面的函数叫做构造函数。当new去调用一个函数,这个时候函数中的this就是创建出来的对象,且函数的返回值默认就是this(隐式返回),所以在函数内部不用再写return返回。
var p2 = new CreatePerson('小强');
而上面创建对象的模式即是构造函数模式。构造函数方法很好用,但是存在一个浪费内存的问题。对于每一个实例对象,CreatePerson方法都是一模一样的内容,每一次生成一个实例,就会多占用一些内存。这样既不环保,也缺乏效率。那么能不能让公有的属性和方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?
alert( p1.showName == p2.showName ); //false
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。我们可以把那些不变的属性和方法,直接定义在prototype对象上。这种方式即原型模式。
function CreatePerson(name){
this.name = name;
}
CreatePerson.prototype.showName = function(){
alert( this.name );
};
var p1 = new CreatePerson('小明');
var p2 = new CreatePerson('小强');
alert( p1.showName == p2.showName ); //true
5、面向对象编程实例:拖拽
先写出普通的写法,然后改成面向对象写法
》普通方法变型
-尽量不要出现函数嵌套函数
-可以有全局变量
-把onload中不是赋值的语句放到单独函数中
》改成面向对象
-Onload中创建对象
-全局变量就是属性
-函数就是方法
-改this指向问题
过程式写法:
<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>
变形后为:
<script type="text/javascript">
var oDiv=null;
var disX=0;
var disY=0;
window.onload=function(){
oDiv=document.getElementById("div1");
oDiv.onmousedown=fnDown;
}
function fnDown(ev){
var ev= ev || window.event;
disX=ev.clientX-oDiv.offsetLeft;
disY=ev.clientY-oDiv.offsetTop;
document.onmousemove=fnMove;
document.onmouseup=fnUp;
return false;
}
function fnMove(ev){
var ev=ev||window.event;
oDiv.style.left=ev.clientX-disX+'px';
oDiv.style.top=ev.clientY-disY+'px';
}
function fnUp(){
document.onmousemove=null;
document.onmouseup=null;
}
</script>
改成面向对象写法:
<script type="text/javascript">
window.onload=function(){
var d1=new Drag('div1'); //onload函数中创建对象
d1.init();
}
function Drag(id){ //构造函数
this.oDiv=document.getElementById(id);
this.disX=0;
this.disY=0;
}
//构造函数的原型下面写方法
Drag.prototype.init=function(){
var This=this;
this.oDiv.onmousedown=function(ev){
var ev=ev || window.event;
This.fnDown(ev);
return false;
};
}
Drag.prototype.fnDown=function(ev){
var This=this;
this.disX=ev.clientX-this.oDiv.offsetLeft;
this.disY=ev.clientY-this.oDiv.offsetTop;
document.onmousemove=function(ev){
var ev=ev || window.event;
This.fnMove(ev);
};
document.onmouseup=this.fnUp;
}
Drag.prototype.fnMove=function(ev){
this.oDiv.style.left=ev.clientX-this.disX+'px';
this.oDiv.style.top=ev.clientY-this.disY+'px';
}
Drag.prototype.fnUp=function(){
document.onmouseup=document.onmousemove=null;
}
</script>