亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

調(diào)用了這么久的JS方法是長在對象、類、值本身還是原型鏈上?

freeflydom
2024年7月24日 16:27 本文熱度 1843

JavaScript這門語言總是能帶給我驚喜,在敲代碼的時候習(xí)以為常的寫法,退一步再看看發(fā)現(xiàn)自己其實(shí)對很多基操只有表面的使用,而從來沒思考過為何要這樣操作。

今天整理JS代碼的時候突然發(fā)出靈魂三連問:

  • 為什么有些時候操作對象,可以直接調(diào)用對象上的方法,但有些時候我們使用類似Array.from()的寫法?

  • 在對象上調(diào)用的方法跟在原型上調(diào)用的方法區(qū)別是什么?這兩者相同么?

  • 為什么JS上可以直接在基礎(chǔ)類型值上調(diào)用對象上面才存在的方法?基礎(chǔ)類型值上調(diào)用的方法與在對象上調(diào)用的方法有區(qū)別么?

不同的方法調(diào)用方式

瞟了眼我的代碼,立馬就發(fā)現(xiàn)了一個調(diào)用類上方法的片段:

const obj = { a: 1 };

console.log(Object.hasOwn(obj, 'a')); // true

// 但是如果在對象上調(diào)用,則會拋不存在的錯誤

console.log(obj.hasOwn('a')); // TypeError: obj.hasOwn is not a function

在上面的例子里,Object.hasOwn是一個可以直接調(diào)用的方法,但令人困惑的是,當(dāng)我們嘗試直接在對象實(shí)例上調(diào)用hasOwn方法時,卻拋出了一個類型錯誤,是不是有點(diǎn)反直覺? 我仔細(xì)想了一想突然發(fā)現(xiàn),其實(shí)這只是一個基礎(chǔ)JS概念的一個外在表現(xiàn),只不過我們習(xí)慣了作為現(xiàn)象使用它,卻很少會想到它背后的邏輯。

靜態(tài)方法與實(shí)例方法

其實(shí),我們需要做的只是區(qū)分JavaScript靜態(tài)方法實(shí)例方法

靜態(tài)方法 是定義在類上的方法,而不是在類的實(shí)例上,靜態(tài)方法內(nèi)部訪問不到this與實(shí)例變量。所以我們只能通過類來調(diào)用這些方法,而不能通過一個實(shí)例來調(diào)用

class MyClass {

  static staticMethod() {

    console.log('這是個靜態(tài)方法');

  }

}


MyClass.staticMethod(); // 正常執(zhí)行

const myInstance = new MyClass();

myInstance.staticMethod(); // Error: myInstance.staticMethod is not a function

實(shí)例方法 是定義在類的原型上的方法,實(shí)例方法內(nèi)可以訪問對象的屬性,也可以訪問this,可以直接在實(shí)例化對象上調(diào)用這些方法

class MyClass {

  instanceMethod() {

    console.log('這是個實(shí)例/對象方法');

  }

}


const myInstance = new MyClass();

myInstance.instanceMethod(); // 正常執(zhí)行

概括來說,上面例子中Object.hasOwn()是一個需要傳參的、在Object這個類上的靜態(tài)方法,所以才需要在類上直接調(diào)用,而不能在實(shí)例對象上調(diào)用;但在例如arr.sort()的調(diào)用,實(shí)際調(diào)用的是實(shí)例對象上的方法

至于為何會做如此區(qū)分,原因是一個簡單的面向?qū)ο缶幊绦枨螅喝绻粋€方法邏輯不涉及對象上的屬性,但又邏輯上屬于這個類,通過接受參數(shù)就可以實(shí)現(xiàn)功能的,則可以作為一個類的靜態(tài)方法存在。但如果它需要直接訪問類上屬性,直接作為實(shí)例方法顯然更加妥當(dāng)。

原型鏈與方法調(diào)用

JavaScript中的每個對象都有一個原型(prototype)(除了Object.protoype也就是所有原型的盡頭),對象的方法實(shí)際上是定義在原型鏈上的。雖然我們可能是在對象上調(diào)用了一個方法,實(shí)際上JavaScript引擎會沿著原型鏈查找該方法并調(diào)用。

