39 #2對象深入- prototype 對象

構造函數的缺點
JavaScript通過構造函數生成新對象抚太,因此構造函數可以視為對象的模板 實例對象的屬性和方法,可以定義在構造函數內部

但同一個構造函數的對象實例之間捶牢,無法共享屬性 是對系統(tǒng)資源的浪費
但同一個構造函數的對象實例之間梯嗽,無法共享屬性 是對系統(tǒng)資源的浪費

所以棄用在構造函數里為實例定義方法

prototype屬性的作用
JavaScript的每個對象都繼承另一個對象杯矩,后者稱為“原型”(prototype)對象 null除外,它沒有自己的原型對象

通過構造函數生成對象實例時巾表,會自動為實例對象分配原型對象 每一個構造函數都有一個prototype屬性汁掠,這個屬性就是實例對象的原型對象

原型對象的屬性不是實例對象自身的屬性

只要修改原型對象,變動就立刻會體現(xiàn)在所有實例對象上

Animal.prototype.color = 'yellow';

cat1.color // "yellow"
cat2.color // "yellow"
上面代碼中集币,原型對象的color屬性的值變?yōu)閥ellow考阱,兩個實例對象的color屬性立刻跟著變
這是因為實例對象其實沒有color屬性,都是讀取原型對象的color屬性
也就是說鞠苟,當實例對象本身沒有某個屬性或方法的時候乞榨,它會到構造函數的prototype屬性指向的對象,去尋找該屬性或方法

如果實例對象自身就有某個屬性或方法当娱,它就不會再去原型對象尋找這個屬性或方法
cat1.color = 'black';

cat1.color // 'black'
cat2.color // 'yellow'

總結一下
原型對象的作用吃既,就是定義所有實例對象共享的屬性和方法
這也是它被稱為原型對象的含義,而實例對象可以視作從原型對象衍生出來的子對象

由于JavaScript的所有對象都有構造函數趾访,而所有構造函數都有prototype屬性态秧,所以所有對象都有自己的原型對象(null除外)

原型鏈
由于原型本身也是對象,所以也有自己的原型扼鞋,于是乎就形成了一條原型鏈(prototype chain)

如果一層層地上溯申鱼,所有對象的原型最終都可以上溯到Object.prototype,即Object構造函數的prototype屬性指向的那個對象
那么云头,Object.prototype對象有沒有它的原型呢捐友?回答可以是有的,就是沒有任何屬性和方法的null對象溃槐,而null對象沒有自己的原型

...... → Object對象實例 → Object.prototype → null

“原型鏈”的作用是匣砖,讀取對象的某個屬性時,JavaScript引擎先尋找對象本身的屬性昏滴,如果找不到猴鲫,就到它的原型去找,如果還是找不到谣殊,就到原型的原型去找
如果直到最頂層的Object.prototype還是找不到拂共,則返回undefined

如果對象自身和它的原型,都定義了一個同名屬性姻几,那么優(yōu)先讀取對象自身的屬性宜狐,這叫做“覆蓋”(overriding)

需要注意的是势告,一級級向上,在原型鏈尋找某個屬性抚恒,對性能是有影響的 所尋找的屬性在越上層的原型對象咱台,對性能的影響越大 如果尋找某個不存在的屬性,將會遍歷整個原型鏈

constructor屬性
構造函數.prototype所指向的原型對象有一個constructor屬性俭驮,默認指向構造函數.prototype對象所在的構造函數
function P() {}

P.prototype.constructor === P// true
由于constructor屬性定義在prototype對象上面回溺,意味著可以被所有實例繼承
實例.constructor 繼承原型(構造函數.prototype)身上的constructor屬性 即:原型的構造函數也是實例的構造函數
constructor屬性的作用,是分辨原型對象到底屬于哪個構造函數
function P() {}
var p = new P();

p.constructor// function P() {}
p.constructor === P.prototype.constructor// true
p.hasOwnProperty('constructor')// false

