我的博客原文地址git
在JavaScript中除值類型以外,其餘的都是對象,爲了說明這點,咱們舉幾個例子
咱們可使用typeof
來作類型判斷github
typeof a; // undefined typeof 1; // number typeof 'wclimb'; // string typeof true; // boolean typeof function(){}; // function typeof []; // object typeof null; // object typeof {}; // object
除了undefined
、number
、string
、boolean
屬於值類型以外,其餘都是對象。你可能要問了,不是還有一個是function
嗎?要校驗他是否是應該對象能夠這樣作:函數
var fn = function(){} fn instanceof Object // true
由上面的例子所示,函數確實是對象,爲何呢?咱們看一下下面的例子this
function Person(name){ this.name = name; } var person = new Person('wclimb'); console.log(person) // Person {name: "wclimb"}
由此咱們能夠得知,對象都是經過函數建立的,這麼說你可能又會說不對,你看下面的就不是函數建立的spa
var person = {name:'wclimb'}
你咋就這麼飄呢?我竟無言以對,沒錯,這是個意外、意外、意外。可是歸根結底他仍是經過函數建立的prototype
var person = new Object() person.name = 'wclimb'
so,如今你只要知道對象是經過函數建立的就能夠了,來跟着我讀:
第一遍 對象都是經過函數建立的
第二遍 對象都是經過函數建立的
第三遍 對象都是經過函數建立的code
function Person(name){ this.name = name } var person1 = new Person('wclimb 1') var person2 = new Person('wclimb 2')
上面Person
就是一個構造函數,咱們經過new
的方式建立了一個實例對象person
咱們來看看person1和person2的constructor
(構造函數)是否是指向Person的對象
person1.constructor === Person // true person2.constructor === Person // true
在JavaScript中,每定義一個函數都會產生一個prototype
(原型)屬性,這個屬性指向函數的原型對象blog
function Person(){} Person.prototype.name = 'wclimb' Person.prototype.age = '24' Person.prototype.sayAge = function(){ console.log(this.age) } var person = new Person() person.sayAge(); // 24
那麼這個prototype
究竟是什麼呢?跟構造函數有關係嗎?ip
上圖就能夠反映出他們之間的關係
其實函數的prototype
指向函數的原型對象,每一個對象都會關聯另一個對象,也就是原型,上面的例子改爲:
Person.prototype = { name: 'wclimb', age: 24, satAge: function(){ console.log(this.age) } }
__proto__
)上面咱們說到每定義一個函數都會產生一個原型,每一個函數它不止有原型,還有一個__proto__
(隱式原型)
每一個對象都有一個__proto__
屬性,指向建立該對象函數的prototype
,咱們能夠來試試,仍是上面的例子:
function Person(){} var person = new Person() person.__proto__ === Person.prototype // true
如今他們的關係圖以下
由上圖咱們能夠知道:
Person.prototype.constructor = Person person.__proto__ = Person.prototype person.constructor = Person
咱們能夠看到person.__proto__
指向構造函數的原型,那麼構造函數的原型即Person
的__proto__
指向哪裏呢?
咱們知道構造函數其實就是由Function
來建立的,由此得出:
Person.__proto__ === Function.prototype
那麼構造函數的原型即Person.prototype
的__proto__
指向哪裏呢?
原型對象實際上是經過Object
生成的,天然而然的得出:
Person.prototype.__proto__ === Object.prototype
那麼Object.prototype
的__proto__
指向哪裏呢?答案是null
,最終獲得下面的圖
拋開這張圖,來看看下面幾道題
person.__proto__
Person.__proto__
Person.prototype.__proto__
Object.__proto__
Object.prototype.__proto__
解:
__proto__
屬性,指向建立該對象函數的prototype
,由於Person是person的構造函數Person === person.constructor
爲true
,因此:person.__proto__ === Person.prototype
Person
構造函數是由Function
建立的,因此能夠得出Person.__proto__ === Fucntion.prototype
Person.prototype
實際上是一個對象,而對象是由Object
建立的,因此 Person.prototype.__proto__ === Object.prototype
Object
對象都是函數建立的,因此Object.__proto__ === Function.prototype
Object.prototype
是一個對象可是他的__proto__
爲null
當咱們要取一個值的時候,會先從實例中取,若是實例中存在,則取實例的值,若是實例不存在,則會順着原型裏找,直到找到
function Person(){} Person.prototype.name = '我來自原型' var person = new Person() person.name = '我來自實例' console.log(person.name); // 我來自實例 delete person.name console.log(person.name)); // 我來自原型
首先person實例中有這個屬性,返回我來自實例
,而後將它刪除以後,會從原型中招,也就是person.__proto__
,由於Person.prototype === person.__proto__
,因此獲得我來自原型
原型和原型鏈基本已經講解完,不過還有待完善,若有錯誤,還望指正
GitHub:wclimb