解释这个 javascript 函数是如何工作的(在 Douglas Crockford 'How Javascript Works' 中找到)
explain how this javascript function works (found in Douglas Crockford 'How Javascript Works')
我想了解 make_binary_op()
函数的工作原理。它需要两个不同的参数
- 函数参数
addop
或mulop
- 一个数组参数(
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
是38
,my_little_stack
是[]
。
首先看一下算法的这个更简单的变体可能会有所帮助,其中没有像函数这样的魔法 returns 函数:
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
的用武之地:它创建(和 returns)一个专门定制的函数
给您想到的运算符(以及您作为参数传递的运算符)。如果将 mul
传递给 make_binary_op
,它将产生
实现上述 binary_op
函数的函数,专门针对 mul
量身定制:调用创建的函数时
它将调用 mul。
但请注意,动态创建的函数只需要一个参数(堆栈),因为另一个参数 (func
)
它已经知道了。它存在于返回该函数的 "closure" 中。
附录
对该模式的一个批评可能是以下观察:虽然使用点符号 (my_little_array.push
) 将项目添加到 my_little_array
,但必须将操作 mul/add 表示为函数调用,其中 my_little_array
作为参数传递。为什么它也不能与点符号一起使用,这样你就可以写 my_little_array.mul()
?
在 JS 语言的当前状态下,您可以使用扩展 Array
的 class(构造函数)来做到这一点,因此除了 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);
我想了解 make_binary_op()
函数的工作原理。它需要两个不同的参数
- 函数参数
addop
或mulop
- 一个数组参数(
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
是38
,my_little_stack
是[]
。
首先看一下算法的这个更简单的变体可能会有所帮助,其中没有像函数这样的魔法 returns 函数:
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
的用武之地:它创建(和 returns)一个专门定制的函数
给您想到的运算符(以及您作为参数传递的运算符)。如果将 mul
传递给 make_binary_op
,它将产生
实现上述 binary_op
函数的函数,专门针对 mul
量身定制:调用创建的函数时
它将调用 mul。
但请注意,动态创建的函数只需要一个参数(堆栈),因为另一个参数 (func
)
它已经知道了。它存在于返回该函数的 "closure" 中。
附录
对该模式的一个批评可能是以下观察:虽然使用点符号 (my_little_array.push
) 将项目添加到 my_little_array
,但必须将操作 mul/add 表示为函数调用,其中 my_little_array
作为参数传递。为什么它也不能与点符号一起使用,这样你就可以写 my_little_array.mul()
?
在 JS 语言的当前状态下,您可以使用扩展 Array
的 class(构造函数)来做到这一点,因此除了 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);