javascript - Javascript Currying 无限关卡
问题描述
我最近看到一些我刚刚发现的代码叫做柯里化,我想。代码如下所示:
layer.components[0]("ADBE Propety1")("ADBE Property 2")("ADBE Property 3");
我有兴趣复制的部分是 . 之后的多组括号components[0]
。Currying 对我来说是新事物(截至今天),闭包可能会变得复杂。所以我需要一些帮助。
我想创建一个类,其中该类的实例有孩子,我可以通过这样的名字找到孩子:
let bins = new Bins(proj);
console.log(bins('Videos')('More')('NiteLite_90.mp4'));
// Return: {name: 'NiteLite_90.mp4', children: []}
使用下面的代码,我可以深入两个级别(低至“更多”),但不能超过此级别。我希望能够深入到无限的层次。
class Bins {
constructor(proj) {
this.bins = this._getBins(proj);
}
bin(name) {
let bin = this.bins.filter(b => b.name === name)[0];
if (bin) {
return (name) => bin.children.filter(b => b.name === name)[0];
} else {
return null;
}
}
_getBins(proj) {
let { children } = proj;
let childs = [];
let self = this;
children.forEach(child => {
let obj = { name: child.name };
if (child.children && child.children.length > 0) {
obj.children = self._getChildren(child);
}
childs.push(obj);
});
return childs;
}
_getChildren(child) {
let children = [];
let self = this;
child.children.forEach(c => {
let obj = { name: c.name };
if (c.children && c.children.length > 0) {
obj.children = self._getChildren(c);
}
children.push(obj);
});
return children;
}
}
let proj = {
children: [
{
name: 'Videos',
children: [
{
name: 'NiteLite_00.mp4',
children: []
},
{
name: 'More',
children: [
{
name: 'NiteLite_90.mp4',
chidlren: []
}
]
},
{
name: 'NiteLite_97.mp4',
children: []
}
]
},
{
name: 'Sequences',
children: [
{
name: 'Oregon Coast',
children: []
}
]
},
{ name: 'Music', children: [] },
]
};
let bins = new Bins(proj);
console.log(bins.bin('Videos')('More')('NiteLite_90.mp4')); // I don't want to have to call `.bins` first
我可以得到一些帮助来设置这个吗?我在这里研究了多个其他 currying 帖子,并查看了几个关于它的博客,但我仍然不明白,我需要一些关于我的代码的具体帮助。
解决方案
你可以有一个递归 curry 函数,可以随心所欲地深入。但是您还有一个额外的问题:您如何知道何时停止返回函数并返回实际对象?
如果您调用bins.bin('Video')('More')
-- 您如何知道是否要返回More
对象的 bin 或将搜索子项的函数More
以便找到该'NiteLite_90.mp4
bin?
以下是一种可能的解决方案,可为您提供两种选择:
class Bins {
search(collection, name) {
const bin = collection.find(b => b.name === name);
if (bin) {
// first create a function that will search through this bin's children
const curry = (name) => this.search(bin.children, name);
// but make the bin itself available through a `.bin` property on the function
curry.bin = bin;
// return this new function so it can be curried
return curry;
} else {
return null;
}
}
bin(name) {
return this.search(this.bins, name);
}
// plus everything you already have in this class, except for the original
// bin(name) function
}
现在,您可以深入无限数量的级别,并且还可以通过.bin
属性访问任何中间箱:
let bins = new Bins(proj);
console.log(bins.bin('Videos').bin);
// { name: "Videos", children: [ ... ] }
console.log(bins.bin('Videos')('More').bin);
// { name: "More", children: [ ... ] }
console.log(bins.bin('Videos')('More')('NiteLite_90.mp4').bin);
// { name: "NiteLite_90.mp4" }
与您的原始方法一样,该search
方法可以返回null
,因此在搜索可能不存在的路径时要小心:
console.log(bins.bin('Videos')('DoesNotExist')('NiteLite_90.mp4').bin);
// Uncaught TypeError: bins.bin(...)(...) is not a function
console.log(bins.bin('Videos')('More')('DoesNotExist.mp4').bin);
// Uncaught TypeError: Cannot read property 'bin' of null
try/catch
因此,为了安全起见,您可能希望将此类调用包装在 a中:
let bin;
try {
bin = bins.bin('Videos')('DoesNotExist')('NiteLite_90.mp4').bin;
} catch (e) {
console.error('Bin not found!');
}
if (bin) {
// do whatever you want with the found bin
}
推荐阅读
- node.js - 在 Angular 项目中在 www.mysite.com/blog 上安装 WordPress
- performance - Jmeter并发线程组,测试计划未在并发线程组图中执行
- c# - 使用数据库使 Identity 核心选项可配置
- django - 如果 else 标记,如何在 Django 中使用 VueJS 变量?
- excel - 将大型 Excel 工作表加载到 Informix 表的最佳方法是什么?
- c++ - 如何在c ++中返回复合函数的函数指针?
- mongodb - 如何理解 mongostat 的结果?
- javascript - 在多个元素上应用 onchange 事件
- reactjs - 如何在 onClick 上创建动态可编辑反应表
- java - 是否可以在堆栈上使用提供的 Java 集合方法,例如 max、min、sort 等...?