JavaScript原型Prototype詳情
1、概述
1.1原型是什么
在JavaScript
中,函數(shù)是一個包含屬性和方法的Function
類型的對象。而原型(Prototype )就是Function類型對象的一個屬性。
在函數(shù)定義是包含了prototype屬性,它的初始值是一個空對象 。在JavaScript中并沒有定義函數(shù)的原始類型,所以原型可以是任何類型。
原型是用于保存對象的共享屬性和方法的,原型的屬性和方法并不會影響函數(shù)本身的屬性和方法。
示例代碼驗(yàn)證如下:
function fun() { console.log('函數(shù)原型') } console.log(fun.prototype) // {}
fun.prototype
返回的也是一個空對象,但是這不說明Object.prototype
中沒有屬性或者方法,這些屬性和方法為不可枚舉的,示例代碼如下所示:
function fun() { console.log('函數(shù)原型') } console.log(fun.prototype) // {} // 通過 Object.getOwnPropertyNames() 獲取全部屬性 console.log(Object.getOwnPropertyNames(fun.prototype)) // [ 'constructor' ]
其中,constructor屬性指向該構(gòu)造函數(shù)的引用,代碼如下:
// constructor屬性 console.log(fun.prototype.constructor) // [Function: fun] console.log(fun.prototype.constructor === fun) // true
1.2獲取原型
了解了原型的概念以及作用之后,我們需要獲取到原型才能對其進(jìn)行操作,在JavaScript
中獲取原型的方式有兩種,如下所示:
通過構(gòu)造函數(shù)的prototype
屬性。
通過Object.getPrototypeOf(obj)
方法。
這兩個的區(qū)別就是構(gòu)造函數(shù)的prototype屬性一般只配合構(gòu)造函數(shù)使用,而Object.getPrototypeOf(obj)方法一般是獲取構(gòu)造函數(shù)實(shí)例化后的對象的原型方法。
實(shí)例代碼如下:
// 構(gòu)造函數(shù) function Person(name) { this.name = name } // 指向構(gòu)造函數(shù)的原型 var p1 = Person.prototype var person = new Person('一碗周') // 指向構(gòu)造函數(shù)的原型 var p2 = Object.getPrototypeOf(person) console.log(p1 === p2) // true
獲取原型后可以跟操作對象似的進(jìn)行操作,因?yàn)樵捅旧砭褪且粋€對象。
2、原型屬性
在JavaScript
中,函數(shù)本身也是一個包含了方法和屬性的對象。接下將學(xué)習(xí)函數(shù)對象的另一個屬性——prototype,這個屬性的初始值是一個空對象。
2.1利用原型添加屬性與方法。
為對象添加屬性和方法的另一種用法就是通過原型為其添加。當(dāng)為一個構(gòu)造函數(shù)添加原型屬性和原型方法時,通過該構(gòu)造函數(shù)new出的所有對象共享該屬性和方法。
PS:所謂的原型屬性或者原型方法就是通過原型添加的屬性或者方法。
添加屬性和方法的方式具有如下幾種方式
直接為其增加屬性或者方法
通過Object.defineProperty()
方法,添加屬性或者方法。這種方式比第一種方式更具有安全性。
直接添加對象到原型。
示例代碼如下所示:
//構(gòu)造函數(shù) function Fun() {} //直接為構(gòu)造函數(shù)添加屬性和方法 Fun.prototype.str = '這是一個字符串' Fun.prototype.fn = function () { console.log('這是一個方法') } //通過 defineProperty 添加屬性或者方法 Object.defineProperty(Fun.prototype, 'MyFun', { value: function () { console.log('this is MyFun') }, }) //測試 console.log(Fun.prototype.str) Fun.prototype.fn() Fun.prototype.MyFun() var fun = new Fun() fun.MyFun() //直接為其定義個對象覆蓋到之前的原型上 Fun.prototype = { name: '一碗周', fun: function () { console.log('this is function') }, } Fun.prototype.fun() var fun = new Fun() fun.fun()
2.2訪問原型屬性原型方法
對于原型來說,最重要的一點(diǎn)就是它的實(shí)時性 。由于在JavaScript中,幾乎所有的對象都是通過傳引用的方式來傳遞的,因此我們所創(chuàng)建的的每個新對象實(shí)體中并沒有一份屬于自己的原型副本。這就意味著我們隨時修改prototype
屬性,并且由同一構(gòu)造器創(chuàng)建的所有對象的prototype屬性也都會同時改變,包括我們之間通過構(gòu)造器創(chuàng)建的屬性和方法。
還是上面那段代碼我們向原型中添加一個新方法,并調(diào)用,示例代碼如下所示:
Fun.prototype.fn = function () { console.log('這是一個方法') } fun.fn() //這是一個方法
我們之前創(chuàng)建的對象可以訪問新加的原型屬性和原型方法。
3、自有屬性與原型屬性
我們先來創(chuàng)建一個構(gòu)造函數(shù),并為其添加兩個原型屬性。
//構(gòu)造函數(shù) function Fun() {} //添加原型屬性和方法 Fun.prototype.name = '一碗粥' Fun.prototype.print = function () { console.log('this is function') }
在通過該構(gòu)造函數(shù)創(chuàng)建一個對象,為其設(shè)置屬性和方法
//通過構(gòu)造函數(shù)創(chuàng)建對象 var fun = new Fun() //為對象添加屬性和方法 fun.name = '一碗周' fun.SayMe = function () { console.log('this is SayMe') }
現(xiàn)在我們的fun
對象,擁有自有屬性/方法兩個,原型屬性/方法兩個。我們依次來訪問這些屬性和方法。
//訪問屬性和方法 console.log(fun.name) // 一碗周 fun.SayMe() // this is SayMe fun.print() // this is function
當(dāng)我們訪問name
屬性時,JavaScript引擎會遍歷fun這個對象的所有屬性,并返回name屬性的值。SayMe()方法也是樣的道理。但是到print()方法時,JavaScript
引擎還是會遍歷這個對象所有屬性,這時就找不到一個叫print()方法了,接下來JavaScript
引擎就會訪問創(chuàng)建當(dāng)前對象的構(gòu)造器函數(shù)的原型,也就是我們的Fun.prototype
,如果其中有該屬性,則立即返回,否則返回undefined
或者拋出異常
結(jié)論:當(dāng)有自有屬性時,優(yōu)先訪問自有屬性,訪問完自有屬性再去訪問原型屬性 。
3.1檢測自有屬性或者原型屬性
現(xiàn)在已經(jīng)知道自有屬性和原型屬性的概念以及用途了,但是我們怎么知道一個屬性時自由屬性還是原有屬性,JavaScript中提供以下兩種方式來檢測一個屬性的情況
使用Object.prototype.hasOwnProperty(prop)
方法來檢測prop屬性是否是自由屬性,該方法返回一個布爾值,如果是自有屬性則返回true,否則返回false。
來使用in關(guān)鍵字來檢測對象以及原型鏈中是否具有指定屬性。
測試代碼如下:
// 通過Object.prototype.hasOwnProperty(prop)方法檢測是否為自有屬性 console.log(fun.hasOwnProperty('name')) // true console.log(fun.hasOwnProperty('print')) // false // 如果一個不存在的屬性檢測結(jié)果也是為false console.log(fun.hasOwnProperty('SayMe')) // true // 通過 in 運(yùn)算符 console.log('name' in fun) // true console.log('print' in fun) // true console.log('SayMe' in fun) // true
通過測試我們發(fā)現(xiàn),這兩個方法并不能檢測一個屬性是不是一個自有屬性或者原型屬性,但是將這兩個方法結(jié)合起來就可以檢測是自有屬性還是原型屬性了,
示例代碼如下:
function DetectionAttributes(obj, attr) { if (attr in obj) { if (obj.hasOwnProperty(attr)) { // 如果是自有屬性屬性返回1 return 1 } else { // 如果是原型屬性返回0 return 0 } } else { // 沒有這個屬性返回 -1 return -1 } }
測試如下:
console.log(DetectionAttributes(fun, 'name')) // 1
console.log(DetectionAttributes(fun, 'print')) // 0
console.log(DetectionAttributes(fun, 'SayMe')) // 1
4、isPrototypeOf()方法
isPrototypeOf()
方法用來檢測一個對象是否存在于另一個對象的原型鏈中,如果存在就返回true,否則就返回false。
實(shí)例代碼如下所示:
// 定義一個對象,用于賦值給原型對象 var obj = function () { this.name = '一碗周' } var Hero = function () {} // 定義構(gòu)造函數(shù) // 將定義的對象賦值給構(gòu)造函數(shù)的原型 Hero.prototype = obj // 通過Hero創(chuàng)建對象 var hero1 = new Hero() var hero2 = new Hero() // 判斷創(chuàng)建的兩個對象是否在 obj 的原型鏈中 console.log(obj.isPrototypeOf(hero1)) // true console.log(obj.isPrototypeOf(hero2)) // true
5、擴(kuò)展內(nèi)置對象
JavaScript中的內(nèi)置對象有些也具prototype
屬性,利用內(nèi)置對象的prototype
屬性可以為內(nèi)置對象擴(kuò)展屬性和方法。
通過原型擴(kuò)展內(nèi)置對象的屬性和方法非常靈活,根據(jù)個性化要求制定JavaScript語言的具體內(nèi)容。
擴(kuò)展內(nèi)置對象的方式有兩種,具體如下所示:
通過直接新增屬性和方法。
通過Object對象的defineProperty()
方法為其新增屬性或者方法。這種方式會比第一種方式要好,是創(chuàng)建的屬性和方法更具有安全性
示例代碼如下所示:
// 為 Object 擴(kuò)展屬性和方法 // 使用第一種方式 Object.prototype.MyPrint = function () { console.log('this is MyPrint()') } // 使用第二種方式 Object.defineProperty(Object.prototype, 'MyInput', { value: function () { console.log('this is MyInput()') }, }) // 調(diào)用 Object.prototype.MyPrint() // this is MyPrint() Object.prototype.MyInput() // this is MyInput()
6、結(jié)語
這篇文章介紹了JavaScript中的原型的概念、原型屬性、如何檢測自有屬性和原型屬性以及如何擴(kuò)展內(nèi)置對象
到此這篇關(guān)于JavaScript原型Prototype詳情的文章就介紹到這了,更多相關(guān)JavaScript原型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Web?Animations?API實(shí)現(xiàn)一個精確計(jì)時的時鐘示例
這篇文章主要為大家介紹了Web?Animations?API實(shí)現(xiàn)一個精確計(jì)時的時鐘示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07微信小程序 wx.request(object) API詳解及實(shí)例代碼
這篇文章主要介紹了微信小程序 wx.request(object) API詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-09-09微信小程序 出現(xiàn)47001 data format error原因解決辦法
這篇文章主要介紹了微信小程序 出現(xiàn)47001 data format error原因解決辦法的相關(guān)資料,需要的朋友可以參考下2017-03-03微信小程序 獲取設(shè)備信息 API實(shí)例詳解
這篇文章主要介紹了微信小程序 獲取設(shè)備信息 API實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2016-10-10