This key / list check is redundant, isn't it? - javascript

so, I am checking for a key in a list (hash), and I must of coded it two different ways but forget to remove a bit of it. lol. But to me, looking at it - it appears redundant. Is this the case?
var somelist = {
a : 'somevalue1',
b : 'somevalue1',
c : 'somevalue1',
d : 'somevalue1',
e : 'somevalue1',
f : 'somevalue1'
}
for(var key in somelist ){
if(somelist.hasOwnProperty(key)){ // <-- redundant
// do something
}
}
if we are looping thru the keys - then the assumption is, it's a property of the list, yes? I want to make sure my brain isn't fried. :-)
I looked over these two posts:
for..in and hasOwnProperty
How do I check if an object has a property in JavaScript?
But my usage seems much more benign. Since I am declaring var key here, isn't it local and I don't have to worry about prototypical chain collisions?
So, it appears that in my usage - it IS redundant or not needed -- but would this be considered 'poor form'. It seems because I do not have this hash sitting in a constructor I don't have to worry about prototypical inheritance etc...
so, my two questions are:
Since I am declaring var key here, isn't it local and I don't have to worry about prototypical chain collisions?
would my usage here be considered 'poor form' even though it isn't needed? I wanted to keep with certain coding standards - but perhaps my intent is wrong here.

It's not about the key where you have to worry. It's the object itself.
Object.prototype[1] = 1;
var somelist = {}
for (var key in somelist) {
alert(key);
}
// '1' was alerted

You just make your code more robust doing that check, and it is recommended as a best practice. However, to keep intendation shallow, I usually do an inverted pattern:
for( var key in obj ) {
if( !obj.hasOwnProperty( key ) ) {
continue;
}
// do something
}
Jo So pointed out a potential conflict, but also your data might just change and then your code can break. A golden rule in software development: Expect failure.

Related

JavaScript variable assignment with OR vs if check [duplicate]

This question already has answers here:
What does the construct x = x || y mean?
(12 answers)
Closed 6 years ago.
In JavaScript I recently realized you could use the OR || logical operator for assignment, and I want to know if it's considered bad practice.
In particular I have some functions that have optional array input, if the input is null or undefined I should just set it to an empty array [], if it has content it should take the content.
I found that using the assignment using the OR operator handles that perfectly in a single line, it's clean. However, it feels like the kind of thing that might be considered bad practice, or may have some horrible pitfalls I'm not considering.
Another approach is a simple if check, which is fairly safe in general.
I want to know if using the || approach seen below has any pitfalls I'm not considering, although it works in this scenario I would appreciate knowing if it works well to keep using this in the future, or to stop using it altogether.
https://jsbin.com/nozuxiwawa/1/edit?js,console
var myArray = ['Some', 'Strings', 'Whatever'];
// Just assign using OR
var pathOne = function(maybeAnArray) {
var array = maybeAnArray || [];
console.log(array);
}
// Assign using IF
var pathTwo = function(maybeAnArray) {
var array = [];
// Covers null and undefined
if (maybeAnArray != null) {
array = maybeAnArray;
}
console.log(array);
}
console.log('Path one:');
pathOne(myArray); // ['Some', 'Strings', 'Whatever']
pathOne(null); // []
console.log('\nPath two:');
pathTwo(myArray); // ['Some', 'Strings', 'Whatever']
pathTwo(null); // []
IMHO the use of the OR || for the purposes of assignment is perfectly valid and is good practice. We certainly use it in our projects and I've seen it used in lots of 3rd party projects that we use.
The thing you need to be aware of is how certain JavaScript objects can be coerced to be other values. So for example, if you're ORing values such as "", false or 0 then they are treated as false... this means that when you have the following:
function f(o) {
var x = o || -1;
return x;
}
Calling:
f(0)
...will return -1... but calling
f(1)
Will return 1 ... even though in both cases you passed a number - because 0 is treated as false -1 is assigned to x.
...that said, as long as you're aware of how the OR operator will treat the operands that you use with it - then it is good JavaScript practice to use it.
i prefer the first option, it's clear for my eyes, but when i need to share my code with others will think about to use second, will be more clear for any.
Now i'm using sonar, and prefer the second option too, will more easy to comprend for machine in inegration works.
Last idea is to use
if(maybeAnArray !== void(0))
Two reasons:
use cast and type conditionals
void(0) will works same for all browsers
Expect it helps yopu
When given the option, I prefer concise code (which must still be readable).
I would say || is common enough that it is considered good practice. Once one has seen it a few times it reads just fine.
In my opinion there are few reasons why you should rather use the second option:
First of all it's much more readable - new developers that are still learning can have problems with understanding notation like var myArray = someArrayArg || [];
If you are using some kind of code checkers like JSLint, they will return warnings and/or errors like Expected a conditional expression and instead saw an assignment. for the statement with var myArray = someArrayArg || [];
We already have something like var myArray = someArrayArg ? someArrayArg : []; that works pretty well

