Prev: FAQ Topic - How can I access the client-side filesystem? (2010-05-11)
Next: apparently wrong function.
From: Matt Kruse on 11 May 2010 09:44 Does anyone here use a general convenience method for deep property access that will not throw an error if any property along the chain is undefined? For example: deep(document, "body.firstChild.style.backgroundColor"); or deep("myElementId.childNodes[3].id"); or deep( myJsonObject, "locations.ca.sandiego.directory.people.smith.john.phone"); This would return undefined if any element along the chain is not there, or index is out of bounds, etc. If the chain gets to the end, it would return the last-evaluated value. This would be convenient for accessing deep properties of objects that may or may not exist, and not having to manually check the chain in your code. I'm curious to know if anyone uses such an approach, or the cons of doing so. Matt Kruse
From: Scott Sauyet on 11 May 2010 10:12 On May 11, 9:44 am, Matt Kruse <m...(a)thekrusefamily.com> wrote: > Does anyone here use a general convenience method for deep property > access that will not throw an error if any property along the chain is > undefined? [ ... ] > > I'm curious to know if anyone uses such an approach, or the cons of > doing so. I used such a technique only once. It was easy enough to write, performed well enough for my uses, and did simplify some code. But as new developers came aboard the project, it was one more thing that they hadn't seen before, and it rarely turned out to be useful enough to justify even the short learning curve. But then again I don't think I've ever written something as deep as your third example. -- Scott
From: Thomas 'PointedEars' Lahn on 11 May 2010 11:29 Matt Kruse wrote: > Does anyone here use a general convenience method for deep property > access that will not throw an error if any property along the chain is > undefined? > > For example: > > deep(document, "body.firstChild.style.backgroundColor"); > or > deep("myElementId.childNodes[3].id"); > or > deep( myJsonObject, > "locations.ca.sandiego.directory.people.smith.john.phone"); getFeature() and isMethod() in JSX:object.js do a similar thing. They could be rewritten to support your requirements using dotsToBrackets() in JSX:types.js. Note that I had opted for several arguments instead because property names may contain `.', `[', or `]'. PointedEars -- Danny Goodman's books are out of date and teach practices that are positively harmful for cross-browser scripting. -- Richard Cornford, cljs, <cife6q$253$1$8300dec7(a)news.demon.co.uk> (2004)
From: Matt Kruse on 11 May 2010 11:52 On May 11, 8:44 am, Matt Kruse <m...(a)thekrusefamily.com> wrote: > Does anyone here use a general convenience method for deep property > access that will not throw an error if any property along the chain is > undefined? Well, here's my stab at it: /* Error-Free Deep Property Access! Returns: Property value, or undefined if any part of the property chain is undefined Usage: $prop( object, 'property_name' ) $prop( 'element_id.property_name' ) $prop( 'element_id.prop1.prop2.prop3' ) $prop( object, 'array_property[0]' ) $prop( object, 'method(arg).property_name.array_property[0] [1].prop' ) $prop( window, 'document.getElementsByTagName(div) [0].childNodes[1].style.color' ) Special Usage: $prop() returns the object last evaluated! if ($prop("id.style.color")) { alert( $prop() ); } JSON Example: var json = { 'a':'1' ,'b': ['x','y','z'] ,'c': { 'array':['1','2','3'] ,'property':'prop!' } } $prop(json,'a') ==> 1 $prop(json,'b[1]') ==> y $prop(json,'c.array[2]') ==> 3 $prop(json,'d.e.f.g') ==> undefined */ var $prop = (function() { var last_match; return function(a,b) { // Calls to $property() return the last match if (typeof a=="undefined") { return last_match; } var context, props = null, p; // If first arg is not a string, assume it's an object to // start from if (typeof a!="string") { context = a; props = b.split("."); } // Otherwise it's just a string where the first part is an // element ID else { props = a.split("."); context = document.getElementById(props.shift()); if (!context) { return; } } while (context && props.length>0) { if (context==null) { return; } p = props.shift(); // If there is an array index [i] at the end, only // process the first part and stick the second part // back on the beginning if ( p.match(/(.+?)(\[\d+\].*)/) ) { p = RegExp.$1; props.unshift(RegExp.$2); } // if the first part itself is an array index [i] // then process it if ( p.match(/^\[(\d+)\]$/) ) { if (!context || !context.length) { return; } context = context[RegExp.$1]; } // If it's a function(arg) call else if ( p.match(/(.*)\((.*?)\)/) ) { context = context[RegExp.$1](RegExp.$2); } // Else it's a regular property else { context = context[p]; } if (typeof context=="undefined") { return; } } last_match = context; return context; } })(); Matt Kruse
From: Scott Sauyet on 11 May 2010 13:19
Matt Kruse wrote: > On May 11, 8:44 am, Matt Kruse <m...(a)thekrusefamily.com> wrote: > >> Does anyone here use a general convenience method for deep property >> access that will not throw an error if any property along the chain is >> undefined? > > Well, here's my stab at it: [ ... ] So this won't allow, for instance, $props("myObj.prop1.prop2[current.value]") Is that right? It needs to have only a single root at the first token. That will cover a lot of possibilities, but the more general case is interesting too. -- Scott |