1

Is there a way to get the name of the variable made with a constructor?

var TestFunction = function () {
  this.name = ???(); // should return '$testName'
}
var $testName = new TestFunction();

$testName.name should return $testName THX

8
  • 3
    Sounds like an X/Y problem. Why do you think you want the function to be able to figure out the variable name like that? What is your actual end goal? Commented Nov 20, 2016 at 12:52
  • It is a cookie system so you can say test = new Cookie('value', 10000);and it would be nice if test.name is test Commented Nov 20, 2016 at 12:55
  • I'm afraid you'll have to repeat it as an argument. Commented Nov 20, 2016 at 12:57
  • 2
    You may want to rethink your structure, and have something like a cookie manager that lets you add a new cookie, passing in the name, value, etc. and it will automatically add it to an object that stores all cookies. Then you don't need to retype the name as a variable, and you can access it from the object by the name you provided. CM.add("test", "value", 10000) ... CM.get("test"). You can even drop the add/get and just have CM be a function that decides what to do based on the number of args. CM("test", "value", 10000) // set cookie ... CM("test") // get cookie Commented Nov 20, 2016 at 13:02
  • @squint's suggestion above is excellent (as always). Commented Nov 20, 2016 at 13:03

1 Answer 1

6

should return '$testName'

That means you're asking how a function can know the name of a variable its result (or rather, the result of new calling it) is about to be assigned to. It can't, there is no mechanism for that, not least because of these possibilities:

a = b = c = d = new TestFunction();
// or
new TestFunction();
// or
foo(new TestFunction());

...but really because fundamentally, the function has no business knowing anything about the context in which it's called other than what the programmer has chosen to tell it by passing as arguments.

Consequently, if you want the function to have that information, you'll need to pass it in, even though that's repetitive:

var $testName = new TestFunction("$testName");

There's a special case (variables at global scope) where you could avoid repeating the name and only pass it as an argument to the function (leaving off the var $testname = part) and then have the function create the "variable," but it would tie the function to global scope, which would fall deep, deep into Bad Idea™ territory. :-)

This is what the special case looks like. Strongly recommend not doing this. (Instead: squint had an excellent suggestion in a comment.)

// STRONGLY RECOMMEND NOT DOING THIS
function TestFunction(name) {
    window[name] = this; // Creates a global
    this.name =name;
}

new TestFunction("$testname");
console.log($testname); // {name: "$testname"}

That works because when you create a property on the global object (which you can access via window on browsers), it creates a global variable.

Please don't do that. :-)


Regarding squint's Proxy idea, it would look something like this:

// Requires ES2016 ("ES6") support in the browser
// Proxy cannot be shimmed, so transpiling won't help
const cookieStore = new Map(); // Our fake storage; you'd use the browser's actual cookie store
function cmAccessor(name, ...args) {
  if (args.length == 0) {
    // Getter; you'd actually use the browser store
    const entry = cookieStore.get(name);
    return entry && entry.value;
  }
  // Setter
  const [value, duration] = args;
  console.log(`Setting '${name}' to '${value}' for ${duration}`);
  // You'd use the real browser store here
  cookieStore.set(name, {value, duration});
}
const CM = new Proxy(Object.create(null), {
  get(target, name) {
    let result = target[name];
    if (!result) {
      result = cmAccessor.bind(null, name);
      target[name] = result;
    }
    return result;
  }
});
CM.cookie1("cookie1 value", 42);
CM.cookie2("cookie2 value", 42);
console.log(CM.cookie1());
console.log(CM.cookie2());

But you'd probably be better off just using a function, a'la jQuery:

// This version is ES5 compatible

const cookieStore = new Map(); // Our fake storage; you'd use the browser's actual cookie store

function CM(name, value, duration) {
  switch (arguments.length) {
    case 0:
      throw new Error("'name' is required");
    case 1:
      // Getter
      // You'd use the browser's real cookie store here
      const entry = cookieStore.get(name);
      return entry && entry.value;
    default:
      // Setter
      console.log("Setting '" + name + "' to '" + value + "' for " + duration);
      // You'd use the real cookie store here
      cookieStore.set(name, {name: name, value: value});
  }
}

// Usage:
CM("cookie1", "cookie1 value", 42);
CM("cookie2", "cookie2 value", 42);
console.log(CM("cookie1"));
console.log(CM("cookie2"));

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.