bestiejs/lodash — pull request #4 by viatropos (2012-04-26 09:21:25+00:00)
Title: added isHash, matches {} but not subclasses (which isObject does)

Tests if object is direct descendant of Object, such as `{}`.

This is useful for determining if an "options hash" is passed in a function with dynamic/overloaded arguments. You may have a function that can take arguments like this:

``` javascript
User.create({name: 'Joe'}); // passed in an Object instance, {}
User.create([{name: 'Joe'}, {name: 'Jane'}]); // passed in an array of {} instances
User.create(new User({name: 'Joe'})); // passed in a User instance, which is a "subclass" of Object, but not a direct {} instance
// the complex case:
User.create(new User({name: 'Joe'}), {validate: false}); // passed in Model, which is NOT a direct {} instance, then passed in a {}.
```

If you wan't to be able to do the last case, you can't use the `_.isObject` function, you'd need to check if the object is a `{}` instance, not a subclass. For example:

``` javascript
Model.create = function() {
var args = Array.prototype.slice.call(arguments);
var options = _.isObject(args[args.length - 1]) ? args.pop() : {};
// The above works in these cases:
//
// Model.create(model, options); // args[args.length - 1] == true
// Model.create(options); // args[args.length - 1] == true
//
// but it fails in this case:
//
// Model.create(model); // args[args.length - 1] == true
//
// The correct way to do this, is to check if it's a "hash":
//
var options = _.isHash(args[args.length - 1]) ? args.pop() : {};
//
// this will work in all of these cases:
//
// Model.create(model, options); // args[args.length - 1] == true
// Model.create(options); // args[args.length - 1] == true
// Model.create(model); // args[args.length - 1] == false
}
```