Javascript class - how to make properties required and optional

I'm building a event tracking api and need to provide a JS class with a list of properties of which some of them will be required and some optional. Also, no new properties should be added.
Once the client instantiates and passes the object based on the class, I will be serializing the object and sending it as query string. I already have this part but not sure how to restrict the client from creating new properties.
How do I go about designing the class in JS?
There are a number of ways of doing the things you're wanting. Required/Optionals are pretty easy with utilities like underscorejs/jquery extend, along with some of underscore's utility methods (map, reduce,etc.).
To prevent an object from actually having additional properties though is a bit trickier. You could run an array of known required/optional properties as a check and do a delete on any property values that don't match your criteria.
Another option is to use something like seal. You read up more about this on mozilla's website here.
So I guess what I'd do is get the required properties working first by doing a sanity check against their existence. Your optionals could be provided and wrapped/unwrapped by using extend.
Finally (and maybe an even better route) would be to force the user to call getter/setter methods like setMyProperty( 'value' ) in order to populate any required/optional property value. This way, you aren't going to have to write a big hairy solution using the tools above.
JS is just funny like that. Neither solution is perfect, but they are both possible solutions. I'm sure there are others too. This is just a part of JS that can be a bit of a pain in the arsonal. Good luck.
>>> Edit <<<
This may not be perfect, but this is what I've done so far for the optional/required properties. I am obviously assuming they would just be passing in a set of properties in the constructor.
var _Required = {
requiredProperty1: null,
requiredProperty2: null,
requiredProperty3: null
};
var _Optionals = {
optionalProperty1: null,
optionalProperty2: null,
optionalProperty3: null
};
var EventTrackerAPI = function( settings ) {
var requiredProp, optionalProp;
this.required = {};
this.optional = {};
for( requiredProp in _Required ) {
if( !settings.hasOwnProperty( requiredProp ) ) {
throw new Error( 'FAILED to create an instance of EventTrackerAPI - Required Property (' + requiredProp + ') Missing!' )
}
this.required[requiredProp] = settings[requiredProp];
}
for( optionalProp in _Optionals ) {
if( settings.hasOwnProperty( optionalProp ) ) {
this.optional[optionalProp] = settings.hasOwnProperty( optionalProp );
} else {
this.optional[optionalProp] = null;
}
}
};
Anyways, I'd probably do something like the above. It isn't perfect yet (since I threw it together in about 10 minutes), but it should be a good start. I would also just not allow access to the private storage either.
When I was ready to actually extract the properties (like when you're ready to serialize), I'd do something similar as is being done in the constructor - just manually go through and grab the things you actually want - everything else would just be discarded this way. As a matter of fact, it may make sense to strip out the optional/required logic and make them methods on the object's prototype (EventTrackerAPI.prototype.extractRequired = function( required ) {.... } for example...)
Why not usign just class with constructor - you will have required properties then

How efficient is the "with" statement?

It is hard to Google for some keywords like "with" word, so I am testing to ask here.
Is the with statement in JavaScript inefficient?
For instance, say I have:
with(obj3) {
with(obj2) {
with(obj1) {
with(obj0) {
eval("(function() { console.log(aproperty) })();");
}
}
}
}
Would the above be more or less efficient, if for instance, I walked over obj0, obj1, obj2, obj3 and merged them together, and then used either:
One with statement alone
Created a parameters string with the keys of obj0, obj1, obj2 and obj3, and an args array for the values and used:
eval("function fn(aproperty, bproperty) { console.log(aproperty); }")
fn.apply(undefined, args);
Which of these three approaches can be deemed to be quicker? I am guessing on with statements but so many with's makes me think I can optimize it further.
If you're looking for options, then you may want to consider a third approach, which would be to create (on the fly if needed) a prototype chain of objects.
EDIT: My solution was broken. It requres the non-standard __proto__ property. I'm updating to fix it, but be aware that this isn't supported in all environments.
var objs = [null,obj3,obj2,obj1,obj0];
for (var i = 1; i < objs.length; i++) {
objs[i].__proto__ = Object.create(objs[i-1]);
}
var result = objs.pop();
This avoids with and should be quicker than merging, though only testing will tell.
And then if all you needed was a product of certain properties, this will be very quick.
var props = ["x2","b1","a3"];
var product = result.y3;
for (var i = 0; i < props.length; i++)
product *= result[props[i]];
Newer browsers have an internal tokening mechanism to make the javascript interpretation cheaper. It is very like JIT in the newer JVMs. I think there isn't a much problem with your deeply embedded with-s, practically it will be some like
__get_aproperty() {
if (obj0.has("aproperty")) return obj0.aproperty;
if (obj1.has("aproperty")) return obj1.aproperty;
if (obj2.has("aproperty")) return obj2.aproperty;
if (obj3.has("aproperty")) return obj3.aproperty;
}
So, the structure of your js is highly embedded, but the structure of the real execution in the JS-engine of the browsers, will be simple and linear.
But the tokenization of the JS, that is costly. And if the JS-engine finds an eval, needs to tokenize.
I voted for the first version.
With statement will make your code run like it's 1980 - literally every optimization implemented in a JIT cannot be used when it's in effect.

How to detect when a property is added to a JavaScript object?

var obj = {};
obj.a = 1; // fire event, property "a" added
This question is different from this one, where ways to detect when an already declared property is changed, being discussed.
this is possible, technically, but since all current JS implementations that I know of are single threaded it won't be very elegant. The only thing I can think of is a brute force interval:
var checkObj = (function(watchObj)
{
var initialMap = {},allProps = [],prop;
for (prop in watchObj)
{
if (watchObj.hasOwnProperty(prop))
{//make tracer object: basically clone it
initialMap[prop] = watchObj[prop];
allProps.push(prop);//keep an array mapper
}
}
return function()
{
var currentProps = [];
for (prop in watchObj)
{
if (watchObj.hasOwnProperty(prop))
{//iterate the object again, compare
if (watchObj[prop] !== initialMap[prop])
{//type andvalue check!
console.log(initialMap[prop] + ' => ' watchObj[prop]);
//diff found, deal with it whichever way you see fit
}
currentProps.push(prop);
}
}
//we're not done yet!
if (currentProps.length < allProps.length)
{
console.log('some prop was deleted');
//loop through arrays to find out which one
}
};
})(someObjectToTrack);
var watchInterval = setInterval(checkObj,100);//check every .1 seconds?
That allows you to track an object to some extent, but again, it's quite a lot of work to do this 10/sec. Who knows, maybe the object changes several times in between the intervals, too.All in all, I feel as though this is a less-then-ideal approach... perhaps it would be easier to compare the string constants of the JSON.stringify'ed object, but that does mean missing out on functions, and (though I filtered them out in this example) prototype properties.
I have considered doing something similar at one point, but ended up just using my event handlers that changed the object in question to check for any changes.
Alternatively, you could also try creating a DOMElement, and attach an onchange listener to that... sadly, again, functions/methods might prove tricky to track, but at least it won't slow your script down as much as the code above will.
You could count the properties on the object and see if has changed from when you last checked:
How to efficiently count the number of keys/properties of an object in JavaScript?
this is a crude workaround, to use in case you can't find a proper support for the feature in the language.
If performance matters and you are in control of the code that changes the objects, create a control class that modifies your objects for you, e.g.
var myObj = new ObjectController({});
myObj.set('field', {});
myObj.set('field.arr', [{hello: true}]);
myObj.set('field.arr.0.hello', false);
var obj = myObj.get('field'); // obj === {field: {arr: [{hello: false}]}}
In your set() method, you now have the ability to see where every change occurs in a pretty high-performance fashion, compared with setting an interval and doing regular scans to check for changes.
I do something similar but highly optimised in ForerunnerDB. When you do CRUD operations on the database, change events are fired for specific field paths, allowing data-bound views to be updated when their underlying data changes.

Number of elements in a javascript object

Is there a way to get (from somewhere) the number of elements in a Javascript object?? (i.e. constant-time complexity).
I can't find a property or method that retrieves that information. So far I can only think of doing an iteration through the whole collection, but that's linear time.
It's strange there is no direct access to the size of the object, don't you think.
EDIT:
I'm talking about the Object object (not objects in general):
var obj = new Object ;
Although JS implementations might keep track of such a value internally, there's no standard way to get it.
In the past, Mozilla's Javascript variant exposed the non-standard __count__, but it has been removed with version 1.8.5.
For cross-browser scripting you're stuck with explicitly iterating over the properties and checking hasOwnProperty():
function countProperties(obj) {
var count = 0;
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
++count;
}
return count;
}
In case of ECMAScript 5 capable implementations, this can also be written as (Kudos to Avi Flax)
function countProperties(obj) {
return Object.keys(obj).length;
}
Keep in mind that you'll also miss properties which aren't enumerable (eg an array's length).
If you're using a framework like jQuery, Prototype, Mootools, $whatever-the-newest-hype, check if they come with their own collections API, which might be a better solution to your problem than using native JS objects.
To do this in any ES5-compatible environment
Object.keys(obj).length
(Browser support from here)
(Doc on Object.keys here, includes method you can add to non-ECMA5 browsers)
if you are already using jQuery in your build just do this:
$(yourObject).length
It works nicely for me on objects, and I already had jQuery as a dependancy.
function count(){
var c= 0;
for(var p in this) if(this.hasOwnProperty(p))++c;
return c;
}
var O={a: 1, b: 2, c: 3};
count.call(O);
AFAIK, there is no way to do this reliably, unless you switch to an array. Which honestly, doesn't seem strange - it's seems pretty straight forward to me that arrays are countable, and objects aren't.
Probably the closest you'll get is something like this
// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
var i = 0;
for ( var p in this ) i++;
return i;
}
alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3
But this creates problems, or at least questions. All user-created properties are counted, including the _length function itself! And while in this simple example you could avoid it by just using a normal function, that doesn't mean you can stop other scripts from doing this. so what do you do? Ignore function properties?
Object.prototype.length = function()
{
var i = 0;
for ( var p in this )
{
if ( 'function' == typeof this[p] ) continue;
i++;
}
return i;
}
alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2
In the end, I think you should probably ditch the idea of making your objects countable and figure out another way to do whatever it is you're doing.
The concept of number/length/dimensionality doesn't really make sense for an Object, and needing it suggests you really want an Array to me.
Edit: Pointed out to me that you want an O(1) for this. To the best of my knowledge no such way exists I'm afraid.
With jquery :
$(parent)[0].childElementCount

Categories