第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

為什么需要原型對(duì)象(在函數(shù)中)?

為什么需要原型對(duì)象(在函數(shù)中)?

吃雞游戲 2023-10-20 16:28:59
我閱讀了大量有關(guān)原型的材料并了解繼承的一般情況。然而,這是困擾我的一件事,我無(wú)法弄清楚。如何使用以下代碼片段實(shí)現(xiàn)原型繼承:// Generic prototype for all letters.let letter = {? getNumber() {? ? return this.number;? }};?let a = {number: 1, __proto__: letter};let b = {number: 2, __proto__: letter};// ...let z = {number: 26, __proto__: letter};?console.log(? a.getNumber(), // 1? b.getNumber(), // 2? z.getNumber(), // 26);下面是這張圖然而,當(dāng)我們開(kāi)始使用實(shí)際的繼承結(jié)構(gòu)(使用 new 關(guān)鍵字)時(shí),它開(kāi)始看起來(lái)像這樣:我明白它是如何運(yùn)作的。我不明白的是,為什么我們突然需要所有子實(shí)例繼承自的 Letter.prototype 對(duì)象,而不是像上面的第一個(gè)圖那樣擁有它。對(duì)我來(lái)說(shuō),第一個(gè)示例似乎沒(méi)有任何問(wèn)題。我能想到的一個(gè)潛在原因是實(shí)際方法允許在類中實(shí)現(xiàn)靜態(tài)方法/屬性。在上面的示例中,如果您添加靜態(tài)方法,那么它將是添加到 Letter 對(duì)象的函數(shù),而不是添加到 Letter.prototype 對(duì)象的函數(shù)。子對(duì)象 (a,b,z) 將無(wú)權(quán)訪問(wèn)該函數(shù)。在第一個(gè)示例中,這種功能必須以不同的方式實(shí)現(xiàn),但我仍然認(rèn)為這不是創(chuàng)建新 Prototype 對(duì)象的充分理由。我認(rèn)為這個(gè)靜態(tài)方法功能可以在沒(méi)有它的情況下實(shí)現(xiàn)。我錯(cuò)過(guò)了什么嗎?
查看完整描述

3 回答

?
紅顏莎娜

TA貢獻(xiàn)1842條經(jīng)驗(yàn) 獲得超13個(gè)贊

我不明白為什么我們突然需要Letter.prototype所有子實(shí)例繼承的對(duì)象,而不是像上面的第一個(gè)圖那樣擁有它。

實(shí)際上那里什么都沒(méi)有改變。const letter它仍然是同一個(gè)對(duì)象,具有與第一個(gè)示例中指定的對(duì)象相同的用途。letter 實(shí)例繼承自它,它存儲(chǔ)getNumber方法,它繼承自Object.prototype.

改變的是附加Letter功能。

對(duì)我來(lái)說(shuō),第一個(gè)例子似乎沒(méi)有什么問(wèn)題。

是的,它是:這{number: 2, __proto__: letter}是一種非常丑陋的創(chuàng)建實(shí)例的方式,并且在必須執(zhí)行更復(fù)雜的邏輯來(lái)初始化屬性時(shí)不起作用。

解決這個(gè)問(wèn)題的方法是

// Generic prototype for all letters.

const letterPrototype = {

  getNumber() {

    return this.number;

  }

};

const makeLetter = (number) => {

  const letter = Object.create(letterPrototype); // {__proto__: letterPrototype}

  if (number < 0) throw new RangeError("letters must be numbered positive"); // or something

  letter.number = number;

  return letter;

}

 

let a = makeLetter(1);

let b = makeLetter(2);

// ...

let z = makeLetter(26);

 

console.log(

  a.getNumber(), // 1

  b.getNumber(), // 2

  z.getNumber(), // 26

);

