简体   繁体   English

Javascript:柯里化函数参数而不设置其函数上下文

[英]Javascript: currying function parameter without setting its function context

My understanding is that as per spec, the parameters set in bind() are final and cannot be overridden.我的理解是,根据规范,在bind()中设置的参数是最终的,不能被覆盖。

I would like to know if there is any way of achieving something like this, which fails to give me the results that I want:我想知道是否有任何方法可以实现这样的目标,但无法给我想要的结果:

const Student = {
    name: "",
    times: function(i, j) {
        return `I am: ${this.name} & think answer is: ${i*j}`;
    }
};

const student1 = {
    name: "student1"
}
const student2 = {
    name: "student2"
}

const askThemTimesBy10 = Student.times.bind(null, 10);

console.log(askThemTimesBy10.bind(student1)(5));
console.log(askThemTimesBy10.bind(student2)(5));

obviously this fails since the function-context is hard-coded at the time of currying.显然这失败了,因为函数上下文在柯里化时是硬编码的。

Now I can clearly do hacks like:现在我可以清楚地进行黑客攻击:

askThemX10 = function(){
    return Student.times.bind(this, 10);
}

askThemXTen = function(i){
    return Student.times.call(this, 10, i);
}

and then use them like:然后像这样使用它们:

console.log(askThemX10.bind(student1)()(5));
console.log(askThemXTen.bind(student1)(5));

or I can define the curried function inside Student etc. etc. but I'd like to know if there is a nicer way of doing this.或者我可以在Student等中定义柯里化函数,但我想知道是否有更好的方法来做到这一点。

Speaking of modern JS.说到现代JS。 If you can transpile your code and do not afraid to use experimental syntax, you may achieve what you want using partial application syntax.如果您可以转译您的代码并且不害怕使用实验性语法,那么您可以使用部分应用程序语法实现您想要的。 Not recommended for production though :)不过不推荐用于生产:)

Demo 演示

const Student = {
    name: "",
    times(i, j) {
        return `I am: ${this.name} & think answer is: ${i*j}`;
    }
};

const student1 = {
    name: "student1"
}
const student2 = {
    name: "student2"
}

const askThemTimesBy10 = Student.times.call(?, 10, ?); // <--- pew pew 

console.log(askThemTimesBy10(student1, 5));
console.log(askThemTimesBy10(student2, 6));

Any time you're thinking of using bind , you're probably doing something wrong.任何时候您考虑使用bind ,您都可能做错了什么。 In this case, use a normal class:在这种情况下,使用普通类:

class Student {
  constructor(name) {
    this.name = name;
  }

  multiply(i, j) {
    return `I am: ${this.name} & think answer is: ${i*j}`;
  }
}

and then create student instances:然后创建学生实例:

const students = [
  new Student("alice"),
  new Student("bob"),
  ...
]

And then make that "... times 10" function either a global:然后使“...乘以 10”函数成为一个全局函数:

function askStudentX10(student, i) {
  return student.multiply(i, 10);
}

Or if you want to keep things nice and namespaced, make it a static function on the Student class:或者,如果您想保持良好的命名空间,请将其设为Student类上的静态函数:

class Student {
  static askStudentX10(student, i) {
    return student.multiply(i, 10);
  }

  constructor(name) {
    ...
  }

  ...
}

Nice and explicit code, no bind required, no potential bind-related bugs.漂亮而明确的代码,不需要bind ,没有潜在的与绑定相关的错误。 Just plain, obvious, code.只是简单明了的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM