js基礎(chǔ)之原型(構(gòu)造函數(shù)、原型和實(shí)例之間的那些屬性)

先看一張圖栽烂!展示了構(gòu)造函數(shù)躏仇、原型和實(shí)例之間的關(guān)系。

由相互關(guān)聯(lián)的原型組成的鏈狀結(jié)構(gòu)就是原型鏈

從圖中可看出腺办,js 中與原型相關(guān)的屬性:對(duì)象有 [[prototype]]屬性(內(nèi)部屬性)焰手、函數(shù)對(duì)象有prototype屬性、原型對(duì)象有constructor屬性怀喉。

[[prototype]]

在 JavaScript 中书妻,原型也是一個(gè)對(duì)象,通過(guò)原型可以實(shí)現(xiàn)對(duì)象的屬性繼承躬拢,JavaScript 的對(duì)象中都包含了一個(gè)" [[Prototype]]"內(nèi)部屬性躲履,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型。這是每一個(gè) JavaScript對(duì)象(除了 null )都具有的一個(gè)屬性.

內(nèi)部屬性聊闯,是不能被直接訪問(wèn)的工猜。所以為了方便查看一個(gè)對(duì)象的原型,F(xiàn)irefox和Chrome中提供了__proto__這個(gè)非標(biāo)準(zhǔn)(不是所有瀏覽器都支持)的訪問(wèn)器(ES5引入了標(biāo)準(zhǔn)對(duì)象原型訪問(wèn)器Object.getPrototype(object))菱蔬。

function Person() {

}
var person = new Person();
console.log(person.__proto__) ;// Person {}
// console.log(Object.getPrototypeOf(person)); // Person {}
console.log(person.__proto__.__proto__); // Object {}

通過(guò)輸出結(jié)果可以看到篷帅,Person {}作為一個(gè)原型對(duì)象,也有__proto__屬性(對(duì)應(yīng)原型的原型)拴泌。

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

null 表示“沒(méi)有對(duì)象”犹褒,即該處不應(yīng)該有值。
所以 Object.prototype.__proto__的值為 null 跟 Object.prototype 沒(méi)有原型弛针,其實(shí)表達(dá)了一個(gè)意思叠骑。

所以查找屬性的時(shí)候查到 Object.prototype 就可以停止查找了。

prototype

在 JavaScript 中削茁,每個(gè)函數(shù)都有一個(gè) prototype 屬性宙枷。當(dāng)一個(gè)函數(shù)被用作構(gòu)造函數(shù)來(lái)創(chuàng)建實(shí)例時(shí),該函數(shù)的 prototype 屬性值將被作為原型賦值給所有對(duì)象實(shí)例(也就是該實(shí)例的__proto__屬性)茧跋,即所有實(shí)例的原型引用的是函數(shù)的 prototype 屬性慰丛。

注:prototype 屬性是函數(shù)對(duì)象特有的。(函數(shù)才會(huì)有的屬性)

function Person() {

}
var person = new Person();
console.log(Person.prototype); // Person {}
console.log(person.__proto__ === Person.prototype) ;// true
// console.log(Object.getPrototypeOf(person) === Person.prototype) // true
console.log(Person.prototype.__proto__) // Object {}
// Person.prototype.__proto__ === Object.prototype // true
console.log(Object.prototype); // Object {}

當(dāng)通過(guò)Person.prototype.__proto__語(yǔ)句獲取實(shí)例 person 對(duì)象原型的原型時(shí)候瘾杭,將得到Object {}對(duì)象诅病,可以看到所有對(duì)象的原型都將追溯到Object {}對(duì)象

  • 查看函數(shù)對(duì)象 Function 的原型
function Person() {}
console.log(Person.__proto__ === Function.prototype); // true
console.log(Person.constructor === Function); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
console.log(Function.prototype.constructor === Function); // true

在 JavaScript 中有個(gè) Function 對(duì)象(類似Object),這個(gè)對(duì)象本身是個(gè)函數(shù)贤笆;所有的函數(shù)(包括Function蝇棉,Object)的原型(__proto__)都是Function.prototype

