国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

寫給Java開發(fā)者看的JavaScript對(duì)象機(jī)制

Charles / 2199人閱讀

摘要:如果你已經(jīng)對(duì)機(jī)制已有了解,但是由于兩者對(duì)象機(jī)制的巨大本質(zhì)差異,對(duì)它和構(gòu)造函數(shù),實(shí)例對(duì)象的關(guān)系仍有疑惑,本文或許可以解答你的問(wèn)題。所有的原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)屬性,這個(gè)屬性的值是指向原型所在的構(gòu)造函數(shù)的指針。

幫助面向?qū)ο箝_發(fā)者理解關(guān)于JavaScript對(duì)象機(jī)制

本文是以一個(gè)熟悉OO語(yǔ)言的開發(fā)者視角,來(lái)解釋JavaScript中的對(duì)象。

對(duì)于不了解JavaScript 語(yǔ)言,尤其是習(xí)慣了OO語(yǔ)言的開發(fā)者來(lái)說(shuō),由于語(yǔ)法上些許的相似會(huì)讓人產(chǎn)生心理預(yù)期,JavaScript中的原型繼承機(jī)制和class語(yǔ)法糖是讓人迷惑的。

如果你已經(jīng)對(duì)prototype機(jī)制已有了解,但是由于兩者對(duì)象機(jī)制的巨大(本質(zhì))差異,對(duì)它和構(gòu)造函數(shù),實(shí)例對(duì)象的關(guān)系仍有疑惑,本文或許可以解答你的問(wèn)題。

我們看下面的代碼,可以看出和OO語(yǔ)言相比,語(yǔ)法上也有很大分別:

// 定義一個(gè)類
class Foo {
  constructor() {
    this.a = "a";
  }
}

//實(shí)例化對(duì)象
const foo = new Foo();

//定義原型的屬性
Foo.prototype.b = "b";

//實(shí)例可以訪問(wèn)屬性
foo.b // "b"

//修改原型的屬性
Foo.prototype.b= "B";


//實(shí)例屬性值沒有被修改
foo.b // "b"

類已經(jīng)定義了怎么還能修改呢?prototype又是什么?

不存在面向?qū)ο?/b>

對(duì)于熟悉了面向?qū)ο蟮拈_發(fā)者而言JS中種種非預(yù)期操作的存在,都是因?yàn)?strong>JavaScript中根本沒有面向?qū)ο蟮母拍?/strong>,只有對(duì)象,沒有類。

即使ES6新添了class語(yǔ)法,不意味著JS引入了面向?qū)ο螅皇窃屠^承的語(yǔ)法糖。

原型是什么

什么是原型?如果說(shuō)類是面向?qū)ο笳Z(yǔ)言中對(duì)象的模版,原型就是 JS中創(chuàng)造對(duì)象的模版。

在面向類的語(yǔ)言中,實(shí)例化類,就像用模具制作東西一樣。實(shí)例化一個(gè)類就意味著“把類的形態(tài)復(fù)制到物理對(duì)象中”,對(duì)于每一個(gè)新實(shí)例來(lái)說(shuō)都會(huì)重復(fù)這個(gè)過(guò)程。

但是在JavaScript中,并沒有類似的復(fù)制機(jī)制。你不能創(chuàng)建一個(gè)類的多個(gè)實(shí)例,只能創(chuàng)建多個(gè)對(duì)象,它們[[Prototype]]關(guān)聯(lián)的是同一個(gè)對(duì)象。

//構(gòu)造函數(shù)
function Foo(){
}
//在函數(shù)的原型上添加屬性
Foo.prototype.prototypeAttribute0 = {status: "initial"};

const foo0 = new Foo();
const foo1 = new Foo();
foo0.prototypeAttribute0 === foo1.prototypeAttribute0 //true
對(duì)象、構(gòu)造函數(shù)和原型的關(guān)系

當(dāng)我們創(chuàng)建一個(gè)新對(duì)象的時(shí)候,發(fā)生了什么,對(duì)象、構(gòu)造函數(shù)和原型到底什么。

先簡(jiǎn)單地概括:

原型用于定義共享的屬性和方法。

構(gòu)造函數(shù)用于定義實(shí)例屬性和方法,僅負(fù)責(zé)創(chuàng)造對(duì)象,與對(duì)象不存在直接的引用關(guān)系。

我們先不用class語(yǔ)法糖,這樣便于讀者理解和暴露出他們之間真正的關(guān)系。

// 先創(chuàng)建一個(gè)構(gòu)造函數(shù) 定義原型的屬性和方法
function Foo() {
    this.attribute0 = "attribute0";
}

