什么是new丑婿?
new運(yùn)算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象類型之一
舉個例子說明下:
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
}
Otaku.prototype.strength = 60
Otaku.prototype.sayYourName = function() {
console.log('I am' + this.name)
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin'
console.log(person.age) // 18
console.log(person.habit) // 'Games'
person.sayYourName() // I am Kevin
從上面的例子中扛伍,實例person可以:
- 訪問到Otaku構(gòu)造函數(shù)中的屬性
- 訪問到Otaku.prototype中的屬性
ps: new一個對象的過長
- 創(chuàng)建一個空對象
- 設(shè)置新對象的constructor屬性為構(gòu)造函數(shù)躏嚎,設(shè)置新對象__proto__屬性指向構(gòu)造函數(shù)的prototype對象
- 使用新對象調(diào)用函數(shù),函數(shù)中的this被指向到新對象的實例
- 將初始化完畢的新對象地址辅柴,保存到等號左邊的變量中
初步實現(xiàn)
因為new是關(guān)鍵字舟舒,所有我們寫一個函數(shù)來模擬new的實現(xiàn)煤伟。
分析:
- 因為new的結(jié)果是一個新對象癌佩,所以在模擬的時候,我們也要建立一個新對象便锨,假設(shè)這個對象為obj围辙,因為obj會具有Otaku構(gòu)造函數(shù)的屬性,我們可以用Otaku.apply(obj, arguments)來給obj添加新的屬性放案。
- 實例的__proto__屬性會指向構(gòu)造函數(shù)的prototype姚建,正是因為建立起這樣的關(guān)系,實例可以訪問原型上的屬性
第一版模擬:
function objectFactory() {
var obj = new Object()
var Constructor = [].shift.call(arguments)
obj.__proto__ = Constructor.prototype
Constructor.apply(obj, arguments)
return obj
}
這一版中:
- 利用new Object()的方式新建了obj
- 取出第一個參數(shù)吱殉,就是我們傳入的構(gòu)造函數(shù)掸冤。此外因為shirt會修改原數(shù)組厘托,所以arguments會被去除第一個參數(shù)
- 將obj的原型指向構(gòu)造函數(shù),這樣obj就可以訪問到構(gòu)造函數(shù)原型中的屬性
- 使用apply稿湿,改變構(gòu)造函數(shù)this的指向到新建的對象铅匹,這樣obj就可以訪問到構(gòu)造函數(shù)中的屬性
- 返回obj
返回效果的實現(xiàn)
假如構(gòu)造函數(shù)有返回值,且返回值是一個對象的時候
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
return {
name: 'Kevin1',
habit: 'Games1'
}
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin1'
console.log(person.age) // undefined
console.log(person.habit) // 'Games1'
從上面的例子中可以看到饺藤,實例person只能訪問返回的對象中的屬性包斑。
如返回值是一個基本類型的值:
function Otaku(name, age) {
this.name = name
this.age = age
this.habit = 'Games'
return 'Otaku Factory'
}
var person = new Otaku('Kevin', 18)
console.log(person.name) // 'Kevin'
console.log(person.age) // 18
console.log(person.habit) // 'Games'
如返回的是基本類型,盡管構(gòu)造函數(shù)是有返回值的策精,但是也相當(dāng)于沒有返回值進(jìn)行處理。
最終代碼實現(xiàn)
function objectFactory() {
var obj = new Object()
var Constructor = [].shift.call(arguments)
if(typeof Constructor !== 'function') {
throw new Error('first argument must be a factory function')
}
obj.__proto__ = Constructor.prototype
var ret = Constructor.apply(obj, arguments)
return typeof ret === 'object' ? ret : obj
}