前端的那些事(六):原型與原型鏈(精選篇)

前言

首先廣為所知的“萬(wàn)物皆對(duì)象”是錯(cuò)誤的。
簡(jiǎn)單基本類型string愕秫,number,boolean焰络,null戴甩,undefined)不是對(duì)象。
復(fù)雜基本類型object)才是對(duì)象舔琅;但是object有九個(gè)內(nèi)置對(duì)象(String 等恐,Number, Boolean,Object课蔬,F(xiàn)unction囱稽, Array,Date二跋, RegExp战惊,Error

舉個(gè)例子:

var num1 = 123;
typeof num1; // "Number"
num1 instanceof Number; // false

var num2 = new Number(123);
typeof num2; // "object"
num2 instanceof Number; // true

其實(shí)num1這種字面量形式,獲取長(zhǎng)度扎即,訪問(wèn)值其實(shí)是不生效的吞获。但是js引擎自動(dòng)幫我們轉(zhuǎn)成Number這種形式了。如num1.length谚鄙。

我們這里簡(jiǎn)單介紹了各拷,不做深入探討,畢竟js引擎幫我們做了闷营,記住一句話烤黍,Object是所有對(duì)象的基類

接下來(lái)用最通俗易懂的方式給大家解釋各種學(xué)術(shù)名稱的原理:
一傻盟、__proto__(指針)

Firefox和Chrome 提供__proto__訪問(wèn)器速蕊,ECMA標(biāo)準(zhǔn)是[[Prototype]],它是對(duì)象內(nèi)置屬性無(wú)法訪問(wèn)娘赴,可以通過(guò)Object.getPrototypeOf()標(biāo)準(zhǔn)方法訪問(wèn)該屬性规哲。

從最簡(jiǎn)單代碼開(kāi)始:

var obj = {};
console.log(obj);

打印的樣子:

image.png

只要是對(duì)象都有__proto__屬性,最底層的constructorObject诽表,也印證了我那句Object是所有對(duì)象的基類唉锌。

二、prototype(原型)

定義

其中每個(gè)函數(shù)對(duì)象都有一個(gè)prototype 屬性竿奏,這個(gè)屬性指向函數(shù)的原型對(duì)象糊秆。

__proto__區(qū)別:

1:每個(gè)對(duì)象都有 __proto__ 屬性,但只有函數(shù)對(duì)象才有 prototype 屬性议双。
2: __proto__指向的是當(dāng)前對(duì)象的原型對(duì)象,而prototype指向的捉片,是以當(dāng)前函數(shù)作為構(gòu)造函數(shù)構(gòu)造出來(lái)的對(duì)象的原型對(duì)象平痰。

function Foo() {
  var name = '小米';
}
Foo.prototype.sayHello = function() {
  console.log('hello 靚仔');
};
console.log(Foo.prototype);

image.png

大家可以看到Foo.prototype有了sayHello的函數(shù),自然可以調(diào)用伍纫。這里有兩個(gè)問(wèn)題宗雇?

  1. sayHello方法想獲取Foo函數(shù)中的name怎么辦?
  2. 圖中constructor的prototype里面也有sayHello函數(shù)是怎么回事莹规?
2.1 解答問(wèn)題1

這就是我們?yōu)楹问褂?code>new進(jìn)行構(gòu)造函數(shù)的原因赔蒲,因?yàn)樗泄灿脤傩裕瘮?shù)共使用,還能繼承舞虱。

function Foo() {
  this.name = '小明';
}
Foo.prototype.sayHello = function() {
  console.log('hello' + this.name);
};

// var obj = {};
// obj.__proto__ = Foo.prototype;
// Foo.call(obj);
// var f = obj;
var f = new Foo();
console.log(f.sayHello());

這里解釋兩件事情:(大廠面試必問(wèn))

  • new是什么欢际,就是我注釋掉的代碼。
  • 為何用prototype創(chuàng)建函數(shù)sayHello矾兜,為了避免每一次new Foo()就創(chuàng)建一次sayHello损趋,占用內(nèi)存,消耗性能椅寺。
2.2 解答問(wèn)題2

直接引出constructor浑槽。

三、constructor(構(gòu)造函數(shù))

function Foo() {
  // ...
}
console.log(Foo.prototype.constructor === Foo); // true

從中可以看出constructor是函數(shù)Foo的prototype內(nèi)置屬性返帕,指向函數(shù)本身桐玻。就是這么簡(jiǎn)單。

繼續(xù)看代碼:

function Foo() {
  // ...
}
var a = new Foo();
console.log(a.constructor === Foo); // true

是不是說(shuō)明構(gòu)造函數(shù)a的constructor指向Foo荆萤,答案是否定的镊靴。

繼續(xù)改代碼

function Foo() {
  // ...
}
Foo.prototype.constructor = {}
var a = new Foo();
console.log(a.constructor === Foo); // false

