Reputation: 3155
I am trying to use underscorejs contribe (http://documentcloud.github.io/underscore-contrib/) and jQuery to construct objects. My code looks like this
1. var rightMap = _.rcurry2(_.map);
2. var tabKeys = ['tab1', 'tab2', 'tab3', 'tab4'],
3. rootElements = _.pipeline(
4. rightMap(function(k){return '#' + k;}),
5. rightMap(function(k){return $(k);}) //Here is what confused me
6. )(tabKeys);
//expected result: [$('#tab1'), $('#tab2'), $('#tab3'),$('#tab4')];
this code works as expected. However, I am not happy with line 5. I wanted to replace line 5 with
rightmap($)
this attempt broke the code. Only $('#tab1') was created. I was getting
[$('#tab1'), [], [],[]];
as the result. I am wondering what is the differences between theses two pieces of code.
Thanks.
Update: I have added the link to the library I am using.
Update: add jsfiddle result http://jsfiddle.net/qbzuduom/1/ is the working situation http://jsfiddle.net/qbzuduom/2/ is the one with problem.
please press f12 in your browser and look at the console to see the difference.
What made the difference in the code?
Update: Thanks to the help from @muistooshort, I was able to generate the desired solution, and gained more understanding of the jquery $ function. Please check http://jsfiddle.net/qbzuduom/6/ for the updated demo
Upvotes: 1
Views: 58
Reputation: 434685
I think your problem is that you misunderstand how _.rcurry2
works or how _.map
works or possibly both.
From the fine _.rcurry2
manual:
Signature:
_.rcurry2(func:Function)
Returns a curried version of
fund
where a maxium of two arguments are processed from right to left.
This, more or less, modifies how the arguments to _.map
are handled so that instead of _.map(a, b)
you can say rightMap(b)(a)
. Note that _.rcurry2
has nothing at all to do with how _.map
calls its function.
Then for _.map
we have:
map
_.map(list, iteratee, [context])
Produces a new array of values by mapping each value in list through a transformation function (iteratee). If list is a JavaScript object, iteratee's arguments will be
(value, key, list)
.
The _.map
documentation leaves something very important out: it doesn't tell you what the iteratee
arguments will be when list
is an array, it only tells you want they'll be when list
is an object. When you _.map
an array, the iterator function is called as:
iteratee(list[i], i, list)
Take note of that second argument, that's where all your problems come from.
If we combine the above, we see that this:
rightMap($)
is the same as saying:
rightMap(function(k, i, list) { return $(k, i, list) })
The $
function does understand more than one argument so that i
will be treated as a "context":
Internally, selector context is implemented with the `.find()` method, so `$( "span", this )` is equivalent to `$( this ).find( "span" )`.
and that gives us:
rightMap(function(k, i, list) { return $(i).find(k) })
which won't find anything useful. I'm guessing that jQuery is doing a simple if(context)
check so the i === 0
case works because 0
is falsey.
In any case, you can't pass $
like that, you need to manually restrict the arguments it gets with something like:
var oneDollar = function() { $(arguments[0]) }
and rightMap(oneDollar)
later on:
var rootElements = _.pipeline(
rightMap(function(k) { return '#' + k }),
rightMap(oneDollar)
)(tabKeys);
Demo: http://jsfiddle.net/ambiguous/f5uvaa4m/
The second argument to $
doesn't seem to be widely used these days so I'm not surprised that you missed it.
Upvotes: 1