凡是通過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 定義函式時被自動賦值,值預設為...