JS:構(gòu)造函數(shù)總結(jié)

本文首發(fā)于 JS:構(gòu)造函數(shù)總結(jié)

什么是構(gòu)造函數(shù)旦签?

構(gòu)造函數(shù)(Constructor)的創(chuàng)建方式和普通函數(shù)一樣。但通常首字母進(jìn)行大寫(xiě),用于和普通函數(shù)區(qū)分污桦。

但是當(dāng)一個(gè)函數(shù)創(chuàng)建好以后琴庵,我們并不知道它是不是構(gòu)造函數(shù)(即使函數(shù)名的首字母為大寫(xiě))骗随。只有當(dāng)它以 new 操作符來(lái)調(diào)用的時(shí)候聘裁,我們才能說(shuō)它是一個(gè)構(gòu)造函數(shù)轰豆。

// 這是一個(gè)通用的默認(rèn)構(gòu)造函數(shù)類(lèi) Car
function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
}

// 分配給 beetle 的一個(gè)新的 Car 對(duì)象引用
let beetle = new Car("Volkswagen", "Beetle", 1938)

console.log(beetle.model) // expected output: "Beetle"

構(gòu)造函數(shù)屬于被實(shí)例化的特定類(lèi)對(duì)象

構(gòu)造函數(shù)屬于被實(shí)例化的特定類(lèi)對(duì)象胰伍,所以它的函數(shù)名同時(shí)也是它的類(lèi)名。

上面代碼中的 Car() 是一個(gè)構(gòu)造函數(shù)酸休,Car 既是它的函數(shù)名骂租,也是它的類(lèi)名。

將構(gòu)造函數(shù) Car 轉(zhuǎn)換為類(lèi)聲明如下:

class Car {
  constructor(make, model, year) {
    this.make = make
    this.model = model
    this.year = year
  }
}

構(gòu)造函數(shù)的作用

構(gòu)造函數(shù)的作用是新建實(shí)例對(duì)象斑司,并且給實(shí)例對(duì)象內(nèi)的成員(屬性或方法)賦值渗饮。

在我們需要?jiǎng)?chuàng)建大量同一類(lèi)型的對(duì)象時(shí),這些對(duì)象都具有某些屬性或方法宿刮,如果我們直接通過(guò)變量加字面量的形式進(jìn)行賦值互站,會(huì)產(chǎn)生很多重復(fù)的代碼。而當(dāng)我們將這些對(duì)象抽象為一個(gè)類(lèi)時(shí)僵缺,創(chuàng)建一個(gè)構(gòu)造函數(shù)胡桃,就可以實(shí)現(xiàn)代碼復(fù)用。

// 通過(guò)變量加字面量的形式依次進(jìn)行賦值
let beetle = { make: "Volkswagen", model: "Beetle", year: "1938" }
let porsche911 = { make: "Porsche", model: "Porsche 911", year: "1963" }
let accord = { make: "Accord", model: "Honda", year: "1976" }
// 通過(guò)構(gòu)造函數(shù)的形式進(jìn)行賦值
let beetle = new Car("Volkswagen", "Beetle", 1938)
let porsche911 = new Car("Porsche", "Porsche 911", 1963)
let accord = new Car("Accord", "Honda", 1976)

this 來(lái)設(shè)置對(duì)象內(nèi)的屬性或方法

function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
  this.introduce = function () {
    alert(`I'm the ${model}. I'm from ${make}. I was made in ${year}.`)
  }
}

通過(guò) new 操作符進(jìn)行調(diào)用

要調(diào)用構(gòu)造函數(shù)磕潮,請(qǐng)使用 new 操作符將新的對(duì)象引用分配給一個(gè)變量/常量翠胰。

let beetle = new Car("Volkswagen", "Beetle", 1938)

構(gòu)造函數(shù)的執(zhí)行過(guò)程

  • 當(dāng)以 new 操作符調(diào)用某一個(gè)構(gòu)造函數(shù)時(shí),構(gòu)造函數(shù)會(huì)立刻在堆內(nèi)存中創(chuàng)建一個(gè)新的內(nèi)存空間自脯,并將這個(gè)內(nèi)存空間的地址賦值給 this亡容。

  • 執(zhí)行函數(shù)體內(nèi)的代碼,當(dāng)構(gòu)造函數(shù)執(zhí)行完畢冤今,會(huì)將 this 賦值給一個(gè)新的實(shí)例 instance,并返回 instance茂缚。

  • 當(dāng)調(diào)用結(jié)束時(shí)戏罢,instance 就是我們所需要的新的對(duì)象。

構(gòu)造函數(shù)的返回值

默認(rèn)情況下脚囊,構(gòu)造函數(shù)的返回值是 this龟糕,即新創(chuàng)建的對(duì)象。

// 這是一個(gè)通用的默認(rèn)構(gòu)造函數(shù)類(lèi) Car
function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
}

