JavaScript構(gòu)造函數(shù)殖妇、實(shí)例、原型對象以及原型鏈

構(gòu)造函數(shù)是一種特殊的函數(shù)破花,主要用來初始化對象谦趣,即為對象成員變量賦初始值,它總與 new 一起使用座每。我們可以把對象中一些公共的屬性和方法抽取出來蔚润,然后封裝到這個(gè)函數(shù)里面。

? ? // 利用構(gòu)造函數(shù)創(chuàng)建對象

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? ? ? this.sing = function() {

? ? ? ? ? ? console.log('我會唱歌');

? ? ? ? }

? ? }

? ? var ldh = new Person('劉德華', 18);

? ? var zxy = new Person('張學(xué)友', 19);

? ? console.log(ldh);

? ? ldh.sing();

? ? zxy.sing();

在 JS 中尺栖,使用構(gòu)造函數(shù)時(shí)要注意以下兩點(diǎn):

構(gòu)造函數(shù)用于創(chuàng)建某一類對象,其首字母要大寫

構(gòu)造函數(shù)要和 new 一起使用才有意義

new 在執(zhí)行時(shí)會做四件事情:

① 在內(nèi)存中創(chuàng)建一個(gè)新的空對象烦租。

② 讓 this 指向這個(gè)新的對象延赌。

③ 執(zhí)行構(gòu)造函數(shù)里面的代碼,給這個(gè)新對象添加屬性和方法叉橱。

④ 返回這個(gè)新對象(所以構(gòu)造函數(shù)里面不需要 return )挫以。

JavaScript 的構(gòu)造函數(shù)中可以添加一些成員,可以在構(gòu)造函數(shù)本身上添加窃祝,也可以在構(gòu)造函數(shù)內(nèi)部的 this 上添加掐松。通過這兩種方式添加的成員,就分別稱為靜態(tài)成員和實(shí)例成員粪小。

靜態(tài)成員:在構(gòu)造函數(shù)本上添加的成員稱為靜態(tài)成員大磺,只能由構(gòu)造函數(shù)本身來訪問

//靜態(tài)成員 在構(gòu)造函數(shù)本身上添加的成員? sex 就是靜態(tài)成員

// 靜態(tài)成員只能通過構(gòu)造函數(shù)來訪問

Person.sex = '男';

console.log(Person.sex);

實(shí)例成員:在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象成員稱為實(shí)例成員,只能由實(shí)例化的對象來訪問

function Person(uname) {

? ? ? ? ? ? this.uname = uname;

? ? ? ? ? ? }

實(shí)例成員就是構(gòu)造函數(shù)內(nèi)部通過this添加的成員 uname就是實(shí)例成員

構(gòu)造函數(shù)通過原型分配的函數(shù)是所有對象所共享的探膊。

JavaScript 規(guī)定杠愧,每一個(gè)構(gòu)造函數(shù)都有一個(gè) prototype 屬性,指向另一個(gè)對象逞壁。注意這個(gè) prototype 就是一個(gè)對象流济,這個(gè)對象的所有屬性和方法,都會被構(gòu)造函數(shù)所擁有腌闯。

我們可以把那些不變的方法绳瘟,直接定義在 prototype 對象上,這樣所有對象的實(shí)例就可以共享這些方法姿骏。

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? ? ? // this.sing = function() {

? ? ? ? //? ? console.log('我會唱歌');

? ? ? ? // }

? ? }

? ? //? 一般情況下,我們的公共屬性定義到構(gòu)造函數(shù)里面, 公共的方法我們放到原型對象身上

? ? Person.prototype.sing = function() {

? ? ? ? console.log('我會唱歌');

? ? }

? ? var ldh = new Person('劉德華', 18);

? ? var zxy = new Person('張學(xué)友', 19);

? ? console.log(ldh.sing === zxy.sing); //true

? ? ldh.sing();

? ? zxy.sing();

原型是什么 糖声?

一個(gè)對象,我們也稱為 prototype 為原型對象。

原型的作用是什么 姨丈?

共享方法畅卓。