現(xiàn)在我們有兩個(gè)價(jià)值觀,makeLetter并且letterPrototype在某種程度上屬于彼此。此外,在比較各種make…函數(shù)時(shí),它們都具有相同的模式,即首先創(chuàng)建一個(gè)繼承自各自原型的新對(duì)象,然后在最后返回它。為了簡(jiǎn)化,引入了通用構(gòu)造:


// generic object instantiation

const makeNew = (prototype, ...args) => {

  const obj = Object.create(prototype);

  obj.constructor(...args);

  return obj;

}


// prototype for all letters.

const letter = {

  constructor(number) {

    if (number < 0) throw new RangeError("letters must be numbered positive"); // or something

    letter.number = number;

  },

  getNumber() {

    return this.number;

  }

};

 

let a = makeNew(letter, 1);

let b = makeNew(letter, 2);

// ...

let z = makeNew(letter, 26);

 

console.log(

  a.getNumber(), // 1

  b.getNumber(), // 2

  z.getNumber(), // 26

);

你能看到我們要去哪里嗎?makeNew實(shí)際上是語(yǔ)言的一部分,即new運(yùn)算符。雖然這可行,但實(shí)際選擇的語(yǔ)法是使constructor值傳遞給new構(gòu)造函數(shù)并將原型對(duì)象存儲(chǔ)在.prototype構(gòu)造函數(shù)上。


查看完整回答
反對(duì) 回復(fù) 2023-10-20
?
炎炎設(shè)計(jì)

TA貢獻(xiàn)1808條經(jīng)驗(yàn) 獲得超4個(gè)贊

原型是 JavaScript 的基礎(chǔ)。它們可用于縮短代碼并顯著減少內(nèi)存消耗。原型還可以控制繼承的屬性,動(dòng)態(tài)更改現(xiàn)有屬性,并向從構(gòu)造函數(shù)創(chuàng)建的所有實(shí)例添加新屬性,而無(wú)需一一更新每個(gè)實(shí)例。它們還可以用于隱藏迭代中的屬性,原型有助于避免大型對(duì)象中的命名沖突。

內(nèi)存消耗

我在jsFiddle做了一個(gè)超級(jí)簡(jiǎn)單的實(shí)際示例,它使用 jQuery,看起來(lái)像這樣:

HTML:<div></div>

JS:const div = $('div'); console.log(div);

如果我們現(xiàn)在查看控制臺(tái),我們可以看到 jQuery 返回了一個(gè)對(duì)象。該對(duì)象有 3 個(gè)自己的屬性,其原型有 148 個(gè)屬性。如果沒(méi)有原型,所有這 148 個(gè)屬性都應(yīng)該被指定為對(duì)象自己的屬性。對(duì)于單個(gè) jQuery 對(duì)象來(lái)說(shuō),這可能是可以承受的內(nèi)存負(fù)載,但您可能會(huì)在一個(gè)相對(duì)簡(jiǎn)單的代碼片段中創(chuàng)建數(shù)百個(gè) jQuery 對(duì)象。

但是,這 148 個(gè)屬性只是開(kāi)始,從第一個(gè)屬性打開(kāi)記錄樹(shù)0,查詢的元素還有很多自己的屬性div,在列表的末尾有一個(gè)原型,HTMLDivElementPrototype。打開(kāi)它,您會(huì)發(fā)現(xiàn)幾個(gè)屬性,以及一個(gè)原型:HTMLElementPrototype。打開(kāi)它,會(huì)顯示一長(zhǎng)串屬性,ElementPrototype位于列表的末尾。打開(kāi),再次揭示了很多屬性,以及一個(gè)名為 的原型NodePrototype。在樹(shù)中打開(kāi)它,然后瀏覽該原型末尾的列表,還有一個(gè)原型, ,EventTargetPrototype最后,鏈中的最后一個(gè)原型是Object,它也有一些屬性。

