如何解决打印咖喱函数不显示捕获的参数
const gt = x => y => y > x
我希望 gt(5)
返回 y => y > 5
但gt(5)
(或gt(5).toString()
)返回y => y > x
如何获取捕获的参数?
解决方法
我希望 gt(5) 返回 y => y > 5
JavaScript 不是这样工作的。 gt(5)
返回的函数代码是 y => y > x
,只是该代码在标识符 x
解析为具有值 5
的绑定的环境中执行,因为这是对该环境的关闭。函数上的 toString
返回函数源代码的字符串版本(或 [ native code ]
周围的函数声明)(spec),因此您仍然会看到 y => y > x
。 toString
返回的字符串不包括该代码运行的环境。
另见:
- How do JavaScript's closures work? - 在这里
- Closures are not complicated - 在我旧的贫血博客上(使用了一些过时的术语,我可能应该解决这个问题)
正如 @VLAZ 在 a comment 中指出的那样,您可以覆盖函数的默认 toString
以赋予它您想要的行为。如果您不介意重复(这几乎不可避免地会导致维护问题):
const gt = x => {
const fn = y => y > x;
fn.toString = () => `y => y > ${x}`;
return fn;
};
console.log(String(gt(5)));
...或者如果您想定义 toString
与原型上的版本具有相同的可枚举性等:
Object.defineProperty(fn,"toString",{
value: () => `y => y > ${x}`,writable: true,configurable: true,});
在一般情况下这样做需要一个合适的 JavaScript 解析器来进行替换。
,仅仅打印在闭包中捕获的变量是不可能的,但是对于 curry 有一个解决方法。我将参考 Brian Lonsdorf 在 Medium Debugging Functional 上的文章,其中详细介绍了 curry 和 compose。我衷心建议阅读文章本身,因为我只会使用必需品。
Brian Lonsdorf 提出了通用 curry
函数的自定义实现。原始版本取自an article by Erin Swenson-Healy。
这是修改后的版本:
function fToString(f) {
return f.name ? f.name : `(${f.toString()})`;
}
function curry(fx) {
var arity = fx.length;
function f1() {
var args = Array.prototype.slice.call(arguments,0);
if (args.length >= arity) return fx.apply(null,args);
function f2() {
return f1.apply(null,args.concat(Array.prototype.slice.call(arguments,0)));
}
f2.toString = function() {
return fToString(fx)+'('+args.join(',')+')';
}
return f2;
};
f1.toString = function() { return fToString(fx); }
return f1;
}
const gt = curry((x,y) => y > x);
const sum3 = curry((x,y,z) => x + y + z);
const ltUncurried = (x,y) => y < x;
const lt = curry(ltUncurried);
console.log(gt(1)); // ((x,y) => y > x)(1)
console.log(sum3(1)); // ((x,z) => x + y + z)(1)
console.log(sum3(1,2)); // ((x,z) => x + y + z)(1,2)
console.log(sum3(1)(2)); // ((x,2)
console.log(lt(1)); // ltUncurried(1)
(为了更好的可读性,我修改了 fToString()
以在 f.toString()
周围包含括号)
这非常灵活,因为它允许对任何函数进行柯里化,而且还提供了对所述函数的更好记录。如果您认为最重要的细节需要,可以修改 toString
实现。
const gt = x => y => y > x
gt(1);
如果您只传递了 1 个参数,例如 gt(1),并且如果您在控制台中检查,x = 1,此时 y 不可用。因此,执行上下文(调用堆栈)将仅显示 x 参数,而对于 gt() 方法,它将仅显示代码 (y > x)。
下面给了我们一个提示,gt(1) 将首先将 x 绑定到 1,然后 返回一个新函数 f(y) = y > x = y > 1
你没有第二次传递第二个参数,这意味着现在函数 f(y) = 1 + y 被执行了,这一次,它会在 y 不可用的时候检查 y。并且参数 x 的值 1 仍然通过 Closure 保留在上下文中。
它看起来和下面的闭包函数一样:-
function add(x) {
return function (y) {
return y > x
}
}
var d = add(1)(2); ===>>>> true
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。