JS面向对象基础篇

什么是面向对象编程

用对象的思想去写代码,就是面向对象编程
数组 Array 时间 Date

面向对象编程(OOP)的特点

抽象:抓住核心问题
封装:只能通过对象来访问方法
继承:从已有对象上继承出新的对象
多态:多对象的不同形态

对象的组成

方法(行为、操作)——函数:过程、动态的
属性——对象下面的变量:状态、静态的

工厂方式

面向对象中的封装函数
改成与系统对象类似写法
首字母大写
New 关键字提取

当new去调用一个函数,函数中的this就是新创建的对象,而且函数的返回值直接为this(隐式返回)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function CreatePerson(name) {
//原料
//var obj = new Object();
//加工
this.name = name;
this.showName = function() {
alert(this.name);
};
//出厂
//return obj; 隐式返回可省略return
}
var p1 = new CreatePerson("adele");
p1.showName();
var p2 = new CreatePerson("adai");
p2.showName();

new后面调用的函数叫做构造函数
构造函数:用来创建对象的函数,叫做构造函数
存在的问题:存在多份showName方法(浪费内存)

1
p1.showName == p2.showName //false

参考分析:
基本类型 : 赋值的时候只是值的复制

1
2
3
4
5
var a = 5;
var b = a;
b += 3;
alert(b); //8
alert(a); //5

对象类型 : 赋值不仅是值的复制,而且也是引用的传递

1
2
3
4
5
var a = [1,2,3];
var b = a;
b.push(4);
alert(b); //[1,2,3,4]
alert(a); //[1,2,3,4]

赋值会在内存中重新生成

1
2
3
4
5
var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(b); //[1,2,3,4]
alert(a); //[1,2,3]

基本类型 比较: 值相同就可以

1
2
3
var a = 5;
var b = 5;
alert(a == b); //true

对象类型比较 : 值和引用都相同才行

1
2
3
4
5
6
7
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

原型-prototype

概念:重写对象方法,让相同方法在内存中存在一份(提高性能)
类比理解:
原型类似于CSS中的Class
普通方法类似于CSS中的Style
普通方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 : 要写在构造函数的下面

1
2
3
4
5
6
7
8
9
10
11
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

原型的优先级低于普通方法

1
2
3
4
var arr = [];
arr.number = 10;
Array.prototype.number = 20;
alert(arr.number); //10

通过原型改写工厂方式

1
2
3
4
5
6
7
8
9
10
11
12
function CreatePerson(name){
this.name = name;
}
CreatePerson.prototype.showName = function(){
alert( this.name );
};
var p1 = new CreatePerson('adele');
p1.showName();
var p2 = new CreatePerson('adai');
p2.showName();
alert( p1.showName == p2.showName ); //true

原则:相同的属性和方法可以加在原型上
面向对象写法(初级):

1
2
3
4
5
6
function 构造函数(){
this.属性
}
构造函数.原型.方法 = function(){};
var 对象1 = new 构造函数();
对象1.方法();

面向对象的选项卡
原则
先写出普通的写法,然后改成面向对象写法
普通方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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中不是赋值的语句放到单独函数中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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指向问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
window.onload = function(){
var t1 = new Tab();
t1.init();
t1.autoPlay();
};
function Tab(){
this.oParent = document.getElementById('div1');
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);
};

this指向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
oDiv.onclick = function(){
this : oDiv
};
oDiv.onclick = show;
function show(){
this : oDiv
}
oDiv.onclick = function(){
show();
};
function show(){
this : window
}