現(xiàn)在,元素的所有這些顯示屬性中的一些屬性div本身就是對(duì)象,例如children,它有一個(gè)自己的屬性 (?length) 和其原型中的一些方法。幸運(yùn)的是,該集合是空的,但如果我們?cè)谠技现刑砑恿藥讉€(gè)div元素,則上面列出的所有屬性都將可用于該集合的每個(gè)子項(xiàng)。

如果沒(méi)有原型,并且所有屬性都是對(duì)象自己的屬性,那么當(dāng)您在閱讀時(shí)達(dá)到此答案中的這一點(diǎn)時(shí),您的瀏覽器仍將在該單個(gè) jQuery 對(duì)象上工作。您可以想象當(dāng)有數(shù)百個(gè)元素收集到 jQuery 對(duì)象時(shí)的工作量。

對(duì)象迭代

那么原型如何幫助迭代呢?JavaScript 對(duì)象有一個(gè)自有屬性的概念,即有些屬性是作為自有屬性添加的,有些屬性是在__proto__.?這個(gè)概念使得將實(shí)際數(shù)據(jù)和元數(shù)據(jù)存儲(chǔ)到同一個(gè)對(duì)象中成為可能。

雖然使用現(xiàn)代 JS 迭代自己的屬性很簡(jiǎn)單,但情況并非Object.keys總是Object.entries如此。在 JS 的早期,只有for..in循環(huán)來(lái)迭代對(duì)象的屬性(很早的時(shí)候什么也沒(méi)有)。通過(guò)in操作符,我們還可以從原型中獲取屬性,并且我們必須通過(guò)hasOwnProperty檢查將數(shù)據(jù)與元數(shù)據(jù)分開(kāi)。如果一切都在自己的屬性中,我們就無(wú)法在數(shù)據(jù)和元數(shù)據(jù)之間進(jìn)行任何分離。

函數(shù)內(nèi)部

為什么原型才成為函數(shù)的屬性呢?嗯,有點(diǎn)不是,函數(shù)也是對(duì)象,它們只是有一個(gè)內(nèi)部 [[Callable]] 插槽,和一個(gè)非常特殊的屬性,可執(zhí)行函數(shù)體。正如任何其他 JS 類型都有一個(gè)用于自身屬性和原型屬性的“儲(chǔ)物柜”一樣,函數(shù)也具有第三個(gè)“儲(chǔ)物柜”,并且具有接收參數(shù)的特殊能力。

函數(shù)自身的屬性通常稱為靜態(tài)屬性,但它們與常規(guī)對(duì)象的屬性一樣是動(dòng)態(tài)的。函數(shù)的可執(zhí)行主體和接收參數(shù)的能力使函數(shù)成為創(chuàng)建對(duì)象的理想選擇。與 JS 中的任何其他對(duì)象創(chuàng)建方法相比,您可以將參數(shù)傳遞給“類”(=構(gòu)造函數(shù)),并進(jìn)行非常復(fù)雜的操作來(lái)獲取屬性的值。參數(shù)也封裝在函數(shù)內(nèi)部,不需要將它們存儲(chǔ)在外部作用域中。

這兩個(gè)優(yōu)點(diǎn)是任何其他對(duì)象創(chuàng)建操作所不具備的(當(dāng)然,您可以在對(duì)象字面量中使用 IIFE ex.,但這有點(diǎn)難看)。此外,構(gòu)造函數(shù)內(nèi)部聲明的變量在函數(shù)外部無(wú)法訪問(wèn),只有在函數(shù)內(nèi)部創(chuàng)建的方法才能訪問(wèn)這些變量。這樣你就可以在“類”中擁有一些“私有字段”。

函數(shù)和陰影的默認(rèn)屬性

當(dāng)我們檢查一個(gè)新創(chuàng)建的函數(shù)時(shí),我們可以看到它有一些自己的屬性(sc 靜態(tài)屬性)。這些屬性被標(biāo)記為不可枚舉,因此它們不包含在任何迭代中。屬性包括arguments <Null>、caller <Null>、length <Number>和contains ,以及函數(shù)本身的name <String>底層。prototype <Object>constructor <Function>prototype <Function>

