3

I'm trying to find the best way to pass an array of arguments to a function, but without altering (or addressing) the execution context.

I have this:

some_args = ["world"];
in.some.namespace.hello.apply(this, some_args);

Unfortunately this changes hellos execution context to the global object.

What's the slickest way of calling hello with in.some.namespace being the execution context?

Writing

in.some.namespace.hello.apply(in.some.namespace, some_args]

looks verbose and errorprone.

3 Answers 3

3

Writing

 in.some.namespace.hello.apply(in.some.namespace.hello, some_args]

looks verbose and errorprone.

(In the below I've changed in. to n. because you can't declare a variable called in and I wanted to provide some live examples.)

Three options, none of them really exciting: ;-)

  1. Use with, despite its bad rep and incompatibility with strict mode

  2. Write yourself a utility function

  3. Use a disposable variable and don't mind some really funky-looking syntax

Use with:

with (n.some) {
    namespace.hello.apply(namespace, some_args);
}

Slightly less repetition, though there's still some, and you have to use with, which is disallowed in strict mode.

Utility function

Example utility function:

function callWith(obj, name, args) {
  return obj[name].apply(obj, args);
}
var n = {
  some: {
    namespace: {
      hello: function(a, b, c) {
        alert(this.name + " says " + [a, b, c].join(", "));
      },
      name: "namespace"
    }
  }
};

callWith(n.some.namespace, "hello", [1, 2, 3]);

(Be careful doing that if you use a minifier that renames methods, as it probably won't update the string.)

Disposable variable and really funky syntax

I want to be clear that I'm not recommending this, just flagging it up as an option: If you have a variable you keep lying around for this purpose, you can do this:

(o = n.some.namespace, o.hello.apply(o, [1, 2, 3]));

E.g.:

var o;
var n = {
  some: {
    namespace: {
      hello: function(a, b, c) {
        alert(this.name + " says " + [a, b, c].join(", "));
      },
      name: "namespace"
    }
  }
};

(o = n.some.namespace, o.hello.apply(o, [1, 2, 3]));

Arguably that's an abusage of the comma operator. At the very least. :-)

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

Comments

0

If you are looking for a way to create a function delegate:

function $createDelegate(instance, method)
{
    return function (someArgs) { return method.apply(instance, someArgs); } 
}

Usage:

var delegate = $createDelegate(in.some.namespace, in.some.namespace.hello);
...
delegate(someArgs);

Which, for instance, is a very useful way to pass callbacks to an event Handler without loosing your context.

4 Comments

arguments contains the arguments used to call the callback. so it's a simple forward
Crowder is correct. I'm trying to find a terse way to invoke a function with an array of values as discrete arguments.
I've edited the response, please review the downvote ;)
I have removed the downvote, but I think you should remove the answer. I am not looking to create a function delegate. I am looking for a short syntax. Your suggestion is longer, not shorter, than doing function.apply(context, args)
0

If the question is simply to write the line of code as short as possible, consider caching in a variable what's redundant (it's also better for perfs as it reduces the number of lookups):

var n = in.some.namespace;
n.hello.apply(n, some_args);

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.