在JavaScript中原型和原型鏈是很抽象的概念,對於大多數人也是最難理解的一部分,掌握原型和原型鏈的本質是JavaScript進階的重要一環。分享一下我對JavaScript原型和原型鏈的理解。
一、 函數對象
JavaScript 中,萬物皆對象。但對象也是有區別的,分爲:普通對象和函數對象,Object 、Function 是 JS 自帶的函數對象。
var myNewObject1 = {};//myNewObject1爲普通對象
var myNewObject2 = new Object();//myNewObject2爲普通對象
var myNewObject3 = new fun1();//myNewObject3爲普通對象
function fun1(){};//fun1爲函數對象
var fun2 = function(){};//fun2爲函數對象
var fun3 = Function('str','console.log(str)');//fun3爲函數對象
console.log(typeof Object);//function
console.log(typeof Function)//function
console.log(typeof fun1);//function
console.log(typeof fun2);//function
console.log(typeof fun3);//function
console.log(typeof myNewObject1);//object
console.log(typeof myNewObject2);//object
console.log(typeof myNewObject3);//object
二、prototype
和__proto__
的區別
2.1 prototype
定義:函數纔有的屬性
2.2 __proto__
定義:每個對象都有的屬性,但__proto__
不是一個規範屬性,只是部分瀏覽器實現了此屬性,對應的標準屬性[[Prototype]]
注:大多數情況下__proto__
可以理解爲“構造器的原型”
__proto__ === constructor.prototype
(如果一個對象是通過Object.create函數構造出來的,.那其proto就不一定是.constructor.prototype了)
var m = {};
console.log(m.prototype); //undefined
console.log(m.__proto__); //Object {}
var n = function(){}
console.log(n.prototype); //n {}
console.log(n.__proto__); //function() {}
三、 原型和原型鏈
3.1 原型
一個對象,其他對象可以通過它實現屬性繼承。
3.2 原型鏈
__proto__
是任何對象都有的屬性,所以會形成一條__proto__
連接起來的鏈條,遞歸訪問__proto__
必須最終到頭,並且值爲NULL。自己是由自己創建的,好像不符合邏輯,但仔細想想,現實世界也有些類似,你是怎麼來的,你媽生的,你媽怎麼來的,你姥姥生的,……類人猿進化來的,那類人猿從哪來,一直追溯下去……,就是無,(NULL生萬物),正如《道德經》裏所說“無,名天地之始”。
當js引擎查找對象的屬性時,先查找對象本身是否存在該屬性,如果不存在,會在原型鏈上查找,而不會查找自身的prototype
var M = function(){};
var m = new M();
console.log(m.__proto__); //M {}(即構造器function M 的原型對象)
console.log(m.__proto__.__proto__); //Object {}(即構造器function Object 的原型對象)
console.log(m.__proto__.__proto__.__proto__); //null
總結
每個對象都有 proto 屬性,但只有函數對象纔有 prototype 屬性