【问题标题】:Javascript: currying function parameter without setting its function contextJavascript:柯里化函数参数而不设置其函数上下文
【发布时间】:2021-01-15 13:30:42
【问题描述】:

我的理解是,按照规范,bind() 中设置的参数是最终的,不能被覆盖。

我想知道是否有任何方法可以实现这样的目标,但无法给我想要的结果:

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

显然这会失败,因为函数上下文在柯里化时是硬编码的。

现在我可以清楚地做以下黑客攻击:

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

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

然后像这样使用它们:

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

或者我可以在 Student 等内部定义柯里化函数,但我想知道是否有更好的方法来做到这一点。

【问题讨论】:

    标签: javascript function-binding


    【解决方案1】:

    说到现代 JS。如果您可以转译您的代码并且不害怕使用实验性语法,那么您可以使用部分应用程序语法来实现您想要的。虽然不推荐用于生产:)

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

    【讨论】:

    【解决方案2】:

    任何时候你想使用bind,你可能做错了什么。在这种情况下,使用普通类:

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

    然后创建学生实例:

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

    然后将“...乘以 10”作为全局函数:

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

    或者,如果您想保持良好的命名空间,请将其设为 Student 类的静态函数:

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

    漂亮而明确的代码,不需要bind,没有潜在的绑定相关错误。简单明了的代码。

    【讨论】:

    • 我会说任何时候使用一个类你做错了什么。 ?
    • 很酷,但也很废话。 bindapply 是 JS 比今天低得多的遗留函数(它们仍然存在,因为我们有意识地选择永远不弃用 JS API,这就是为什么我们仍然有一些疯狂的东西,比如document.write),而现代类语法就是这样。使用现代 JS,而不是 20 年前的 JS。
    • 哈哈,我实际上来自功能 BE 背景,所以我非常喜欢我的绑定和咖喱等等。 :) 有趣的是看到关于这个主题的不同意见。
    • 虽然我是在开玩笑,但工具只是工具,bind还是有用的。此外,“使用现代 JS”的说法也很糟糕。
    • 非常有用,但在极少数情况下,这就是为什么如果你在普通的现代 JS 中使用bind,它几乎是给定的不应该使用bind。就像在这种情况下。如果您正在用 JS 编写转译器,那就不同了,但是除了“这是编写 JS 代码的古老方式,您真的应该学习和编写现代 JS”之外,这个问题中的代码并没有什么特别之处。
    猜你喜欢
    • 2016-01-01
    • 2021-02-07
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多