472,984 Members | 2,096 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,984 software developers and data experts.

How to create an arbitrary object at runtime?

Can anyone suggest how to create an arbitrary object at runtime
WITHOUT using the deprecated eval() function. The eval() method works
ok (see below), but is not ideal.

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
eval("var o = new " + s + "();");
alert(o.fullname);

Note: I want the type name of the object to be represented as a string
(in this case "Client" -- this is a non-negotiable requirement).
I also tried the following (which appears to fail):

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
var o = new Object();
o.construct = s;
alert(o.fullname);
eval() is handy but not future-proof, so any suggestions would be
welcome.

Kind regards,
Steve
Jul 23 '05 #1
8 3123


Steve Neill wrote:
Can anyone suggest how to create an arbitrary object at runtime
WITHOUT using the deprecated eval() function. The eval() method works
ok (see below), but is not ideal.
eval is not deprecated, it is certainly part of a dynamic scripting
language like JavaScript.

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
eval("var o = new " + s + "();");
alert(o.fullname);

Note: I want the type name of the object to be represented as a string
(in this case "Client" -- this is a non-negotiable requirement).
I also tried the following (which appears to fail):

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";


var o = new this[s]();

should do in browsers (as long as your functions like Client are global
functions and not nested).

--

Martin Honnen
http://JavaScript.FAQTs.com/
Jul 23 '05 #2
On 20 Oct 2004 09:46:53 -0700, sn****@mxlogic.com (Steve Neill) wrote:
var s = "Client";
eval("var o = new " + s + "();");
o=new window[s]alert(o.fullname);


It's a good idea to read the FAQ and the FAQ notes, there's a lot of
good stuff there.

Jim.
Jul 23 '05 #3
Steve Neill wrote:
Can anyone suggest how to create an arbitrary object at
runtime WITHOUT using the deprecated eval() function. The
eval() method works ok (see below), but is not ideal.
eval is deprecated as a method of objects, and as JScript never
implemented it as such it was never really viable to use that method
(though it still has not been removed from Mozilla/Gecko browsers). eval
is un-deprecated in the current ECMA 262 standard (3rd edition) and
should be available in all implementations (however, ECMAScript 'Compact
Profile' (ECMA 327) are allowed to implement eval such that it just
throws exceptions whenever it is called).

There are better reasons for not using eval, such as not really needing
to in this context.
function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
eval("var o = new " + s + "();");
On the other hand, the above eval use can be re-arranged so that all of
the string concatenation can be avoided:-

var o = new (eval(s))();

- allowing for the much more flexible use of arguments with the
constructor identified by the string value of - s -. it should also
execute faster that way, but not nearly as fast as it would if - eval -
was not used at all.

(looking at the production rules for the - new - operator, I suspect
that parenthesising the function call is required to turn the
CallExpression - eval(s) - into a PrimaryExpression. PrimaryExpressions
being allowed as operands for - new -, while CallExpressions are not)
alert(o.fullname);

Note: I want the type name of the object to be represented
as a string (in this case "Client" -- this is a
non-negotiable requirement).
Don't jump to this conclusion too quickly, if you can passa the value of
variable holding a string that is the identifier of a function
(constructor) around could you instead pass the value of a variable
holding a reference to that function about instead? It is quite viable
to do:-

function Client(){ ... }
function Other(){ ... }

var f1 = Client; // reference to the 'Client' function object
var f2 = Other; // reference to the 'Other' function object

function getNewObject( constrct ){
return new constrct(); //Indirect and anonymous use of
//the constructor passed as the
//parameter - constrct.
}

var o1 = getNewObject( f1 ); //Client instance
var o2 = getNewObject( f2 ); //Other instance

var o3 = new f1(); //another Client instance
var o4 = new f2(); //another Other instance

- or something more indirect. Passing references to functions about is
not necessarily different to passing strings about.
I also tried the following (which appears to fail):

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
var o = new Object();
o.construct = s;
alert(o.fullname);
I wouldn't say it failed, it is clear that the outcome programmed in the
code is the alerting of an undefined value, and that is what it did
(successfully), didn't it?
eval() is handy but not future-proof, so any suggestions
would be welcome.


There probably is not future-proofing issue here. There is a code design
issue as any use of - eval - is almost certainly indicative of
ill-conceived design (as there are so very few circumstances where its
use is appropriate/required, especially given how dynamic javascript is
to start with).

In javascript all functions are objects and all functions may be
constructors (they can all be called as constructors but the ones
explicitly returning ECMAScript native Object types will not be
successful constructors, and most will not be useful constructors). As a
result you can reference functions that you want to use as constructors
in exactly the same way as you reference any objects.

