摘要:下面列幾個權(quán)威指南里面介紹的關(guān)于原型的方法獲取一個實例對象的原型才支持部分瀏覽器也支持一個屬性判斷一個構(gòu)造函數(shù)是否是指定實例對象的原型
JS中的原型對象
白天寫了一篇【JS中創(chuàng)建對象的方法】,寫完以后感覺意猶未盡(實際情況是感覺原型那塊內(nèi)容沒有交
代清楚),所以開這一篇繼續(xù)聊聊關(guān)于JavaScript中的原型對象
相信用過vue的童鞋,都經(jīng)常這樣做,用Vue.prototype.xxx = xxx 把一個方法或者屬性添加到Vue對象的原型上,
這樣,我們在vue實例的任何地方,都可以用這個方法或?qū)傩粤?,我最喜歡用的,就是把異步請求庫
(我比較喜歡用axios)掛載到vue原型上:
// 一般是./src/mian.js // 這里為了方便理解就直接引入axios,實際使用,我們可以先用axios封裝一個異步請求模塊 // 在模塊里做一些攔截或者處理,然后再導(dǎo)入這個模塊。具體做法看 import axios from "axios" import Vue from "vue" import App from "./App" // 為所有Vue實例添加一個post模塊,可以在vue實例中直接使用this.post Vue.prototype.post = axios new Vue({ el: "#app", components: { App }, template: "" })
這了是prototype就是我們所說的原型,那什么是原型呢? 我們看看MDN給的解釋
當談到繼承時,JavaScript 只有一種結(jié)構(gòu):對象。每個對象都有一個私有屬性(稱之為 [[Prototype]]),
它指向它的原型對象(prototype)。該 prototype 對象又具有一個自己的 prototype ,
層層向上直到一個對象的原型為 null。根據(jù)定義,null 沒有原型,并作為這個原型鏈中的最后一個環(huán)節(jié)。
視乎看起好有點拗口,沒關(guān)系,我用自己的話總結(jié)了一下
1.prototype其實就是存在于對象中的一個特殊的對象,你可以把它理解為對象的一個屬性或方法,
如 a.prototype,看起來是不是很像對象a的一個屬性呢?2.每個對象都有一個prototype,除了null
那這個prototype是干嘛的呢? 其實回頭看看上面關(guān)于vue的代碼就知道了,
prototype最主要的作用就是該原型所屬對象的所有實例,都能共享prototype里的屬性和方法
上面的代碼中,通過向Vue.prototype中添加一個post方法,然后就可以在所有vue實例中使用該方法,就是個簡單的實踐。
我們回頭看看 【JS中創(chuàng)建對象的方法】里面的原型模式
function Student(){} // 聲明一個空函數(shù) Student.prototype.name = "xiaohong" Student.prototype.age = 17 Student.prototype.gender = "f" Student.prototype.study = fucntion() { console.log("我在學(xué)習(xí)...")}
我們先定義了一個空函數(shù),注意:這個時候,我們并沒有認為的給函數(shù)添加一個prototype屬性/方法,
而Student卻自動有了prototype,然后我們往prototype里面添加了name,age,gender屬性和study方法,
然后我們用new實例化2個Student對象出來
var studentA = new Student() console.log(studentA.name) // xiaohong console.log(studentA.age) // 17 console.log(studentA.gender) // f studentA.study() // 我在學(xué)習(xí)... var studentB = new Student() console.log(studentB.age) // xiaohong console.log(studentB.name) // 17 console.log(studentB.gender) // f studentB.study() // 我在學(xué)習(xí)...
上面的例子可以看出,對象的prototype里面的屬性和方法,在該對象的所有實例里面,都是共享的
那如果我們想要讓實例對象有自己的屬性/方法,該怎么辦呢? 比如,我想讓studentB的名字是"lili",
很簡單,直接在實例對象上添加該屬性/方法:
studentA.name = "lili" studentA.study = function () { console.log("我在偷懶") } console.log(studentA.name) // lili console.log(studentB.name) // xiaohong studentA.study() // 我在偷懶 studentB.study() // 我在學(xué)習(xí)...
可以看出,studentA的屬性/方法被改變的時候,studentB沒有對應(yīng)的跟著改變,這是為什么呢?
不是說好的全所有prototype里的屬性/方法都是共享的嗎?事實上,prototype里的屬性/方法,確實是共享的,
問題出在我們是在實例對象上賦值,所以這個屬性/方法,是屬于實例的,而不是屬于prototype的,prototype的屬性,
也無法在實例對象上寫入,也就是說,實例對象和prototype上,同時存在了 name屬性和study方法,那么,
為什么 studentA 和 studentB 訪問到的屬性/方法 會不一樣呢? 其實每次訪問一個屬性/方法的時候,
都會先從實例對象開始查找,如果實例上有,就直接返回,如果實例上沒有,就繼續(xù)往prototype上查找,有就返回,
如果prototype上還有 prototype,那么還會繼續(xù)網(wǎng)上查找,直到原型鏈的最頂層。如果都沒有查到,則會返回undefined。
那么新的問題來了,我們該如何判斷一個屬性,是屬于實例本身的,還是屬于prototype的? 答案是hasOwnProperty方法,
hasOwnProperty方法可以檢測到實例對象里面有沒有給定的屬性,該方法只能檢測到實例里面的屬性,檢測不到prototype上的
studentA.hasOwnProperty("name") // true studentB.hasOwnProperty("name") // false
那如果想同時查找實例對象和原型對象prototype呢?我們可以用 in 操作符
"name" in studentA // true "name" in studentB // true
有了這2個方法,我們就可以組合起來判斷屬性是屬于實例還是原型了。
這里老是說到實例,不得不提一下,實例對象雖然是構(gòu)造函數(shù)“構(gòu)造”出來的,但是其實跟構(gòu)造函數(shù)沒有直接聯(lián)系,
實例對象內(nèi)部指向的是構(gòu)造函數(shù)的prototype(原型)。 實例跟構(gòu)造函數(shù)的一個間接關(guān)系是
實例.prototype.constructor --> 構(gòu)造函數(shù)
關(guān)于原型的介紹就到這里,有需要更深入的童鞋,建議去讀一下javascript權(quán)威指南。里面關(guān)于原型的介紹比我這詳細。
下面列幾個javascript權(quán)威指南里面介紹的關(guān)于原型的方法
獲取一個實例對象的原型 (ES5才支持)
Object.getPrototypeOf(studentA) // Student.prototype
部分瀏覽器(chrome,safari,firefox)也支持一個屬性 __proto__
studentA.__proto__ == Student.prototype
判斷一個構(gòu)造函數(shù)是否是指定實例對象的原型
Student.prototype.isPrototypeOf(studentA) // true
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94160.html
摘要:此用來定義通過構(gòu)造器構(gòu)造出來的對象的原型,構(gòu)造器內(nèi)部的代碼用來給對象初始化。 對象繼承 VS 類繼承 在 class-based 的面向?qū)ο蟮氖澜缋?,要出現(xiàn)對象,必須先有類。類之間可以繼承,類再使用 new 操作創(chuàng)建出實體,父子對象之間的繼承體現(xiàn)在父類和子類上。你不能說 對象 a 繼承了對象 b,只能說 class A 繼承了 class B,然后他們各自有一個實例a、b。 JS中實現(xiàn)...
摘要:原型對象是由創(chuàng)建的,因此原型對象的構(gòu)造函數(shù)是構(gòu)造函數(shù)也可以是稱為對象,原型對象也就繼承了其生父構(gòu)造函數(shù)中的數(shù)據(jù),也同時繼承了原型對象的數(shù)據(jù)。當然這條原型鏈中的數(shù)據(jù),會被還是還是這類構(gòu)造函數(shù)繼承,但是不會被這些繼承,他們不處于同一個鏈條上。 js中,F(xiàn)unction的本質(zhì)是什么?Object的本質(zhì)又是什么?js中有幾條原型鏈? showImg(https://segmentfault.c...
摘要:每個原型都有一個屬性指向關(guān)聯(lián)的構(gòu)造函數(shù)由于實例對象可以繼承原型對象的屬性,所以實例對象也擁有屬性,同樣指向原型對象對應(yīng)的構(gòu)造函數(shù)。 showImg(https://segmentfault.com/img/remote/1460000017183104?w=1300&h=834); 構(gòu)造函數(shù):function Foo ( ) { }; 實例對象:let f1=new Foo; 談到...
摘要:對象重新認識面向?qū)ο竺嫦驅(qū)ο髲脑O(shè)計模式上看,對象是計算機抽象現(xiàn)實世界的一種方式。除了字面式聲明方式之外,允許通過構(gòu)造器創(chuàng)建對象。每個構(gòu)造器實際上是一個函數(shù)對象該函數(shù)對象含有一個屬性用于實現(xiàn)基于原型的繼承和共享屬性。 title: JS對象(1)重新認識面向?qū)ο? date: 2016-10-05 tags: JavaScript 0x00 面向?qū)ο?從設(shè)計模式上看,對象是...
閱讀 3270·2021-11-24 10:43
閱讀 4234·2021-11-24 10:33
閱讀 3815·2021-11-22 09:34
閱讀 2155·2021-10-11 10:58
閱讀 3784·2021-10-11 10:58
閱讀 884·2021-09-27 13:36
閱讀 3607·2019-08-30 15:54
閱讀 2993·2019-08-29 18:41