原型鏈和原型

構造函數建立對象函數

==========我們先來一個栗子=======學習

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

相關文章
相關標籤/搜索