简体   繁体   English

解释这个 javascript 函数是如何工作的(在 Douglas Crockford 'How Javascript Works' 中找到)

[英]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它需要两个不同的参数

  1. a function parameter addop or mulop函数参数addopmulop
  2. an array parameter ( 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.answer38my_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需要是一个函数,可以mulopmul作用上述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.它存在于返回该函数的“闭包”中。

Addendum附录

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的类(构造函数)来做到这一点,这样除了pushpop之外,它还可以支持addmul

 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.

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