您好,登錄后才能下訂單哦!
本篇內容主要講解“JavaScript原型與原型鏈知識點有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JavaScript原型與原型鏈知識點有哪些”吧!
在JavaScript中,函數是一個包含屬性和方法的Function
類型的對象。而原型(Prototype)
就是Function
類型對象的一個屬性。
在函數定義時就包含了prototype
屬性,它的初始值是一個空對象。在JavaScript中并沒有定義函數的原型類型,所以原型可以是任何類型。
原型是用于保存對象的共享屬性和方法的,原型的屬性和方法并不會影響函數本身的屬性和方法。
// Function類型的屬性->所有函數都具有的屬性 console.log(Function.prototype);//[Function] // 定義函數 function fn() { console.log('this is function'); } //原型的默認值是空對象 console.log(fn.prototype);//fn {} // 函數包含構造函數 ——> 所有引用類型其實都是構造函數 console.log(Number.prototype); //[Number: 0] console.log(Object.prototype);//{}
通過如下兩種方式可以獲取對象的原型,從而設置共享的屬性和方法:
通過構造函數的prototype
屬性
通過Object對象的getPrototype
(obj)方法。
function fn() { console.log('this is function'); } //使用訪問對象的屬性語法結構 console.log(fn.prototype);//fn {} console.log(fn['prototype']);//fn {} //Object類型提供getPrototypeOf()方法 console.log(Object.getPrototypeOf(fn));//[Function]
Object.getOwnPropertyDescriptors()
方法用來獲取一個對象的所有自身屬性的描述符。
var result = Object.getOwnPropertyDescriptor(Object.prototype,'constructor'); console.log(result) //輸出結果如下: //{ // value: [Function: Object], // writable: true, // enumerable: false, // configurable: true // }
constructor是在創建函數的時候自動添加的,指向構造函數本身
通過如下兩種方式可以設置原型的屬性和方法:
原型的屬性和方法單獨進行定義。
構造函數.prototype.屬性名 = 屬性值 ;構造函數.prototype.方法名 = function(){} ;
直接為原型定義一個新對象。
當我們需要在原型上添加很多很多屬性的時候 一遍一遍的去寫
構造函數.prototype.屬性名
太麻煩了,可以直接修改整個prototype
構造函數.prototype = { 屬性名:屬性值, 方法名:function(){}}
function foo () {}foo.prototype = { constructor: foo, name: 'jam', age: 18, address: '北京市'}var fn = new foo()console.log(fn.address) // 北京市
每個對象中都會具有一個isPrototypeOf()
方法,該方法用來判斷一個對象是否是另一個對象的原型。
示例代碼如下: // 通過初始化器方式定義對象 var obj = { name:'jam' } // 定義構造函數 function Hero() {} // 將對象obj賦值給構造函數Hero的原型 Hero.prototype = obj; // 通過構造函數創建對象 var hero = new Hero(); // isPrototypeOf()方法判斷指定對象是否是另一個對象的原型 var result = obj.isPrototypeOf(hero); console.log(result);//true
驗證了
obj
對象是hero
對象的原型
接下來我們使用一段代碼來展開對原型鏈的認識:
場景:查找obj對象身上的address屬性 js執行的步驟: 1. 會觸發get操作 2. 在當前的對象中查找屬性 3. 如果沒有找到,這個時候會去原型鏈(__proto__)對象上查找 1. 查找到結束 2. 沒查找到一直順著原型鏈查找,直到查找到頂層原型(頂層原型是什么暫時賣個關子)
var obj = { name: 'jam', age: 19 } /* 要求:查找obj對象身上的address屬性 */ // 原型鏈一層一層向上查找,如果一直沒有找到,直到查找到頂層原型結束 obj.__proto__ = {} obj.__proto__.__proto__ = {} obj.__proto__.__proto__.__proto__ = { address: '北京市' } console.log(obj.address) // 北京市 console.log(obj.__proto__.__proto__.__proto__) // { address: '北京市' }
最終查找到address屬性
那么這里有一個問題,如果一直沒有查到,會無窮盡的去查找嗎?接下來我們就來了解一下
上面我們說到,順著原型鏈不會無休止的去查找,當查到頂層原型的時候,如果還沒查到就會返回undefined
。
那么頂層原型是什么呢?
示例代碼如下:
var obj = { name: 'jam' }console.log(obj.__proto__) // {}console.log(obj.__proto__.__proto__) // null
字面量對象obj的原型是:
{}
。{}
就是頂層的原型
當我們繼續向上打印__proto__
時,返回一個null值,就證明上一層就已經是頂層原型了
如下圖是針對第一段代碼中缺少的頂層原型做的補充:
頂層原型就是Object.prototype
3.1 那么什么地方是原型鏈的盡頭呢?比如第三個對象是否也有原型__proto__
屬性呢?
var obj = {name:'jam'}obj.__proto__ = {}obj.__proto__.__proto__ = {}obj.__proto__.__proto__.__proto__ = {}console.log(obj.__proto__.__proto__.__proto__.__proto__) // {}
我們發現上面打印結果為 空對象{}
事實上這個原型就是我們最頂層的原型了
var obj = { name: 'jam', age: 19 } console.log(obj.__proto__) // {} console.log(Object.prototype) // {} console.log(obj.__proto__ === Object.prototype) // true
Object是所有類的父類
所以obj.__proto__其實就是Object.prototype ,console.log(obj.__proto__ === Object.prototype) // true
我們可以看出結果Object.prototype就是頂層原型
從Object直接創建出來的對象的原型都是 {}
3.2 那么我們可能會問:{}
原型有什么特殊的嘛?
特殊點1:該對象有原型屬性,但是它的原型屬性已經指向的是null,也就是已經是頂層原型了;
console.log(obj.__proto__.__proto__.__proto__.__proto__.__proto__) // null
特殊點2:該對象上有甚很多默認的屬性和方法;
雖然打印Object.prototype
的結果為空對象{},但它不是空的,只是里面的屬性不可枚舉而已,例如我們就打印constructor
屬性看看
<!-- 可以看出是有constructor屬性的 ,并不是空的-->console.log(Object.prototype.constructor) // [Function: Object] <!-- constructor 指回了Object -->
我們也可以通過Object.getOwnPropertyDescriptors()
方法獲取Object.prototype
中的所有自身屬性的描述符。
console.log(Object.getOwnPropertyDescriptors(Object.prototype)) // 如下長截圖所示
到此,相信大家對“JavaScript原型與原型鏈知識點有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。