2017-08-19 63 views
3

在問之前,我曾試圖做我的功課,並避免重複。因此,我已經閱讀了大約20個問題和答案(主要針對SO),這些問題都涉及到toString()。但不幸的是,他們都沒有回答我的實際問題。所以在這裏我們去...是Object.prototype.toString函數還是屬性?

許多例子包含的代碼那樣:

Object.prototype.toString.call(someVariable); 

我只是想知道爲什麼toString這裏可以使用類似的屬性。我已閱讀Object.prototypeMDN和其他地方的參考。他們全部列表函數toString()Object.prototype成員當中,但沒有財產toString

此外,我在我的代碼中的幾個地方使用上面顯示的那樣的一行。出於測試目的,我已經添加了括號,使其「乾淨」:

Object.prototype.toString().call(someVariable); 

顯然,這並沒有使「乾淨」,但只是做它返回錯誤的結果或還送瀏覽器失速(我目前在研究究竟發生了什麼的過程中)。

我已經閱讀了一些關於調用沒有括號的函數的問題和答案。但即使我接受上面顯示的第一行代碼實際上調用了一個函數(儘管它看起來像訪問某個屬性),但仍然無法解釋爲什麼當我添加第二個代碼行中顯示的括號時出現了錯誤。能夠不帶圓括號地調用函數不應該表示不能用圓括號調用它們,應該如何調用它們?

我不認爲這個問題已經有了答案(如果是的話,我表示歉意),那麼任何人都可以給出一個簡短的解釋嗎?

+0

'對象。prototype'是另一個普通的對象,'toString'是它的一個屬性,賦值爲一個函數。就像'{sayHello:function(){console.log(「hello」)}' – Redu

+0

typeof Object.prototype.toString – Surely

+0

這聽起來像你有一些其他語言背景知識(如斯卡拉)根據你的假設。我對麼? –

回答

2

功能只是值。 toString是其值爲函數的Object.prototype對象的屬性。

()是函數調用運算符。 Object.prototype.toString不會調用某個函數;它只是提取Object.prototype.toString屬性的值(這恰好是一個函數)。

函數也是對象,具有它們自己的屬性。這就是爲什麼你可以做Object.prototype.toString.call(...):此得到Object.prototype.toString功能,然後取其call屬性,然後調用它(這是允許的,因爲call值是另一個函數)。

這適用即使沒有涉及屬性:

var foo = function() { return "hello"; }; 
 
var bar = foo; 
 
console.log(bar); 
 
console.log(bar());

第一行分配一個函數值到foo變量。

第二行相同的值分配給bar,從foo讀取。請注意,我們沒有調用該函數,而是像其他任何值一樣傳遞它。

第一console.log顯示函數本身。

第二console.log顯示調用該函數,因爲我們使用()的結果。

+1

前幾天我們討論了關於對象是價值的問題,我想你會對es-discuss郵件列表中的這兩個主題感興趣:https://esdiscuss.org/topic/are-objects-values和https://esdiscuss.org/topic/are-the-values-of-objects-the-references-to-them。基本上,據我所知,我們都是對的。 :-)再次感謝你挑戰我的假設,這是一個學習練習。 –

3

是Object.prototype.toString函數還是屬性?

Object.prototype.toString是屬性。該屬性的是對函數的引用。正是這樣:

var obj = {f: function() { } }; 

在那裏,obj.f是一個屬性,它的值是對函數的參考。

Object.prototype.toString初始值在the spec稱爲%ObjProto_toString%本徵函數。它可以被覆蓋,但是這樣做可能會破壞很多東西。


要記住的一點是,在JavaScript中,函數只是從Function.prototype繼承*和是可調用的對象。就像其他對象一樣,您可以在屬性和變量中保留對它們的引用(您甚至可以爲函數本身添加屬性),傳遞這些引用等等。這與許多處理「類」和方法以及其他語言的語言形成鮮明對比各種功能作爲特殊的,非對象的東西。


* (主機提供的對象不需要從Function.prototype繼承,但在現代環境中的大多數都;在一些過時的瀏覽器,有些則沒有)

+1

感謝您的幫助和+1。我會接受melpomene的回答,因爲他解釋了完整的鏈,直到最後的'.call(...)',並且他需要更多的觀點:-),並且他對我的問題(主要來源我擔心的是'toString()'在「methods」部分列出,而不是在所有參考文獻中的「properties」部分),他解釋了原因。 – Binarus

+0

@Binarus:總是接受你認爲最有幫助的答案,並且不要擔心有人被交叉,你不接受他們的答案。這是他們的問題,不是你的問題。 :-)如果你發現上面的幫助,我也很高興。 –

1

歡迎使用JavaScript。確實,在某些情況下(new f)沒有()可以調用函數,但在這種情況下不能。您所看到的是對用作對象的函數的引用,但不叫(還)。這是一件很平常的事情,雖然在這種情況下它可能比平常更隱晦,所以我會解釋爲什麼這樣做。

當你明確地調用它的call方法(每個函數都繼承了函數原型的函數)時,函數最終會被調用,它允許你將函數體中的this綁定到某個任意對象。你的第一個例子可能someVariable.toString()做同樣的事情。那麼爲什麼要使用更長的形式?

好,someVariable可能沒有toString方法(如果它是null或undefined,因爲它們不是物品,不能將裝箱的對象),在這種情況下使用someVariable.toString會拋出一個TypeError。或者其原型toString方法可能具有與基本對象不同的行爲。在這種情況下,我想,筆者想用一個老派的伎倆獲取對象的「種」,其中涉及對事實的名稱Object.prototype.toString總是返回"[Object whatever]"其中「無所謂」將成爲構造函數的名稱或空或未定義。

+0

感謝您的幫助。這裏有一篇關於'.call()'的好文章:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call我的主要問題是'toString()'是在「方法」部分,而不是在我看到的所有參考文獻中的「屬性」部分。但Melpomene對我原來的問題發表了評論(除了他的回答)並解釋了原因。 – Binarus

+0

不客氣。我知道我並沒有完全回答你的問題,但其他人做得比我快。我雖然你可能仍然想知道爲什麼使用'call',所以我貼了。 – Touffy

相關問題