JS原型與原型鏈

2021-09-12 00:15:05 字數 3951 閱讀 5438

凡是通過new function()建立的物件都是函式物件,其他的是普通物件

var o1 = {}; 

var o2 =new object();

var o3 = new f1();

function

f1(){};

var f2 = function

(){};

var f3 = new function('str','console.log(str)');

console.log(typeof object); //function

console.log(typeof function); //function

console.log(typeof f1); //function

console.log(typeof f2); //function

console.log(typeof f3); //function

console.log(typeof o1); //object

console.log(typeof o2); //object

console.log(typeof o3); //object複製**

以上例子中,o1、o2、o3均為普通物件(例項物件),f1、f2、f3均為函式物件(抽象物件)

任何乙個例項都有乙個constructor(建構函式)屬性,該屬性(是乙個指標)指向了例項的建構函式。即

例項的constructor === 建構函式

function person(name, age, job)  

}var person1 = new person('zaxlct', 28, 'software engineer');

var person2 = new person('mick', 23, 'doctor');複製**

console.log(person1.constructor == person); //true

console.log(person2.constructor == person); //true

複製**

每個物件都有proto屬性,但只有函式物件才有 prototype 屬性。函式物件的prototype指向函式的原型物件。換而言之,只有函式物件才存在原型物件,函式物件的prototype屬性指向了其原型物件。

舉個例子

function

person

(){}

person.prototype.name = 'linlin';

person.prototype.age = 25;複製**

以上**完全等價於

function

person

(){}

person.prototype = 複製**

由於函式物件的prototype屬性指向的是其原型物件,而上述例子中,person.prototype指向的是乙個普通物件,由此我們可知,原型物件是乙個普通函式。

所有的原型物件都有乙個constructor(建構函式)屬性,這個屬性是乙個指標,指向prototype屬性所在的函式。

person.prototype.constructor == person複製**

聯絡之前知識,例項的constructor === 建構函式,在此我們可以將person.prototype當成person的乙個例項person1,於是以上**可看作是等價如下:

person1.constructor == person複製**

也就是在person建立的時候,建立了乙個它的例項化物件並且賦值給它的prototype,基本過程如下:

var a = new person();

person.prototype = a;複製**

結論:原型物件(person.prototype)是建構函式(person)的乙個例項。

原型物件的主要作用是用於繼承。所有定義在原型物件上的屬性,都可以被建構函式例項化的物件繼承。

js在建立物件的時候,不管是普通物件還是函式物件,都會內建乙個叫做__proto__的屬性,用於指向建立它的建構函式的原型物件。

var person = new person();

person._proto_ === person.prototype複製**

需要注意的是,這種指向關係存在於例項(person)和建構函式的原型物件(person.prototype)之間,而非例項(person)於建構函式(person)之間。

prototype是儲存乙個函式物件所有方法的真正存在,換句話說,當我們定乙個函式物件的時候,該函式物件的所有方法和屬性其實是儲存在該物件的prototype屬性上,而非存在於函式本身。以下例子可以說明:

function person(age)

person.prototype.*** = 'male';

var p = new person(10);

console.log(person.name) //undifined

console.log(person.age) //undifined

console.log(person.***) //undifined

console.log(p.name) //'person'

console.log(p.age) //10

console.log(p.***) //'male'

複製**

可以看出,我們無法直接獲取到函式物件的任何屬性,是因為所有屬性存在於函式物件的prototype屬性上,而非存在於函式本身,而使用例項物件直接訪問到函式物件的所有屬性,這是因為例項物件的_proto_屬性指向的是其建構函式的是原型物件,即建構函式的prototype,通過原型鏈就可以訪問到prototype上的所有屬性。

當查詢乙個例項的屬性時,會先從這個例項的自定義屬性上查詢,如果沒有的話,會通過_proto_去例項所屬的類的原型(例項的建構函式)上找,如果還沒有的話,就會通過原型的_proto_object的原型上去找,如此層層往上,直到_proto_指向的是null。這種通過_proto_在物件之間構成的關係,就稱為原型鏈

如果例項和原型都共存乙個相同的屬性,在訪問該屬性時,指向的是例項上的屬性,而非原型上的屬性,這種情況稱為屬性遮蔽

如下

function

fn()

fn.prototype.b = 3;

fn.prototype.c = 4;

var f = new fn();

console.log(f.a) // a是自身屬性,該屬性的值為1

console.log(f.b) // b是自身屬性,該屬性的值為2,原型上也有屬性'b',但由於「屬性遮蔽」所以無法訪問

console.log(f.c) // c不是自身屬性,會通過原型鏈往它的原型上去查詢,而原型上有屬性『c』,該屬性的值為4

console.log(f.d) // d不是自身屬性,會通過

複製**

原型鏈是指物件之間通過_proto_建立起來的指向關係,所以原型鏈的形成依靠的是_proto_,而非prototype

js 原型與原型鏈

5條原型規則 1.所有的引用型別 陣列 物件 函式 都具有物件特性,即可自由擴充套件屬性 除了 null 除外 2.所有的引用型別 陣列 物件 函式 都有乙個 proto 隱式原型 屬性,屬性值是乙個普通的物件。3.所有的函式,都有乙個prototype 顯式原型 屬性,屬性值也是乙個普通的物件。4...

js原型與原型鏈

定義函式的時候都建立了乙個函式物件,裡面有個prototype屬性指向了乙個object空物件,這個物件就是函式的原型物件。原型物件中有個constructor屬性,指向函式物件 通過new建立的物件,有個 proto 屬性 左右都是兩個下劃線 它等於對應建構函式的的prototype的值,如上圖。...

js 高階 原型與原型鏈

所有函式都有乙個特別的屬性 prototype 顯式原型屬性 所有例項物件都有乙個特別的屬性 proto 隱式原型屬性 1.每個函式都有乙個prototype屬性,它預設指向乙個物件 objectg 即稱為 原型物件 顯式原型與隱式原型的關係 函式的prototype 定義函式時被自動賦值,值預設為...