我正试图从头开始重写_.invoke函数,并且只能让它工作一半。我的函数应该接受一个集合、一个methodName和可选的附加参数,并返回一个数组,其结果是对集合中的每个值调用由methodName指示的方法。传递给调用的任何额外参数都将被转发到方法调用。
这是我的密码:
_.invoke = function (collection, methodName) {
let res = [];
if (Array.isArray(collection)) {
for (let i = 0; i < collection.length; i++) {
res.push(collection[i][methodName](arguments));
}
} else {
for (const [key, value] of Object.entries(collection)) {
res.push(value[methodName](arguments));
}
}
return res;
};
由于没有正确传递参数,它目前失败了。有人能给我任何建议或建议,为什么会发生这种情况?
发布于 2020-12-08 15:28:09
您传递的是arguments
伪数组,而不是它的内容,并且传递的是整个过程,但是您可能不想传递方法名称的集合。
相反,在函数签名上使用rest参数,然后在调用该方法时将其展开:
_.invoke = function (collection, methodName, ...args) {
// ^^^^^^^^^−−−−−−− rest param
let res = [];
if (Array.isArray(collection)) {
for (let i = 0; i < collection.length; i++) {
res.push(collection[i][methodName](...args));
// ^^^−−−−−−−−−−−−−−− spread notation
}
} else {
for (const [key, value] of Object.entries(collection)) {
res.push(value[methodName](...args));
// ^^^−−−−−−−−−−−−−−−−−−−−−−− spread notation
}
}
return res;
};
附带注意:您可能希望允许任何可迭代的,而不仅仅是一个数组,并且可以使用Object.values
获取对象值的数组。
_.invoke = function (collection, methodName, ...args) {
const iterable = isIterable(collection) ? collection : Object.values(collection);
const res = Array.from(iterable).map(entry => entry[methodName](...args));
return res;
};
...where isIterable
是:
function isIterable(obj) {
return obj && typeof obj[Symbol.iterator] === "function";
}
或者,如果执行数组的浅表副本会不必要地困扰您:
_.invoke = function (collection, methodName, ...args) {
const array = Array.isArray(collection)
? collection
: isIterable(collection) ? Array.from(collection) : Object.values(collection);
const res = array.map(entry => entry[methodName](...args));
return res;
};
如果您需要在collection
上重复执行这三步操作,您可以使用一个助手函数:
function arrayForAny(x) {
const array = Array.isArray(x) ? x : isIterable(x) ? Array.from(x) : Object.values(x);
}
您还可以检查是否喜欢数组,并将它们传递到Array.from
,而不是在它们上使用Object.values
。但我已经爬过山顶了所以..。;-)
https://stackoverflow.com/questions/65201722
复制相似问题