• 原文地址:function.caller considered harmful
  • 原文作者:Benedikt Meurer
  • 译文出自:掘金翻译计划
  • 本文永久链接:github.com/xitu/gold-m…
  • 译者:yankwan
  • 校对者:Starriers

今天我收到来自微软的 Patrick Kettner 提的这个问题,然而我发现这个问题是我已经回答过的,只不每次的问题稍有不同而已。

最终我发现是自己在第一次看到这个问题的时候理解错了这个问题,并且当别人在 Twitter 上回应的时候我也没有足够重视这个问题。

最后 Patrick 又提醒我一次,我才发现引起他兴趣的并不是 arguments.caller,而是函数对象的 "caller" 这个神秘的属性 ——— 准确来说是非严格模式下的函数对象。

JavaScript 在历史上曾提供了一个有魔力的 foo.caller 属性,它可以返回调用 foo 函数的引用。使用该属性存在着众多问题,例如它可能会因跨域调用产生安全问题、它在复杂的 JavaScript 引擎中实现的不够充分、它难以维护和测试、诸如对闭包的内联插入,逃逸分析和标量替换的优化都变得不可行,甚至在调用 "caller" 的属性访问器时,这些优化在返回的调用函数中也无法实现。


很多不可思议的事在非严格模式函数中都被限制了。严格模式下函数通过 AddRestrictedFunctionProperties 定义 "caller" 的访问器,当访问该属性的时候会抛出一个类型错误。

对于非严格模式的函数,目前 EcmaScript 规格中的定义也是非常模糊的,基本上对它没有做任何的规范限制。在章节 16.2 禁止扩展中说到:

如果扩展非严格模式或内置函数对象的时候,将对象自己的属性命名为 "caller" ,并且它的值通过 [[Get]] 或者 [[GetOwnProperty]] 定义的话,这种情况下必须保证不是严格模式。如果它是作为一个访问器属性,通过 [[Get]] 属性获取它的值将会返回调用它的函数,那么这个时候不会返回严格模式下的函数。

所以在非严格模式函数下的 "caller" 属性,或多或少完全实现了既定的行为。唯一的限制是如果有 yield 一个变量,那么这个变量一定不是严格模式下的函数。所以在非严格模式下,给 "caller" 赋一个默认值 42 是一个合理做法。显然实现中并没有这么做 —— 尽管有把这个添加到 V8 中的想法,同时现在也极不建议大家使用 foo.caller。


这是我们目前如何在 V8 中实现这些(有误导性的)特性 —— 也正是如何在 Chrome 和 Node.js 中运行的。"caller" 这个属性在非严格模式函数中是一个特殊的访问器,其实现方法 FunctionCallerGetter 在 accessors.cc 源码文件中实现,同时在该文件实现的还有核心的逻辑方法 FindCaller。要理解下面这些规则可以说是比较困难的,但这就是当你在非严格模式下访问 foo.caller时我们底层代码所做的事:

  1. 首先找到函数 foo 的最近一次的调用,例如 foo 的最后一次还没返回给调用方的调用。
  2. 如果当前 foo 不存在被调用的情况,则立即返回 null。
  3. 如果处于正被调用的情况,我们通过查看非用户层的 JavaScript 代码的调用情况,找到它的上级调。
  4. 如果通过上述规则没有找到上级调用,我们直接返回 null。
  5. 如果能找到上级调用,如果它是严格模式的函数或者是我们不需要访问的 —— 例如来自不同域的函数 —— 这种情况下我们也返回 null。
  6. 否则的话,我们则返回上级调用的闭包。

这里给出了一个它们如何工作的简单例子:

现在你对 foo.caller 是怎么工作已经有了一个基本的了解,这里我强烈建议你不要再使用它。正如上述所说的,它基本上是一个不能保证完全实现的特性。我们目前仍然会提供支持,但对于 arguments.caller,正如在 crbug.com/691710 提到的一样,我们可能在某个时间会移除它 —— 因为我们希望能够对闭包做逃逸分析和标量替换 —— 所以不要依赖它 —— 同时显然其他 JavaScript 引擎或许根本不支持这种特性。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 Android、iOS、前端、后端、区块链、产品、设计、人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划、官方微博、知乎专栏。