當(dāng)創(chuàng)建了一個(gè)函數(shù),就會(huì)為該函數(shù)創(chuàng)建一個(gè)prototype屬性,它指向函數(shù)原型。

所有的原型對(duì)象都會(huì)自動(dòng)獲得一個(gè)constructor屬性,這個(gè)屬性的值是指向原型所在的構(gòu)造函數(shù)的指針。

現(xiàn)在定義原型的屬性和方法

Foo.prototype.prototypeMethod0 = function() {
    console.log("this is prototypeMethod0");
}

Foo.prototype.prototypeAttribute0 = "prototypeAttribute0";

好了,現(xiàn)在,新建一個(gè)對(duì)象,

const foo = new Foo();

foo.attribute0 // "attribute0"
foo.prototypeAttribute0 //"prototypeAttribute0"
foo.prototypeMethod0() // this is prototypeMethod0

它擁有自己的實(shí)例屬性attribute0,并且可以訪問(wèn)在原型上定義的屬性和方法,他們之間的引用關(guān)系如圖所示。

當(dāng)調(diào)用構(gòu)造函數(shù)創(chuàng)建實(shí)例后,該實(shí)例的內(nèi)部會(huì)包含一個(gè)指針(內(nèi)部對(duì)象),指向構(gòu)造函數(shù)的原型對(duì)象。

當(dāng)讀取實(shí)例對(duì)象的屬性時(shí),會(huì)在實(shí)例中先搜尋,沒有找到,就會(huì)去原型鏈中搜索,且總是會(huì)選擇原型鏈中最底層的屬性進(jìn)行訪問(wèn)。

對(duì)象的原型可以通過(guò)__proto__在chrome等瀏覽器上訪問(wèn)。

__proto__是對(duì)象的原型指針,prototype是構(gòu)造函數(shù)所對(duì)應(yīng)的原型指針。

語(yǔ)法糖做了什么

ES6推出了class語(yǔ)法,為定義構(gòu)造函數(shù)和原型增加了便利性和可讀性。

class Foo {
    constructor(){
        this.attribute0 = "attribute0";
    }

    prototypeMethod0(){
        console.log("this is prototypeMethod0")
    }
}

/* 相當(dāng)于下面的聲明*/
function Foo() {
    this.attribute0 = "attribute0";
}

Foo.prototype.prototypeMethod0 = function() {
    console.log("this is prototypeMethod0")
}

class中的constractor相當(dāng)于構(gòu)造函數(shù),而class中的方法相當(dāng)于原型上的方法。、

值得注意的特性 屬性屏蔽 —— 避免實(shí)例對(duì)象無(wú)意修改原型

看這段代碼,思考輸出的結(jié)果。

class Foo {
    prototypeMethod0(){
        console.log("this is prototypeMethod0")
    }
}

const foo0 = new Foo();
const foo1 = new Foo();

foo0.prototypeMethod0 === foo0.__proto__.prototypeMethod0 // true

foo0.prototypeMethod0 = () => console.log("foo0 method");
foo0.prototypeMethod0(); //??
foo1.prototypeMethod0(); //??
foo0.prototypeMethod0 === foo0.__proto__.prototypeMethod0 // ??

輸出的結(jié)果是

foo0.prototypeMethod0(); // foo0 method
foo1.prototypeMethod0(); // this is prototypeMethod0
foo0.prototypeMethod0 === foo0.__proto__.prototypeMethod0 // false

我們知道對(duì)象(即便是原型對(duì)象),都是運(yùn)行時(shí)的。

創(chuàng)建之初,foo本身沒有prototypeMethod0這個(gè)屬性,訪問(wèn)foo0.prototypeMethod0將會(huì)讀取foo0.__proto__.prototypeMethod0

直接修改foo0.prototypeMethod0沒有改變__proto__上的方法原因是存在屬性屏蔽

現(xiàn)在的情況是:想要修改foo0.prototypeMethod0prototypeMethod0foo中不存在而在上層(即foo.__proto__中存在),并且這不是一個(gè)特殊屬性(如只讀)。

那么會(huì)在foo中添加一個(gè)新的屬性。

這便是為什么直接修改卻沒有影響__proto__的原因。

小結(jié)

再溫習(xí)一遍這些定義:

原型用于定義共享的屬性和方法。

構(gòu)造函數(shù)用于定義實(shí)例屬性和方法,僅負(fù)責(zé)創(chuàng)造對(duì)象,與對(duì)象不存在直接的引用關(guān)系。