As Martin has said, if the constructor function is defined in the global
scope it becomes a property of the global object (on a browser the
global object is the window object), and a bracket notation property
accessor syntax, with a reference to the global object as the
MemberExpression/CallExpression to the left of the brackets, can access
any properties of the global object based on the value of a string
variable (or expression resulting in a string).

In code executing in the global context, or within function bodies that
are not being called as methods of object, the - this - keyword is a
reference to the global object.

var o = new this[ s ]();

Other references to the global object are available on web browsers in
the form of the - self - and - window - properties of the global object.

var o = new window[ s ]();

var o = new self[ s ](); // I don't recommend ever
// using - self - in this context.

Other methods of getting a reference to the global object include:
Making your own global variable that reefers to the global object by
executing:-

var global = this;

- in the global context as the page loads. This allows any code to use
the global variable - global - to refer to the global variable. E.G.:

var o = new global[ s ]();

A global function could be created:-

function getGlobal(){
return this;
}

- and allow any code to call that function from any context to get a
reference to the global object. E.G.:-

var o = new getGlobal()[ s ]();

A reference to the global object may also be retrieved in any context
(including an object's method, where - this - would refer to that
object) through the inline execution of a function expression that
returns - this -, allowing such a value to be assigned to a variable
local to a method without any external dependencies. E.G.:-

AnyObject.prototype.exampleFnc = function(){
var localGlobalRef = (function(){return this;})();
...
var o = new localGlobalRef[ s ]();
}

- Or as a rather heavyweight one-off:-

var o = new ((function(){return this;})())[ s ]();

Richard.
Jul 23 '05 #4
In article <25*************************@posting.google.com> , Steve Neill
<sn****@mxlogic.com> writes
Can anyone suggest how to create an arbitrary object at runtime
WITHOUT using the deprecated eval() function. The eval() method works
ok (see below), but is not ideal.

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
eval("var o = new " + s + "();");
alert(o.fullname);

Note: I want the type name of the object to be represented as a string
(in this case "Client" -- this is a non-negotiable requirement).

<snip>

Would you be happy writing
var o = new f[s]();

If you would then make f (with a better name) an object whose properties
(methods) are the constructor functions you want to use.

John
--
John Harris
Jul 23 '05 #5
Steve Neill wrote:
Can anyone suggest how to create an arbitrary object at runtime
WITHOUT using the deprecated eval() function. The eval() method works
ok (see below), but is not ideal.


As a related question: does anybody know how to create an object at
runtime, by applying it an array of arguments ?

I know how to forward a function call:

function forwarder()
{
/* dest is the function the call is forwarded to: */
return dest.apply(this, arguments);
}
but, given

function CTor(a1, a2)
{
print("CTor - a1 = " + a1 + " a2 = " + a2);
}

How do I have my forwarder function returns a constructed CTor ? A few
guesses, that won't work:

return new (CTor.apply( null, arguments) ); // new fails

return (new CTor).apply( null, arguments); // .apply fails
The closest I could get was by using an helper function to construct my
object in two passes.

function constructWithArgs( fun, args )
{
var tmp = new fun; // first, make an object of 'fun' constructor
fun.apply(tmp, args); // second, 'fills' it with arguments
return tmp;
}

But this requires that "new fun" won't fail, and some other constraints
on fun.

Any clue ?

Alexis
--
Some domain is free
Jul 23 '05 #6
Alexis Nikichine wrote:
Steve Neill wrote: <snip> As a related question: does anybody know how to create an
object at runtime, by applying it an array of arguments ? <snip> The closest I could get was by using an helper function to
construct my object in two passes.
That seems a reasonable approach. The problem, I assume, is that the
constructor gets called twice and may not behave correctly when it finds
it has no arguments on the first call.
function constructWithArgs( fun, args )
{
var tmp = new fun; // first, make an object of 'fun'
constructor fun.apply(tmp, args); // second, 'fills' it with
arguments return tmp;
}

But this requires that "new fun" won't fail, and some
other constraints on fun.


In ECMAScript all objects are the same type, but augmented in different
ways. The augmentation of an Object created with a constructor is the
assigning of the function's - prototype - object to the Object's
internal [[Prototype]] property and any additional property creation
done by the constructor itself. Your function achieves this because
creating the Object with - new fun - sets up the internal [[Prototype]]
property and then using - apply - with the constructor as a function
does the rest of the augmentation. But it cannot prevent the first call
to the constructor without arguments from mis-configuring the object in
a way that the second call will not correct/override.

However, as all ECMAScript objects are the same type you should be able
to achieve satisfactory results by using an empty constructor with the -
new - operator, having assigned the - prototype - property of - fun - to
that empty constructor. Thus having the internal [[Prototype]] property
of the constructed Object assigned fun's prototype. And then use apply
with the constructor:-