【译】function.caller 被认为是有害的相关推荐

  1. [js] callee和caller的区别和作用是什么?

    [js] callee和caller的区别和作用是什么? arguments.callee 指的是当前函数 Function.caller 指的是调用当前函数的函数 举个例子:function a() ...

  2. JavaScript 工作必知(九)function 说起 闭包问题

    大纲 Function Caller 返回函数调用者 Callee 调用自身 作用域 闭包 function 函数格式 function getPrototyNames(o,/*optional*/ ...

  3. Flash Actionscript 2.0中的函数与事件 之 函数类(Function Class)

    Flash Actionscript 2.0中的函数与事件  之  函数类(Function Class) 作者:LeeFJ 函数是什么,在面向对象里面通常称为方法(Method),但是在AS2.0里 ...

  4. Javascript 中 callee 和 caller

    1.arguments.callee 返回正在执行的函数本身的引用,是arguments的一个属性. 当函数的名称未知时,例如匿名函数,使用callee很有用 用来代替函数名,降低耦合性 注: 这个属 ...

  5. Simulink Function模块竟可以这样测

    Simulink Simulink是美国Mathworks公司推出的一种强大的可视化仿真工具,现已应用到包括汽车.航空.工业自动化等领域.Simulink不仅提供了多种特定功能的模块,还提供Simul ...

  6. call、aplly、caller、callee分别是什么?

    call和aplly的区别: 概念: call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向.因为 JavaScr ...

  7. callee 和 caller

    callee 定义 arguments.callee,指向当前函数的引用.匿名函数和立即执行函数因为没有函数名,需要使用 callee 来返回当前函数名. function inner() {cons ...

  8. 翻译连载 | JavaScript轻量级函数式编程-第5章:减少副作用 |《你不知道的JS》姊妹篇...

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  9. JavaScript(1)——基础语法部分(CSDN)

    前言:本篇文章原文为我在语雀上的学习笔记Javascript(1)--基础语法部分 web 发展史 Mosaic,是互联网历史上第一个获普遍使用和能够显示图片的网页浏览器.于 1993年问世. 199 ...

最新文章

  1. 传感器融合-数据篇(自动驾驶)
  2. Windows上卸载SqlServer数据库
  3. 20201014 《人工智能与大数据》第1节课 笔记
  4. Python-基础知识-控制流程和文件操作
  5. 设计模式---代理模式
  6. 1 redux初探、用react开发数值增值案例
  7. python接口自动化2-发送post请求
  8. 前端学习(1702):前端系列javascript之this
  9. 数论 —— 线性同余方程组与中国剩余定理
  10. 牛客多校第五场 G subsequence 1 最长公共子序列/组合数
  11. MySQL Membership
  12. 2012.12.26 晚 小雨
  13. silverlight将字符串转化为控件
  14. 全网首发:为什么依赖库编译时加了-fPIC,还是提示依赖库要使用-fPIC?
  15. matlab如何释放内存,怎么能释放已经使用的内存
  16. C语言程序判断一个数是否是素数,C语言中怎么判断一个数是否是素数(即质数)...
  17. Unity实现将图片上传到服务器功能
  18. 基于单片机电梯5层带模拟控制系统设计(毕设)
  19. 输入直角三角形的两个直角边的长度 a、b,求斜边 c 的长度。
  20. 理解误区——mysql中tinyint与Java的数据类型的对应关系;tinyint(1) 与tinyint(4)的区别

热门文章

  1. Google更新最大的带注释图像数据集,添加本地化叙述
  2. 机器学习验证集为什么不再有新意?
  3. AI 影像诊断平台的5大设计要点
  4. 基于飞桨PaddlePaddle的语义角色标注任务全解析
  5. 谷歌将AutoML应用于Transformer架构,翻译结果飙升,已开源
  6. SAP携欧洲众巨头建立“工业4.0开放联盟”
  7. 干货丨史上最好记的神经网络结构速记表(经典资源,值得收藏)
  8. 《2022城市大脑建设标准研究报告》在京正式发布
  9. 人工智能将如何改变芯片设计
  10. 2021年AI关键趋势,AI芯片初创公司可能发生并购