阅读 198

Function之caller

前言

函数的调用关系,谁调用了谁,我是谁,你清楚吗?

除了Error的stack获取信息外,你还知道哪些手段知道了?

今天就一起学习学习caller和callee这两个属性。

caller

获取指定函数的调用者。

在浏览器控制台,执行下面的代码:

function sum(num1, num2) {     console.log("caller:",sum.caller);     return num1 + num2; } sum(1, 2); // caller: null function doSum() {     sum(1, 2) } doSum(); // caller: ƒ doSum() { //    sum(1, 2) // } 复制代码

可以看到全局作用域下,返回的是null,反之是调用该函数的函数。

在nodejs(v12.14.1)环境下执行 node [文件名].js, 返回值如下:

// caller: [Function] // caller: [Function: doSum] 复制代码

我们稍微调整一下代码, 把输出的信息调整为sum.caller.toString()

function sum(num1, num2) {     console.log("caller:",sum.caller.toString());     return num1 + num2; } sum(1, 2); // 输出结果: /*  caller: function (exports, require, module, __filename, __dirname) {     function sum(num1, num2) {         console.log("caller:",sum.caller.toString());         return num1 + num2;     }     sum(1, 2);     function doSum() {         sum(1, 2)     }     doSum()  } */ function doSum() {     sum(1, 2) } doSum() // 输出结果 /* caller: function doSum() {     sum(1, 2) } */ 复制代码

可以看到使用node [文件名].js执行js文件的时候,最终被包裹成如下函数

function (exports, require, module, __filename, __dirname) {     // 省略代码 } 复制代码

严格模式的caller

修改sum函数为下面的代码,再执行代码:

function sum(num1, num2) {     "use strict";     console.log("caller:",sum.caller.toString());     return num1 + num2; } 复制代码

截图_20211207101209.png 可以看到,严格模式下, caller, callee, arguments属性都是不可用的。

平时大家都使用了严格模式吗? 其实很多库,都还在使用arguments参数,因为实在是太香,太方便了。

caller的用途

跟踪调用信息

可以用于跟踪函数的调用层级关系,是不是很秀?

function getStack(fn) {     const stacks = [];     let caller  = fn.caller;     while (caller) {         stacks.unshift(caller.name);         caller = caller.caller;     }     return stacks; } function a() {     console.log("a")     const stacks = getStack(a);     console.log("stacks:", stacks); } function b() {     a();     console.log("b"); } function c() {     b();     console.log("c") } c();  // stacks: (2) ['c', 'b'] 复制代码

检查被调用环境

function getCaller(fun) {    const caller = fun.caller;    if (caller == null) {       console.log("caller is global context");    } else{       console.log("caller.name:" + caller);   }   return fun.caller } function add(){     getCaller(add) } add() // caller is global context 复制代码

小结

一句话总结: caller, 谁调用了我?

注意点:

  1. 严格模式下,不可用

  2. 全局作用域内被调用,caller为null

用途:

  1. 调用环境检查

  2. 调用栈信息收集

这就对应了前言的话,除了Error能获取调用栈信息, caller也不失为一种取巧的获取方式,当然有一定的局限性,又何妨,特定场景有作用,就够了。

今天你收获了吗?


作者:一花一个世界
链接:https://juejin.cn/post/7017679608807948318


文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