javascript
JavaScript 原型 原型链
JavaScript 原型
本文講介紹JavaScript原型 以及JavaScript的原型鏈
JS中的原型和原型鏈
所有的引用類型(數組、函數、對象)可以自由擴展屬性(除null以外)
所有的函數都有一個prototype屬性(顯式原型)
所有的引用類型都有一個__proto__屬性(隱式原型)
所有引用類型 它的__proto__屬性指向它的構造函數的 prototype屬性
當試圖得到一個對象的屬性時 如果這個對象不存在這個屬性,那么就會去它的 __ proto__的路線去查找 也就是構造函數中的 prototype 中去查找
一、原型的使用和原型的概念
1.顯式原型 prototype
在我們創建一個函數的時候 每個函數都會有一個prototype(原型)屬性 這個屬性指向一個對象,這個對象包含著可以實例共享的屬性和方法 你可以不必再構造函數中定義對象的實例信息 而直接將這些信息直接添加到原型對象中
// ↓ -------- 創建一個構造函數 --------function Person(name,age) {this.name = name;this.age = age;}Person.prototype.sex = "man" // ↓ -------- 在原型中添加一條方法 ---------Person.prototype.seyLove = function () {console.log(name +" love 1024")}; // ↓ -------- 實例化這個對象 ----------var man = new Person("伊凡ED",20);console.log(man)console.log(man.name+" sex="+man.sex);Person.prototype.seyLove()// - ↑ 輸出結果 = Person?{name: "伊凡ED", age: 20} // 伊凡FD sex=man // love 1024如果我們再構造函數內定義好這個seyLove方法的話 那么我們用這個構造函數構造的每一個對象里都會擁有seyLove這個方法 這樣我們就浪費了很多的資源 我們完全可以給需要用到的對象添加需要的方法? 那么 我們就可以用原型方法 并且這個方法可以繼承 需要了解繼承可以在我的博客搜索 JavaScript 繼承
2.隱式原型(原型對象)__proto__
JavaScript中的所有對象(除了null)都具有的一個屬性 __proto__ 所有的__proto__都是指向它的構造函數的 prototype 屬性 下面的例子最后一行也向我們證明了這一點?
// ↓ -------- 創建一個構造函數 --------function Person(name,age) {this.name = name;this.age = age;}Person.prototype.sex = "man" // ↓ -------- 在原型中添加一條方法 ---------Person.prototype.seyLove = function () {console.log(name +" love 1024")}; // ↓ -------- 實例化這個對象 ----------var man = new Person("伊凡ED",20);console.log(man)console.log(man.name+" sex="+man.sex);Person.prototype.seyLove()console.log(man.__proto__)console.log(Person.prototype)console.log(man.__proto__===Person.prototype)// - ↑ 上面的代碼輸出 :Person?{name: "伊凡FD", age: 20} // 伊凡ED sex=man // love 1024 // {sex: "man", seyLove: ?, constructor: ?} // {sex: "man", seyLove: ?, constructor: ?} // true我們接著用一張圖清楚的標明他的指向
3.Object
既然 剛才說所有的對象 都有一個__proto__屬性 那么我們原型的__proto__指向哪里呢?
// ↓ -------- 創建一個構造函數 --------function Person(name,age) {this.name = name;this.age = age;}Person.prototype.sex = "man"// ↓ -------- 在原型中添加一條方法 ---------Person.prototype.seyLove = function () {console.log(name +" love 1024")};// ↓ -------- 實例化這個對象 ----------var man = new Person("伊凡FD",20);console.log(man.__proto__.__proto__)// - ↑ 上面的輸出:/* constructor: ? Object()* hasOwnProperty: ? hasOwnProperty()* isPrototypeOf: ? isPrototypeOf()* propertyIsEnumerable: ? propertyIsEnumerable()* toLocaleString: ? toLocaleString()* toString: ? toString()* valueOf: ? valueOf()* __defineGetter__: ? __defineGetter__()* __defineSetter__: ? __defineSetter__()* __lookupGetter__: ? __lookupGetter__()* __lookupSetter__: ? __lookupSetter__()* get __proto__: ? __proto__()* set __proto__: ? __proto__()* */得到的結果看著還很長 我們順著這條線 來到了Object構造函數的原型?
4.null
這次我們打印Object.prototype的__proto__ 輸出為null (萬物皆對象 對象皆為空)
// ↓ -------- 創建一個構造函數 --------function Person(name,age) {this.name = name;this.age = age;}Person.prototype.sex = "man"// ↓ -------- 在原型中添加一條方法 ---------Person.prototype.seyLove = function () {console.log(name +" love 1024")};// ↓ -------- 實例化這個對象 ----------var man = new Person("伊凡FD",20);console.log(man.__proto__.__proto__.__proto__)// - ↑ 上面的輸出:null5.原型的查找屬性
現在我可以解釋一下 原型的查找屬性 根據上面的__proto__ 如果在一個對象中查找某個屬性 未查找到 則會順著__proto__的路線向上查找 也就是 先去查找顯性原型中有沒有該屬性 如果沒有 他就會沿著__proto__的路線一直向上找 也就是他會根據構造安徽函數的原型去查找 ?如果都沒又找到 最后只能輸出null 萬物皆為空
6.constructor?
以上的指針指向的都是原型 剛才也說了每一個對象都有一個__proto__ 每一個__proto__ 都指向的是原型 而每一個原型 都又一個關聯的構造函數 而constructor 就是指向這個函數的
// ↓ -------- 創建一個構造函數 --------function Person(name,age) {this.name = name;this.age = age;}Person.prototype.sex = "man"// ↓ -------- 在原型中添加一條方法 ---------Person.prototype.seyLove = function () {console.log(name +" love 1024")};// ↓ -------- 實例化這個對象 ----------var man = new Person("伊凡ED",20);console.log(man.__proto__.constructor?);console.log(man.__proto__.constructor.prototype?);console.log(man.__proto__.__proto__.constructor?);console.log(man.__proto__.__proto__.constructor.prototype?);// - ↑ 輸出結果:/* ? Person(name,age) {* this.name = name;* this.age = age;* }* {sex: "man", seyLove: ?, constructor: ?}* ? Object() { [native code] }* {constructor: ?, __defineGetter__: ?, * __defineSetter__: ?,* hasOwnProperty: ?,* __lookupGetter__: ?,* …}* */情況如下圖:
我們在使用原型的時候 一般將需要擴展的方法寫在構造函數的prototype屬性中 避免寫在__proto__屬性里面。
?
總結
以上是生活随笔為你收集整理的JavaScript 原型 原型链的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前段基础 HTML 第三章文字与段落标记
- 下一篇: 暑假社会实践心得