## 面向对象
**创建多个类似对象的解决方案**
### 工厂模式
带参数的函数里面创建对象
~~~
function box(a,b){
var obj=new Object(); //创建对象
obj.a=a;
obj.b=b;
obj.run=function(){
return this.a+this.b;
}
return obj;
}
var box1=box("田伟",100); //创建对象
var box2=box('111','222');
alert(box1.run());
~~~
//识别
alert(box1 instanceof Object);
问题:多个对象无法区分是哪个函数创建的
### 构造函数模式
~~~
function Box(name,age){ //创建对象,首字母大写
//后台自动创建new Object();
this.name=name;
this.age=age;
this.run=function(){
return this.name+this.age;
}
}
var box1=new Box("田伟",100); //对象实例化
var box2=new Box("田伟",100); //对象实例化
alert(box1.run());
~~~
**好处:**
无需new Object();
无需返回
//识别
alert(box1 instanceof Box);
### 对象冒充模式
在构造函数模式上,实例方式不同
~~~
function Box(name,age){ //创建对象,首字母大写
//后台自动创建new Object();
this.name=name;
this.age=age; //实例属性
this.run=function(){ //实例方法
return this.name+this.age;
}
}
var o=new Object();
Box.call(o,"田伟",100);
alert(o.run());
~~~
* * * * *
## 原型
每个函数都一个prototype的原型属性,这个属性是对象。这个对象包含一系列共享属性和方法
函数默认生成__proto__的属性指针,指向prototype对象的属性constructor,起对象实例和原型对象对应的连接作用
~~~
function Box(){}; //什么都不能有,有的话叫实例属性
Box.prototype.name="田伟";
Box.prototype.age=100; //原型属性
Box.prototype.run=function(){ //原型方法
return this.name=this.age;
}
var box1=new Box();
alert(box1.name);
~~~
使用字面量方式创建原型对象,改造上面的例子
~~~
function Box(){};
Box.prototype={
constructor:Box,//强制指向Box
name:"田伟",
age:100,
run:function(){
return this.name+this.age;
}
}
var box1=new Box();
alert(box1.name);
~~~
如果原型里面有引用类型的属性,如数组,属性值实例化也会共享,无法独立,所以使用:
### 组合构造函数+原型模式
独立的部分用构造函数创建,共享的部分用原型创建
~~~
function Box(name,age){
this.name=name;
this.age=age;
this.family=['姐姐','妹妹'];
};
Box.prototype={
constructor:Box,
run:function(){
return this.name+this.age;
}
}
var box1=new Box("田伟",100);
alert(box1.name);
~~~
上面的例子没有封装,解决:
### 动态原型模式
把原型放到构造函数里面,但原型只应该初始化一次,if
~~~
function Box(name,age){
this.name=name;
this.age=age;
this.family=['姐姐','妹妹'];
if(typeof this.run!='function'){
Box.prototype.run=function(){
return this.name+this.age;
}
}
};
var box1=new Box("田伟",100);
alert(box1.name);
~~~
* 每个实例方法,属性的地址是不一样的
* 原型方法,属性的地址是共享的
![](https://box.kancloud.cn/ede2eb45160c1dc3bef1dc6273c6d1dc_447x372.png)
![](https://box.kancloud.cn/2fddb28f58b83794c4702382ded29a42_666x393.png)
`alert(box1.__proto__);`
实例属性和原型属性都有值,优先调用实例属性,如下:
![](https://box.kancloud.cn/861a2c60252d368dc995ba6b8bb5ebec_695x418.png)
可以删除实例属性:delete box1.name;
删除原型属性:delete Box.prototype.name;
* * * * *
基本类型也可以找出原型方法
alert(Array.prototype.sort);
## 继承
~~~
function Box(){
this.name="tian";
}
function Desk(){
this.age=100;
}
Desk.prototype=new Box(); //通过原型继承box的属性
var desk1=new Desk();
alert(desk1.name);
~~~
![](https://box.kancloud.cn/3ba2ed322a88836e55d6c9b4b778a181_735x528.png)