成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深度解析原型中的各個難點(diǎn)

zhangke3016 / 2997人閱讀

摘要:的過程新生成了一個對象鏈接到原型綁定返回新對象在調(diào)用的過程中會發(fā)生以上四件事情,我們也可以試著來自己實(shí)現(xiàn)一個創(chuàng)建一個空的對象獲得構(gòu)造函數(shù)鏈接到原型綁定,執(zhí)行構(gòu)造函數(shù)確保出來的是個對象對于實(shí)例對象來說,都是通過產(chǎn)生的,無論是還是。

prototype

首先來介紹下 prototype 屬性。這是一個顯式原型屬性,只有函數(shù)才擁有該屬性?;旧纤泻瘮?shù)都有這個屬性,但是也有一個例外

let fun = Function.prototype.bind()

如果你以上述方法創(chuàng)建一個函數(shù),那么可以發(fā)現(xiàn)這個函數(shù)是不具有 prototype 屬性的。

prototype 如何產(chǎn)生的

當(dāng)我們聲明一個函數(shù)時,這個屬性就被自動創(chuàng)建了

function Foo() {}

并且這個屬性的值是一個對象(也就是原型),只有一個屬性 constructor

constructor 對應(yīng)著構(gòu)造函數(shù),也就是 Foo。

constructor

constructor 是一個公有且不可枚舉的屬性。一旦我們改變了函數(shù)的 prototype ,那么新對象就沒有這個屬性了(當(dāng)然可以通過原型鏈取到 constructor)。

那么你肯定也有一個疑問,這個屬性到底有什么用呢?其實(shí)這個屬性可以說是一個歷史遺留問題,在大部分情況下是沒用的,在我的理解里,我認(rèn)為他有兩個作用:

1.讓實(shí)例對象知道是什么函數(shù)構(gòu)造了它
2.如果想給某些類庫中的構(gòu)造函數(shù)增加一些自定義的方法,就可以通過 xx.constructor.method 來擴(kuò)展

__proto__

這是每個對象都有的隱式原型屬性,指向了創(chuàng)建該對象的構(gòu)造函數(shù)的原型。其實(shí)這個屬性指向了 [[prototype]],但是 [[prototype]] 是內(nèi)部屬性,我們并不能訪問到,所以使用 __proto__ 來訪問。

因?yàn)樵?JS 中是沒有類的概念的,為了實(shí)現(xiàn)類似繼承的方式,通過 __proto__ 將對象和原型聯(lián)系起來組成原型鏈,得以讓對象可以訪問到不屬于自己的屬性。

實(shí)例對象的 __proto__ 如何產(chǎn)生的

從上圖可知,當(dāng)我們使用 new 操作符時,生成的實(shí)例對象擁有了 __proto__屬性。

function Foo() {}
// 這個函數(shù)是 Function 的實(shí)例對象
// function 就是一個語法糖
// 內(nèi)部調(diào)用了 new Function(...)

所以可以說,在 new 的過程中,新對象被添加了 __proto__ 并且鏈接到構(gòu)造函數(shù)的原型上。

new 的過程
1.新生成了一個對象
2.鏈接到原型
3.綁定 this
4.返回新對象
在調(diào)用 new 的過程中會發(fā)生以上四件事情,我們也可以試著來自己實(shí)現(xiàn)一個 new

function create() {
    // 創(chuàng)建一個空的對象
    let obj = new Object()
    // 獲得構(gòu)造函數(shù)
    let Con = [].shift.call(arguments)
    // 鏈接到原型
    obj.__proto__ = Con.prototype
    // 綁定 this,執(zhí)行構(gòu)造函數(shù)
    let result = Con.apply(obj, arguments)
    // 確保 new 出來的是個對象
    return typeof result === "object" ? result : obj
}

對于實(shí)例對象來說,都是通過 new 產(chǎn)生的,無論是 function Foo() 還是 let a = { b : 1 } 。

對于創(chuàng)建一個對象來說,更推薦使用字面量的方式創(chuàng)建對象。因?yàn)槟闶褂?new Object() 的方式創(chuàng)建對象需要通過作用域鏈一層層找到 Object,但是你使用字面量的方式就沒這個問題。

function Foo() {}
// function 就是個語法糖
// 內(nèi)部等同于 new Function()
let a = { b: 1 }
// 這個字面量內(nèi)部也是使用了 new Object()
Function.__proto__ === Function.prototype

對于對象來說,xx.__proto__.contrcutor 是該對象的構(gòu)造函數(shù),但是在圖中我們可以發(fā)現(xiàn) Function.__proto__ === Function.prototype,難道這代表著 Function 自己產(chǎn)生了自己?

答案肯定是否認(rèn)的,要說明這個問題我們先從 Object 說起。

從圖中我們可以發(fā)現(xiàn),所有對象都可以通過原型鏈最終找到 Object.prototype ,雖然 Object.prototype 也是一個對象,但是這個對象卻不是 Object 創(chuàng)造的,而是引擎自己創(chuàng)建了 Object.prototype 。所以可以這樣說,所有實(shí)例都是對象,但是對象不一定都是實(shí)例。

