簡體   English   中英

在 JavaScript ES6 中,如果 console.log() 不調用 obj.toString(),它使用什么?

[英]In JavaScript ES6, if console.log() doesn't invoke obj.toString(), what does it use?

這個問題中有一些相關信息: 在標准的 JavaScript ES6 環境中,什么時候調用 .toString()?

通過多態, toString()是通過 Object 類的接口發送給對象的標准消息(或在對象上調用的標准方法)。

但顯然, console.log()不使用它:

// Inside of Node

> let aSet = new Set([1,3,5]);

> aSet.toString()
'[object Set]'

> console.log(aSet);
Set { 1, 3, 5 }

> let aMap = new Map([["foo", 1], ["bar", 2]])

> aMap.toString()
'[object Map]'

> console.log(aMap)
Map { 'foo' => 1, 'bar' => 2 }

那么console.log()使用什么? 它不是valueOf() ,因為valueOf()在這種情況下只返回對象本身,當沒有原始值可用時。

“特殊情況”它是什么類並執行不同的操作會很丑陋 - 因為多態性,具有標准的“動詞”,在這種情況下toString() ,是應該使用的。 找出類是什么並執行不同的操作(例如使用 switch 語句),這正是我們在 OOP 中不想做的。

console.log()以及其他console方法是依賴於實現的。

我的回答僅適用於 Node.js。


在查看了 Node.js 的內部源文件后,發現在 Node (v12) 中, console方法使用一種常見的方式來顯示值: util.formatWithOptions方法。

它的內部源代碼是用 JavaScript 編寫的,它調用內部格式化程序函數(位於internal/util/inspect.js ),根據對象的類型格式化對象,例如:

  • 原語被簡單地字符串化。
  • 對普通對象的屬性進行迭代,以顯示它們。
  • 數組根據它們的length進行迭代。
  • SetMap對象的值使用它們的迭代器來查找。

console是主機提供的對象,其實現因主機而異。 Chrome 的與 Firefox 的不同,后者與 Node.js 的不同,后者不同於... :-)

通常,他們檢查您記錄的內容的類型,然后顯示實施者認為是您記錄的內容的合理表示的任何內容。 對於對象和數組,這通常涉及查詢對象/數組的內容(而不是調用toString )並顯示這些內容的表示。 (他們甚至可能使用 JavaScript 引擎的內部功能查詢內容,而不是通過對象的 JavaScript 可訪問 API。)在像大多數瀏覽器中的“實時”控制台中,控制台甚至保留對對象的引用,因此您可以擴展它並深入了解它的屬性( 此問題的答案中有詳細信息)。

(在一個階段,Node.js的控制台看上去名為對象上的方法inspect和使用的,但原來是為那里的對象有問題的inspect是不是意味着要使用這種方式,並已被刪除。至於我知道他們沒有使用以符號命名的方法將其添加回來。)

WHATWG 社區提供了一個單獨的console規范: Console Living Standard

在該規范中查找console.log時,您可以通過部分2.1 Logger獲得部分2.3 Printer ,其中指出:

實現如何打印args取決於實現,但實現應該用空格或類似的東西分隔對象,因為這已成為開發人員的期望。

通常,控制台實現將希望提供豐富的用戶界面,具有可擴展的項目、樣式,允許深入到構建整體值的原始值。 它不必在 JavaScript 中實現,並且調用toString可能不是那么方便,知道即使({ a: 1 }).toString()返回"[object Object]" ,這也不是那么有用。

有時,給定的信息超出了您可以在代碼中同步查詢的內容,就像 promise 對象的情況一樣。 在控制台中,輸出這些對象的當前狀態,而在代碼中,您至少需要調用then (或執行await )以獲取該信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM