1、什么是面向对象编程
•用对象的思想去写代码,就是面向对象编程
- 过程式写法
- 面向对象写法
过程式写法如下
function test(){}
for(){}
if(){}
• 我们一直都在使用对象
如数组 Array 时间 Date都是对象
//创建
var arr = new Array(); //[] ,底下分别有些方法
var date = new Date();
//arr的方法
arr.length
arr.push();
arr.sort();
//date的方法
date.getDate();
我们把系统自带的对象,叫做系统对象
• 面向对象编程(OOP)的特点 最好的学习方法就是多练习
- 抽象:抓住核心问题 抽是抽取,象是具象
- 封装:只能通过对象来访问方法
- 继承:从已有对象上继承出新的对象 其实就是复用代码
- 多态:多对象的不同形态 复用的另外一种形式,但是用的不多,因js语言是弱类型类型
• 对象的组成
- 方法(行为、操作)——函数:过程、动态的
- 属性——变量:状态、静态的
属性和方法的区别
//系统对象下的数组
var arr = [];//对象
arr.number = 10; //对象下面的变量:叫做对象的属性
//alert( arr.number );
//alert( arr.length );
arr.test = function(){ //把一个函数写在对象下面,或者说对象下面的函数 : 叫做对象的方法
alert(123);
};
arr.test();
//以下是常见的方法,加括号的是方法,不加是属性
arr.push();
arr.sort();
2、创建第一个面向对象程序
•为对象添加属性和方法
–Object对象
–this指向
–创建两个对象 : 重复代码过多
以下是一个完成的面向对象的程序
var obj=new Object(); //创建了一个空的对象
obj.name='小明'; //创建的属性
obj.showName=function(){ //创建的方法
alert(this.name);
}
obj.showName();//调用
面向对象中难点this指向,谁调用的就是指向谁
3.工厂方式与构造函数
工厂方式 其实就是封装函数
1.面向对象中的封装函数
-
//工厂方式 : 封装函数 function creatName(name){ //1.原料 var obj=new Object(); //2.加工 obj.name=name; obj.showName=function(){ alert( this.name ); //此时this的指向是window } //3.出场 return obj; } var p1 = creatName('小明');//创建对象 p1.showName(); //调用方法 var p2 = creatName('小强'); p2.showName();
2.改成与系统对象类似写法
-
- 首字母大写
- New 关键字提取
- This指向为新创建的对象
//当new去调用一个函数 : 这个时候函数中的this就是创建出来的对象,而且函数的的返回值直接就是this啦(隐式返回)
//new后面调用的函数 : 叫做构造函数
function CreatePerson(name){
this.name = name;
this.showName = function(){
alert( this.name );
};
}
var p1 = new CreatePerson('小明');
p1.showName();
var p2 = new CreatePerson('小强');
p2.showName();
alert( p1.showName == p2.showName ); //false
3.构造函数的定义
- 用来创建对象的函数,叫做构造函数
4.存在的问题
- 对象的引用
- 浪费内存
为什么p1和p2是false,这和类型的传递有关,内存和值都相等才相等
基本类型 : 赋值的时候只是值的复制
var a = 5;
var b = a;
b += 3;
alert(b); //8
alert(a); //5 基本类型 : 赋值的时候只是值的复制
对象类型 : 赋值不仅是值的复制,而且也是引用的传递
var a = [1,2,3];
var b = a;
b.push(4);
alert(b); //[1,2,3,4]
alert(a); //[1,2,3,4] 对象类型 : 赋值不仅是值的复制,而且也是引用的传递
var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(b); //[1,2,3,4]
alert(a); //[1,2,3]
var a = 5;
var b = 5;
alert(a == b); //true基本类型 : 值相同就可以
var a = [1,2,3];
var b = [1,2,3];
alert( a == b ); //false //对象类型 : 值和引用都相同才行
var a = [1,2,3];
var b = a;
alert( a==b ); //true
5.原型 :作用是去改写对象下面公用的方法或者属性 , 让公用的方法或者属性在内存中存在一份 ( 提高性能 )
3原型-prototype
• 概念
–重写对象方法,让相同方法在内存中存在一份(提高性能)
• 学习原型
–类比 : CSS中的Class
- 原型 : CSS中的class
- 普通方法 : CSS中的style
//CSS中的style 普通写法
var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2];
arr.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
arr2.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
alert( arr.sum() ); //15
alert( arr2.sum() ); //10
普通写法再一定情况下会代码冗长,重复
• 通过原型改写工厂方式
–原则
»相同的属性和方法可以加载原型上
»混合的编程模式
原型 : prototype : 要写在构造函数的下面
改写以上求和代码
var arr = [1,2,3,4,5];
var arr2 = [2,2,2,2,2];
Array.prototype.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
};
alert( arr.sum() ); //15
alert( arr2.sum() ); //10
相同情况下普通写法style方式的优先级会比原型高
var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number); //10
•总结面向对象写法
-----构造函数加属性,原型加方法
function CreatePerson(name){
this.name = name;
}
CreatePerson.prototype.showName = function(){
alert( this.name );
};
var p1 = new CreatePerson('小明');
//p1.showName();
var p2 = new CreatePerson('小强');
//p2.showName();
alert( p1.showName == p2.showName ); //true 再内存中只存在一份
面向对象的写法 按照下面的方式进行练习
<script>
function 构造函数(){
this.属性
}
构造函数.原型.方法 = function(){};
//使用
var 对象1 = new 构造函数();
对象1.方法();
</script>
举例:面向对象的选项卡
• 原则
–先写出普通的写法,然后改成面向对象写法
布局
<style>
#div1 div{ width:200px; height:200px; border:1px #000 solid; display:none;}
.active{ background:red;}
</style>
<script>
</script>
</head>
<body>
<div id="div1">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block">11111</div>
<div>22222</div>
<div>33333</div>
</div>
</body>
</html>
步骤一:普通写法
window.onload = function(){
var oParent = document.getElementById('div1');
var aInput = oParent.getElementsByTagName('input');
var aDiv = oParent.getElementsByTagName('div');
for(var i=0;i<aInput.length;i++){
aInput[i].index = i;
aInput[i].onclick = function(){
for(var i=0;i<aInput.length;i++){
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
};
}
};
步骤二:.开始改写:原则
》》. 普通方法变型
• 尽量不要出现函数嵌套函数
• 可以有全局变量 ,把局部的变成全局的变量
• 把onload中不是赋值的语句放到单独函数中
var oParent = null;
var aInput = null;
var aDiv = null;
window.onload = function(){
oParent = document.getElementById('div1');
aInput = oParent.getElementsByTagName('input');
aDiv = oParent.getElementsByTagName('div');
init();
};
function init(){
for(var i=0;i<aInput.length;i++){
aInput[i].index = i;
aInput[i].onclick = change;
}
}
function change(){
for(var i=0;i<aInput.length;i++){
aInput[i].className = '';
aDiv[i].style.display = 'none';
}
this.className = 'active';
aDiv[this.index].style.display = 'block';
}
步骤三:»改成面向对象
- 全局变量就是属性
- 函数就是方法
- Onload中创建对象 进行调用
- 改this指向问题: 事件或者是定时器,尽量让面向对象中的this指向对象
oDiv.onclick = function(){
this : oDiv
};
oDiv.onclick = show;
function show(){
this : oDiv
}
oDiv.onclick = function(){
show();
};
function show(){
this : window
}
this的指向特别容易出问题
window.onload = function(){
var t1 = new Tab();
t1.init();
};
function Tab(){
this.oParent = document.getElementById('div1');
this.aInput = this.oParent.getElementsByTagName('input');
this.aDiv = this.oParent.getElementsByTagName('div');
}
Tab.prototype.init = function(){
var This = this;
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].index = i;
this.aInput[i].onclick = function(){
This.change(this);
};
}
};
Tab.prototype.change = function(obj){
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].className = '';
this.aDiv[i].style.display = 'none';
}
obj.className = 'active';
this.aDiv[obj.index].style.display = 'block';
};
面向对象适合复杂开发,很简单的开发其实不太适合,不然反而代码更加冗长
<div id="div1">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block">11111</div>
<div>22222</div>
<div>33333</div>
</div>
<div id="div2">
<input class="active" type="button" value="1">
<input type="button" value="2">
<input type="button" value="3">
<div style="display:block">11111</div>
<div>22222</div>
<div>33333</div>
</div>
window.onload = function(){
var t1 = new Tab('div1');
t1.init();
t1.autoPlay();
var t2 = new Tab('div2');
t2.init();
t2.autoPlay();
};
function Tab(id){
this.oParent = document.getElementById(id);
this.aInput = this.oParent.getElementsByTagName('input');
this.aDiv = this.oParent.getElementsByTagName('div');
this.iNow = 0;
}
Tab.prototype.init = function(){
var This = this;
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].index = i;
this.aInput[i].onclick = function(){
This.change(this);
};
}
};
Tab.prototype.change = function(obj){
for(var i=0;i<this.aInput.length;i++){
this.aInput[i].className = '';
this.aDiv[i].style.display = 'none';
}
obj.className = 'active';
this.aDiv[obj.index].style.display = 'block';
};
Tab.prototype.autoPlay = function(){
var This = this;
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';
},2000);
};
面向对象其实就是模仿系统对象的一些行为
var arr = [4,7,1,3];
arr.sort(); // 1 3 4 7
var arr2 = [4,7,1,3];
arr2.push(5);
arr2.sort(); // 1 3 4 5 7
知识点:
- 理解面向对象
- JS中对象的组成
- 用工厂方法创建一个对象
- 原型的概念和使用
- 修改系统对象(及原型)
- 混合的构造函数/原型方式