这是一个有效的递归函数吗?
Is this a valid recursive function?
我在库中发现了一个递归表达式,非常困惑。
代码在这里:
https://github.com/tappleby/redux-batched-subscribe/blob/master/src/index.js#L22
export function batchedSubscribe(batch) {
if (typeof batch !== 'function') {
throw new Error('Expected batch to be a function.');
}
const listeners = [];
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
function notifyListenersBatched() {
batch(() => listeners.slice().forEach(listener => listener()));
}
return next => (...args) => {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
};
}
具体这部分:
return next => (...args) => {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
};
这怎么不是无限递归?
我们都对此感到困惑的原因是箭头函数,如果写成单个语句,隐式调用 return
.
例如一个像这样的简单函数:
const add = (a, b) => a + b;
相当于
var add = function(a, b) {
return a + b;
}
知道这一点我们可以去掉糖并转换箭头函数:
return next => function(...args) { // body }
真的是这里发生的事情,如果我们更进一步,我们会得到:
return function(next) {
return function(...args) {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
}
}
包含代码的两个函数实际上都是无名的。 next
是一个函数,但不是要返回的函数之一。它作为变量传递到第一个返回的函数中。
这里没有递归,而是有很多函数组合,这是像 redux 这样从函数式编程中汲取了很多东西的库所期望的。
How is this not infinite recursion?
这里绝对没有递归。语法 next => (...args) => …
不会转换为
return function next(...args) {
const store = next(...args);
…
而是
return function(next) {
return function(...args) {
const store = next(...args);
…
所以除非那个函数的调用者做了一些奇怪的事情,比如 var f = batchedSubscribe(…); f(f)(f)…;
,它不会调用自己。
我在库中发现了一个递归表达式,非常困惑。 代码在这里: https://github.com/tappleby/redux-batched-subscribe/blob/master/src/index.js#L22
export function batchedSubscribe(batch) {
if (typeof batch !== 'function') {
throw new Error('Expected batch to be a function.');
}
const listeners = [];
function subscribe(listener) {
listeners.push(listener);
return function unsubscribe() {
const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
}
function notifyListenersBatched() {
batch(() => listeners.slice().forEach(listener => listener()));
}
return next => (...args) => {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
};
}
具体这部分:
return next => (...args) => {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
};
这怎么不是无限递归?
我们都对此感到困惑的原因是箭头函数,如果写成单个语句,隐式调用 return
.
例如一个像这样的简单函数:
const add = (a, b) => a + b;
相当于
var add = function(a, b) {
return a + b;
}
知道这一点我们可以去掉糖并转换箭头函数:
return next => function(...args) { // body }
真的是这里发生的事情,如果我们更进一步,我们会得到:
return function(next) {
return function(...args) {
const store = next(...args);
const subscribeImmediate = store.subscribe;
function dispatch(...dispatchArgs) {
const res = store.dispatch(...dispatchArgs);
notifyListenersBatched();
return res;
}
return {
...store,
dispatch,
subscribe,
subscribeImmediate
};
}
}
包含代码的两个函数实际上都是无名的。 next
是一个函数,但不是要返回的函数之一。它作为变量传递到第一个返回的函数中。
这里没有递归,而是有很多函数组合,这是像 redux 这样从函数式编程中汲取了很多东西的库所期望的。
How is this not infinite recursion?
这里绝对没有递归。语法 next => (...args) => …
不会转换为
return function next(...args) {
const store = next(...args);
…
而是
return function(next) {
return function(...args) {
const store = next(...args);
…
所以除非那个函数的调用者做了一些奇怪的事情,比如 var f = batchedSubscribe(…); f(f)(f)…;
,它不会调用自己。