The fact is, it's 2012. We all appreciate V8 making the web fast. It's stuff like this, however, that makes me question the sanity of those <i>still</i> promoting node.js<p>The fact of the matter is that JS is bad at all the things a programming language is supposed to be good at. JS can't even perform integer math. It's also fairly alone in being async by default (and no, comparisons to erlang do not count).<p>Does JS work? Sure, but believing JS is good is a special kind of delusion. We have decades of language research to work with, and once again we see the pull of the lowest common denominator.
As a shortcut, in underscore.js you can:<p><pre><code> _.has(object, key)
</code></pre>
or<p><pre><code> _(object).has(key)
</code></pre>
<a href="http://underscorejs.org/#has" rel="nofollow">http://underscorejs.org/#has</a>
It's a pretty good illustration of why associative arrays in Javascript are a design failure, by conflating different notions in the same implementations:<p>- objects are not hashes<p>- hashes are not arrays<p>It sounds like somebody reading the classic quote by Saint Exupéry, "A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.", and concluding: "Well, if I mash all the elements to a paste, there won't be anything to take away."
Is there some type of injection vulnerability here?<p>Is it possible to attack a node.js server that creates objects via some API and give it a name that overwrites an internal javascript property? Your content would be the javascript injected code that might get run when the property is used internally?
Aw gee, you want a real hash in JavaScript, how hard can it be? Here's a quick and dirty one I whipped up in five minutes. It worked the first time with only one bug - I forgot to remove the prefix in the forEach method at first.<p><pre><code> function Hash() {
this.hash = {};
}
Hash.prefix = '#hash#prefix#_';
Hash.prototype.get = function( key ) {
return this.hash[ Hash.prefix + key ];
};
Hash.prototype.set = function( key, value ) {
return this.hash[ Hash.prefix + key ] = value;
};
Hash.prototype.del = function( key ) {
delete this.hash[ Hash.prefix + key ];
};
Hash.prototype.forEach = function( callback ) {
for( var key in this.hash ) {
if( key.indexOf(Hash.prefix) == 0 ) {
callback.call( this, this.hash[key], key.slice(Hash.prefix.length) );
}
}
};
// Q&D test
// Let's try to break things by extending Object.prototype!
Object.prototype.spindizzy = true;
var hash = new Hash;
console.log( hash.get( 'a' ), hash.get( 'b' ) );
hash.set( 'a', 'AA' );
console.log( hash.get( 'a' ), hash.get( 'b' ) );
hash.set( 'b', 'BB' );
hash.forEach( function( value, key ) {
console.log( key, value );
});
hash.del( 'a' );
console.log( hash.get( 'a' ), hash.get( 'b' ) );
hash.del( 'b' );
console.log( hash.get( 'a' ), hash.get( 'b' ) );
</code></pre>
I'm sure I missed something, but this doesn't seem like rocket science.<p>Of course, you do lose the syntactic sugar of [] dereferencing so it looks like part of the language, but life is full of tradeoffs! :-)<p>And I suppose there is still a way to break it, if you extend Object.prototype with something that happens to match Hash.prefix. I guess you could use hasOwnPrototype to prevent this. Ah well, maybe I do have a bug after all, but at least it's a good start.
<p><pre><code> if (!posts.hasOwnProperty(req.body.slug)) {
posts[req.body.slug] = new Post(req.body);
res.send(200);
}
</code></pre>
Maybe I'm missing something, but doesn't that code also happily assign to properties like "constructor", not just "hasOwnProperty"?
I think this problem can be easily solved by encapsulating access/creation methods of posts objects in a object say postStore where posts variable is private property and the object have savePost(slug) and getPost(slug) methods where access/creation methods are defined by yourself. If posts object is that much mission critical than it should not be exposed to outer world.
> Our program, however, is still susceptible to potential misbehaving. Let’s say our user decides to call his blog post "hasOwnProperty".<p>This will virtually never happen. If you're worried about it, put an early return (if (name === 'hasOwnProperty') return). End of story.
Contrary to this Stack thread: <a href="http://stackoverflow.com/questions/1143498/difference-between-an-object-and-a-hash" rel="nofollow">http://stackoverflow.com/questions/1143498/difference-betwee...</a>
Other than lists which can be represented by JSON arrays, hashes do fine jobs at describing most data and most "objects".<p>This post goes off the rails almost immediately with "Normally this would work fine, but let’s consider that the user could pick any of the keys that are present in any JavaScript object as a name." WTF? The author almost immediately is confusing his/her current situation with the request body and what's in it.<p>Then we find ourselves quizzically with "We therefore change our code to leverage hasOwnProperty". Umm, I don't think most developers would find themselves "therefore" doing this.