简体   繁体   中英

How to tell which key called a function in javascript

If I have an object with multiple keys calling the same function and this function is implemented outside its scope, how to determine which key called this function? For example:

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
}

It is possible

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
}

Explanation: arguments.callee is reference to the function to which the arguments object belongs. And this is basically "a thing before the dot" at the moment of function invocation, therefore your Population object. Now what you do is lookup the called function instance in the object and you are done.

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

FYI, new Error().stack will give you stacktrace like below,

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

I understood your question to be how can I associate a person's age with their name. The way I would do it is to create objects which describe people. Each object would have two attributes, a name and an age.

The objects (people) would then be stored in an array which is the population.

 // 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); } 

You haven't explained why you don't want to "pass a parameter", or what exactly the requirement to not pass a parameter is. My guess is that you want to keep the returned integer (or other value) dynamic in some sense specific to your context.

Here's how I might suggest doing it, although it's still not clear if it's a good idea:

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM