狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

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

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

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

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

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

  • 在對象上調用的方法跟在原型上調用的方法區別是什么?這兩者相同么?

  • 為什么JS上可以直接在基礎類型值上調用對象上面才存在的方法?基礎類型值上調用的方法與在對象上調用的方法有區別么?

不同的方法調用方式

瞟了眼我的代碼,立馬就發現了一個調用類上方法的片段:

const obj = { a: 1 };

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

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

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

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

靜態方法與實例方法

其實,我們需要做的只是區分JavaScript靜態方法實例方法

靜態方法 是定義在類上的方法,而不是在類的實例上,靜態方法內部訪問不到this與實例變量。所以我們只能通過類來調用這些方法,而不能通過一個實例來調用

class MyClass {

  static staticMethod() {

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

  }

}


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

const myInstance = new MyClass();

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

實例方法 是定義在類的原型上的方法,實例方法內可以訪問對象的屬性,也可以訪問this,可以直接在實例化對象上調用這些方法

class MyClass {

  instanceMethod() {

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

  }

}


const myInstance = new MyClass();

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

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

至于為何會做如此區分,原因是一個簡單的面向對象編程需求:如果一個方法邏輯不涉及對象上的屬性,但又邏輯上屬于這個類,通過接受參數就可以實現功能的,則可以作為一個類的靜態方法存在。但如果它需要直接訪問類上屬性,直接作為實例方法顯然更加妥當。

原型鏈與方法調用

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

const arr = [1, 2, 3];

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

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

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

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


// ❌顯然object上沒有join方法,這樣調用會報錯

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


// 成功在object上調用join!!

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

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

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

基礎類型的自動包裝

雖然其他支持面向對象編程范式的語言也有類似行為,也就是對基本類型的自動包裝自動拆包,但為了百分百掌握JavaScript的行為與他們的異同,還是再來確定一遍吧

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

JavaScript對于以下的基本類型,都有對應的包裝類型。可以通過typeof操作結果是基本類型名還是object來確認:

  • string - String

  • number - Number

  • boolean - Boolean

  • symbol - Object

  • bigint - Object

讓我們列一下他們基本類型對應包裝類型的使用:

// 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"

所以,在基本類型上調用方法,等同于創建這個基本類型對應的包裝類型的對象并調用方法,最后拆包并返回原始類型的值。本質上還是調用了同類型包裝行為創建的對象上的方法。

"str".toUpperCase();

// 等同于

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

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

轉自https://www.cnblogs.com/camwang/p/18259567 作者CamWang 

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