__proto__是對(duì)象的原型指針,prototype是構(gòu)造函數(shù)的原型指針。

在解釋原型作用的文章或書籍中,我們會(huì)聽到繼承這樣的術(shù)語(yǔ),其實(shí)更準(zhǔn)確地,委托對(duì)于JavaScript中的對(duì)象模型來(lái)說(shuō),是一個(gè)更合適的術(shù)語(yǔ)。

委托行為意味著某些對(duì)象在找不到屬性或者方法引用時(shí)會(huì)把這個(gè)請(qǐng)求委托給另一個(gè)對(duì)象。對(duì)象之間的關(guān)系不是復(fù)制而是委托。

參考

《JavaScript高級(jí)程序設(shè)計(jì)》

《你不知道的JavaScript》

本文僅供解惑,要在腦袋里形成系統(tǒng)的概念,還是要看書呀。

有疑問(wèn)歡迎大家一起討論。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/108193.html

相關(guān)文章

  • Java開發(fā)

    摘要:大多數(shù)待遇豐厚的開發(fā)職位都要求開發(fā)者精通多線程技術(shù)并且有豐富的程序開發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問(wèn)題在面試中經(jīng)常會(huì)被提到。將對(duì)象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對(duì)象稱之為反序列化。 JVM 內(nèi)存溢出實(shí)例 - 實(shí)戰(zhàn) JVM(二) 介紹 JVM 內(nèi)存溢出產(chǎn)生情況分析 Java - 注解詳解 詳細(xì)介紹 Java 注解的使用,有利于學(xué)習(xí)編譯時(shí)注解 Java 程序員快速上手 Kot...

    LuDongWei 評(píng)論0 收藏0
  • 寫給小白看的JS異步

    摘要:主線程在啟動(dòng)程序時(shí)被創(chuàng)建,用于執(zhí)行函數(shù)。用戶自主創(chuàng)建的若干進(jìn)程相對(duì)于主線程而言就是子線程。子線程和主線程都是獨(dú)立的運(yùn)行單元,各自的執(zhí)行互不影響,因此能夠并發(fā)執(zhí)行。這就是的異步機(jī)制了。 某天突然寫了個(gè)方法要從后臺(tái)調(diào)用數(shù)據(jù),顯示在前臺(tái)頁(yè)面,但是輸出結(jié)果總是空undefined,得不到數(shù)據(jù)。多方找資料才發(fā)現(xiàn),原來(lái)是入了JS異步的坑。 我們常常聽到單線程、多線程、同步、異步這些概念,那么這些東...

    gghyoo 評(píng)論0 收藏0
  • 26自學(xué)轉(zhuǎn)行前端(寫給和1年前一樣迷茫的我的你)

    摘要:轉(zhuǎn)行前端有哪些疑慮在人生的抉擇處,尋求一些別人的經(jīng)驗(yàn)和總結(jié),無(wú)可厚非,但是決定了就一定要堅(jiān)定的走下去,謹(jǐn)慎是為了更好的堅(jiān)持,而不是放棄的理由。寫在前面這里前后端指的是開發(fā)的前后端。 轉(zhuǎn)行前端有哪些疑慮? 在人生的抉擇處,尋求一些別人的經(jīng)驗(yàn)和總結(jié),無(wú)可厚非,但是決定了就一定要堅(jiān)定的走下去,謹(jǐn)慎是為了更好的堅(jiān)持,而不是放棄的理由。寫在前面:這里前后端指的是web開發(fā)的前后端。1、前端崗位需...

    番茄西紅柿 評(píng)論0 收藏2637
  • 26自學(xué)轉(zhuǎn)行前端(寫給和1年前一樣迷茫的我的你)

    摘要:轉(zhuǎn)行前端有哪些疑慮在人生的抉擇處,尋求一些別人的經(jīng)驗(yàn)和總結(jié),無(wú)可厚非,但是決定了就一定要堅(jiān)定的走下去,謹(jǐn)慎是為了更好的堅(jiān)持,而不是放棄的理由。寫在前面這里前后端指的是開發(fā)的前后端。 轉(zhuǎn)行前端有哪些疑慮? 在人生的抉擇處,尋求一些別人的經(jīng)驗(yàn)和總結(jié),無(wú)可厚非,但是決定了就一定要堅(jiān)定的走下去,謹(jǐn)慎是為了更好的堅(jiān)持,而不是放棄的理由。寫在前面:這里前后端指的是web開發(fā)的前后端。1、前端崗位需...

    番茄西紅柿 評(píng)論0 收藏2577

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<