# 創建對象的方式
## 創建對象的方式1:使用Object構造器
```
var box = new Object()
box.name = 'lee'
```
存在的問題是:創建多個類似的對象,就需要重復實例化,寫多次上面的重復代碼
## 創建對象的方式2:工廠模式
```
funciton createObject (name, age) {
var obj = new Object()
obj.name = name
obj.age = age
obj.run = function () {
return this.name + this.age
}
return obj
}
var box1 = createObject('Lee', 100)
var box2 = createObject('Jack', 200)
alert(box1.run())
alert(box2.run())
```
工廠模式解決了重復實例化的問題,但還有一個問題,那就是識別問題,因為根部無法搞清楚他們到底是哪個對象的實例
```
typeof box1 // object
typeof box2 // object
box1 instanceof Object // true
box2 instanceof Object // true
```
無論怎樣,所產生的所有實例都是Object類型,無法區分每個實例到底是那個對象的實例
## 創建對象的方式3:構造函數(方法)
ECMAScript中可以詞用構造函數(方法)可以用來創建特定的對象。類似于Object對象
```
function Box (username, age) {
this.username = username
this.age = age
this.run = function () {
return this.username + this.age
}
}
var box1 = new Box('Lee', 100)
var box2 = new Box('Jack', 200)
box1 instanceof Box // true,即通過Box產生的實例都是Box類型的
```
即解決了重復實例化的問題,又解決了對象識別的問題,但問題是,這里并沒有new Object(),為什么可以實例化Box()?這個是哪里來的呢?
使用了構造函數的方法,和使用工廠模式的方法他們不同之處如下:
1. 構造函數方式沒有顯示的創建對象(new Object());
2. 直接將屬性和方法賦值給this對象;
3. 沒有return語句。
規范:
1. 函數名和實例化構造名相同且大寫(PS:非強制,單這么寫有助于區分構造函數和普通函數)
2. 通過構造函數創建對象,必須使用new 運算符
構造函數生產對象的過程如下:
1. 當使用了構造函數,并且new 構造函數(),那么后臺就自動執行了 new Object();
2. 將構造函數的作用于給新對象,(即 new Object()創建出來的對象),而函數體內部的this就代表new Object()出來的對象;
3. 執行構造函數內部的代碼;
4. 返回新對象(后臺直接返回)。
使用對象冒充的方式進行調用:
```
var obj = new Object()
Box.call(obj, 'Lee', 100)
obj.run()
```
構造函數內部的方法是引用類型,相當于
```
this.run = new Function('return this.name + this.age')
```
這樣一來每個實例都會有自己的一個run方法體占據內存空間,可以通過構造函數外面綁定一個函數的方法來保證引用地址的一致性,但這種做法沒什么必要,并且因為run()是全局函數,所以外部也可以調用
```
function Box (username, age) {
this.username = username
this.age = age
this.run = run
}
function run () {
return this.username + this.age
}
run() // 外部惡意調用
```