Function 對(duì)象作為一個(gè)函數(shù)芥永,就會(huì)有prototype屬性篡殷,該屬性將對(duì)應(yīng) function () {}對(duì)象。
Function 對(duì)象作為一個(gè)對(duì)象埋涧,就有__proto__屬性板辽,該屬性對(duì)應(yīng)"Function.prototype",也就是說(shuō)棘催,Function.__proto__ === Function.prototype
對(duì)于 Function 的原型對(duì)象Function.prototype劲弦,該原型對(duì)象的__proto__屬性將對(duì)應(yīng)Object {}

  • 如何理解原型:每一個(gè)JavaScript對(duì)象(null除外)在創(chuàng)建的時(shí)候就會(huì)與之關(guān)聯(lián)另一個(gè)對(duì)象,這個(gè)對(duì)象就是我們所說(shuō)的原型醇坝,每一個(gè)對(duì)象都會(huì)從原型"繼承"屬性瓶您。

上面說(shuō)的都是通過(guò)構(gòu)造函數(shù)創(chuàng)建對(duì)象,當(dāng)使用對(duì)象字面量的形式創(chuàng)建對(duì)象時(shí)纲仍,該對(duì)象的原型就是Object.prototype

let obj = {};
obj.__proto__ === Object.prototype;

construcor

每個(gè)原型對(duì)象都有一個(gè) constructor 屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)贸毕。

實(shí)例與原型(原型鏈的屬性查找):當(dāng)讀取實(shí)例的屬性時(shí)郑叠,如果找不到,就會(huì)查找該實(shí)例對(duì)象關(guān)聯(lián)的原型中的屬性明棍,如果還查不到乡革,就去找原型的原型,一直找到最頂層 Object 為止摊腋。如果仍然沒(méi)有找到指定的屬性沸版,就會(huì)返回 undefined。

即當(dāng)通過(guò)原型鏈查找一個(gè)屬性的時(shí)候兴蒸,首先查找的是對(duì)象本身的屬性视粮,如果找不到才會(huì)繼續(xù)按照原型鏈進(jìn)行查找。

function Person() {
}
var person = new Person();
console.log(Person === Person.prototype.constructor); // true
console.log(person.constructor == Person); // true

當(dāng)獲取 person.constructor 時(shí)橙凳,其實(shí) person 中并沒(méi)有 constructor 屬性,當(dāng)不能讀取到constructor 屬性時(shí)蕾殴,會(huì)從 person 的原型也就是 Person.prototype 中讀取。

構(gòu)造函數(shù) Person 利用其原型對(duì)象上的 constructor 引用了自身岛啸,當(dāng)構(gòu)造函數(shù) Person 作為構(gòu)造函數(shù)來(lái)創(chuàng)建對(duì)象時(shí)钓觉,原型上的 constructor 就被遺傳到了新創(chuàng)建的實(shí)例對(duì)象上,從原型鏈角度講坚踩,構(gòu)造函數(shù) Person 就是新對(duì)象的類型荡灾。這樣做的意義是,讓新對(duì)象在誕生以后,就具有可追溯的數(shù)據(jù)類型批幌。

由此础锐,可以通過(guò)constructor這個(gè)屬性,來(lái)判斷一個(gè)對(duì)象類型逼裆。尤其用來(lái)判斷 js 內(nèi)置對(duì)象的類型郁稍。

判斷內(nèi)置對(duì)象的類型

  1. null 和 undefined 是無(wú)效的對(duì)象,因此是不會(huì)有 constructor 存在的胜宇,這兩種類型的數(shù)據(jù)需要通過(guò)其他方式來(lái)判斷耀怜。
  2. 函數(shù)的 constructor 是不穩(wěn)定的,這個(gè)主要體現(xiàn)在自定義對(duì)象上桐愉,當(dāng)開(kāi)發(fā)者重寫 prototype 后财破,原有的 constructor 引用會(huì)丟失,constructor 會(huì)默認(rèn)為 Object
function Person () {}
Person.prototype = {'name': 'xql'};
var person = new Person();
console.log(person.constructor === Person); // false
console.log(person.constructor === Object); // true

prototype 被重新賦值的是一個(gè) { }从诲, { } 是 new Object() 的字面量左痢,因此 new Object() 會(huì)將 Object 原型上的 constructor 傳遞給 { },也就是 Object 本身系洛。

