Function.prototype.caller
非標準:此特性未標準化。我們不建議在生產環境中使用非標準特性,因為它們瀏覽器支援有限,並且可能會更改或被移除。但是,在沒有標準選項的特定情況下,它們可以是合適的替代方案。
已棄用:此特性不再推薦。雖然某些瀏覽器可能仍然支援它,但它可能已經從相關的網路標準中刪除,可能正在刪除過程中,或者可能僅為相容性目的而保留。請避免使用它,如果可能,請更新現有程式碼;請參閱本頁底部的相容性表格以指導您的決策。請注意,此特性可能隨時停止工作。
注意: 在 嚴格模式下,訪問函式的 caller 會丟擲錯誤 — 該 API 已被移除且沒有替代方案。這是為了防止程式碼能夠“遍歷呼叫棧”,這既帶來了安全風險,也嚴重限制了內聯和尾呼叫最佳化等最佳化的可能性。有關更多解釋,您可以閱讀 arguments.callee 棄用的理由。
caller 屬性是 Function 例項的一個訪問器屬性,它返回呼叫此函式的函式。對於 嚴格模式、箭頭函式、非同步函式和生成器函式,訪問 caller 屬性會丟擲 TypeError。
描述
如果函式 f 是由頂層程式碼呼叫的,則 f.caller 的值為 null;否則,它就是呼叫 f 的函式。如果呼叫 f 的函式是嚴格模式函式,則 f.caller 的值也為 null。
請注意,ECMAScript 規範僅指定了一個行為,即 Function.prototype 具有一個初始的 caller 訪問器,該訪問器無條件地為任何 get 或 set 請求丟擲 TypeError(稱為“毒丸訪問器”),並且不允許實現更改此語義,除非是非嚴格模式的普通函式,在這種情況下,它不能具有嚴格模式函式的值。caller 屬性的實際行為,如果不是丟擲錯誤,則由實現定義。例如,Chrome 將其定義為自己的資料屬性,而 Firefox 和 Safari 則擴充套件了初始的“毒丸”Function.prototype.caller 訪問器,以特殊處理非嚴格函式作為 this 值的情況。
(function f() {
if (Object.hasOwn(f, "caller")) {
console.log(
"caller is an own property with descriptor",
Object.getOwnPropertyDescriptor(f, "caller"),
);
} else {
console.log(
"f doesn't have an own property named caller. Trying to get f.[[Prototype]].caller",
);
console.log(
Object.getOwnPropertyDescriptor(
Object.getPrototypeOf(f),
"caller",
).get.call(f),
);
}
})();
// In Chrome:
// caller is an own property with descriptor {value: null, writable: false, enumerable: false, configurable: false}
// In Firefox:
// f doesn't have an own property named caller. Trying to get f.[[Prototype]].caller
// null
此屬性取代了已廢棄的 arguments 物件的 arguments.caller 屬性。
特殊的 __caller__ 屬性,它返回呼叫者的啟用物件,從而允許重建呼叫棧,由於安全原因已被移除。
示例
檢查函式 caller 屬性的值
以下程式碼檢查函式 caller 屬性的值。
function myFunc() {
if (myFunc.caller === null) {
return "The function was called from the top!";
}
return `This function's caller was ${myFunc.caller}`;
}
重建呼叫棧和遞迴
請注意,在遞迴的情況下,您無法使用此屬性重建呼叫棧。考慮以下情況:
function f(n) {
g(n - 1);
}
function g(n) {
if (n > 0) {
f(n);
} else {
stop();
}
}
f(2);
呼叫 stop() 時,呼叫棧將是:
f(2) -> g(1) -> f(1) -> g(0) -> stop()
以下為真:
stop.caller === g && f.caller === g && g.caller === f;
因此,如果您嘗試在 stop() 函式中像這樣獲取堆疊跟蹤:
let f = stop;
let stack = "Stack trace:";
while (f) {
stack += `\n${f.name}`;
f = f.caller;
}
迴圈將永遠不會停止。
嚴格模式 caller
如果呼叫者是嚴格模式函式,則 caller 的值為 null。
function callerFunc() {
calleeFunc();
}
function strictCallerFunc() {
"use strict";
calleeFunc();
}
function calleeFunc() {
console.log(calleeFunc.caller);
}
(function () {
callerFunc();
})();
// Logs [Function: callerFunc]
(function () {
strictCallerFunc();
})();
// Logs null
規範
不屬於任何標準。
瀏覽器相容性
載入中…