gpt4 book ai didi

javascript - 为什么在Crockford的 `this`方法中使 `curry`无效?

转载 作者:可可西里 更新时间:2023-11-01 01:18:30 25 4
gpt4 key购买 nike

在道格拉斯·克罗克福德(Douglas Crockford)的书“Javascript:The Good Parts”中,他提供了curry方法的代码,该方法接受一个函数和参数,并返回已添加参数的函数(显然,这不是what "curry" means,而是"partial application"的示例)。这是代码,我已经对其进行了修改,因此无需他编写其他自定义代码即可使用:

Function.prototype.curry = function(){
var slice = Array.prototype.slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to null, which will cause `this` to refer to the window
return that.apply(null, args.concat(slice.apply(arguments)));
};
};

因此,如果您有 add函数:
var add = function(num1, num2) {
return num1 + num2;
};

add(2, 4); // returns 6

您可以创建一个已经具有一个参数的新函数:
var add1 = add.curry(1);

add1(2); // returns 3

很好但是我想知道的是为什么他将 this设置为 null?预期的行为会不会是curried方法与原始方法相同,包括相同的 this

我的 curry 版本如下所示:
Function.prototype.myCurry = function(){
var slice = [].slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to whatever `this` is when myCurry is called
return that.apply(this, args.concat(slice.apply(arguments)));
};
};

示例

(Here is a jsfiddle of the example)
var calculator = {
history: [],
multiply: function(num1, num2){
this.history = this.history.concat([num1 + " * " + num2]);
return num1 * num2;
},
back: function(){
return this.history.pop();
}
};

var myCalc = Object.create(calculator);
myCalc.multiply(2, 3); // returns 6
myCalc.back(); // returns "2 * 3"

如果我尝试这样做,道格拉斯·克罗克福德(Douglas Crockford)的方式:
myCalc.multiplyPi = myCalc.multiply.curry(Math.PI);
myCalc.multiplyPi(1); // TypeError: Cannot call method 'concat' of undefined

如果我按照自己的方式做:
myCalc.multiplyPi = myCalc.multiply.myCurry(Math.PI);
myCalc.multiplyPi(1); // returns 3.141592653589793
myCalc.back(); // returns "3.141592653589793 * 1"

但是,我觉得如果道格拉斯·克罗克福德(Douglas Crockford)做到了,他可能有充分的理由。我想念什么?

最佳答案

原因1-不容易提供一般解决方案
问题是您的解决方案不通用。如果调用者未将新功能分配给任何对象,也不将其分配给完全不同的对象,则multiplyPi函数将停止工作:

var multiplyPi = myCalc.multiply.myCurry(Math.PI);
multiplyPi(1); // TypeError: this.history.concat is not a function
因此,克罗克福德的解决方案和您的解决方案都无法保证该功能将被正确使用。这样一来,可以更容易地说 curry函数仅对“函数”起作用,而不对“方法”起作用,并将 this设置为 null可以强制这样做。我们可能只是推测,因为克罗克福德在书中没有提到。
原因2-正在解释功能
如果您问“为什么Crockford不使用这个或那个”,那么很可能的答案是:“就证明的事情而言,这并不重要。” Crockford在 函数一章中使用了此示例。子章节 curry的目的是:
  • 显示函数是可以创建和操作
  • 的对象
  • 演示闭包的另一种用法
  • 展示如何操纵参数。

  • 对于对象的一般用法进行微调并不是本章的目的。由于这甚至是不可能的,也是有问题的(请参见原因1),因此,在其中放置 null而不是在其中放置可能会引起疑问的东西(如果它确实有效)则更具教育意义(尽管对您的情况没有帮助:-) )。
    结论
    就是说,我认为您可以对自己的解决方案充满信心!在您的情况下,没有特别的理由遵循Crockfords的决定将 this重设为 null尽管您的解决方案仅在某些情况下有效,并且并非100%干净,但您必须知道。然后干净的“面向对象”解决方案将是要求对象在其内部创建其方法的克隆,以确保所得方法将保留在同一对象内。

    关于javascript - 为什么在Crockford的 `this`方法中使 `curry`无效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21002417/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com