有了constructor屬性表鳍,就可以從實例新建另一個實例
function Constr() {}
var x = new Constr();

var y = new x.constructor();//相當于:new Constr()
y instanceof Constr // true

由于constructor屬性是一種原型對象與構造函數的關聯(lián)關系馅而,所以修改原型對象的時候,務必要小心

修改原型對象后譬圣,再生成實例(這個順序不能變!!)
否則:實例.constructor瓮恭,instanceof運算符 結果都反過來且理解不了
function A() {}
function B() {}

A.prototype = B.prototype;//先改變原型,再生成實例(符合我的理解思路,按這個記憶)
var a = new A();

a instanceof A // true 反映的是實例與構造函數的關系,改原型當然不受影響
a.constructor.name // B 因為在修改原型對象后沒有指定舊原型身上的constructor屬性,自然就調新原型身上的constructor屬性

養(yǎng)成好習慣,修改原型對象時一并校正constructor屬性的指向
// 避免這種寫法C.prototype = {
method1: function (...) { ... },
// ...};

// 較好的寫法C.prototype = {
constructor: C,
method1: function (...) { ... },
// ...};

// 好的寫法C.prototype.method1 = function (...) { ... };

function A() {}
function B() {}

A.prototype = B.prototype;
A.prototype.constructor = A; // 好習慣修改原型對象后,重新指定原型上的constructor的屬性
var a = new A();

a instanceof A
a.constructor.name // A 重新指定原型的constructor屬性,就不走新原型身上的constructor

構造函數身上不僅有prototype屬性指向實例原型對象
構造函數還有name屬性,顯示構造函數的名稱

function Foo() {}
var f = new Foo();

Foo.name // "Foo"
f.constructor.name // "Foo"

Object.prototype.isPrototypeOf() [多情]
對象實例的isPrototypeOf方法,用來判斷X是不是實例的原型對象
由于isPrototypeOf() 對整個原型鏈上的對象都有效厘熟,因此同一個實例屯蹦,可能會有多個原型對象都返回true
var o1 = {};
var o2 = Object.create(o1);
var o3 = Object.create(o2);
//原型鏈 o3→o2→o1

o2.isPrototypeOf(o3) // true
o2 是 o3的原型對象
o1.isPrototypeOf(o3) // true
o1 是 o3的原型對象

instanceof運算符 [多情]
instanceof運算符返回一個布爾值,表示對象實例是否是某個構造函數拍出來的
var v = new Vehicle();
v instanceof Vehicle // true
instanceof運算符的左邊是實例對象,右邊是構造函數
它的運算實質:檢查右邊構造函數的prototype屬性所指向的原型對象,是否在左邊對象實例的原型鏈上
v instanceof Vehicle
// 等同于
Vehicle.prototype.isPrototypeOf(v)
由于instanceof對整個原型鏈上的對象都有效绳姨,因此同一個對象實例登澜,可能會對多個構造函數都返回true
var d = new Date();
d instanceof Date // true
d instanceof Object // true

Object.getPrototypeOf()
Object對象的又一個靜態(tài)方法↓ 返回對象實例的原型對象
Object.keys() Object. getOwnPropertyNames()

因為這個原型對象是該實例原型鏈中最內層的,所以它是獲取原型對象的標準方法
function Ft() {}
var f = new Ft ();
Object.getPrototypeOf(f) === Ft.prototype// true

Object.setPrototypeOf()[不常用]
Object對象的又一個靜態(tài)方法↓
Object.keys() Object. getOwnPropertyNames()

Object.setPrototypeOf()
接收兩個參數,第一個是現(xiàn)有對象飘庄,第二個是原型對象 脑蠕,并返回現(xiàn)有對象(它的原型對象已被設置)
var a = {x: 1};
var b = {y: 2};

var c = Object.setPrototypeOf(a, b);

c.x //1 c自身的x屬性
c.y //2 c從它的原型對象b上繼承來的y屬性

