什么是面向对象?
1.面向对象的概念
面向对象是一种以抽象方式创建基于现实世界模型的思想!英文简称OOP
2.面向对象的特征/特点
面向对象具有三大特征: 封装、继承、多态
3.使用面向对象的优点/优势
优点/优势
- 灵活性
- 可维护性
- 复用性
创建面向对象有几种模式?
- 工厂模式(创建多个相似对象)
- 构造函数模式(不完美,实例的每个方法都是又创建了一次)
- 原型模式(有不能修改数据的问题,修改一个实力影响多个实例)
- 构造+原型(几近完美,构造函数内写属性,原型内写方法。解决了他们各自的缺点)
继承
- 原型链继承
- 构造函数继承
- 寄生组合继承
原型链继承
function Father(){
this.money=1000,
this.house=2
}
Father.prototype.eat=function(){
console.log('noodle')
}
function Son(){
this.name='张三'
}
var p = new Father();
Son.prototype=p;
var son=new Son();
console.log(son.name)
console.log(son.money)
console.log(son.house)
console.log(son.eat())
原型链存在的问题:
- (1)子类型的所有实例都可以共享父类型的属性
- (2)子类型的实例无法在不影响所有对象的情况下,给父类型的构造函数传递参数,就是你想修改某个实例属性的时候,修改的会是每个实例的属性
如此完成了原型链继承!
构造函数+原型链+call/apply继承
function Father(){
this.money=1000,
this.house=2,
this.food=['banana']
}
Father.prototype.eat=function(){
console.log('noodle')
}
function Son(){
Father.call(this)
this.name='张三'
}
var p = new Father();
Son.prototype=p;
Son.prototype.constructor=Son;
var son=new Son();
var son2=new Son();
son2.food.push('apple')
console.log(son.food)
console.log(son2.food)
完美解决了不能更改引用数据缺点!下面是解决传参的问题
function Father(money,house,food){
this.money=money,
this.house=house,
this.food=food
}
Father.prototype.eat=function(){
console.log('noodle')
}
function Son(name,money,house,food){
Father.call(this,money,house,food);
this.name=name
}
var p = new Father();//不需要在这里传参
Son.prototype=p;
Son.prototype.constructor=Son;
var son=new Son('Tom',2104132,'2套',['banana']);
var son2=new Son('Jack',210412,'1套',[]);
son2.food.push('apple')
console.log(son.food)
console.log(son2.food)
还存在的一个问题
- 因为call本来就拷贝了一份需要继承的数据,而在p的实例中也有一份,又因为p中有继承的方法不可舍去,所以相当于写了重复的代码
- 接下来会使用寄生式组合继承解决这个问题
寄生式组合继承
function Father(money,house,food){
this.money=money,
this.house=house,
this.food=food
}
Father.prototype.eat=function(){
console.log('noodle')
}
function Son(name,money,house,food){
Father.call(this,money,house,food);
this.name=name
}
function Temp(){
}
Temp.prototype=Father.prototype;
var temp = new Temp() ;//不需要在这里传参
Son.prototype=temp;
temp.constructor=Son;
var son=new Son('Tom',2104132,'2套',['banana']);
var son2=new Son('Jack',210412,'1套',[]);
son2.food.push('apple')
console.log(son.food)
console.log(son2.food)
console.log(son2.eat())
完美的解决代码重复的问题,原理就是在Son与Father增加一个叫Temp的构造函数,让Temp的实例成为Son实例与Father.prototype的纽扣。
理解:没有new Father 的动作,只是让son,son2经过temp找到了Temp.prototype的eat方法