前言
在寫復(fù)雜的 JavaScript 應(yīng)用之前雹舀,充分理解原型鏈繼承的工作方式是每個(gè) JavaScript 程序員必修的功課虚吟。
JavaScript中并沒有類(class)邦鲫;Js是基于原型(prototype-based)來(lái)實(shí)現(xiàn)的面向?qū)ο螅∣OP)的編程范式的庆捺,但并不是所有的對(duì)象都擁有prototype這一屬性
var a = {},b = 'shi';
var fn = function(){};
a.prototype // undefined
b.prototype // undefined
fn.prototype // Object {constructor: function}
prototype
屬性只有 function
對(duì)象定義時(shí)才有,函數(shù)本身也是對(duì)象。想要明白原型問(wèn)題我們先明白幾個(gè)基本概念撬即。
一、function粒竖、Function蕊苗、Object和{}
function
是JavaScript的關(guān)鍵字朽砰,用于定義函數(shù)變量瞧柔,一般有2種定義方式
function f1(){
console.log('This is function f1!');
}
typeof(f1); //=> 'function'
var f2 = function(){
console.log('This is function f2!');
}
typeof(f2); //=> 'function'
Function
是函數(shù)類型實(shí)例的構(gòu)造函數(shù)(constructor), 本質(zhì)也是函數(shù)撼唾,類似還有Object
或String
券坞、Number
等,都是Js內(nèi)置類型實(shí)例的構(gòu)造函數(shù)倍靡,構(gòu)造函數(shù)主要作用就是創(chuàng)建相應(yīng)類型的實(shí)例,實(shí)現(xiàn)原型鏈捡需。
var f3 = new Function("console.log('This is function f3!');");
f3(); //=> 'This is function f3!'
typeof(f3); //=> 'function'
typeof(Function); //=> 'function'
Object,它用于生成對(duì)象類型饰剥,其簡(jiǎn)寫形式為{},其實(shí)和function和Function的關(guān)系類似顾孽。
var o1 = new Object();
typeof(o1); //=> 'object'
var o2 = {};
typeof(o2); //=> 'object'
typeof(Object); //=> 'function'
二、prototype 和 _proto_
prototype
屬性只有函數(shù)類型對(duì)象才有,上面說(shuō)的很清楚了。而__proto__
是所有JavaScript對(duì)象都內(nèi)置的屬性[[Prototype]]锚贱,而這個(gè)屬性指向構(gòu)造函數(shù)(類似父類)的prototype
屬性,從而繼承屬性.
舉個(gè)例子:
var Person = function(){};
Person.prototype.type = 'Person';
Person.prototype.maxAge = 100;
var p = new Person();
console.log(p.maxAge);
p.name = 'rainy';
// 修正Person.prototype.constructor為Person本身
Person.prototype.constructor === Person; //=> true
p.__proto__ === Person.prototype; //=> true
console.log(p.prototype); //=> undefined
一圖勝千言
Person是一個(gè)函數(shù)類型的變量关串,因此自帶了prototype屬性拧廊,prototype屬性中的constructor又指向Person本身;通過(guò)new關(guān)鍵字生成的Person類的實(shí)例p1晋修,通過(guò)__proto__
屬性指向了Person的原型吧碾。
注意:
遵循ECMAScript標(biāo)準(zhǔn),someObject.[[Prototype]] 符號(hào)是用于指派 someObject 的原型墓卦。這個(gè)等同于 JavaScript 的__proto__
屬性倦春。從 ECMAScript 6 開始, [[Prototype]] 可以用Object.getPrototypeOf()和Object.setPrototypeOf()訪問(wèn)器來(lái)訪問(wèn)。
三落剪、原型鏈
原型鏈?zhǔn)腔?__proto__
的睁本。JavaScript 對(duì)象有一個(gè)指向一個(gè)原型對(duì)象的鏈。當(dāng)試圖訪問(wèn)一個(gè)對(duì)象的屬性時(shí)忠怖,它不僅僅在該對(duì)象上搜尋呢堰,還會(huì)搜尋該對(duì)象的原型,以及該對(duì)象的原型的原型凡泣,依此層層向上搜索枉疼,直到找到一個(gè)名字匹配的屬性或到達(dá)原型鏈的末尾。
舉例說(shuō)明:
// Node
var Obj = function(){};
var o = new Obj();
o.__proto__ === Obj.prototype; //=> true
o.__proto__.constructor === Obj; //=> true
Obj.__proto__ === Function.prototype; //=> true
Obj.__proto__.constructor === Function; //=> true
Function.__proto__ === Function.prototype; //=> true
Object.__proto__ === Object.prototype; //=> false
Object.__proto__ === Function.prototype; //=> true
Function.__proto__.constructor === Function;//=> true
Function.__proto__.__proto__; //=> {}
Function.__proto__.__proto__ === o.__proto__.__proto__; //=> true
o.__proto__.__proto__.__proto__ === null; //=> true
來(lái)張圖更直觀一些
到了這里问麸,其實(shí)有個(gè)問(wèn)題大家沒注意往衷,new
關(guān)鍵詞到底起了什么作用呢?
其實(shí)開頭的圖已經(jīng)給出答案:new
關(guān)鍵詞的最主要的作用就是完成上圖所示實(shí)例與父類原型之間關(guān)系的串接严卖,并創(chuàng)建一個(gè)新的對(duì)象.
有興趣深入看這里:JS 的 new 到底是干什么的席舍?
文筆有限,才疏學(xué)淺哮笆,文中若有不對(duì)之處来颤,還望告知汰扭。
個(gè)人博客
參考文章