Object.create()[不常用]
Object對象的又一個靜態(tài)方法↓
Object.keys() Object. getOwnPropertyNames()

Object.create()
它接受一個對象作為參數,返回一個新對象 后者完全繼承前者的屬性方法跪削,即原有對象成為新對象的原型
var A = {
print: function () {
console.log('hello');
}
};

var B = Object.create(A);

B.print() // hello B從它的原型對象A上繼承來的print方法

下面三種方式生成的新對象是等價的
var o1 = new Object();
var o2 = Object.create(Object.prototype);// o2的原型對象是Object.prototype,o2就是Object對象實例
var o3 = {}; // 對象字面量方法

如果想要生成一個不繼承任何屬性(比如沒有toString和valueOf方法)的對象谴仙,可以將Object.create的參數設為null
var o = Object.create(null);

o.valueOf()
// TypeError: o.valueOf is not a function

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碾盐,隨后出現(xiàn)的幾起案子晃跺,更是在濱河造成了極大的恐慌,老刑警劉巖毫玖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掀虎,死亡現(xiàn)場離奇詭異,居然都是意外死亡付枫,警方通過查閱死者的電腦和手機烹玉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阐滩,“玉大人春霍,你說我怎么就攤上這事∫睹迹” “怎么了址儒?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衅疙。 經常有香客問我莲趣,道長,這世上最難降的妖魔是什么饱溢? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任喧伞,我火速辦了婚禮,結果婚禮上绩郎,老公的妹妹穿的比我還像新娘潘鲫。我一直安慰自己,他們只是感情好肋杖,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布溉仑。 她就那樣靜靜地躺著,像睡著了一般状植。 火紅的嫁衣襯著肌膚如雪浊竟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天津畸,我揣著相機與錄音振定,去河邊找鬼。 笑死肉拓,一個胖子當著我的面吹牛后频,可吹牛的內容都是我干的。 我是一名探鬼主播暖途,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼卑惜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丧肴?” 一聲冷哼從身側響起残揉,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芋浮,沒想到半個月后抱环,有當地人在樹林里發(fā)現(xiàn)了一具尸體蜡塌,經...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡协饲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了恍飘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘤旨。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡梯啤,死狀恐怖,靈堂內的尸體忽然破棺而出存哲,到底是詐尸還是另有隱情因宇,我是刑警寧澤七婴,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站察滑,受9級特大地震影響打厘,放射性物質發(fā)生泄漏。R本人自食惡果不足惜贺辰,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一户盯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧饲化,春花似錦莽鸭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撩笆,卻和暖如春捺球,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背夕冲。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工氮兵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人歹鱼。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓泣栈,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弥姻。 傳聞我的和親對象是個殘疾皇子南片,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內容

  • 文/臉妹 圖/臉妹 漠河疼进,我第一次聽說它的時候是在高二,舍友說將來要去漠河看極光秧廉,我那時候還不知道漠河在哪伞广,只能...
    會飛的臉妹閱讀 564評論 2 6
  • 今天看到個問題,編輯工程提示Unknown type name 'NSString'疼电,如下圖 導致出現(xiàn)異常的原因是...
    snail小菜閱讀 264評論 0 0
  • 今日三只青蛙: 1.冥想嚼锄。? 2.時間管理100講第44講。? 3.簡書蔽豺。兩天后補上区丑。 早起打卡記錄
    Eason媽咪閱讀 193評論 0 0
  • 今兒個有些累,早上跑了幾圈,中午和下午你們排練去幫忙沧侥,就覺得整個人體力不支了可霎,想著你們老師最近一直這種強度的工作,...
    萍萍淡淡閱讀 164評論 3 2
  • 第一課 李清照 歡迎來到云帆學院正什! 很高興能和各位同學在春天里相遇在云帆學院啥纸。 我們這個學期會學到很多有趣的人物和...
    田源ty閱讀 704評論 0 0