通常俊性,為了規(guī)范開(kāi)發(fā),在重寫對(duì)象原型時(shí)一般都需要重新給 constructor 賦值描扯,以保證對(duì)象實(shí)例的類型不被篡改定页。

hasOwnProperty()

function Person () {}
var person = new Person();
person.hasOwnProperty('constructor'); // false

hasOwnProperty()Object.prototype的一個(gè)方法,該方法能判斷一個(gè)對(duì)象是否包含自定義屬性而不是原型鏈上的屬性绽诚,因?yàn)?code>hasOwnProperty()"是 JavaScript 中唯一一個(gè)處理屬性但是不查找原型鏈的函數(shù)典徊。

hasOwnProperty()還有一個(gè)重要的使用場(chǎng)景,就是用來(lái)遍歷對(duì)象的屬性恩够。

function Person(name, age){
    this.name = name;
    this.age = age;
}

Person.prototype.getInfo = function(){
    console.log(this.name + " is " + this.age + " years old");
};


var person = new Person("Will", 28);

for(var attr in person){
    console.log(attr);
}
// name
// age
// getInfo

for(var attr in person){
    if(person.hasOwnProperty(attr)){
        console.log(attr);
    }
}
// name
// age

References

JavaScript深入之從原型到原型鏈
徹底理解JavaScript原型
判斷JS數(shù)據(jù)類型的四種方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卒落,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蜂桶,更是在濱河造成了極大的恐慌儡毕,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扑媚,死亡現(xiàn)場(chǎng)離奇詭異妥曲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)钦购,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門檐盟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人押桃,你說(shuō)我怎么就攤上這事葵萎。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵羡忘,是天一觀的道長(zhǎng)谎痢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)卷雕,這世上最難降的妖魔是什么节猿? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮漫雕,結(jié)果婚禮上滨嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己浸间,他們只是感情好太雨,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著魁蒜,像睡著了一般囊扳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兜看,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天锥咸,我揣著相機(jī)與錄音,去河邊找鬼细移。 笑死搏予,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的葫哗。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼球涛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼劣针!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起亿扁,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捺典,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后从祝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體襟己,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屈藐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年义屏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了和簸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捐友。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡换可,死狀恐怖背蟆,靈堂內(nèi)的尸體忽然破棺而出毛仪,到底是詐尸還是另有隱情排嫌,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布仿吞,位于F島的核電站滑频,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏唤冈。R本人自食惡果不足惜峡迷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望你虹。 院中可真熱鬧绘搞,春花似錦、人聲如沸售葡。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挟伙。三九已至楼雹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間尖阔,已是汗流浹背贮缅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留介却,地道東北人谴供。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像齿坷,于是被迫代替她去往敵國(guó)和親桂肌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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

  • JS中原型鏈永淌,說(shuō)簡(jiǎn)單也簡(jiǎn)單崎场。 首先明確: 函數(shù)(Function)才有prototype屬性,對(duì)象(除Object...
    前小白閱讀 3,907評(píng)論 0 9
  • 普通創(chuàng)建對(duì)象和字面量創(chuàng)建對(duì)象不足之處:雖然 Object 構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢杂脕?lái)創(chuàng)建單個(gè)對(duì)象遂蛀,但這些方式有...
    believedream閱讀 2,360評(píng)論 2 18
  • ??面向?qū)ο螅∣bject-Oriented李滴,OO)的語(yǔ)言有一個(gè)標(biāo)志螃宙,那就是它們都有類的概念,而通過(guò)類可以創(chuàng)建任意...
    霜天曉閱讀 2,096評(píng)論 0 6
  • 因?yàn)椴皇锹糜瓮舅匀瞬皇翘貏e的多所坯,天氣也成全人谆扎,絕對(duì)的天然氧吧! 我們爬到200米標(biāo)識(shí)的時(shí)候芹助,他就讓我先...
    風(fēng)箏2017閱讀 719評(píng)論 0 0
  • 2017年10月24日燕酷,是令我激動(dòng)的一天籍凝。從這一天開(kāi)始,我有幸參加了吉林省特級(jí)教師王佩瑩語(yǔ)文名師工作室在上...
    流星瑩瑩閱讀 410評(píng)論 0 0