牆裂建議您在看這篇文章以前閱讀一遍我以前寫的文章 深刻淺出面向對象和原型【概念篇1】,由於此篇文章涉及到很多相關概念都在上篇文章裏啦
對象是老生常談的概念了,在這裏咱們來簡單複習一下segmentfault
var obj = { a: 1, b: "hello", c: true, d: function () { console.log("hello") }, e: { e_1: "對象內儲存一個對象" } }
對象是一個儲存一系列無序 key: value【鍵值對】 的集合的容器函數
注意:核心是要將對象做爲一個容器看待
使用對象做爲容器的這個特性咱們能夠進行封裝,這會產生兩個好處this
new 運算符接受一個函數 F 及其參數:new F(arguments...)spa
function People(name) { this.name = name this.sayName = function () { console.log(name) } // 通常在這個函數裏不要 return // 若是return引用類型的話,等於把return的值賦值給p1 } People() // this指向全局變量,name和sayName成爲了全局變量的屬性 var p1 = new People('sad') // 第一步:instance = {} 建立了一個類的實例 —— 空對象,而且將空的對象的__proto__屬性設置爲 F.prototype,也就是說 // 第二步:執行函數People(),並傳入參數"sad",並將this指向p1 // 第三步:return instance【實例】 , 即把instance賦值給p1 // 請注意 People()是一個函數,new People()是構造函數 var p2 = new People('angry')
instance 的中文意思爲 實例
那麼 instanceof 天然就是用來判斷對象是否爲某個類型的實例prototype
console.log(p1 instanceof People) // true // 意思是判斷 對象(p1)是否爲某個類型(People)的實例 // p1 是由 People 構建出來的,天然是People的實例,返回爲true
但須要注意的是,instanceof 運算符的工做原理是檢測 類的prototype 是否存在實例的原型鏈上3d
console.log(p1 instanceof Object) // true // 由於Object.prototype能夠被實例p1以原型鏈的方式訪問到
構造函數在解決了上面全部問題,同時爲實例帶來了類型
但能夠注意到在上例中,每一個的實例的方法做用是同樣的
可是每一個實例被建立的時候都要從新聲明一遍,浪費了內存code
// 咱們再來看一下這個函數 function People(name) { this.name = name this.sayName = function () { console.log(name) } // 每一個實例的sayName方法倒是相同的,並且每出現一個新實例,都是新聲明一個函數,大大地浪費了內存 }
能不能給People的實例都使用同一個sayName方法呢對象
任何函數使用new表達式就是構造函數,也就是說這個函數成爲了一個類blog
// 仍是這個例子 function People(name) { this.name = name this.sayName = function () { console.log(name) } } var p1 = new People('sad') var p2 = new People('angry') // People自己就有prototype屬性 console.log(People.prototype) // {constructor: ƒ} // 而每一個對象也都會帶有一個__proto__屬性,指向這個構造函數【實例】的類 // 全部的實例都共用一個prototype console.log(p1.__proto__ === People.prototype) // true console.log(p2.__proto__ === People.prototype) // true
// 實例能夠經過__prop__訪問到其 類 的prototype屬性,這就意味着類的prototype對象能夠做爲一個公共容器,供全部實例訪問。 People.prototype.test = "abc" console.log(p1.test) // abc // p1這個對象沒有test屬性,可是能夠經過它的__proto__屬性訪問到People的prototype屬性
上述關係咱們用一張圖來幫助你們更好地理解
由上咱們能夠知道ip
prototype至關於全部實例均可以訪問到的一個公共容器,這個公共容器也是這些實例的類的屬性
那麼如何解決內存浪費問題呢?
Answer:重複的東西移動到公共容器裏就能夠了
function People(name) { this.name = name // 每一個對象的name屬性時不一樣的,這點無可厚非 } People.prototype.sayName = function () { console.log(this.name) } // 將sayName方法放入People的原型中 var p1 = new People('sad') var p2 = new People('angry') console.log(p1.sayName()) console.log(p2.sayName())