等待!函數(shù)中有兩個(gè)單獨(dú)的屬性具有相同的名稱,甚至具有不同的類型?是的,底層prototype__proto__函數(shù)的 ,另一個(gè)prototype是函數(shù)自己的屬性,它遮蔽了底層prototype。__proto__當(dāng)為存在于中的同名屬性分配值時(shí),所有對(duì)象都有一種隱藏 的屬性的機(jī)制__proto__。之后,對(duì)象本身無(wú)法__proto__直接訪問(wèn)該屬性,即被隱藏。陰影機(jī)制保留了所有屬性,并且這種方式可以處理一些命名沖突。仍然可以通過(guò)原型引用隱藏的屬性來(lái)訪問(wèn)它們。

控制繼承

由于prototype是該函數(shù)自己的屬性,它是免費(fèi)的戰(zhàn)利品,您可以用新對(duì)象替換它,或者根據(jù)需要對(duì)其進(jìn)行編輯,從而不會(huì)對(duì)底層“ ”產(chǎn)生影響,并且不會(huì)__proto__與“不動(dòng)__proto__”原則。

原型繼承的強(qiáng)大之處恰恰在于編輯或替換原型的能力。你可以選擇你想要繼承的內(nèi)容,也可以選擇原型鏈,通過(guò)從其他對(duì)象繼承原型對(duì)象。

創(chuàng)建實(shí)例

使用構(gòu)造函數(shù)創(chuàng)建對(duì)象的工作原理可能在 SO 帖子中已經(jīng)解釋了數(shù)千次,但我在這里再次做了一個(gè)簡(jiǎn)短的摘要。

創(chuàng)建構(gòu)造函數(shù)的實(shí)例已經(jīng)很熟悉了。當(dāng)使用運(yùn)算符調(diào)用構(gòu)造函數(shù)時(shí)new,會(huì)創(chuàng)建一個(gè)新對(duì)象,并將其放入this構(gòu)造函數(shù)內(nèi)使用。分配給的每個(gè)屬性都this成為新創(chuàng)建的實(shí)例自己的屬性,并且prototype構(gòu)造函數(shù)的屬性中的屬性被淺復(fù)制到__proto__實(shí)例的。

這樣,所有對(duì)象屬性都保留其原始引用,并且不會(huì)創(chuàng)建實(shí)際的新對(duì)象,只是復(fù)制引用。這提供了將對(duì)象扔掉的能力,而無(wú)需每次在其他對(duì)象中需要它們時(shí)都重新創(chuàng)建它們。當(dāng)像這樣鏈接時(shí),它還可以以最小的努力同時(shí)對(duì)所有實(shí)例進(jìn)行動(dòng)態(tài)編輯。

原型構(gòu)造函數(shù)

那么構(gòu)造函數(shù)中的constructorin是什么意思呢?prototype該函數(shù)最初指的是構(gòu)造函數(shù)本身,它是一個(gè)循環(huán)引用。但是當(dāng)你創(chuàng)建一個(gè)新的原型時(shí),你可以重寫其中的構(gòu)造函數(shù)。構(gòu)造函數(shù)可以從另一個(gè)函數(shù)中獲取,也可以完全省略。這樣您就可以控制實(shí)例的“類型”。當(dāng)檢查一個(gè)實(shí)例是否是特定構(gòu)造函數(shù)的實(shí)例時(shí),可以使用instanceof運(yùn)算符。該運(yùn)算符檢查原型鏈,如果從鏈中找到另一個(gè)函數(shù)的構(gòu)造函數(shù),則將其視為該實(shí)例的構(gòu)造函數(shù)。這樣,從原型鏈中找到的所有構(gòu)造函數(shù)都是實(shí)例的構(gòu)造函數(shù),并且實(shí)例的“類型”是這些構(gòu)造函數(shù)中的任何一個(gè)。