接下來我們來看 Function.prototype 這個特殊的對象,如果你在瀏覽器將這個對象打印出來,會發(fā)現(xiàn)這個對象其實(shí)是一個函數(shù)。

我們知道函數(shù)都是通過 new Function() 生成的,難道 Function.prototype 也是通過 new Function() 產(chǎn)生的嗎?答案也是否定的,這個函數(shù)也是引擎自己創(chuàng)建的。首先引擎創(chuàng)建了 Object.prototype ,然后創(chuàng)建了 Function.prototype ,并且通過 __proto__ 將兩者聯(lián)系了起來。這里也很好的解釋了上面的一個問題,為什么 let fun = Function.prototype.bind() 沒有 prototype 屬性。因?yàn)?Function.prototype 是引擎創(chuàng)建出來的對象,引擎認(rèn)為不需要給這個對象添加 prototype 屬性。

所以我們又可以得出一個結(jié)論,不是所有函數(shù)都是 new Function() 產(chǎn)生的。
有了 Function.prototype 以后才有了 function Function() ,然后其他的構(gòu)造函數(shù)都是 function Function() 生成的。

現(xiàn)在可以來解釋 Function.__proto__ === Function.prototype 這個問題了。因?yàn)橄扔械?Function.prototype 以后才有的 function Function() ,所以也就不存在雞生蛋蛋生雞的悖論問題了。對于為什么 Function.__proto__ 會等于 Function.prototype ,個人的理解是:其他所有的構(gòu)造函數(shù)都可以通過原型鏈找到 Function.prototype ,并且 function Function() 本質(zhì)也是一個函數(shù),為了不產(chǎn)生混亂就將 function Function() 的 __proto__ 聯(lián)系到了 Function.prototype 上。

總結(jié)

Object 是所有對象的爸爸,所有對象都可以通過 __proto__ 找到它

Function 是所有函數(shù)的爸爸,所有函數(shù)都可以通過 __proto__ 找到它

Function.prototype 和 Object.prototype 是兩個特殊的對象,他們由引擎來創(chuàng)建

除了以上兩個特殊對象,其他對象都是通過構(gòu)造器 new 出來的

函數(shù)的 prototype 是一個對象,也就是原型

對象的 __proto__ 指向原型, __proto__ 將對象和原型連接起來組成了原型鏈

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/98259.html

相關(guān)文章

  • 【進(jìn)階3-5期】深度解析 new 原理及模擬實(shí)現(xiàn)

    摘要:使用指定的參數(shù)調(diào)用構(gòu)造函數(shù),并將綁定到新創(chuàng)建的對象。由構(gòu)造函數(shù)返回的對象就是表達(dá)式的結(jié)果。情況返回以外的基本類型實(shí)例中只能訪問到構(gòu)造函數(shù)中的屬性,和情況完全相反,結(jié)果相當(dāng)于沒有返回值。 定義 new 運(yùn)算符創(chuàng)建一個用戶定義的對象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對象的實(shí)例。 ——(來自于MDN) 舉個栗子 function Car(color) { this.color = co...

    Baaaan 評論0 收藏0
  • JS筆記

    摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...

    rottengeek 評論0 收藏0
  • JavasScript重難點(diǎn)知識

    摘要:忍者級別的函數(shù)操作對于什么是匿名函數(shù),這里就不做過多介紹了。我們需要知道的是,對于而言,匿名函數(shù)是一個很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...

    forsigner 評論0 收藏0
  • 前端秋招面試總結(jié)

    摘要:前言秋招宣告結(jié)束,面試了接近家公司,有幸拿到,感謝這段時間一起找工作面試的朋友和陪伴我的人。一定要提前準(zhǔn)備好,不然面試官叫你說遇到的難點(diǎn),或者直接問問題時可能會懵逼。 前言 秋招宣告結(jié)束,面試了接近20家公司,有幸拿到offer,感謝這段時間一起找工作面試的朋友和陪伴我的人。這是一段難忘的經(jīng)歷,相信不亞于當(dāng)年的高考吧,也許現(xiàn)在想起來高考不算什么,也許只有經(jīng)歷過秋招的人才懂得找工作的艱辛...

    Gu_Yan 評論0 收藏0
  • 前端秋招面試總結(jié)

    摘要:前言秋招宣告結(jié)束,面試了接近家公司,有幸拿到,感謝這段時間一起找工作面試的朋友和陪伴我的人。一定要提前準(zhǔn)備好,不然面試官叫你說遇到的難點(diǎn),或者直接問問題時可能會懵逼。 前言 秋招宣告結(jié)束,面試了接近20家公司,有幸拿到offer,感謝這段時間一起找工作面試的朋友和陪伴我的人。這是一段難忘的經(jīng)歷,相信不亞于當(dāng)年的高考吧,也許現(xiàn)在想起來高考不算什么,也許只有經(jīng)歷過秋招的人才懂得找工作的艱辛...

    Scholer 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<