var constructWithArgs = (function(){
function Dummy(){ ; }// Scope-contained, "private",
// dummy constructor. No other code
// needs access to this constructor.
return (function(fun, args){
Dummy.prototype = fun.prototype;
var tmp = new Dummy; // Internal [[Prototype]] of new
// object is set to fun.prototype
// but no other properties are
// created/changed.
fun.apply(tmp, args); // Use constructor to create/apply
// new properties to the Dummy instance,
// creating an object indistinguishable
// form one created with - fun -.
return tmp; // Return the new object
})
})();
//^^ Inline function expression call, returning the second inner
//function and assuaging it to the global variable - constructWithArgs
Richard.
Jul 23 '05 #7
Alexis Nikichine <al**************@somedomain.fr> writes:
The closest I could get was by using an helper function to construct
my object in two passes.

function constructWithArgs( fun, args )
{
var tmp = new fun; // first, make an object of 'fun' constructor
fun.apply(tmp, args); // second, 'fills' it with arguments
return tmp;
}

But this requires that "new fun" won't fail, and some other
constraints on fun.


It should be possible to create an object that is indistinguishable
from one created using the constructor, but actually using another
constructor that you know will not fail. It will still be two-phase,
but the first phase is under your control :).
---
function newApply(constructor, argsArray) {
function dummyConstructor (){};
dummyConstructor.prototype = constructor.prototype;
var object = new dummyConstructor();
var sndObject = constructor.apply(object, argsArray);
return (typeof sndObject == "object" ? sndObject : object);
}
---
(It really implements the behavior of [[Construct]] on function
objects as specified in ECMA 262 section 13.2.2, except using apply to
call the function with an array of arguments).

You can the use it as:
---
function Const(x,y) {
this.x = x;
this.y = y;
}
Const.prototype.z = 42;

var o = newApply(Const,[2,4]); // equivalent to: new Const(2,4)
alert([o instanceof Const, o.x, o.y, o.z]); // true,2,4,42
---

/L
--
Lasse Reichstein Nielsen - lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
Jul 23 '05 #8
Perfect! Now that I see the solution it's so obvious!! Thanks :)

John G Harris <jo**@nospam.demon.co.uk> wrote in message news:<TH**************@jgharris.demon.co.uk>...
In article <25*************************@posting.google.com> , Steve Neill
<sn****@mxlogic.com> writes
Can anyone suggest how to create an arbitrary object at runtime
WITHOUT using the deprecated eval() function. The eval() method works
ok (see below), but is not ideal.

function Client() { }
Client.prototype.fullname = "John Smith";
var s = "Client";
eval("var o = new " + s + "();");
alert(o.fullname);

Note: I want the type name of the object to be represented as a string
(in this case "Client" -- this is a non-negotiable requirement).

<snip>

Would you be happy writing
var o = new f[s]();

If you would then make f (with a better name) an object whose properties
(methods) are the constructor functions you want to use.

John

Jul 23 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

47
by: Mountain Bikn' Guy | last post by:
Take some standard code such as shown below. It simply loops to add up a series of terms and it produces the correct result. // sum numbers with a loop public int DoSumLooping(int iterations) {...
5
by: Honestmath | last post by:
Hello everyone, I'm using a root finding algorithm in a function that only takes as arguments a function pointer and two variables that represent guesses at the roots of the function. int...
7
by: dog | last post by:
I've seen plenty of articles on this topic but none of them have been able to solve my problem. I am working with an Access 97 database on an NT4.0 machine, which has many Access reports. I...
3
by: equip200 | last post by:
I have a third party program that has the ability to control my program trough ActiveX/COM. My program is built in c#? What would I need to do to have the third party program connect to my...
15
by: Amit D.Shinde | last post by:
I am adding a new picturebox control at runtime on the form How can i create click event handler for this control Amit Shinde
5
by: Lance | last post by:
I need to create a Drawing.Bitmap from an array of integer values. My current technique creates a bitmap that eventually becomes corrupt (i.e., the bitmap's pixels change to a different color...
7
by: Dave Taylor | last post by:
I have a DataTable with three string columns, "Value", "Format" and "Type" However, some of the rows contain numbers and dates in the Value field. So I would like to be able to format the output...
3
by: JohnR | last post by:
I have a form with a number of text boxes, comboboxes etc. What I would like to do is create an event handler for the "mouseenter" event for each of the controls whereby I display information...
28
by: walterbyrd | last post by:
Python seems to have a log of ways to do collections of arbitrary objects: lists, tuples, dictionaries. But what if I want a collection of non-arbitrary objects? A list of records, or something...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
1
by: Teri B | last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course. 0ne-to-many. One course many roles. Then I created a report based on the Course form and...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.