對象都會有一個(gè)屬性__proto__ 指向構(gòu)造函數(shù)的 prototype原型對象,之所以我們對象可以使用構(gòu)造函數(shù)prototype 原型對象的屬性和方法蟋恬,就是因?yàn)閷ο笥衉_proto__原型的存在翁潘。

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? }

? ? Person.prototype.sing = function() {

? ? ? ? console.log('我會唱歌');

? ? }

? ? var mingo = new Person('小明', 18);

? ? var zxy = new Person('張學(xué)友', 19);

? ? mingo.sing();

? ? console.log(mingo); // 對象身上系統(tǒng)自己添加一個(gè) __proto__ 指向我們構(gòu)造函數(shù)的原型對象 prototype

? ? console.log(mingo.__proto__ === Person.prototype); //true

__proto__對象原型和原型對象prototype是等價(jià)的

(如圖箭頭指向,mingo是Person構(gòu)造函數(shù)創(chuàng)建出來的一個(gè)對象實(shí)例歼争,這個(gè)對象實(shí)例的原型(__proto__)拜马,就是Person構(gòu)造函數(shù)的原型對象prototype。)

__proto__對象原型的意義就在于為對象的查找機(jī)制提供一個(gè)方向沐绒,或者說一條路線俩莽,但是它是一個(gè)非標(biāo)準(zhǔn)屬性, 因此實(shí)際開發(fā)中乔遮,不可以使用這個(gè)屬性扮超,它只是內(nèi)部指向原型對象 prototype

對象原型__proto__和構(gòu)造函數(shù)prototype原型對象(其實(shí)指的就是同一個(gè))里面有一個(gè)屬性 constructor 屬性 ,constructor 我們稱 為構(gòu)造函數(shù)蹋肮,因?yàn)樗富貥?gòu)造函數(shù)本身出刷。

constructor 主要用于記錄該對象引用于哪個(gè)構(gòu)造函數(shù),它可以讓原型對象重新指向原來的構(gòu)造函數(shù)坯辩。

一般情況下馁龟,對象的方法都在構(gòu)造函數(shù)的原型對象中設(shè)置。如果有多個(gè)對象的方法漆魔,我們可以給原型對象采取對象形式賦值坷檩,但是這樣就會覆蓋構(gòu)造函數(shù)原型對象原來的內(nèi)容,這樣修改后的原型對象 constructor 就不再指向當(dāng)前構(gòu)造函數(shù)了改抡。

此時(shí)矢炼,我們可以在修改后的原型對象中,添加一個(gè) constructor 指向原來的構(gòu)造函數(shù)雀摘。

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? }

? ? // 很多情況下,我們需要手動的利用constructor 這個(gè)屬性指回 原來的構(gòu)造函數(shù)

? ? Person.prototype = {

? ? ? ? // 如果我們修改了原來的原型對象,給原型對象賦值的是一個(gè)對象,則必須手動的利用constructor指回原來的構(gòu)造函數(shù)

? ? ? ? constructor: Person,

? ? ? ? sing: function() {

? ? ? ? ? ? console.log('我會唱歌');

? ? ? ? },

? ? ? ? movie: function() {

? ? ? ? ? ? console.log('我會演電影');

? ? ? ? }

? ? }

? ? var mingo = new Person('小明', 18);

? ? var zxy = new Person('張學(xué)友', 19);

? ? console.log(Person.prototype);

? ? console.log(mingo.__proto__);

? ? console.log(Person.prototype.constructor);

? ? console.log(mingo.__proto__.constructor);

每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對象裸删,原型對象都包含一個(gè)指向構(gòu)造函數(shù)的指針,而實(shí)例都包含一個(gè)指向原型對象的內(nèi)部指針阵赠。那么假如我們讓原型對象等于另一個(gè)類型的實(shí)例涯塔,結(jié)果會怎樣?顯然清蚀,此時(shí)的原型對象將包含一個(gè)指向另一個(gè)原型的指針匕荸,相應(yīng)地,另一個(gè)原型中也包含著一個(gè)指向另一個(gè)構(gòu)造函數(shù)的指針枷邪。假如另一個(gè)原型又是另一個(gè)類型的實(shí)例榛搔,那么上述關(guān)系依然成立。如此層層遞進(jìn),就構(gòu)成了實(shí)例與原型的鏈條践惑。這就是所謂的原型鏈的基本概念腹泌。——摘自《javascript高級程序設(shè)計(jì)》

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? }

