JavaScrpit中new的實(shí)現(xiàn)(筆記)

new


一句話介紹 new:

new 運(yùn)算符創(chuàng)建一個(gè)用戶(hù)定義的對(duì)象類(lèi)型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象類(lèi)型之一

也許有點(diǎn)難懂,我們?cè)谀M new 之前,先看看 new 實(shí)現(xiàn)了哪些功能。

舉個(gè)例子:

// Muku 御宅族,簡(jiǎn)稱(chēng)宅
function Muku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}

// 因?yàn)槿狈﹀憻挼木壒?,身體強(qiáng)度讓人擔(dān)憂
Muku.prototype.strength = 60;

Muku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

var person = new Muku('Kevin', '18');

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60

person.sayYourName(); // I am Kevin復(fù)制代碼

從這個(gè)例子中,我們可以看到,實(shí)例 person 可以:

  1. 訪問(wèn)到 Muku 構(gòu)造函數(shù)里的屬性
  2. 訪問(wèn)到 Muku.prototype 中的屬性
    接下來(lái),我們可以嘗試著模擬一下了。

因?yàn)?new 是關(guān)鍵字,所以無(wú)法像 bind 函數(shù)一樣直接覆蓋,所以我們寫(xiě)一個(gè)函數(shù),命名為 objectFactory,來(lái)模擬 new 的效果。用的時(shí)候是這樣的:

function Muku () {
    ……
}

// 使用 new
var person = new Muku(……);
// 使用 objectFactory
var person = objectFactory(Muku, ……)復(fù)制代碼

初步實(shí)現(xiàn)

分析:

因?yàn)?new 的結(jié)果是一個(gè)新對(duì)象,所以在模擬實(shí)現(xiàn)的時(shí)候,我們也要建立一個(gè)新對(duì)象,假設(shè)這個(gè)對(duì)象叫 obj,因?yàn)?obj 會(huì)具有Muku 構(gòu)造函數(shù)里的屬性,想想經(jīng)典繼承的例子,我們可以使用 Muku.apply(obj, arguments)來(lái)給 obj 添加新的屬性。

我們知道實(shí)例的 proto 屬性會(huì)指向構(gòu)造函數(shù)的 prototype,也正是因?yàn)榻⑵疬@樣的關(guān)系,實(shí)例可以訪問(wèn)原型上的屬性。

現(xiàn)在,我們可以嘗試著寫(xiě)第一版了:

// 第一版代碼
function objectFactory() {
    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    Constructor.apply(obj, arguments);

    return obj;

};復(fù)制代碼

在這一版中,我們:

  1. new Object() 的方式新建了一個(gè)對(duì)象 obj
  2. 取出第一個(gè)參數(shù),就是我們要傳入的構(gòu)造函數(shù)。此外因?yàn)?shift 會(huì)修改原數(shù)組,所以 arguments 會(huì)被去除第一個(gè)參數(shù)
  3. obj 的原型指向構(gòu)造函數(shù),這樣 obj 就可以訪問(wèn)到構(gòu)造函數(shù)原型中的屬性
  4. 使用 apply,改變構(gòu)造函數(shù) this 的指向到新建的對(duì)象,這樣 obj 就可以訪問(wèn)到構(gòu)造函數(shù)中的屬性
  5. 返回 obj
function Muku (name, age) {
    this.name = name;
    this.age = age;

    this.habit = 'Games';
}

Muku.prototype.strength = 60;

Muku.prototype.sayYourName = function () {
    console.log('I am ' + this.name);
}

function objectFactory() {
    var obj = new Object(),
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    Constructor.apply(obj, arguments);
    return obj;
};

var person = objectFactory(Muku, 'Kevin', '18')

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // 60

person.sayYourName(); // I am Kevin復(fù)制代碼

返回值效果實(shí)現(xiàn)

接下來(lái)我們?cè)賮?lái)看一種情況,假如構(gòu)造函數(shù)有返回值,舉個(gè)例子:

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return {
        name: name,
        habit: 'Games'
    }
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // Kevin
console.log(person.habit) // Games
console.log(person.strength) // undefined
console.log(person.age) // undefined復(fù)制代碼

在這個(gè)例子中,構(gòu)造函數(shù)返回了一個(gè)對(duì)象,在實(shí)例 person 中只能訪問(wèn)返回的對(duì)象中的屬性。

而且還要注意一點(diǎn),在這里我們是返回了一個(gè)對(duì)象,假如我們只是返回一個(gè)基本類(lèi)型的值呢?

再舉個(gè)例子:

function Otaku (name, age) {
    this.strength = 60;
    this.age = age;

    return 'handsome boy';
}

var person = new Otaku('Kevin', '18');

console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.strength) // 60
console.log(person.age) // 18復(fù)制代碼

結(jié)果完全顛倒過(guò)來(lái),這次盡管有返回值,但是相當(dāng)于沒(méi)有返回值進(jìn)行處理。

所以我們還需要判斷返回的值是不是一個(gè)對(duì)象,如果是一個(gè)對(duì)象,我們就返回這個(gè)對(duì)象,如果沒(méi)有,我們?cè)摲祷厥裁淳头祷厥裁础?/p>

再來(lái)看第二版的代碼,也是最后一版的代碼:

// 第二版的代碼
function objectFactory() {
    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    var ret = Constructor.apply(obj, arguments);

    return typeof ret === 'object' ? ret : obj;

};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容