面向對象:面向對象、原型
對原型、原型鏈、 Function、Object 的理解
什麼是 JS 原型鏈?
轉載以上文章
一、OOP(Object-oriented programming, 面向對象編程)
1、wiki的解釋
面向對象編程(OOP)是一種基於“對象”概念的編程範式。該對象包含數據(屬性),以及一些執行過程的代碼(即方法)。對象的一個特性是,調用對象的方法過程可以訪問並經常修改與其關聯的對象的數據字段(對象具有“this”或“self”的概念)。
2、面向對象的思路:
把某個功能看成一個整體(對象),通過調用對象的某個方法來啓動功能。在用的時候不去考慮這個對象內部的實現細節,在去實現這個對象細節的時候不用管誰在調用
3、例子
面向對象的寫法
Car.擰鑰匙()
Car.掛擋()
Car.踩油門()
二、構造對象
1、代碼
通過new 函數名('參數,參數')得到一個對象,就相當於這個對象就是這個函數構造出來的,這個對象是函數的實例
function Person(name) {
this.name = name
this.sayName = function() {
console.log(this.name)
}
}
var p = new Person('hunger')
2、instanceof
instanceof是一個操作符,可以判斷對象是否爲某個函數的實例
p1 instanceof Person; // true
p1 instanceof Object;// true
instanceof判斷的是對象,非對象的數據不能判斷
1 instanceof Number; // false
3、構造函數的過程
- 創建一個空對象 {},假設名字是 tmpObj,並空對象的__proto__特性指向函數的prototype屬性
- 執行 Person 函數,執行過程中對 this 操作就是對 tmpObj 進行操作
- 函數執行完後返回剛剛創建的 tmpObj
- 把 tmpObj 賦值給 p (p也指向同一個對象)
4、構造函數的原型鏈
1、對函數使用new表達式就是構造函數
2、每個函數都有名稱爲prototype屬性,叫做原型,是一個對象
3、每個對象都有一個內部屬性 _proto_(規範中沒有指定這個名稱,但是瀏覽器都這麼實現的) 指向其類型的prototype屬性,類的實例也是對象,其__proto__屬性指向“類”的prototype
4、所有實例(對象)都會通過原型鏈引用到類型(函數)的prototype(原型),prototype相當於特定類型所有實例都可以訪問到的一個公共容器,一般用來共同調用的函數
總結:
我們通過函數定義了類Person,類(函數)自動獲得屬性prototype
每個類的實例都會有一個內部屬性__proto__,指向類的prototype屬性
5、舉個栗子
默認情況下,我們寫構造函數是不需要return的,構造函數自動將this代表的對象返回出來!
但如果我們寫了return語句,如果return是基本類型,會被認爲寫錯了無效。obj1和2還是this代表的對象。如果return是對象,那構造的對象就等於return後面的對象。
//obj1={a:1,b:2} obj2={a:1,b:2}
三、原型和原型鏈
1、查找數組valueof方法,講原型鏈
所有數組都是由Array這個函數構建的。數組的所有方法都是Array.prototype或者他們的原型鏈上面的。當我們直接賦值的方式生成一個數組的時候,就相當於直接用new Array的方法構建一個對象
Array函數也是由object函數構建的Array instanceof Object===true
數組可以調用valueof這個方法,但valueof這個方法不在Array.protototype內而是在object.prototype內。
首先 a數組 會找自己的 valueof方法;沒有找到,就會沿着__proto__ 屬性繼續到構造函數 Array 的 prototype 裏找 valueof 方法;如果還是沒有找到,再繼續往 Array.prototype 的 proto 即 Object.prototype 找 valueof 方法,最後找到 valueof 方法。
總結:一個對象調用其方法,先在自己的自由屬性內去找,找不到就去原型上去找,如果原型內也找不到,就到原型的原型上去找,直到找到該方法。而這構成的鏈就是原型鏈。如下圖
2、關於原型鏈的規律總結
- 當 new 一個函數的時候會創建一個對象,『函數.prototype』 等於 『被創建對象.__proto__』
- 一切函數都是由 Function 這個函數創建的,所以『Function.prototype === 被創建的函數.__proto__』
- 一切函數的原型對象都是由 Object 這個函數創建的,所以『Object.prototype ===
一切函數.prototype.__proto__』
建議閱讀若愚老師這邊文章裏面的例子,鞏固印象對原型、原型鏈、 Function、Object 的理解