const arr = [1, 2, 3];

console.log(arr.join('-')); // "1-2-3"

console.log(Array.prototype.join.call(arr, '-')); // "1-2-3"

上面的例子里,join方法是數(shù)組的實(shí)例方法。實(shí)例方法可以直接在數(shù)組的實(shí)例上調(diào)用,也可以通過Array.prototype.join.call的方式來調(diào)用,這倆本質(zhì)上是一樣的。唯一區(qū)別是Array.prototype.join.call允許我們在任何類似數(shù)組的對象上調(diào)用這個方法,哪怕它不是一個真正的數(shù)組。
等等?我們可以在不是數(shù)組的值上調(diào)用join?是的

const pseudoArray = { 0: 'one', 1: 'two', 2: 'three', length: 3 };


// ❌顯然object上沒有join方法,這樣調(diào)用會報錯

pseudoArray.join(','); // Error: pseudoArray.join is not a function


// 成功在object上調(diào)用join!!

const result = Array.prototype.join.call(pseudoArray, ',');

console.log(result); // "one,two,three"

所以,在對象上調(diào)用實(shí)例方法,等同于按照這個對象的原型鏈一層一層向父類上找同名方法來調(diào)用。

基礎(chǔ)類型的自動包裝

雖然其他支持面向?qū)ο缶幊谭妒降恼Z言也有類似行為,也就是對基本類型的自動包裝自動拆包,但為了百分百掌握J(rèn)avaScript的行為與他們的異同,還是再來確定一遍吧

每當(dāng)我們在基本類型值上(例如"hello"6)上調(diào)用方法,JavaScript引擎都會先使用基本類型對應(yīng)的包裝類型對值進(jìn)行包裝,調(diào)用對應(yīng)的方法,最后將包裝對象丟掉還原基礎(chǔ)類型。這是個引擎內(nèi)部的隱式操作,所以我們沒有任何的感知。

JavaScript對于以下的基本類型,都有對應(yīng)的包裝類型??梢酝ㄟ^typeof操作結(jié)果是基本類型名還是object來確認(rèn):

  • string - String

  • number - Number

  • boolean - Boolean

  • symbol - Object

  • bigint - Object

讓我們列一下他們基本類型對應(yīng)包裝類型的使用:

// string

const primitiveString = "hello";

const objectString = new String("hello");

console.log(typeof primitiveString); // "string"

console.log(typeof objectString); // "object"


// number

const primitiveNumber = 42;

const objectNumber = new Number(42);

console.log(typeof primitiveNumber); // "number"

console.log(typeof objectNumber); // "object"


// boolean

const primitiveBoolean = true;

const objectBoolean = new Boolean(true);

console.log(typeof primitiveBoolean); // "boolean"

console.log(typeof objectBoolean); // "object"


// symbol

const primitiveSymbol = Symbol("description");

const objectSymbol = Object(primitiveSymbol);

console.log(typeof primitiveSymbol); // "symbol"

console.log(typeof objectSymbol); // "object"


// bigint

const primitiveBigInt = 123n;

const objectBigInt = Object(primitiveBigInt);

console.log(typeof primitiveBigInt); // "bigint"

console.log(typeof objectBigInt); // "object"

所以,在基本類型上調(diào)用方法,等同于創(chuàng)建這個基本類型對應(yīng)的包裝類型的對象并調(diào)用方法,最后拆包并返回原始類型的值。本質(zhì)上還是調(diào)用了同類型包裝行為創(chuàng)建的對象上的方法。

"str".toUpperCase();

// 等同于

(new String("str")).toUpperCase()

// 當(dāng)然,這里巧了,toUpperCase()本來也沒想返回包裝類型的對象

轉(zhuǎn)自https://www.cnblogs.com/camwang/p/18259567 作者CamWang 

該文章在 2024/7/24 16:28:51 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財務(wù)費(fèi)用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved