構造函數建立對象函數
==========我們先來一個栗子=======學習
function Person(name){ //構造函數 this.name=name; }this
Person.prototype.printName=function( ){ //原型對象
alert(this.name); }
var person1=new Person('ming'); //實例化對象
console.log(person1.__proto__); //這裏本身打印一下,印象更深入
console.log(person1.constructor);// console.log(Person.prototype);//
var person2=new Person('Frank');
(注意這裏的大小寫)Person的實例person1中包含了name屬性,同時也自動生成一個__proto__屬性,該屬性指向Person的prototype,能夠訪問到prototype內定義的printName方法,大概就 是這個樣子的:每一個JavaScript函數都有prototype屬性,這個屬性引用了一個對象,這個對象就是原型對象。原型對象初始化的時候是空的,咱們能夠在裏面自定義任何屬性和方法,這些方法和屬性都將被該構造函數所建立的對象繼承。(下一篇我會更詳細的介紹原型,很暴力的)prototype
實例是經過構造函數建立的。實例一創造出來就具備constructor屬性(指向構造函數)和proto屬性(指向原型對象),指針
構造函數中有一個prototype屬性,這個屬性是一個指針,指向它的原型對象。code
原型對象內部也有一個指針(constructor屬性)指向構造函數:Person.prototype.constructor = Person;對象
實例能夠訪問原型對象上定義的屬性和方法。繼承
在這裏person1和person2就是實例,prototype是他們的原型對象。ip
//========再來一個栗子===========原型鏈
function Animal(name){ //構造函數
this.name = name; //設置對象屬性}
Animal.prototype.behavior = function() {
console.log("this is a "+this.name);
}
var Dog = new Animal("dog");
var Cat = new Animal("cat");
Dog.behavior();//經過Dog對象直接調用behavior方法
Cat.behavior(); //"this is a cat"
console.log(Dog.behavior==Cat.behavior);// true;
//總結:構造函數的prototype上定義的方法確實能夠經過對象直接調用到,並且代碼是共享的。prototype屬性指向Animal對象。
================= 開始正題 ==================
-1-Prototype:
每一個函數都有一個prototype屬性,也只有函數有該屬性。
function Person(){ }
Person.prototype.name = 'name';
var person1 = new Person();
var person2 = new Person();
console.log(person1.name) // name
console.log(person2.name) //name
問:那這個函數的prototype屬性到底指向的是什麼呢?是這個函數的原型嗎?
| |
| |
總結:函數的prototype屬性指向了一個對象,這個對象正是調用該構造函數而建立的實例的原型,也就是這個例子中的person1和person2的原型。
問:什麼是原型?每個JavaScript對象(null除外)在建立的時候就會與之關聯另外一個對象,這個對象就是咱們所說的原型,每個對象都會從原型」繼承」屬性。
-2-proto:
怎麼表示實例與實例原型,也就是person和Person.prototype之間的關係呢,這時候咱們就要講到第二個屬性:
proto。每個JavaScript對象(除了null)都具備的一個屬性,叫proto,這個屬性會指向該對象的原型。
function Person( ){
}
var person = new Person();
console.log(person.proto === Person.prototype); //true
問:既然實例對象和構造函數均可以指向原型,那麼原型是否有屬性指向構造函數或者實例呢?
-3- constructor
沒有指向實例的,由於一個構造函數能夠生成多個實例,可是原型指向構造函數是有的,這就要講到第三個屬性:construcotr,每一個原型都有一個constructor屬性指向關聯的構造函數
爲了驗證這一點,咱們能夠嘗試:
function Person() {
}
console.log(Person === Person.prototype.constructor); //true
精華----綜上總結:(看清大下寫)
function Person() { //構造函數
}
var person = new Person(); //實例對象
console.log(person.proto == Person.prototype) //true
console.log(Person.prototype.constructor == Person) // true// 順便學習一個ES5的方法,能夠得到對象的原型console.log(Object.getPrototypeOf(person) === Person.prototype) //true
實例與原型
當讀取實例的屬性時,若是找不到,就會查找與對象關聯的原型中的屬性,若是還查不到,就去找原型的原型,一直找到最頂層爲止。
======舉個例子:=========
function Person() {
}
Person.prototype.name = 'name';
var person = new Person();
person.name = 'name of this person';
console.log(person.name) // name of this person
delete person.name;
console.log(person.name) // name
我設置了person的name屬性,因此我能夠讀取到爲’name of this person’,當我刪除了person的name屬性時,讀取person.name,從person中找不到就會從person的原型也就是person.proto == Person.prototype中查找,幸運的是咱們找到了爲’name’,可是萬一尚未找到呢?哪原型的原型又是什麼呢?
在前面,我說過原型也是一個對象,既然是對象,我就能夠用最原始的方式建立它,那就是
var obj = new Object();//字面兩建立對象new一個
obj.name = 'name';
console.log(obj.name) // name
因此原型對象是經過Object構造函數生成的,結合以前所講,實例的proto指向構造函數的prototype,
原型鏈
問:Object.prototype的原型是什麼?
null,嗯,對就是null,因此查到Object.prototype就能夠中止查找了
補充,最後,補充和糾正本文中一些不嚴謹的地方:
首先是constructor,
function Person() {
}
var person = new Person();
console.log(person.constructor === Person); // true
當獲取person.constructor時,其實person中並無constructor屬性,當不能讀取到constructor屬性時,會先從person的原型也就是Person.prototype中讀取,正好原型中有該屬性,因此
person.constructor === Person.prototype.constructor