## 面向對象
**創建多個類似對象的解決方案**
### 工廠模式
帶參數的函數里面創建對象
~~~
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);
~~~
* 每個實例方法,屬性的地址是不一樣的
* 原型方法,屬性的地址是共享的


`alert(box1.__proto__);`
實例屬性和原型屬性都有值,優先調用實例屬性,如下:

可以刪除實例屬性: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);
~~~