毫無(wú)疑問(wèn),所有這一切也可以通過(guò)其他設(shè)計(jì)來(lái)實(shí)現(xiàn)。但要回答“為什么”這個(gè)問(wèn)題,我們需要深入研究 JS 的歷史。Brendan Eich 和 Allen Wirfs-Brock 最近出版的一本著作為這個(gè)問(wèn)題提供了一些線索。

每個(gè)人都同意 Mocha 將是基于對(duì)象的,但沒(méi)有類,因?yàn)橹С诸悤?huì)花費(fèi)太長(zhǎng)時(shí)間,并且存在與 Java 競(jìng)爭(zhēng)的風(fēng)險(xiǎn)。出于對(duì) Self 的欽佩,Eich 選擇從使用具有單個(gè)原型鏈接的委托的動(dòng)態(tài)對(duì)象模型開(kāi)始。

引用:JavaScript 第 8 頁(yè):前 20 年,由 Brendan Eich 和 Allen Wirfs-Brock 撰寫。

通過(guò)閱讀這本書可以獲得更深入的解釋和背景。

代碼部分

在您的編輯中,代碼注釋中出現(xiàn)了一些問(wèn)題。正如您所注意到的,ES6 類語(yǔ)法隱藏了常規(guī)構(gòu)造函數(shù)。該語(yǔ)法不僅僅是構(gòu)造函數(shù)的語(yǔ)法糖,它還添加了一種更具聲明性的方式來(lái)創(chuàng)建構(gòu)造函數(shù),并且還能夠子類化一些本機(jī)對(duì)象,例如 Array。

  • “?JS 不能那樣工作” 正確,method不是類自己的屬性(= 函數(shù))。

  • 這就是它的工作原理” 是的,在類中創(chuàng)建的方法被分配給該類的原型。

  • 刪除原型對(duì)象中對(duì)它的引用”不可能,因?yàn)樵鸵驯粌鼋Y(jié)。您可以通過(guò)顯示類的描述符來(lái)看到這一點(diǎn)。

  • 其余代碼...不做評(píng)論,不推薦。


查看完整回答
反對(duì) 回復(fù) 2023-10-20
?
神不在的星期二

TA貢獻(xiàn)1963條經(jīng)驗(yàn) 獲得超6個(gè)贊

對(duì)我來(lái)說(shuō),第一個(gè)例子似乎沒(méi)有什么問(wèn)題。


這不是(客觀上),某些人(如道格拉斯·克羅克福德)經(jīng)常主張避免.prototype并this一起使用Object.create(類似于您的__proto__例子)。


那么為什么人們更喜歡使用類、繼承和.prototype呢?


原型就是重用

通常創(chuàng)建原型的原因是重用功能(如上所述getNumber)。為了做到這一點(diǎn),使用構(gòu)造函數(shù)很方便。


構(gòu)造函數(shù)只是創(chuàng)建對(duì)象的函數(shù)。在“舊”JavaScript 中你會(huì)這樣做:


function Foo(x) { // easy, lets me create many Xs

  this.x = x;

}

// easy, shares functionality across all objects created with new Foo

Foo.prototype.printX() {

  console.log(this.x); 

}

// note that printX isn't saved on every object instance but only once

(new Foo(4)).printX();

ES2015 使這變得更加容易:


class Foo { // roughly sugar for the above with subtle differences.

  constructor(x) { this.x = x; }

  printX() { console.log(this.x); }

}

總結(jié)一下:你不必使用 .prototype 和類,人們這樣做是因?yàn)樗苡杏?。?qǐng)注意,兩個(gè)示例中的原型鏈都一樣大。


查看完整回答
反對(duì) 回復(fù) 2023-10-20
  • 3 回答
  • 0 關(guān)注
  • 158 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)