原因很簡(jiǎn)單,就是Foo.prototype的constructor被我們?cè)O(shè)置為{}了观腊,也就是說(shuō)a.constructor是{}了邑闲,說(shuō)明這個(gè)constructor不安全,在某些情況梧油,我們得讓它恢復(fù)苫耸,所以你會(huì)看到如下代碼:

function Person() {}
Person.prototype = {
  constructor: Person, //這里指向Person,就不會(huì)丟失了
  name: '欣雨',
  age: 19,
  sayName: function() {
    console.log(this.name + '年齡' + this.age);
  },
};
// console.log(Person.prototype);
var p = new Person();
p.sayName(); // 欣雨年齡19

constructor介紹完了儡陨,我們來(lái)解釋一下2.2的問(wèn)題吧褪子,上述注釋代碼的console.log(Person.prototype)打開(kāi),打印一下看看:

image.png

只要你通過(guò)原型prototype創(chuàng)建屬性和方法時(shí)骗村,那么Person.prototypeconstructor下就會(huì)有prototype屬性包含你創(chuàng)建的嫌褪。(這里不是很重要,知道就好)

就是我在介紹2prototype(原型)所說(shuō):__proto__指向的是當(dāng)前對(duì)象的原型對(duì)象胚股,而prototype指向的笼痛,是以當(dāng)前函數(shù)作為構(gòu)造函數(shù)構(gòu)造出來(lái)的對(duì)象的原型對(duì)象。

四琅拌、原型鏈

定義:

原型鏈就是通過(guò)proto屬性從當(dāng)前對(duì)象開(kāi)始查找它的原型對(duì)象(通過(guò)prototype生成的)缨伊,一直查找到null為止。

function Person() {}
Person.prototype = {
  constructor: Person, //這里指向Person进宝,就不會(huì)丟失了
  name: '欣雨',
  age: 19,
  sayName: function() {
    console.log(this.name + '年齡' + this.age);
  },
};
var p = new Person();
console.log(p);

打印的p下面就是空對(duì)象刻坊,而需要的屬性在proto下面。

類型:
默認(rèn)的原型鏈結(jié)構(gòu)就是:當(dāng)前對(duì)象 -> 構(gòu)造函數(shù).prototype -> Object.prototype -> null
繼承改變默認(rèn)原型鏈結(jié)構(gòu)党晋,其實(shí)通過(guò)_proto查找即可谭胚。

五徐块、函數(shù)的構(gòu)造函數(shù)Function

普通函數(shù):

function foo(num) {
  console.log(num);
}
foo(2);  // 2

構(gòu)造函數(shù):

var foo = new Function('num', 'console.log( num )');
foo(2);  // 2

好處就是:
Function是使用字符串構(gòu)建函數(shù),那么就可以在程序運(yùn)行過(guò)程中構(gòu)建函數(shù)灾而。
以前的函數(shù)必須一開(kāi)始就寫好胡控,再經(jīng)過(guò)預(yù)解析,一步一步的運(yùn)行绰疤。

寫一些底層代碼铜犬,為了性能可以使用。

六 instanceof 原理

A instanceof B 的原理?(面試城崆欤考題)

查看對(duì)象B的prototype指向的對(duì)象是否在對(duì)象A的[[prototype]]鏈上

A.__proto__ === B.prototype
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末癣猾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子余爆,更是在濱河造成了極大的恐慌纷宇,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛾方,死亡現(xiàn)場(chǎng)離奇詭異像捶,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)桩砰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門拓春,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人亚隅,你說(shuō)我怎么就攤上這事硼莽。” “怎么了煮纵?”我有些...
    開(kāi)封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵懂鸵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我行疏,道長(zhǎng)匆光,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任酿联,我火速辦了婚禮终息,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘贞让。我一直安慰自己采幌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布震桶。 她就那樣靜靜地躺著,像睡著了一般征绎。 火紅的嫁衣襯著肌膚如雪蹲姐。 梳的紋絲不亂的頭發(fā)上磨取,一...
    開(kāi)封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音柴墩,去河邊找鬼忙厌。 笑死,一個(gè)胖子當(dāng)著我的面吹牛江咳,可吹牛的內(nèi)容都是我干的逢净。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼歼指,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼爹土!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起踩身,我...
    開(kāi)封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤胀茵,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后挟阻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體琼娘,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年附鸽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脱拼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡坷备,死狀恐怖熄浓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情击你,我是刑警寧澤玉组,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站丁侄,受9級(jí)特大地震影響惯雳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸿摇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一石景、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拙吉,春花似錦潮孽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至佛舱,卻和暖如春椎例,著一層夾襖步出監(jiān)牢的瞬間挨决,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工订歪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脖祈,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓刷晋,卻偏偏與公主長(zhǎng)得像盖高,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子眼虱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355