pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/caller

x.455dc24ca3b6b460.js" type="module">

此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。

View in English Always switch to English

Function.prototype.caller

非标准: 该特性尚未标准化。我们不建议在生产环境中使用非标准特性,因为它们在浏览器中的支持有限,且可能发生变化或被移除。不过,在没有标准选项的特定情况下,它们可以作为合适的替代方案。

已弃用: 不再推荐使用该特性。虽然一些浏览器仍然支持它,但也许已从相关的 web 标准中移除,也许正准备移除或出于兼容性而保留。请尽量不要使用该特性,并更新现有的代码;参见本页面底部的兼容性表格以指导你作出决定。请注意,该特性随时可能无法正常工作。

备注:严格模式下,访问函数的 caller 属性会抛出错误——该 API 已被移除且没有替代品。这是为了防止代码能够“遍历堆栈”,这既存在安全风险,也严重限制了内联和尾调用优化等优化的可能性。如需更多解释,请阅读 arguments.callee 的弃用原因

Function 实例的 caller 访问器属性返回调用该函数的函数。对于严格模式、箭头函数、异步函数和生成器函数来说,访问 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 值。

js
(function f() {
  if (Object.hasOwn(f, "caller")) {
    console.log(
      "caller 是一个自有属性,具有描述符",
      Object.getOwnPropertyDescriptor(f, "caller"),
    );
  } else {
    console.log(
      "f 没有名为 caller 的自有属性。尝试获取 f.[[Prototype]].caller",
    );
    console.log(
      Object.getOwnPropertyDescriptor(
        Object.getPrototypeOf(f),
        "caller",
      ).get.call(f),
    );
  }
})();

// 在 Chrome 中:
// caller 是一个自有属性,具有描述符 {value: null, writable: false, enumerable: false, configurable: false}

// 在 Firefox 中:
// f 没有名为 caller 的自有属性。尝试获取 f.[[Prototype]].caller
// null

此属性取代了 arguments 对象的已弃用的 arguments.caller 属性。

出于安全原因,特殊属性 __caller__ 已被移除,它返回调用者的激活对象,从而允许重建堆栈。

示例

检查函数 caller 属性的值

以下代码检查函数的 caller 属性的值。

js
function myFunc() {
  if (myFunc.caller === null) {
    return "该函数是从顶层调用的!";
  } else {
    return `该函数的调用者是 ${myFunc.caller}`;
  }
}

重建调用堆栈和递归

请注意,在递归的情况下,你不能使用该属性重建调用堆栈。参考以下示例:

js
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()

以下是条件表达式为真:

js
stop.caller === g && f.caller === g && g.caller === f;

因此,如果你尝试像这样在 stop() 函数中获取堆栈跟踪:

js
let f = stop;
let stack = "Stack trace:";
while (f) {
  stack += `\n${f.name}`;
  f = f.caller;
}

循环永远不会停止。

严格模式下的 caller

如果调用者是严格模式函数,则 caller 的值为 null

js
function callerFunc() {
  calleeFunc();
}

function strictCallerFunc() {
  "use strict";
  calleeFunc();
}

function calleeFunc() {
  console.log(calleeFunc.caller);
}

(function () {
  callerFunc();
})();
// 输出 [Function: callerFunc]

(function () {
  strictCallerFunc();
})();
// 输出 null

规范

不属于任何标准。

浏览器兼容性

参见

pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy