【问题标题】:How to tell which key called a function in javascript如何判断哪个键调用了javascript中的函数
【发布时间】:2019-10-08 01:20:24
【问题描述】:

如果我有一个具有多个键调用同一个函数的对象,并且该函数在其范围之外实现,如何确定哪个键调用了该函数?例如:

function tellYourAge() {
   return function()
   {
       // I already know here that this refers to Population
       // For example, console.log(this) will print the Population object
   }
}

{
   let Population = {
     Mahdi: tellYourAge(),
     Samuel: tellYourAge(),
     Jon: tellYourAge()
   };

   Population.Mahdi(); // It should log 18
   Population.Samuel(); // It should log 20
   Population.Jon(); // It should log 21
}

【问题讨论】:

  • 将密钥作为参数传递,例如:Mahdi: tellYourAge('Mahdi')
  • 那些已经是独立的函数了。
  • I want to do it without passing a parameter 为什么?
  • 没有从键到值的链接。您要么必须通过它,要么必须重新考虑它的设置方式。
  • 您无法完全按照描述的方式实现此目的。您可以使用块范围或 Function.prototype.bind 来做一些事情。

标签: javascript function object


【解决方案1】:

有可能

function tellYourAge() {
   return function()
   {
       var f = arguments.callee;
       var key = Object.keys(this).filter(key => this[key] === f)[0];
       console.log(key);
   }
}

{
   let Population = {
     Mahdi: tellYourAge(),
     Samuel: tellYourAge(),
     Jon: tellYourAge()
   };

   Population.Mahdi(); // prints Mahdi
   Population.Samuel(); // prints Samuel
   Population.Jon(); // prints Jon
}

解释:arguments.callee 是对arguments 对象所属函数的引用。而this 在函数调用时基本上是“点之前的东西”,因此您的Population 对象。现在你要做的是在对象中查找被调用的函数实例,你就完成了。

【讨论】:

【解决方案2】:
function tellYourAge() {
   return function()
   {
      var s = new Error().stack;
      if(s.includes('Mahdi')){
        console.log('Age is 18');
      }

      else if(s.includes('Samuel')){
        console.log('Age is 20');
      }

      else if(s.includes('Jon')){
        console.log('Age is 21');
      } 
   }
}

{
   let Population = {
     Mahdi: tellYourAge(),
     Samuel: tellYourAge(),
     Jon: tellYourAge()
   };

   Population.Mahdi(); // It should log 18
   Population.Samuel(); // It should log 20
   Population.Jon(); // It should log 21
}
Output:
Age is 18
Age is 20
Age is 21

仅供参考,new Error().stack 会为您提供如下所示的堆栈跟踪,

Error
    at Object.Samuel (<anonymous>:4:20)
    at <anonymous>:1:19

【讨论】:

  • 这如何回答我的问题?
  • 检查我更新的代码。我认为我们只能从堆栈跟踪中找出密钥。
  • @MahdiJaber ...从您给出的示例以及不想以任何形式向任何函数提供任何参数的要求...这正是您将获得的满足所有要求的唯一方法这些要求。
  • 希望 OP 实际上并没有这样做,但我赞成,因为这是一个合法的答案。在胁迫下,我也完成了堆栈检查代码。我想这里特别令人震惊的是 A:它是主程序流程的一部分,而不是记录器或错误处理程序。 B:它正在创建一个错误。 (有没有办法在没有错误的情况下请求堆栈?)和 C:它将堆栈解析为字符串,这显然容易出错。
【解决方案3】:

我理解您的问题是如何将一个人的年龄与他们的名字联系起来。我这样做的方式是创建描述人的对象。每个对象都有两个属性,一个名字和一个年龄。

然后将对象(人)存储在人口数组中。

// Create a constructor function which defines a Person
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// Create an array of Population to store the Persons (people)
var Population = [];
Population.push(new Person('Mahdi', 18));
Population.push(new Person('Samuel', 20));
Population.push(new Person('John', 21));

// Counter and limit variables
var i, l;

// Loop through the Population and display the information about the people
l = Population.length;
for (i = 0; i < l; i++) {
  let person = Population[i];
  console.log(person.name + " is " + person.age);
}

【讨论】:

    【解决方案4】:

    你还没有解释为什么你不想“传递参数”,或者究竟不传递参数的要求是什么。我的猜测是,您希望在特定于您的上下文的某种意义上保持返回的整数(或其他值)动态。

    以下是我可能建议的方式,尽管目前尚不清楚这是否是个好主意:

    function tellYourAge() {
      return function(name)
      {
        let ages = {
          Mahdi: 18,
          Samuel: 20,
          Jon: 21,
        };
        return ages[name];
      }
    }
    
    {
      let makePopulation = function(names){
        let pop = {};
        names.forEach(function(n){
          pop[n] = tellYourAge().bind(pop, n);
        });
        return pop;
      };
    
      let Population = makePopulation("Mahdi", "Samuel", "Jon");
    
      Population.Mahdi(); // It should log 18
      Population.Samuel(); // It should log 20
      Population.Jon(); // It should log 21
    }
    

    【讨论】:

    • 新功能makePopulation的引入只是文体。我不喜欢看到变量发生突变,就像上面的 pop 一样。有时在设置相关值时有必要;在这些情况下,我喜欢将突变/初始化封装起来,这样就可以将其考虑在程序流程的其余部分之外。
    猜你喜欢
    • 2015-03-29
    • 2010-11-02
    • 1970-01-01
    • 2010-10-28
    • 2016-11-14
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多