我正在使用Underscore.js扩展我对更复杂的javascript概念的知识和理解,并希望有人可以帮助我理解_.iteratee函数在特定示例中的执行方式。
这是一个例子,到目前为止对我的理解有评论。
我正在使用_.map函数:
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]
最底层是正在使用的相关功能,其中一些无关紧要的功能如_.keys被遗漏。
我的理解是:
在_.map函数中,函数体内iteratee
的第一个实例的设置如下:iteratee = _.iteratee(iteratee, context);
基于_.iteratee
函数(因为函数被传递到_.map)应该评估为createCallback(value, context, argCount)
。
下次{_ 1}}变量(现在应该是回调函数)在_.map函数中使用时:iteratee
。
这是我迷路的地方。
问题:
假设我上面的#1假设确实是正确的,当我们到达循环内的_.map函数的这一行时:results[index] = iteratee(obj[currentKey], currentKey, obj);
我们实际调用的是results[index] = iteratee(obj[currentKey], currentKey, obj);
。那么createCallback(obj[currentKey], currentKey, obj)
是否会传递给createCallback中的obj[currentKey]
参数? (似乎没有意义)。
如果上述情况属实,我在迷失的地方是,func
评估createCallback
obj
的{{1}}是createCallback
的值argCount
}。我不明白createCallback
中switch语句的哪一部分被引用。
在这种情况下调用哪个switch语句?
如果我有,我应该能够完成对createCallback内部闭包的追踪。我们非常感谢您提供的任何其他信息以指导我。
感谢。
功能
_。地图
_.map = _.collect = function(obj, iteratee, context) {
if (obj == null) return [];
iteratee = _.iteratee(iteratee, context);
var keys = obj.length !== +obj.length && _.keys(obj),
length = (keys || obj).length,
results = Array(length),
currentKey;
for (var index = 0; index < length; index++) {
currentKey = keys ? keys[index] : index;
results[index] = iteratee(obj[currentKey], currentKey, obj);
}
return results;
};
createCallback的
var createCallback = function(func, context, argCount) {
if (context === void 0) return func;
switch (argCount == null ? 3 : argCount) {
case 1: return function(value) {
return func.call(context, value);
};
case 2: return function(value, other) {
return func.call(context, value, other);
};
case 3: return function(value, index, collection) {
return func.call(context, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(context, accumulator, value, index, collection);
};
}
return function() {
return func.apply(context, arguments);
};
};
_。iteratee
_.iteratee = function(value, context, argCount) {
if (value == null) return _.identity;
if (_.isFunction(value)) return createCallback(value, context, argCount);
if (_.isObject(value)) return _.matches(value);
return _.property(value);
};
答案 0 :(得分:0)
在这一特定行中,
results[index] = iteratee(obj[currentKey], currentKey, obj);
iteratee
实际上会像这样被调用
iteratee(<actual value of obj[currentKey]>, currentKey, obj);
因此,obj
不会传递给iteratee
函数。
在您的情况下,由于您将对象作为第一个参数传递,因此在每次迭代时,results
累积行将评估与此类似的内容
results[0] = iteratee(1, "one", obj);
results[1] = iteratee(2, "two", obj);
results[2] = iteratee(3, "three", obj);
iteratee = 当执行此行时,
_.iteratee(iteratee, context);
iteratee
实际上是您作为_.map
的参数之一传递的函数。由于您未明确传递context
对象,因此默认情况下该值为undefined
。所以,
if (context === void 0) return func;
签入createCallback
函数将评估为true
(自undefined == void 0
起),您实际传递给_.map
的函数将用作回调函数。