? ? Person.prototype.sing = function() {

? ? ? ? console.log('我會唱歌');

? ? }

? ? var mingo = new Person('小明', 18);

? ? // 1. 只要是對象就有__proto__ 原型, 指向原型對象

? ? console.log(Person.prototype);

? ? console.log(Person.prototype.__proto__ === Object.prototype);//true

? ? // 2.我們Person原型對象里面的__proto__原型指向的是 Object.prototype

? ? console.log(Object.prototype.__proto__);

? ? // 3. 我們Object.prototype原型對象里面的__proto__原型? 指向?yàn)?null

? ? console.log(Object);

Object 是 JavaScript 中最頂級的對象尔觉,其它所有對象都是基于它的凉袱,包括你創(chuàng)建的函數(shù)

① 當(dāng)訪問一個(gè)對象的屬性(包括方法)時(shí),首先查找這個(gè)對象自身有沒有該屬性侦铜。

② 如果沒有就查找它的原型(也就是 __proto__指向的 prototype 原型對象)专甩。

③ 如果還沒有就查找原型對象的原型(Object的原型對象)。

④ 依此類推一直找到 Object 為止(null)钉稍。

⑤ __proto__對象原型的意義就在于為對象成員查找機(jī)制提供一個(gè)方向涤躲,或者說一條路線。

1構(gòu)造函數(shù)中的this 指向我們實(shí)例對象

2原型對象里面放的是方法, 這個(gè)方法里面的this 指向的是 這個(gè)方法的調(diào)用者, 也就是這個(gè)實(shí)例對象

? ? function Person(uname, age) {

? ? ? ? this.uname = uname;

? ? ? ? this.age = age;

? ? }

? ? var that;

? ? Person.prototype.sing = function() {

? ? ? ? console.log('我會唱歌');

? ? ? ? that = this;

? ? ? ? console.log(this);


? ? }

? ? var mingo = new Person('小明', 18);

? ? // 1. 在構(gòu)造函數(shù)中,里面this指向的是對象實(shí)例 mingo

? ? // 2.原型對象函數(shù)里面的this 指向的也是 實(shí)例對象 mingo

? ? mingo.sing();

? ? console.log(that === mingo); //true

深圳網(wǎng)站建設(shè)www.sz886.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末贡未,一起剝皮案震驚了整個(gè)濱河市种樱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俊卤,老刑警劉巖缸托,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瘾蛋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)矫限,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門哺哼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叼风,你說我怎么就攤上這事取董。” “怎么了无宿?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵茵汰,是天一觀的道長。 經(jīng)常有香客問我孽鸡,道長蹂午,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任彬碱,我火速辦了婚禮豆胸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘巷疼。我一直安慰自己晚胡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著估盘,像睡著了一般瓷患。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遣妥,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天擅编,我揣著相機(jī)與錄音,去河邊找鬼燥透。 笑死沙咏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的班套。 我是一名探鬼主播肢藐,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼吱韭!你這毒婦竟也來了吆豹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤理盆,失蹤者是張志新(化名)和其女友劉穎痘煤,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體猿规,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡衷快,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了姨俩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蘸拔。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖环葵,靈堂內(nèi)的尸體忽然破棺而出调窍,到底是詐尸還是另有隱情,我是刑警寧澤张遭,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布邓萨,位于F島的核電站,受9級特大地震影響菊卷,放射性物質(zhì)發(fā)生泄漏缔恳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一洁闰、第九天 我趴在偏房一處隱蔽的房頂上張望褐耳。 院中可真熱鬧,春花似錦渴庆、人聲如沸铃芦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刃滓。三九已至仁烹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咧虎,已是汗流浹背卓缰。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留砰诵,地道東北人征唬。 一個(gè)月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像茁彭,于是被迫代替她去往敵國和親总寒。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355