什么是面向对象?
面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。
面向过程是分步执行
面向对象是关注整体,按模块执行
创建对象
字面量创建
// 创建对象
var obj = {
// 添加属性
name : "xiaoming",
age : "12",
// 添加方法
introduction : function(){
console.log( "我是" + this.name);
}
}
// 调用方法
obj.introduction();
内置构造函数
// 创建对象
var obj = new Object();
// 添加属性
obj.name = "xiaoming";
obj.age = "12";
// 添加方法
obj.introduction = function(){
console.log( "我是" + this.name);
}
// 调用方法
obj.introduction();
工厂函数构造对象
// 构造函数
function creatObject( name , age ){
var obj = new Object();
// 原料
obj.name = name;
obj.age = age;
// 加工
obj.introduction = function(){
console.log( "我是" + this.name + "今年" + this.age );
}
// 出厂
return obj;
}
// 创建对象
var student1 = creatObject( "xiaoming" , 33)
var student2 = creatObject( "xiaohong" , 23)
// 调用方法
student1.introduction();
student2.introduction();
构造函数创建
//构造函数创建的对象;
// 构造函数
function creatObject( name , age ){
this.name = name; //把数据存入对象中
this.age = age;
// 创建方法
this.introduction = function(){
console.log( "我是" + this.name + "今年" + this.age );
console.log(this)
// this指向的是当前对象
}
// 函数内调用
this.introduction();
}
// 创建对象
var student1 = new creatObject( "xiaoming" , 33)
// 在这里用new创建函数中可以省去new Object()
var student2 = new creatObject( "xiaohong" , 23)
原型对象prototype
// 构造函数
function creatObject( name , age ){
this.name = name; //把数据存入对象中
this.age = age;
// 调用方法
this.introduction();
}
// 创建方法
creatObject.prototype.introduction = function(){
console.log( "我是" + this.name + "今年" + this.age );
console.log(this)
// this指向的是当前对象
}
// 创建对象
var student1 = new creatObject( "xiaoming" , 33)
// 在这里用new创建函数中可以省去new Object()
var student2 = new creatObject( "xiaohong" , 23)
原型方法简化
当函数功能较多时可以将原来的原型对象编成我们的对象
// 构造函数
function creatObject( name , age ){
this.name = name; //把数据存入对象中
this.age = age;
// 调用方法
this.showName();
this.showAge();
}
// 创建方法
creatObject.prototype = {
// 赋值之后 constructor 没有了,需要我们手动填写
constructor : creatObject,
showName : function(){
console.log( "我是" + this.name);
console.log(constructor)
},
showAge : function(){
console.log( "今年" + this.age );
}
}
// 创建对象
var student1 = new creatObject( "xiaoming" , 33)
// 在这里用new创建函数中可以省去new Object()
var student2 = new creatObject( "xiaohong" , 23)
面向对象案例(萤火虫效果)
面向对象编程分为三个阶段 OOA(面向对象分析)、OOD(面向对象设计)、OOP(面向对象编程)
OOA
- 创建元素.放入页面;
- 设置随机位置; 有边界的;
- 设置随机的目标;
- 运动;
- 运动结束之后,需要重新设置随机目标,重新进行运动…
OOD
function Glowworm(){
}
Glowworm.prototype = {
constructor : Glowworm,
init : function(){
// 所有的耦合关系都在这里;
// 创建元素;
// 放入页面有一个随机位置;
// 运动;
},
// 创建元素
createGlowwormEle : function(){
},
// 设置边界
glowwormBoundary : function(){
},
// 运动目标
glowwormTarget : function(){
},
// 运动
glowwormAnimate : function(){
}
}
OOP
function Glowworm( selector ){
this.container = document.querySelector(selector);
// 获取父元素放入当前对象的container中
this.init();
// 调用init方法;
}
Glowworm.prototype = {
constructor : Glowworm,
init : function(){
// 调用创建方法来创建萤火虫
this.ele = this.createGlowwormEle();
// 让萤火虫出现的位置是随机的;
// 1. 获取随机位置;
var boundary = this.glowwormBoundary();
// 2. 将随机位置赋值给萤火虫;
this.ele.style.left = boundary.left + "px";
this.ele.style.top = boundary.top + "px";
// 让萤火虫随机移动; 需要一个运动的目标点;
// 运动需要实现的复杂功能;
animate(this.ele , this.glowwormBoundary() , function(){
animate(this.ele , this.glowwormBoundary() , arguments.callee.bind(this) );
// callee指向当前匿名函数
}.bind(this));
// 封装中的animate this会指向window,需要用bind来更改指向
},
createGlowwormEle : function(){
var ele = document.createElement("div")
ele.className = "fire-bug";
this.container.appendChild(ele);
return ele;
},
glowwormBoundary : function(){
// min 0 max 容器的宽度 - 元素的宽度;
var left_max = this.container.offsetWidth - this.ele.offsetWidth;
var top_max = this.container.offsetHeight - this.ele.offsetHeight;
return {
left : parseInt(left_max * Math.random() + 1),
top : parseInt(top_max * Math.random() + 1),
}
},
glowwormAnimate : function(){
}
}
for(var i = 0 ; i < 20 ; i ++){
new Glowworm("#container");
//重复调用20次
}
</script>
animate为封装的方法
function animate( ele , attr_options , callback ){
// 1. 获取元素当前的属性;
// 因为数据增加,所以重新建立 attr_options结构;
// console.log(attr_options);
for(var attr in attr_options){
// 我们需要记录的数据有 : 属性名 : 目标点, 当前元素的属性;
// { "width" : {
// target : 200 ,
// iNow : 元素的属性值;
// }
// }
// attr : width : height;
attr_options[attr] = {
// 目标点 : 传入的数据;
target : attr_options[attr],
// 元素当前的属性值 ;
iNow : parseInt( getComputedStyle(ele)[attr] )
}
// console.log(attr_options[attr])
}
// 关闭开启定时器;
clearInterval( ele.timer );
ele.timer = setInterval( function(){
// 1. 获取速度; width : height :
for(var attr in attr_options){
// attr : width | height;
var item = attr_options[attr];
// console.log(item , attr);
var target = item.target;
var iNow = item.iNow;
// 运动所必须的值我们都有了;
// 计算速度;
var speed = (target - iNow) / 10;
// 速度取整;
speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
// 终止条件 :
if( Math.abs( target - iNow) <= Math.abs(speed) ){
// 终止定时器 ;
// 送他一把;
// clearInterval( ele.timer );
// ele.style[attr] = target + "px";
// 终止条件不可靠,因为目标的不一致会让运动次数执行不同,有可能提前关闭定时器;
ele.style[attr] = target + "px";
// 一条运动完成删除对象里面的数据;
delete attr_options[attr];
// 如果对象里面没有属性了,那么我们关闭定时器就可以了;
for(var num in attr_options){
// 如果attr_options里面有属性,那么此时我就不应该终止定时器;
return false;
}
clearInterval(ele.timer);
typeof callback === "function" ? callback() : "";
}else{
// 元素运动;
// 因为 iNow 是一个临时变量,所以不能再去操作iNow , 要去操作iNow 的数据源;
// 多花点经历理解这段代码;
attr_options[attr].iNow += speed;
ele.style[attr] = attr_options[attr].iNow + "px";
}
}
} , 30)
}