JavaScript'有Ruby等价物吗;s函数.prototype.bind
Is there a Ruby equivalent for JavaScript's Function.prototype.bind?
JavaScript快乐时光趣味乐园
// make a method
var happy = function(a, b, c) {
console.log(a, b, c);
};
// store method to variable
var b = happy;
// bind a context and some arguments
b.bind(happy, 1, 2, 3);
// call the method without additional arguments
b();
输出。耶!
1 2 3
Ruby
# make a method
def sad a, b, c
puts a, b, c
end
# store method to variable
b = method(:sad)
# i need some way to bind args now
# (this line is an example of what i need)
b.bind(1, 2, 3)
# call the method without passing additional args
b.call
所需输出
1, 2, 3
值得一提的是,我知道JavaScript可以通过传递给.bind
的第一个参数来更改绑定的上下文。在Ruby中,即使我不能改变上下文,我也会有99%的快乐。我主要需要简单地将参数绑定到方法。
问题
有没有一种方法可以将参数绑定到Ruby Method
的实例,这样当我在没有其他参数的情况下调用method.call
时,绑定的参数仍然会传递给该方法?
目标
这是一个常见的JavaScript习惯用法,我认为它在任何语言中都很有用。目标是将方法M
传递给接收器R
,其中R不需要(或具有)当R执行该方法时向M发送哪些(或多少)参数的内在知识。
JavaScript演示如何使用
/* this is our receiver "R" */
var idiot = function(fn) {
console.log("yes, master;", fn());
};
/* here's a couple method "M" examples */
var calculateSomethingDifficult = function(a, b) {
return "the sum is " + (a + b);
};
var applyJam = function() {
return "adding jam to " + this.name;
};
var Item = function Item(name) {
this.name = name;
};
/* here's how we might use it */
idiot(calculateSomethingDifficult.bind(null, 1, 1));
// => yes master; the sum is 2
idiot(applyJam.bind(new Item("toast")));
// => yes master; adding jam to toast
通常,在Ruby中不需要重新绑定方法。相反,您使用块:
# This is our receiver "R"
def idiot(&block)
puts("yes, master; #{block.call}")
end
# Here's a couple method "M" examples
def calculateSomethingDifficult(a, b)
return "the sum is #{a + b}"
end
def applyJam(object)
return "adding jam to " + object.name
end
class Item
attr_reader :name
def initialize(name)
@name = name
end
end
# Here's how we might use it
idiot do
calculateSomethingDifficult(1, 1)
end
#=> yes master; the sum is 2
# You *can* change calling context too (see instance_exec), but I'd
# discourage it. It's probably better to just pass the object as a
# parameter.
idiot do
applyJam(Item.new("toast"))
end
#=> yes master; adding jam to toast
如果你真的想像在JavaScript中那样"绑定"方法,这是绝对可能的:
class Method
def bind *args
Proc.new do |*more|
self.call *(args + more)
end
end
end
这应该使您的示例工作几乎正如您最初描述的那样:
# make a method
def sad a, b, c
puts a, b, c
end
# store method to variable
b = method(:sad)
# Get a "bound" version of the method
b = b.bind(1, 2, 3)
# call the method without passing additional args
b.call
如果您确实需要它,您可能可以定义Object#bindable_method
来返回一些BindableMethod
类,以执行您想要的操作。不过,在大多数情况下,我认为以上内容应该适用于您。
Proc#curry
类似于JavaScript中的bind
。
def happy(a, b, c, d = 100)
puts a, b, c, d
end
proc = method(:happy).to_proc.curry # proc is now a curried Proc
b = proc.call(1,2) # b is a curried Proc with 1 and 2 bound as the first arguments
b.call(3) # Call the proc, providing the 3rd argument
你不能完全复制你的示例代码,因为当用必要的参数调用curried proc时,它会返回proc的结果——换句话说,你不能绑定所有的参数,然后再调用proc——你必须至少保留一个参数未绑定。
这并不一定比Ajedi32提供的代码更好,但我认为值得一提的是,因为它是Ruby内置的。
请参阅此处的文档:http://ruby-doc.org/core-2.2.0/Proc.html#method-i-curry
- 直接在函数声明上使用function.prototype.bind
- 如何迭代Array.prototype函数
- 如何通过 Function.prototype.apply() 更改调用函数的参数
- 如何将参数应用于String.prototype.format函数
- "可变变量可从闭包“”访问;在传递给Array.prototype.every的函数中
- JavaScript继承构造函数.prototype
- Prototype.js 1.7:将collect与显式函数一起使用会返回与内联函数不同的结果,原因是什么
- JavaScript 的 Array 调用和函数在 Prototype 中失败
- node.js 使用 function.prototype.apply 执行的泛型函数
- 在节点 0.11 中使用 ES6 箭头函数,w/ foo.prototype
- Object.Prototype 方法和 IIFE(立即调用的函数表达式)中的“use strict”
- 为什么更改函数的 .prototype 会影响已使用该构造函数创建的对象的“实例”
- 模拟“类”时,为什么要在 .prototype 属性中设置方法,而不是在构造函数本身中设置方法
- HTML5 Canvas:通过 Image.prototype 创建一个 Image.onload() 函数
- 可从作为参数传递给 Event.observe() (prototype.js) 的函数中访问的变量.为什么
- 仅返回数组数据,而不返回使用 Array.prototype 的函数本身
- 调用带有挂起的 Parens 与 Function.prototype.call 的函数表达式
- JavaScript'有Ruby等价物吗;s函数.prototype.bind
- Javascript-Prototype没有读取构造函数变量
- 如何将附加到Object的函数移动到Object.prototype