473,395 Members | 2,468 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Validating existence of "deep" object

Consider the following two functions:

function func1() {
var o ;
if ( (o=document.forms)
&& (o=o[0])
&& (o=o.elements)
&& (o=o.sel)
&& (o=o.options)
&& (o=o[0])
&& (o=o.value)
) {
return true;
}
return false;
}

function func2() {
if (document.forms
&& document.forms[0]
&& document.forms[0].elements
&& document.forms[0].elements.sel
&& document.forms[0].elements.sel.options
&& document.forms[0].elements.sel.options[0]
&& document.forms[0].elements.sel.options[0].value)
{
return true;
}
return false;
}

The perform the same function of making sure that the entire object chain
exists before trying to reference the "deep" object. This may not be a
perfect example, but in some cases it is definitely necessary to validate
all the way down the object chain that things exist how you expect them to
(for example, a json response).

The first function seems to run 3-5x faster in IE and FF, as I would expect
it to.

Is there a cleaner way to write the first function to get the same
functionality but be more readable?

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 16 '07 #1
15 1684
On Feb 16, 6:35 am, "Matt Kruse" <newsgro...@mattkruse.comwrote:
Consider the following two functions:

function func1() {
var o ;
if ( (o=document.forms)
&& (o=o[0])
&& (o=o.elements)
&& (o=o.sel)
&& (o=o.options)
&& (o=o[0])
&& (o=o.value)
) {
return true;
}
return false;

}

function func2() {
if (document.forms
&& document.forms[0]
&& document.forms[0].elements
&& document.forms[0].elements.sel
&& document.forms[0].elements.sel.options
&& document.forms[0].elements.sel.options[0]
&& document.forms[0].elements.sel.options[0].value)
{
return true;
}
return false;

}

The perform the same function of making sure that the entire object chain
exists before trying to reference the "deep" object. This may not be a
perfect example, but in some cases it is definitely necessary to validate
all the way down the object chain that things exist how you expect them to
(for example, a json response).

The first function seems to run 3-5x faster in IE and FF, as I would expect
it to.

Is there a cleaner way to write the first function to get the same
functionality but be more readable?

--
Matt Krusehttp://www.JavascriptToolbox.comhttp://www.AjaxToolbox.com
Hm, that's a mess. I don't know if this is any cleaner:

function func1() {
var o=document, i=0, ps = ['forms', 0, 'elements', 'sel', 'options',
0, 'value'];
while (o=o[ps[i++]]);
return (i == ps.length);
}

Seems a little obfuscated to me, but it's something to ponder.

-David

Feb 16 '07 #2
On Feb 16, 12:11 pm, "David Golightly" <davig...@gmail.comwrote:
On Feb 16, 6:35 am, "Matt Kruse" <newsgro...@mattkruse.comwrote:
Consider the following two functions:
function func1() {
var o ;
if ( (o=document.forms)
&& (o=o[0])
&& (o=o.elements)
&& (o=o.sel)
&& (o=o.options)
&& (o=o[0])
&& (o=o.value)
) {
return true;
}
return false;
}
function func2() {
if (document.forms
&& document.forms[0]
&& document.forms[0].elements
&& document.forms[0].elements.sel
&& document.forms[0].elements.sel.options
&& document.forms[0].elements.sel.options[0]
&& document.forms[0].elements.sel.options[0].value)
{
return true;
}
return false;
}
The perform the same function of making sure that the entire object chain
exists before trying to reference the "deep" object. This may not be a
perfect example, but in some cases it is definitely necessary to validate
all the way down the object chain that things exist how you expect them to
(for example, a json response).
The first function seems to run 3-5x faster in IE and FF, as I would expect
it to.
Is there a cleaner way to write the first function to get the same
functionality but be more readable?
--
Matt Krusehttp://www.JavascriptToolbox.comhttp://www.AjaxToolbox.com

Hm, that's a mess. I don't know if this is any cleaner:

function func1() {
var o=document, i=0, ps = ['forms', 0, 'elements', 'sel', 'options',
0, 'value'];
while (o=o[ps[i++]]);
return (i == ps.length);

}

Seems a little obfuscated to me, but it's something to ponder.

-David
What about this?

var testDeep = function (o) {
o = o || window;
for ( var i = 1, a = arguments.length; i < a; i ++ ) {
if ( ! (arguments[i] in o) ) {
return undefined;
}
o = o[arguments[i]];
}
return o;
};

