我們通常建立乙個物件無非就兩種方式:
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 其次先來看下構造 函式建...