在克罗克福德的“咖喱”方法中,“this”无效吗? [英] Is there a reason why `this` is nullified in Crockford's `curry` method?

查看:92
本文介绍了在克罗克福德的“咖喱”方法中,“this”无效吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Douglas Crockford的书Javascript:The Good Parts中,他提供了一个 curry 方法的代码,该方法接受一个函数和参数,并返回已添加参数的函数(显然,这不是真正的咖喱的含义,而是部分申请。这是我修改过的代码,以便在没有其他一些自定义代码的情况下工作:

In Douglas Crockford's book "Javascript: The Good Parts" he provides code for a curry method which takes a function and arguments and returns that function with the arguments already added (apparently, this is not really what "curry" means, but is an example of "partial application"). Here's the code, which I have modified so that it works without some other custom code he made:

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)));
  };
};

因此,如果您有添加功能:

So if you have an add function:

var add = function(num1, num2) {
  return num1 + num2;
};

add(2, 4);          // returns 6

你可以创建一个已经有一个参数的新函数:

You can make a new function that already has one argument:

var add1 = add.curry(1);

add1(2);           // returns 3

工作正常。但我想知道的是为什么他将这个设置为 null ?预期的行为是不是curried方法与原始方法相同,包括相同的

That works fine. But what I want to know is why does he set this to null? Wouldn't the expected behavior be that the curried method is the same as the original, including the same this?

我的咖喱版本看起来像这样:

My version of curry would look like this:

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)));
  };
};

示例

(以下是该示例的jsfiddle)

(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"

如果我尝试做道格拉斯·克罗克福德的方式:

If I try to do it Douglas Crockford's way:

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按照他的方式行事,他可能有充分的理由。我缺少什么?

However, I feel like if Douglas Crockford did it his way, he probably has a good reason. What am I missing?

推荐答案

原因1 - 不容易提供一般解决方案



问题是你的解决方案并不普遍。如果调用者没有将新函数分配给任何对象,或者将其分配给完全不同的对象,则 multiplyPi 函数将停止工作:

var multiplyPi = myCalc.multiply.myCurry(Math.PI);
multiplyPi(1);  // TypeError: this.history.concat is not a function

所以,Crockford和你的解决方案都不能确保该功能将正确使用。然后可能更容易说 curry 函数仅适用于函数,而不适用于方法,并设置 null 强制执行此操作。我们可能只会猜测,因为Crockford在书中没有提到。

So, neither Crockford's nor your solution can assure that the function will be used correctly. Then it may be easier to say that the curry function works only on "functions", not "methods", and set this to null to force that. We might only speculate though, since Crockford doesn't mention that in the book.

如果你问为什么Crockford没有使用这个或那个 - 很可能的答案是:对于所展示的问题,它并不重要。 Crockford使用这个例子在功能一章中。分章咖喱的目的是:

If you asking "why Crockford didn't use this or that" - the very likely answer is: "It wasn't important in regard to the demonstrated matter." Crockford uses this example in the chapter Functions. The purpose of the sub-chapter curry was:


  • 以显示函数是您可以创建和操作的对象

  • 以演示闭包的另一种用法

  • 以显示如何操纵参数。

将此文件用于对象的一般用法并不是本章的目的。因为它是有问题的,甚至不可能(参见原因1),如果把 c> null 放在那里,那就更有教育意义了提出问题,如果它确实有效(虽然在你的情况下没有帮助: - ))。

Finetuning this for a general usage with objects was not purpose of this chapter. As it is problematic if not even impossible (see Reason 1), it was more educational to put there just null instead if putting there something which could raise questions if it actually works or not (didn't help in your case though :-)).

那就是说,我认为你对你的解决方案充满信心!在你的情况下没有特别的理由跟随Crockfords决定将重置改为 null 您必须意识到,您的解决方案仅在某些情况下有效,并且不是100%干净。然后清理面向对象的解决方案将要求对象在其自身内部创建其方法的克隆,以确保结果方法将保留在同一对象中。

That said, I think you can be perfectly confident in your solution! There's no particular reason in your case to follow Crockfords' decision to reset this to null. You must be aware though that your solution only works under certain circumstances, and is not 100% clean. Then clean "object oriented" solution would be to ask the object to create a clone of its method inside itself, to ensure that the resultant method will stay within the same object.

这篇关于在克罗克福德的“咖喱”方法中,“this”无效吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