admin管理员组

文章数量:1427091

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
}

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
}
Share Improve this question edited May 21, 2019 at 16:26 Mahdi Jaber asked May 21, 2019 at 15:37 Mahdi JaberMahdi Jaber 2311 gold badge4 silver badges12 bronze badges 11
  • 4 Pass the key as a parameter like: Mahdi: tellYourAge('Mahdi') – imvain2 Commented May 21, 2019 at 15:39
  • 1 Those are already separate functions. – SLaks Commented May 21, 2019 at 15:41
  • 8 I want to do it without passing a parameter why? – Mosh Feu Commented May 21, 2019 at 15:42
  • 4 There is no link from the key to the value. You either have to pass it or you have to rethink how it is being set up. – epascarello Commented May 21, 2019 at 15:44
  • 2 You cannot achieve this exactly in the manner described. You might be able to do something either with block scoping or Function.prototype.bind. – AlexMA Commented May 21, 2019 at 15:49
 |  Show 6 more ments

4 Answers 4

Reset to default 9 +50

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
}

本文标签: How to tell which key called a function in javascriptStack Overflow