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

问题描述 投票:1回答:1

我想了解make_binary_op()功能是如何工作的。它需要两个不同的参数

  1. 函数参数addopmulop
  2. 数组参数(my_little_stack / my_little_array

我已经使用firefox调试器来观察执行但仍然不明白make_binary_op()函数是如何工作的。我得到所有的流行音乐和推动等。

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

代码按指定的方式工作。 answer的值是38my_little_stack最后是[]

javascript function stack binary-operators
1个回答
1
投票

首先看一下算法的这个简单变​​体可能会有所帮助,其中没有像返回函数的函数那样神奇:

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

我想你将能够理解它是如何工作的:新的binary_op函数同时接受一个回调函数(对两个参数执行操作)和一个堆栈。然后它从堆栈中弹出两个值,将它们传递给回调函数,从中获取结果,并将该结果(可能是总和或产品)推送到堆栈上。因此,堆栈的大小减小了1:两个操作数被func的结果所取代。

假设您遵循其工作方式,现在看看我们如何能够实现这一目标而不是:

binary_op(mul, my_little_stack);

......我们可以这样写:

mulop(my_litte_stack);

mulop将需要一个功能,可以结合mul做的和上面的binary_op做的一气呵成。

这就是函数make_binary_op的用武之地:它创建(并返回)一个专门为您想到的运算符量身定制的函数(以及作为参数传递的函数)。如果你将mul传递给make_binary_op,它将生成一个实现上述binary_op函数的函数,专门针对mul:当调用创建的函数时,它将调用mul。但请注意,动态创建的函数如何只需要一个参数(堆栈),因为另一个参数(func)已经为它所知。它出现在返回该函数的“闭包”中。

附录

对这种模式的一个批评可能是以下观察:虽然使用点符号(my_little_array)将项添加到my_little_array.push,但是mul / add操作必须像函数调用一样表示,其中my_little_array作为参数传递。为什么不能使用点符号,所以你可以写my_little_array.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);
© www.soinside.com 2019 - 2024. All rights reserved.