新手理解的JS原型鏈

2021-09-12 23:50:07 字數 4516 閱讀 5041

我們通常建立乙個物件無非就兩種方式:

1. var obj= new object();//new 乙個object的例項

2. var obj= {};//物件字面量

當我們想要建立自定義的物件時,需要用到建構函式。

建構函式和普通函式有兩個區別:

1. 便於和普通函式區分,函式名首字母大寫。    

2. 使用 `new` 操作符呼叫,返回乙個例項物件。

除此之外和普通函式一摸一樣。

我們使用建構函式person來建立兩個例項物件:

function person(name)

}var person1 = new person('小明');

var person2 = new person('小紅');

console.log(person1);//

console.log(person2);//

上面的例子不難理解,雖然這兩個例項物件都有sayname方法,而且他們兩個的作用也是一樣的,但卻是兩個方法,只是名字和作用一樣。

畫個圖表示一下:

如果還不明白,我在打個比喻:

就像a街上有一間麥當勞,在b街上也開了一間麥當勞,它們都叫麥當勞,作用也是一樣的。但是你總不能說他們是一間麥當勞吧?

person1.sayname === person2.sayname;//false
如果這樣的話,我們每構造出來乙個物件,都要單獨為這個物件建立出乙個專屬於它自己使用的sayname,這是很占用記憶體的。

那我們能不能讓所有的例項物件都共同使用乙個sayname方法,來節省記憶體,提公升效率呢?這需要我們先理解原型物件的概念。

我們先了解原型物件的概念。

每個物件都有原型物件(null除外),我們用__proto__表示,每個函式都有prototype屬性,指向例項的原型物件。
對照這句話,按照我們上面的例子,也就是說person.prototype指向person1的原型物件(__proto__),

person.prototype === person1.__proto__; // true
為了便於理解,來看一張圖。

恩~他們的關係大概就是這樣。

原型鏈簡單用一句話概括就是:

原型鏈就是 物件的__proto__所連線的鏈狀結構
為了方便我們理解原型鏈,舉乙個簡單的例子:

function f()

f.prototype.b = 3;

f.prototype.c = 4;

var o = new f();//

//原型鏈:

//o --> o.__proto__ --> o.__proto__.__proto__ --> null

// 其中的 --> 就表示 __proto__ 也就是原型鏈

console.log(o.a); // 1

// o上有a這個屬性嗎?有的,該屬性的值為1

console.log(o.b); // 2

// o上有b這個屬性嗎?有的,該屬性的值為2

// 原型上也有乙個'b'屬性,但是它不會被訪問到.這種情況稱為"屬性遮蔽 "

console.log(o.c); // 4

// o上有c這個屬性嗎?沒有,那看看原型上有沒有

// o.__proto__上有c這個屬性嗎?有的,該屬性的值為4

console.log(o.d); // undefined

// o上有d這個屬性嗎?沒有,那看看原型上有沒有

// o.__proto__ 上有d這個屬性嗎?沒有,那看看它的原型上有沒有

// o.__proto__.__proto__ 為 null,停止搜尋

// 沒有找到d屬性,返回undefined。

我們畫張圖來表示:

圖中這條紅色的線就是原型鏈。

由此可見,例項物件可訪問自己原型物件上的屬性和方法,額..準確來說是:

當乙個物件 查詢屬性或方法時,自己有,停止查詢,返回結果。

自己沒有,順著__proto__一直向上查詢,如找到,停止查詢,返回結果。

如果一直找到了原型鏈的最頂端(null),還沒有找到,返回undefined

我們先回顧一下那個sayname的問題:

怎麼讓所有的例項物件都是用乙個sayname方法呢

現在我們可以使用原型物件來解決這個問題了。

我們把sayname方法放到例項的原型物件上面,也就是person.prototype上面來供所有例項使用:

function person(name)

person.prototype.sayname=function ()

var person1 = new person('小明');

var person2 = new person('小紅');

person1.sayname === person2.sayname;//true

用圖表示:

說一下我的經歷,一開始理解原型鏈時,一直在prototype__proto__constructor在這個三個屬性中繞來繞去。

為了便於理解,我把constructor放在最後了。

constructor字面意思就很容易理解,建構函式的意思。

一句話解釋:

每個原型物件都有乙個 constructor 屬性指向 關聯的建構函式。
還是上面那個例子:

console.log(person.prototype.constructor);//person()
需要注意的一點是,例項物件上沒有constructor屬性。

但是:

console.log(person1.constructor) ;//person()
得出這個結果很簡單:

例項上查詢不到constructor屬性 --> 順著__proto__在原型物件上找 --> 找到並返回。

object.prototype

剛才我們說了建立物件的兩種方式:字面量建立物件和使用new操作符建立物件。

這兩種方式建立出來的物件都會繼承object.prototyoe上的方法。

比如,我們使用字面量新建立乙個物件o:

var o = ;

o.tostring();//"[object object]"

//查詢過程: o --> o.__proto__ 找到返回

o.__proto__ === object.prototype;//true

o這個的物件本身並沒有tostring這個方法,但它卻可以使用tostring方法。

因為它繼承了object.prototyoe上的tostring的方法。

null

既然物件都會繼承自object.prototype上面的方法,那它自己的原型又是什麼呢。答案是null

object.prototype.__prototype__ === null;//true
以上僅自己學習所得,如有不當之處 望指出。

js 原型 原型鏈理解

執行發現如下 自定義乙個函式,函式包含兩個關鍵資料 prototype,proto 1 原型 prototype person具有prototype屬性 包含我們定義的屬性name,age以及constructor,並且constructor指向我們的person函式,可以理解為prototype就...

js原型鏈理解

關於原型鏈的問題也是領悟了很久,有時候突然覺得什麼都懂了,但下乙個問題出現令人一臉蒙比,好像又什麼都不懂,這是最近的一點經驗,記下來方便以後複習。先貼上最經典的原型煉圖,說實話,這圖是真的很精髓了 首先我們要知道這句話 js中所有的東西 當然都是物件 都有 proto 所有的函式除了有 proto ...

js原型鏈的理解

其實之前對js原型鏈有個基本的理解,但工作中用到的並不多,逐漸忘記了。所以準備寫個部落格。我覺得首先得明白乙個,就是每一次建立乙個建構函式 其實就是普通的函式 的時候,都會根據乙個特定的規則建立乙個原型屬性 prototype 其中包括兩項 construct和 proto 其次先來看下構造 函式建...