f



Passing a variable number of arguments into the a constructor being used with the `new' keyword

Is it possible?

Example:

foo(1,2,3);    /* === */    foo.apply(window, [1,2,3]);

// but

new Foo(1,2,3);    /* === */    ???
0
Andrey
12/10/2008 10:59:39 PM
comp.lang.javascript 38370 articles. 2 followers. javascript4 (1315) is leader. Post Follow

8 Replies
46115 Views

Similar Articles

[PageSpeed] 5

On 2008-12-10 23:59, Andrey Fedorov wrote:
> Is it possible?
> 
> Example:
> 
> foo(1,2,3);    /* === */    foo.apply(window, [1,2,3]);
> 
> // but
> 
> new Foo(1,2,3);    /* === */    ???

If you just want to call the Foo constructor with a variable argument
list, you could do it like this:

  var x = {};
  Foo.apply(x, [1,2,3]);

To properly set up the prototype you need a little more:

  function Dummy() {}
  Dummy.prototype = Foo.prototype;
  var x = new Dummy();
  x.constructor = Foo;

  Foo.apply(x, [4,5,6]);


  - Conrad
0
Conrad
12/10/2008 11:29:53 PM
On Dec 10, 5:59=A0pm, Andrey Fedorov <afedor...@gmail.com> wrote:
> Is it possible?
>
> Example:
>
> foo(1,2,3); =A0 =A0/* =3D=3D=3D */ =A0 =A0foo.apply(window, [1,2,3]);
>
> // but
>
> new Foo(1,2,3); =A0 =A0/* =3D=3D=3D */ =A0 =A0???

new Foo( [1,2,3] ); // one argument, any length
0
Martin
12/11/2008 3:07:20 PM
> To properly set up the prototype you need a little more [...]

This is what I'm doing now. My problem is that then, the `constructor'
property still isn't set correctly and hence the `instanceof' operator
doesn't work. One solution I'm considering is:

  function Foo(arg1, arg2, ...) {
    if (!arg.length) return; // required
    // rest of code
  }

  function new_obj(type, args) {
    x = new type();
    type.apply(x, [1,2,3]);
    return x;
  }

  x = new_obj(Foo, [1,2,3]);

But I'd love to be able to avoid that starting line inside of Foo.

Martin Rinehart wrote:
> new Foo( [1,2,3] ); // one argument, any length

I don't know if you're serious, but this is actually where I'm
leaning, if I don't figure out an elegant way of doing the former.

Cheers,
Andrey
0
Andrey
12/11/2008 4:09:13 PM
On Dec 11, 4:09 pm, Andrey Fedorov wrote:
> ... . My problem is that then, the `constructor'
> property still isn't set correctly

If you don't like the way a 'constructor' property is set then why not
set it the way you want it?

> and hence the `instanceof' operator
> doesn't work. ...

The - instanceof - operator does not employ, and so has no interest
in, the - constructor - properties of objects. The instance of
operator makes an assertion about the runtime relationship between the
value assigned to the - prototype - property of a function and the
objects on the prototype chain of an object (produces a true result if
the function's prototype property value at that time is the same
object as one of the objects on the prototype chain of the operand
object).
0
Henry
12/11/2008 4:54:49 PM
Andrey Fedorov <afedorov2@gmail.com> writes:

> Is it possible?
>
> Example:
>
> foo(1,2,3);    /* === */    foo.apply(window, [1,2,3]);
>
> // but
>
> new Foo(1,2,3);    /* === */    ???

No.

What you can do is to make Foo handle an array argument properly:

 function Foo(yadda, yadda2) {
   if (arguments.length == 1 && yadda instanceof Array) {
     Foo.apply(this, yadda);
     return this;
   }
 }

I.e., calling the constructor as a function on the new object using
apply.

/L
-- 
Lasse Reichstein Holst Nielsen
 'Javascript frameworks is a disruptive technology'
  
0
Lasse
12/11/2008 4:58:30 PM
Andrey Fedorov wrote:
> Is it possible?

Is *what* possible?  <http://jibbering.com/faq/#posting>

> Example:
> 
> foo(1,2,3);    /* === */    foo.apply(window, [1,2,3]);
> 
> // but
> 
> new Foo(1,2,3);    /* === */    ???

IIUC, short of modifying Foo() to accept an Array object reference,
IMHO there is a good chance that the following worked:

  var f = new Foo();
  Foo.apply(f, [1, 2, 3]);

(Examples where it doesn't work this way include Date() since per
specification it ignores all arguments when [[Call]]ed rather than
[[Construct]]ed.)

Is this only a theoretical question or do you have an actual case
where you need it?


PointedEars
-- 
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
  -- Richard Cornford, cljs, <f806at$ail$1$8300dec7@news.demon.co.uk>
0
Thomas
12/11/2008 9:27:28 PM
Andrey Fedorov wrote:
>> To properly set up the prototype you need a little more [...]
> 
> This is what I'm doing now. My problem is that then, the `constructor'
> property still isn't set correctly and hence the `instanceof' operator
> doesn't work. One solution I'm considering is:
> 
>   function Foo(arg1, arg2, ...) {
>     if (!arg.length) return; // required

Probably you mean

  if (!arguments.length) return; // required

>     // rest of code
>   }
> 
>   function new_obj(type, args) {
>     x = new type();
      ^       ^^^^
Using `type' as an identifier is a bad idea, it might become a reserved
word.  Not declaring `x' a local variable is worse, especially here:

>     type.apply(x, [1,2,3]);
                 ^
>     return x;
             ^
>   }
> 
>   x = new_obj(Foo, [1,2,3]);
    ^   ^
        |
Identifiers for constructors should start uppercase.

> But I'd love to be able to avoid that starting line inside of Foo.

Why would you want to avoid using the gauntlet?  Why waste resources going
through initialization when it is doomed to fail?  (Note that a constructor
call will return an object reference no matter the return value.)

Please include an attribution line for each quotation level you leave in:

<http://jibbering.com/faq/#posting>


PointedEars
-- 
Use any version of Microsoft Frontpage to create your site.
(This won't prevent people from viewing your source, but no one
will want to steal it.)
  -- from <http://www.vortex-webdesign.com/help/hidesource.htm>
0
Thomas
12/11/2008 10:13:41 PM
Thomas 'PointedEars' Lahn wrote:
> Andrey Fedorov wrote:
>>   function new_obj(type, args) {
>>     x = new type();
>       ^       ^^^^
> Using `type' as an identifier is a bad idea, it might become a reserved
> word.  Not declaring `x' a local variable is worse, especially here:
> 
>>     type.apply(x, [1,2,3]);
>                  ^
>>     return x;
>              ^
>>   }
>>
>>   x = new_obj(Foo, [1,2,3]);
>     ^   ^
>         |
> Identifiers for constructors should start uppercase.

new_obj() is not [[Constructed]] here, it serves as a factory.  But the
recommendation would definitely apply to `type', and changing that
accordingly would address two potential problems in one step.


PointedEars
-- 
var bugRiddenCrashPronePieceOfJunk = (
    navigator.userAgent.indexOf('MSIE 5') != -1
    && navigator.userAgent.indexOf('Mac') != -1
)  // Plone, register_function.js:16
0
Thomas
12/11/2008 11:03:28 PM
Reply: