From: JJ on
Hi all

I wanted to ask a question about below code I found in a Javascript
file:

[---SNIP---]
// Action Constants
function Action() {}
// Action types, Action names
Action.Type = { ADD: 0, UPDATE: 1, CLOSE: 2 };
Action.Name = [ "add.web", "save.web", "close" ];

....(continued)...

function getActionType( iTxnCode, sStatus )
{
var iActionType;
switch( iTxnCode ) {
case DwngTxn.TpisTxCode.INCIDENT_SUBMITTAL:
if( !sStatus )
iActionType = Action.Type.ADD;
else
iActionType = Action.Type.UPDATE;
break;

....(continued)...
[---SNIP---]


The question is that the person who developed above code seems to be
creating a function like an object (correct me if I am wrong) and then
giving it two array(?) attributes "Type" and "Name" which he/she then
populates with values.

Later in the code he/she then refers to these in the expressions:
iActionType = Action.Type.ADD;
....and...
iActionType = Action.Type.UPDATE;



My question is about that I have tried to find more information on the
web about doing this but have not seen much of anything. Could anyone
give me a brief description of what is going on above and what the
benefits of above is (or is it just to keep the code clean)?

Thanks in advance,
From: Thomas 'PointedEars' Lahn on
JJ wrote:

> // Action Constants
> function Action() {}
> // Action types, Action names
> Action.Type = { ADD: 0, UPDATE: 1, CLOSE: 2 };
> Action.Name = [ "add.web", "save.web", "close" ];

Note that those are not real constants, but currently there is no better
interoperable way.

> [...]
> if( !sStatus )
> iActionType = Action.Type.ADD;
> else
> iActionType = Action.Type.UPDATE;

Can (and IMHO should) be written as follows:

var iActionType = (sStatus) ? Action.Type.UPDATE : Action.Type.ADD;

> [...]
>
> The question is that the person who developed above code seems to be
> creating a function like an object (correct me if I am wrong)

Functions *are* first-class objects in ECMAScript implementations, with a
double meaning of "object" here.

> and then giving it two array(?) attributes "Type" and "Name" which he/she
> then populates with values.

No, that Function instance is augmented with two _properties_, one storing
a reference to an Object instance (initialized with `{'...`}') and the
other storing a reference to an Array instance (initialized with
`['...`]'). (JavaScript != Java)

> Later in the code he/she then refers to these in the expressions:
> iActionType = Action.Type.ADD;
> ...and...
> iActionType = Action.Type.UPDATE;
>
> My question is about that I have tried to find more information on the
> web about doing this but have not seen much of anything.

It really is not much of a mystery if you know that functions are objects.

> Could anyone give me a brief description of what is going on above and
> what the benefits of above is (or is it just to keep the code clean)?

Yes, using an object as if it was a namespace is a way to keep the global
context clean. The Global Object would then have only one user-defined
property, not several. However, the function here is a waste of resources
if it is never called; in that case

var Action = {
Type: { ADD: 0, UPDATE: 1, CLOSE: 2 };
Name: [ "add.web", "save.web", "close" ];
};

would have sufficed. In any way the property names of the "non-constants"
should have started lowercase as they do not denote constructors, i.e.
`Action.type.ADD' or even `action.type.ADD'.


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> (404-comp.)
From: David Mark on
JJ wrote:
> Hi all
>
> I wanted to ask a question about below code I found in a Javascript
> file:
>
> [---SNIP---]
> // Action Constants
> function Action() {}
> // Action types, Action names
> Action.Type = { ADD: 0, UPDATE: 1, CLOSE: 2 };
> Action.Name = [ "add.web", "save.web", "close" ];
>
> ...(continued)...

Appears to be a botched attempt at writing a constructor. I assume they
call this (once) at some point. They should have just used an object
literal:-

var action = {
type : { ADD: 0, UPDATE: 1, CLOSE: 2 },
name : [ "add.web", "save.web", "close" ]
};

>
> function getActionType( iTxnCode, sStatus )
> {
> var iActionType;
> switch( iTxnCode ) {
> case DwngTxn.TpisTxCode.INCIDENT_SUBMITTAL:
> if( !sStatus )
> iActionType = Action.Type.ADD;
> else
> iActionType = Action.Type.UPDATE;
> break;
>
> ...(continued)...
> [---SNIP---]
>
>
> The question is that the person who developed above code seems to be
> creating a function like an object (correct me if I am wrong) and then
> giving it two array(?) attributes "Type" and "Name" which he/she then
> populates with values.

Functions _are_ objects, though using them in lieu of an Object object
(as is the case here) is not a sound practice.

>
> Later in the code he/she then refers to these in the expressions:
> iActionType = Action.Type.ADD;
> ...and...
> iActionType = Action.Type.UPDATE;
>
>
>
> My question is about that I have tried to find more information on the
> web about doing this but have not seen much of anything. Could anyone
> give me a brief description of what is going on above and what the
> benefits of above is (or is it just to keep the code clean)?

No benefits (just confusion). It's simply another bad JS example (the
Web is crawling with them).
From: Thomas 'PointedEars' Lahn on
David Mark wrote:

> JJ wrote:
>> The question is that the person who developed above code seems to be
>> creating a function like an object (correct me if I am wrong) and then
>> giving it two array(?) attributes "Type" and "Name" which he/she then
>> populates with values.
>
> Functions _are_ objects,

No doubt about that.

> though using them in lieu of an Object object
> (as is the case here) is not a sound practice.

IBTD. We do not know whether Action() is ever called, and properties on
constructors and functions in general can be a powerful tool. For example,
I am using it in my Map implementation as follows:

/**
* Returns <code>true</code> if the argument is a {@link Map}
*
* @param o : Object
* @return boolean
*/
Map.isInstance = function (o) {
return !!o && o.constructor === this;
};


PointedEars
--
Anyone who slaps a 'this page is best viewed with Browser X' label on
a Web page appears to be yearning for the bad old days, before the Web,
when you had very little chance of reading a document written on another
computer, another word processor, or another network. -- Tim Berners-Lee
From: David Mark on
Thomas 'PointedEars' Lahn wrote:
> David Mark wrote:
>
>> JJ wrote:
>>> The question is that the person who developed above code seems to be
>>> creating a function like an object (correct me if I am wrong) and then
>>> giving it two array(?) attributes "Type" and "Name" which he/she then
>>> populates with values.
>> Functions _are_ objects,
>
> No doubt about that.
>
>> though using them in lieu of an Object object
>> (as is the case here) is not a sound practice.
>
> IBTD. We do not know whether Action() is ever called,

Ack. I misread partial paste as:-

function Action() {
// Action types, Action names
Action.Type = { ADD: 0, UPDATE: 1, CLOSE: 2 };
Action.Name = [ "add.web", "save.web", "close" ];

....(continued)...

Which would seem to imply a botched constructor. I suppose if it were a
lowercase, then the only complaint is the (seemingly) inexplicable use
of a Function object where an Object object would be more appropriate.

> and properties on
> constructors and functions in general can be a powerful tool.

Sometimes, but this doesn't look like one of those times.

> For example,
> I am using it in my Map implementation as follows:
>
> /**
> * Returns <code>true</code> if the argument is a {@link Map}
> *
> * @param o : Object
> * @return boolean
> */
> Map.isInstance = function (o) {
> return !!o && o.constructor === this;
> };

I would lose the truthy test and document that this method accepts
objects only. If passed undefined (or whatever), it _should_ throw an
exception, rather than fail silently as, in such a case, there is
clearly something wrong with the calling code (and the author should
best be advised of it).

Consider these two (incorrect) calls of API.isOwnProperty:-

API.isOwnProperty(undefined, 'someproperty'); // exception
API.isOwnProperty(someObject, 'somenonexistentproperty'); // true

....and granted, the results may _appear_ to be mistakes in the library,
but the unforgiving nature is fully intended (and definitely more useful
than glossing over obvious mix-ups in the calling code).

From the docs:-

"The isOwnProperty function tests if the specified object does not
inherit the specified property from its prototype. The property is
stipulated to exist. This function is typically used to filter inherited
properties within for-in loops.

Note the object must be native, not a host object."

For example, the method is meant to be used in this fashion:-

for (var i in o) {
if (API.isOwnProperty(o, i)) {
// Do something with o[i]
}
}

As an aside, as with some of the array module functions, in some cases
you can fool this with:

o.someProperty = undefined;

The isOwnProperty function will return false unless there is such a
property defined (meaning it exists and is _not_ the undefined value) on
o's prototype. I need to add this bit to the documentation. I have an
idea on how the array module functions can get around this too (without
using the disallowed - in - operated). You might wonder why I disallow
the - in - operator in the core. It is because I want to be able to
test the core (or at least the low-level bits) in _everything_ For
instance, I just tested the latest build in NN4.7 (minus the Ajax and
Flash modules as they have try-catch of course) this morning. You might
also wonder why I would want to test _anything_ in NN4.7. It should be
obvious that the less features found in a browser, the greater the
likelihood that gaps in the feature detection will be exposed (and there
appear to be none at this point).
 |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10 11
Prev: how to get url of script
Next: question of logic?