[英]explain how this javascript function works (found in Douglas Crockford 'How Javascript Works')
I would like to understand how the make_binary_op()
function works.我想了解
make_binary_op()
函数是如何工作的。 It takes two different parameters它需要两个不同的参数
addop
or mulop
addop
或mulop
my_little_stack
/ my_little_array
)my_little_stack
/ my_little_array
) I've used the firefox debugger to watch the execution but still do not understand how the make_binary_op()
function works.我已经使用 firefox 调试器来观察执行,但仍然不明白
make_binary_op()
函数是如何工作的。 I get all the pops and pushes, etc.我得到了所有的流行音乐和推动等。
function make_binary_op(func) { return function(my_little_array) { let wunth = my_little_array.pop(); let zeroth = my_little_array.pop(); my_little_array.push(func(zeroth, wunth)); return my_little_array; }; }; let addop = make_binary_op(function(zeroth, wunth) { return zeroth + wunth; }); let mulop = make_binary_op(function(zeroth, wunth) { return zeroth * wunth; }); let my_little_stack = []; my_little_stack.push(3); my_little_stack.push(5); my_little_stack.push(7); mulop(my_little_stack); // my_little_stack is [3, 35] addop(my_little_stack); // my_little_stack is [38] let answer = my_little_stack.pop(); // my_little_stack is [] console.log(answer);
The code works as specified.代码按规定工作。 The value
answer
is 38
and my_little_stack
is []
at the end.值
answer
是38
, my_little_stack
是[]
。
It may help to first look at this simpler variant of the algorithm, where there is no such magic as a function that returns a function:首先看看算法的这个更简单的变体可能会有所帮助,其中没有函数返回函数这样的魔法:
function binary_op(func, my_little_array) { // Two arguments let wunth = my_little_array.pop(); let zeroth = my_little_array.pop(); my_little_array.push(func(zeroth, wunth)); return my_little_array; }; let add = function(zeroth, wunth) { // No call to make_binary_op return zeroth + wunth; }; let mul = function(zeroth, wunth) { return zeroth * wunth; }; let my_little_stack = []; my_little_stack.push(3); my_little_stack.push(5); my_little_stack.push(7); binary_op(mul, my_little_stack); // we need to pass two arguments binary_op(add, my_little_stack); let answer = my_little_stack.pop(); console.log(answer);
I think you will be able to understand how this works: the new binary_op
function takes both a callback function (that performs a operation on two arguments) and a stack.我想您将能够理解这是如何工作的:新的
binary_op
函数采用回调函数(对两个参数执行操作)和堆栈。 It then pops two values from the stack, passes them to the callback function, gets the result from it, and pushes that result (possibly a sum or a product) on the stack.然后它从堆栈中弹出两个值,将它们传递给回调函数,从中获取结果,并将该结果(可能是总和或乘积)压入堆栈。 The stack has thus reduced in size by 1: two operands were replaced by the
func
's result on them.因此堆栈的大小减少了 1:两个操作数被
func
对它们的结果替换。
Assuming you follow how this works, now see how we could make it that instead of this:假设您遵循它的工作原理,现在看看我们如何做到这一点而不是这样:
binary_op(mul, my_little_stack);
... we could write this: ...我们可以这样写:
mulop(my_litte_stack);
mulop
would need to be a function that can combine what mul
does and what the above binary_op
does, in one go. mulop
需要是一个函数,可以mulop
将mul
作用和上述binary_op
作用结合起来。
That is where the function make_binary_op
comes in: it creates (and returns) a function that is specifically tailored to the operator you have in mind (and which you pass as argument).这就是函数
make_binary_op
用武之地:它创建(并返回)一个专门为您想到的运算符(并且作为参数传递)量身定制的函数。 If you pass mul
to make_binary_op
, it will produce a function that implements the above binary_op
function, specifically tailored to mul
: when that created function is invoked it will call mul.如果您将
mul
传递给make_binary_op
,它将生成一个实现上述binary_op
函数的函数,专门为mul
量身定制:当该创建的函数被调用时,它将调用mul。 But note how that dynamically created function only needs one argument (the stack), because the other argument ( func
) is already known to it.但请注意,动态创建的函数如何只需要一个参数(堆栈),因为它已经知道另一个参数 (
func
)。 It is present in the "closure" in which that function was returned.它存在于返回该函数的“闭包”中。
One critique on this pattern could be the following observation: while items are added to my_little_array
using dot-notation ( my_little_array.push
), the operations mul/add have to be expressed like function calls where my_little_array
is passed as argument.对这种模式的一种批评可能是以下观察:虽然使用点符号 (
my_little_array.push
) 将项目添加到my_little_array
,但操作 mul/add 必须表达为函数调用,其中my_little_array
作为参数传递。 Why could it not be made to work with the dot-notation also, so that you could write my_little_array.mul()
?为什么不能让它也与点符号一起使用,以便您可以编写
my_little_array.mul()
?
In the current state of the JS language you could do that with a class (constructor) that extends Array
, so that besides push
and pop
it can also support add
and mul
:在 JS 语言的当前状态下,您可以使用扩展
Array
的类(构造函数)来做到这一点,这样除了push
和pop
之外,它还可以支持add
和mul
:
class PolishCalc extends Array { static registerBinaryOp(func) { this.prototype[func.name] = function () { let wunth = this.pop(); let zeroth = this.pop(); this.push(func(zeroth, wunth)); return this; } } } // Extend the prototype with add and mul methods: PolishCalc.registerBinaryOp(function add(zeroth, wunth) { return zeroth + wunth; }); PolishCalc.registerBinaryOp(function mul(zeroth, wunth) { return zeroth * wunth; }); let polishCalc = new PolishCalc; polishCalc.push(3, 5, 7); let answer = polishCalc.mul().add().pop(); // the method calls can be chained... console.log(answer);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.