Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions test/utility.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@
assert.equal(undefPropertyOf('curly'), void 0, 'should return undefined when obj is undefined');
});

QUnit.test('method', function(assert) {
var stooge = {name: function() { return 'moe'; }, sum: function(a, b, c) { return a + b + c; }};
assert.equal(_.method('name')(stooge), 'moe', 'should return the results of calling the method with the given name');
assert.equal(_.method('sum')(stooge, 1, 2, 3), 6, 'should pass rest of arguments to named method for evaluation');
assert.equal(_.method(function() { return this.name(); })(stooge), 'moe', 'should apply a function literal passed.');
assert.equal(_.method(function(a, b, c) { return this.sum(a, b, c); })(stooge, 1, 2, 3), 6, 'should pass arguments when applying a function literal.');
assert.equal(_.method('macerena')(stooge), void 0, 'should return undefined for non-existant method name on defined object');
assert.equal(_.method('name')(null), void 0, 'should return undefined for null object');
assert.equal(_.method()(stooge), void 0, 'should return undefined for undefined method name on existing object');
assert.equal(_.method()(void 0), void 0, 'should return undefined for undefined method name on undefined object');
});

QUnit.test('random', function(assert) {
var array = _.range(1000);
var min = Math.pow(2, 31);
Expand Down
15 changes: 15 additions & 0 deletions underscore.js
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,21 @@

_.property = property;

// Generates a function for a given object that returns the passed function's return value.
// Accepts a method name or function literal for value.
// If value is a string, function assumes this string is a method name on the
// referenced object.
_.method = function(value) {
return restArgs(function(obj, args) {
if (obj == null) { return; }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this not valid when a function is provided?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method responds to both a string literal (a method name) or a function literal. This check is to sort out if the value passed is a function literal, so that later we know what to call apply on.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any rational why should func not be called if it is a function literal and obj is null?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My current rational is that this invocation pattern doesn't make much sense to me. e.g.,

_().method(function() { /* function body *. })
_.method(null, function () { /* function body */ })

since both would be more easily written as a plain function literal, and this invocation pattern reads to me as 'call the provided method on undefined'.

That said, if allowing an undefined object in this position is more in keeping with underscore's style, I'm happy to update so we can call _.method on undefined objects.

var func = _.isFunction(value) ? value : obj[value];
if (func) {
return func.apply(obj, args);
}
});
};


// Generates a function for a given object that returns a given property.
_.propertyOf = function(obj) {
return obj == null ? function(){} : function(key) {
Expand Down