testDeep(document,'forms', 0, 'elements', 'sel', 'options', 0,
'value');

Returns document.forms[0].elements.sel.options[0].value, if it exists.

While I haven't tested it, I'd suspect that this function or any other
like it will perform slower than your single if with multiple
assignment expressions.

--i

Feb 17 '07 #3
On Feb 16, 4:26 pm, "Isaac Schlueter" <isaacschlue...@gmail.com>
wrote:
On Feb 16, 12:11 pm, "David Golightly" <davig...@gmail.comwrote:
On Feb 16, 6:35 am, "Matt Kruse" <newsgro...@mattkruse.comwrote:
Consider the following two functions:
<..>
>
What about this?

var testDeep = function (o) {
o = o || window;
Not so good as seen from here. Just guessing, but did you perhaps
intend:

var testDeep = function () {
o = arguments[0] || window;

....
testDeep(document,'forms', 0, 'elements', 'sel', 'options', 0, 'value');

../rh

Feb 17 '07 #4
On Feb 16, 7:13 pm, ron.h.h...@gmail.com wrote:
On Feb 16, 4:26 pm, "Isaac Schlueter" <isaacschlue...@gmail.com>
wrote:
var testDeep = function (o) {
o = o || window;

Not so good as seen from here. Just guessing, but did you perhaps
intend:

var testDeep = function () {
o = arguments[0] || window;
6 of one, half-dozen of the other. These two are functionally
equivalent:

function(x) { alert(x); }
function() { alert(arguments[0]; }

The only difference between your suggestion and mine is that yours
slips "o" into the global scope, because you forgot the "var".
Tsk tsk :P

--i

Feb 17 '07 #5
On Feb 16, 7:28 pm, "Isaac Schlueter" <isaacschlue...@gmail.com>
wrote:
On Feb 16, 7:13 pm, ron.h.h...@gmail.com wrote:
On Feb 16, 4:26 pm, "Isaac Schlueter" <isaacschlue...@gmail.com>
wrote:
var testDeep = function (o) {
o = o || window;
Not so good as seen from here. Just guessing, but did you perhaps
intend:
var testDeep = function () {
o = arguments[0] || window;

6 of one, half-dozen of the other. These two are functionally
equivalent:

function(x) { alert(x); }
function() { alert(arguments[0]; }

The only difference between your suggestion and mine is that yours
slips "o" into the global scope, because <..>
Not quite so. Your iteration starts at "1" which means that you'll
miss "document", thereby returning a value based on whether "o" was
passed. Tsk tsk :P

In either case, if "window" gets selected, it turns into something of
a "deep test" of whether you're in a browser environment, because
there's nothing to take you beyond "window".
>you forgot the "var".
Tsk tsk :P
Accepted with appropriate chagrin :)

../rh

Feb 17 '07 #6
David Golightly wrote:
function func1() {
var o=document, i=0, ps = ['forms', 0, 'elements', 'sel', 'options',
0, 'value'];
while (o=o[ps[i++]]);
return (i == ps.length);
}
Seems a little obfuscated to me, but it's something to ponder.
Definitely. Using your loop structure, I got to this:

var exists = (function(){
var regex = /\[["']?([^"'\]]+)["']?\]/g;
return function(obj) {
var o=window,i=0;
obj = obj.replace(regex,".$1").split('.');
while (o=o[obj[i++]]);
return (i == obj.length+1);
}
})();
exists("document.forms[0].elements['sel'].options[0].value");

The regex could be improved (I believe it will fail on forms['name[]']) but
overall it's an improvement, and generalized!

Thanks.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 17 '07 #7
On Feb 16, 8:52 pm, "Matt Kruse" <newsgro...@mattkruse.comwrote:
David Golightly wrote:
function func1() {
var o=document, i=0, ps = ['forms', 0, 'elements', 'sel', 'options',
0, 'value'];
while (o=o[ps[i++]]);
return (i == ps.length);
}
Seems a little obfuscated to me, but it's something to ponder.

Definitely. Using your loop structure, I got to this:

var exists = (function(){
var regex = /\[["']?([^"'\]]+)["']?\]/g;
return function(obj) {
var o=window,i=0;
obj = obj.replace(regex,".$1").split('.');
while (o=o[obj[i++]]);
return (i == obj.length+1);
}})();

exists("document.forms[0].elements['sel'].options[0].value");

The regex could be improved (I believe it will fail on forms['name[]']) but
overall it's an improvement, and generalized!
Here's an example of an alternative regex you can try:

text.match(/[a-z]+|\d+|"[^"]+"|'[^']+'/gi)

It should turn your string into an ordered array of accessors.

By the way, is "value" correct, or should it be "text"? IE's option
element doesn't have a "value" property.

../rh
Feb 17 '07 #8
ro********@gmail.com wrote:
By the way, is "value" correct, or should it be "text"? IE's option
element doesn't have a "value" property.
Of course it does! How else would you get the value?

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 17 '07 #9
On Feb 17, 6:05 am, "Matt Kruse" <newsgro...@mattkruse.comwrote:
ron.h.h...@gmail.com wrote:
By the way, is "value" correct, or should it be "text"? IE's option
element doesn't have a "value" property.

Of course it does! How else would you get the value?
That would be a good point!

It has a value property, and the "value" property has a value that is
not "undefined" provided one assigns a value e.g. in the HTML ...
which I had neglected to do :(. IE doesn't default the "value" to the
"text" value in that case but it seems that FF and Opera do.

I think I've paged in <selectnow, but some HTML remediation may
still be required :).

../rh
Feb 17 '07 #10
ro********@gmail.com said the following on 2/17/2007 11:28 AM:
On Feb 17, 6:05 am, "Matt Kruse" <newsgro...@mattkruse.comwrote:
>ron.h.h...@gmail.com wrote:
>>By the way, is "value" correct, or should it be "text"? IE's option
element doesn't have a "value" property.
Of course it does! How else would you get the value?

That would be a good point!

It has a value property, and the "value" property has a value that is
not "undefined" provided one assigns a value e.g. in the HTML ...
which I had neglected to do :(. IE doesn't default the "value" to the
"text" value in that case but it seems that FF and Opera do.

I think I've paged in <selectnow, but some HTML remediation may
still be required :).
<URL:
http://groups.google.com/group/comp....029b734629d5c5
>
Enjoy :)

--
Randy
Chance Favors The Prepared Mind
comp.lang.javascript FAQ - http://jibbering.com/faq/index.html
Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/
Feb 17 '07 #11
On Feb 16, 8:52 pm, "Matt Kruse" <newsgro...@mattkruse.comwrote:
David Golightly wrote:
function func1() {
var o=document, i=0, ps = ['forms', 0, 'elements', 'sel', 'options',
0, 'value'];
while (o=o[ps[i++]]);
return (i == ps.length);
}
Seems a little obfuscated to me, but it's something to ponder.

Definitely. Using your loop structure, I got to this:

var exists = (function(){
var regex = /\[["']?([^"'\]]+)["']?\]/g;
return function(obj) {
var o=window,i=0;
obj = obj.replace(regex,".$1").split('.');
while (o=o[obj[i++]]);
return (i == obj.length+1);
}})();

exists("document.forms[0].elements['sel'].options[0].value");

The regex could be improved (I believe it will fail on forms['name[]']) but
overall it's an improvement, and generalized!

Thanks.

--
Matt Krusehttp://www.JavascriptToolbox.comhttp://www.AjaxToolbox.com
Hm, what's wrong with

var value;
try {
value = document.forms[0].elements['sel'].options[0].value;
} catch (ex) {
// value remains undefined
}

if (typeof(value) != 'undefined') {
// blah blah blah
}

inline, instead of using a function? Guaranteed to be quicker, and
since your function just returns a boolean value, it'll give the same
result...

-David

Feb 18 '07 #12
David Golightly wrote:
Hm, what's wrong with
var value;
try {
value = document.forms[0].elements['sel'].options[0].value;
} catch (ex) {
// value remains undefined
}
Will unnecessarily fail in any browser not implementing try/catch.

To generalize it, you need to pass in the object string and eval() it, which
in my tests causes it to run about the same speed as my previous function.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 18 '07 #13
VK
On Feb 18, 7:46 pm, "Matt Kruse" <newsgro...@mattkruse.comwrote:
David Golightly wrote:
Hm, what's wrong with
var value;
try {
value = document.forms[0].elements['sel'].options[0].value;
} catch (ex) {
// value remains undefined
}
Bingo! This is as the fastest and the most reliable one to use for
many years in the row already. I skept on the "glory" to remind it
exactly because I knew in advance the criticism template. At least
because it was Golightly and not VK we avoided derragatory terms in
response.
Will unnecessarily fail in any browser not implementing try/catch.
Which are?
Oh, sorry, I've forgotten the plot again: "it doesn't matter that
there are not any to care of - but theoretically there can be some
day".
To generalize it, you need to pass in the object string and eval() it, which
in my tests causes it to run about the same speed as my previous function.
That is not technically possible. JScript/JavaScript doesn't cache
dispid's but re-retrieves them over and over again even within the
same block. This is why your way was times quicker than the old-
fashioned "step-by-step nesting". For the same reason try-catch will
be times quicker than your own way. It does not imply of course try-
catch exclusively: the pure productivity is rarely the only
consideration to care about.

Feb 18 '07 #14
David Golightly wrote:
<snip>
Hm, what's wrong with

var value;
try {
value = document.forms[0].elements['sel'].options[0].value;
} catch (ex) {
// value remains undefined
}

if (typeof(value) != 'undefined') {
// blah blah blah
}
<snip>

Three things may be raised as objections. The first is that try-catch was
introduced into the language an ECMA 262, 3rd Ed. and is not
back-compatible with previous versions. Fortunately the last few years
have seen pre-3rd edition implementations virtually disappear so that
objection is probably no longer significant.

However, in general try-catch is not particularly useful in javascript
because it can only catch all exceptions, in contrast to the hierarchical
exception handling in, for example, Java. This results in code that
either handles all exceptions identically (which will be inappropriate in
many cases, and may conceal programming errors (say you spell 'forms'
wrongly; you never see the exception and may find it hard to see why the
function never goes into the 'blah blah blah' branch regardless of the
input (while seeing a "document.froms has no properties" error would give
the game away first time))) or that tests the nature of each exception
and re-throws the ones that it cannot handle. The latter suffers from the
very considerable variation in exceptions thrown in differing
environments and so the considerable effort required in picking up all
the variations of the ones that can be handled.

The next objection would be the software design principle that you do not
use an error handling mechanism for program flow control. Whether that
objection applies to this example is questionable. I think it probably
comes down on the right side using error handling for flow control.

Finally there is the principle for defensive programming where you do not
provoke the throwing of an exception where you can test for the
conditions that might result in the throwing of the exception. Obviously
here the exception generating condition can be tested for, as that is the
subject of this thread. The advantage of that approach is that if an
exception is thrown then it is not the expected exception, and so
probably signifies something that needs additional attention.

Richard.

Feb 18 '07 #15
VK
On Feb 18, 10:20 pm, "Richard Cornford" <Rich...@litotes.demon.co.uk>
wrote:
The first is that try-catch was
introduced into the language an ECMA 262, 3rd Ed. and is not
back-compatible with previous versions. Fortunately the last few years
have seen pre-3rd edition implementations virtually disappear so that
objection is probably no longer significant.
Wow! I mean like... wow!

:-)

Feb 18 '07 #16

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

Similar topics

2
by: Nick Jacobson | last post by:
This question is with regard to the * operator as used for sequence concatenation. There's the well-known gotcha: a = ] b = a*3 b = 4 print b
1
by: Alfonso Morra | last post by:
Hi, I have the ff data types : typedef enum { VAL_LONG , VAL_DOUBLE , VAL_STRING , VAL_DATASET }ValueTypeEnum ;
1
by: Jesper Denmark | last post by:
Hi, Is deep serialization possible using XML. Know any good tutorials?. By deep serialization I mean the ability that an object being serialized automatically serialize its members. E.g ...
4
by: lars.uffmann | last post by:
Hey everyone! I am (still) working on a project that I took over from former students, so don't blame me for the criminal approach on coding *g* The problem I have is fairly easy and while I...
40
by: Mark P | last post by:
I'm implementing an algorithm and the computational flow is a somewhat deep. That is, fcn A makes many calls to fcn B which makes many calls to fcn C, and so on. The return value of the outermost...
6
by: =?ISO-8859-1?Q?Ignacio_Burgue=F1o?= | last post by:
Hi everyone. I'm dealing with some javascript code which uses eval to access properties of an object. For instance, I have the following: var events = {}; events.flatUsers = {};...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.