// 分配給 beetle 的一個(gè)新的 Car 對(duì)象引用
let beetle = new Car("Volkswagen", "Beetle", 1938)

console.log(beetle) // expected output: { make: 'Volkswagen', model: 'Beetle', year: '1938' }

特殊情況下悔耘,構(gòu)造函數(shù)可以返回一個(gè)指定的值讲岁。

function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
  return {
    name: `${make} ${model} ${year}`,
  }
}

let beetle = new Car("Volkswagen", "Beetle", 1938)

console.log(beetle) // expected output: { name: 'Volkswagen Beetle 1938' }

構(gòu)造函數(shù)的繼承

通過(guò) callapply 方法

function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
}

function Wheel(make, model, year) {
  Car.call(this, make, model, year)
  this.wheels = 4
}

let beetle = new Wheel("Volkswagen", "Beetle", 1938)

console.log(beetle.wheels) // expected output: 4

通過(guò) prototype 屬性

function Car(make, model, year) {
  this.make = make
  this.model = model
  this.year = year
}

function Wheel() {
  this.wheels = 4
}

// 將 Wheel 的原型對(duì)象賦值給 Car 的原型對(duì)象
Car.prototype = new Wheel()
// 糾正繼承鏈
Car.prototype.constructor = Car

let beetle = new Car("Volkswagen", "Beetle", 1938)

console.log(beetle.wheels) // expected output: 4

構(gòu)造函數(shù)(Constructor)和類(lèi)(Class)的區(qū)別

構(gòu)造函數(shù)是一個(gè)普通的函數(shù)。在 ES6 之前,我們習(xí)慣用構(gòu)造函數(shù)去創(chuàng)建一個(gè)類(lèi)缓艳。不過(guò)后來(lái) ES6 定義了 Class 關(guān)鍵字校摩,它可以理解為是構(gòu)造函數(shù)的一個(gè)語(yǔ)法糖,可以讓我們更加方便地創(chuàng)建一個(gè)類(lèi)阶淘。

class Car {
  constructor(make, model, year) {
    this.make = make
    this.model = model
    this.year = year
  }
}

類(lèi)只能使用 new 操作符調(diào)用衙吩,否則會(huì)報(bào)錯(cuò)。

class Car {
  constructor(make, model, year) {
    this.make = make
    this.model = model
    this.year = year
  }
}
// 報(bào)錯(cuò)
Car(make, model, year) // typeError: Class constructor Car cannot be invoked without 'new'

class 可以通過(guò) extends 關(guān)鍵字很方便的實(shí)現(xiàn)繼承

class Car {
  constructor(make, model, year) {
    this.make = make
    this.model = model
    this.year = year
  }
}

class Beetle extends Car {
  constructor(make, model, year) {
    // super 用于訪問(wèn)和調(diào)用一個(gè)對(duì)象的父對(duì)象上的函數(shù)
    // 傳遞給 super 的參數(shù)會(huì)被傳遞給父類(lèi)的構(gòu)造函數(shù)
    super(make, model, year)
    // super() 只能在使用 this 之前調(diào)用
    this.wheels = 4
  }
}

let myBeetle = new Beetle("volkswagen", "beetle", 1967)

console.log(myBeetle) // expected output: Beetle {make: "volkswagen", model: "beetle", year: 1967, wheels: 4}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溪窒,一起剝皮案震驚了整個(gè)濱河市坤塞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澈蚌,老刑警劉巖摹芙,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宛瞄,居然都是意外死亡浮禾,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)坛悉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)伐厌,“玉大人,你說(shuō)我怎么就攤上這事裸影≌豕欤” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵轩猩,是天一觀的道長(zhǎng)卷扮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)均践,這世上最難降的妖魔是什么晤锹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮彤委,結(jié)果婚禮上鞭铆,老公的妹妹穿的比我還像新娘。我一直安慰自己焦影,他們只是感情好车遂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著斯辰,像睡著了一般舶担。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彬呻,一...
    開(kāi)封第一講書(shū)人閱讀 51,182評(píng)論 1 299
  • 那天衣陶,我揣著相機(jī)與錄音柄瑰,去河邊找鬼。 笑死剪况,一個(gè)胖子當(dāng)著我的面吹牛教沾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拯欧,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼详囤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了镐作?” 一聲冷哼從身側(cè)響起藏姐,我...
    開(kāi)封第一講書(shū)人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎该贾,沒(méi)想到半個(gè)月后羔杨,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杨蛋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年兜材,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逞力。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡曙寡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寇荧,到底是詐尸還是另有隱情举庶,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布揩抡,位于F島的核電站户侥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏峦嗤。R本人自食惡果不足惜蕊唐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烁设。 院中可真熱鬧替梨,春花似錦、人聲如沸装黑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)曹体。三九已至,卻和暖如春硝烂,著一層夾襖步出監(jiān)牢的瞬間箕别,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留串稀,地道東北人除抛。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像母截,于是被迫代替她去往敵國(guó)和親到忽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容