【问题标题】:Deprecated property caller in browsers浏览器中不推荐使用的属性调用者
【发布时间】:2020-01-14 06:55:17
【问题描述】:

在尝试使用已弃用的 "caller" 属性时,我在浏览器中遇到了异常行为。使用了以下浏览器:Google Chrome 79.0.3945.117Firefox 72.0.1Edge 44.18362.449.0

让我们从一个基本的例子开始:

function start(){}
start.hasOwnProperty("caller")

谷歌浏览器:true,Firefox:false,Edge:true

事实上,只有在 Firefox 中,每个声明的函数才不会使用自己的“调用者”属性。

在这样的例子中:

function start(){"use strict"};
start.hasOwnProperty("caller")

谷歌浏览器:false,Firefox:false,Edge:false


我们看下面的代码

function a(){b()}
function b(){"use strict";c()}
function c(){console.log(c.caller)}
delete Function.prototype.caller;
a()

我们看到了什么?我们看到 Edge 中只发生了一个错误,谷歌浏览器通过向我们显示 null 值来隐藏它,Firefox 返回 undefined 因为它无法在任何地方找到名为 "caller" 的此类属性。

虽然这种情况在规范中被描述为:

如果实现扩展了任何具有名为“caller”的自有属性的函数对象,则使用 [[Get]] 或 [[GetOwnProperty]] 观察到的该属性的值不能是严格的函数对象。如果它是访问器属性,则作为属性的 [[Get]] 属性值的函数在调用时绝不能返回严格函数。

如果我们执行上面的代码但删除"use strict",那么在谷歌浏览器和Edge中我们会注意到条目console.log (c.caller)给我们一个调用当前函数的函数,如果@中没有"caller"属性987654340@。但是在这种情况下 Firefox 是静默的,并产生与严格模式相同的结果 - "undefined"

顺便说一句,如果我们去掉这些函数的原型,什么都不会改变:

function a(){b()}
function b(){"use strict";c()}
function c(){console.log(c.caller)}
delete Function.prototype.caller;
Object.setPrototypeOf(a,null);
Object.setPrototypeOf(b,null);
Object.setPrototypeOf(c,null);
a();

使用 Firefox,一切都变得非常简单:

  1. 在严格模式下
    1. 没有为函数定义"caller" 属性
    2. 调用"caller"属性时,属性取自Function.prototype
    3. 调用"caller" 属性会引发错误。
  2. 在正常模式下
    1. 没有为函数定义"caller" 属性
    2. 调用"caller"属性时,属性取自Function.prototype
    3. 调用"caller" 属性不会引发错误。

虽然 Firefox 也不是那么简单。规范说明如下:https://tc39.es/ecma262/#sec-addrestrictedfunctionproperties。也就是说,规范说您需要在调用时在Function.prototype 中定义有错误的属性。规范清楚地将"caller" 访问器属性定义为包含错误的属性。但是 Firefox 在正常模式下,“调用者”属性似乎要么被覆盖,要么最初在两种类型的代码上定义:严格和不严格。这种行为是 Firefox 实现错误吗?

关于 Google Chrome 和 Edge:

  1. 在严格模式下
    1. 没有为函数定义"caller" 属性
    2. 调用"caller"属性时,属性取自Function.prototype
    3. 调用“caller”属性会引发错误。
  2. 在正常模式下
    1. 为函数定义了"caller" 属性
    2. 当调用"caller" 属性时,该属性不是取自Function.prototype(在哪里?)
    3. 调用"caller" 属性不会引发错误。

在这种情况下,最令人费解的是 Google Chrome 和 Edge 如何在删除了 Function.prototype 的情况下获取 "caller" 属性的值(在 Function.prototype 中有一个 "caller" 属性的 getter 和 setter,并且在常规函数中,"caller" 属性既没有 getter 也没有 setter)?

【问题讨论】:

  • Function.prototype.caller 尚未正确指定,请参阅这个冗长的讨论:github.com/tc39/ecma262/issues/562
  • @evilpie 我知道什么 Function.prototype.caller 没有指定。如果你仔细阅读我的帖子,你会明白我的问题是关于浏览器行为而不是规范。此外,规范对“调用者”属性有许多限制。看起来 Firefox 在正常代码中破坏了它们,它不是在 Function.Prototype.caller 中创建一个带有错误的访问器属性,而是一个带有显示调用当前代码的函数的函数的附件属性。

标签: javascript google-chrome firefox ecmascript-6 microsoft-edge


【解决方案1】:

function.caller 属性返回调用指定函数的函数。此属性在严格模式禁止。

【讨论】:

    猜你喜欢
    • 2014-01-26
    • 2013-01-11
    • 2010-10-14
    • 2017-04-05
    • 2017-12-07
    • 1970-01-01
    • 2011-01-15
    • 2015-10-22
    • 1970-01-01
    相关资源
    最近更新 更多