如果参数是绑定函数,则无法正确调用回调

Callback can not be invoked properly, if the parameter is a bound function

当函数需要回调作为参数时,我认为提供这样的绑定函数是有意义的

function invokeCb(cb){
    cb();
}
function test(x){
    console.log(x)
}
const para="xyz";

invokeCb(test.bind(null,para)) //(1)
invokeCb(()=>{test(para)}) //(2)

我看不出 (1) 有什么问题。然而,当谈到现实世界时,我遇到了一些意想不到的行为

这里有一个例子,在redux

store.subscribe(
    ()=>{(saveState.bind(null,store.getState()))()}
)

可以工作,而

store.subscribe(saveState.bind(null,store.getState()))

无法正确调用,即 store.getState() 似乎从未正确调用过

如果您需要更多上下文。这里:https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

也许我遗漏了两种形式之间的一些细微差别,谁能指出来?

区别是

  • 评估store.getState()的时间
  • return 值(通过使用不带 return 的大括号,您可以抑制它)

let data = "abc";
function invokeCb(cb){
    data = "xyz";
    console.log(cb());
}
function test(x){
    console.log(x);
    return x.toUpperCase();
}
invokeCb(test.bind(null, data)); // abc ABC
invokeCb(()=>{ test(data); }); // xyz undefined

经过一番调查,我找到了错误的真正原因!

这里是演示代码:

function invokeCb(cb){
    cb();
}
function test(x){
    console.log(x)
}

let counter=0;
function getData(){
  return ({counter:counter++})
}

const bindVersion=test.bind(null,getData())
const invokeVersion=()=>test(getData())

//first time
invokeCb(bindVersion) //{counter:0}
invokeCb(invokeVersion) //{counter:1}

//second time
invokeCb(test.bind(null,getData())) //{counter:0}
invokeCb(()=>{test(getData())}) //{counter:2}

//third time 
invokeCb(test.bind(null,getData())) //{counter:0}
invokeCb(()=>{test(getData())}) //{counter:3}

解释:

  • 使用bind版本时,参数固定。即一次 它是 bound 无法更改。
  • 另一方面,直接调用函数时, 参数是 dynamic ,即它总是可以得到更新的数据

结论:

从不 将动态参数绑定到函数

在我的例子中,case stateimmutable in reduxstore.getState() return 每次都是一个新的引用,使用 bind , 它总是得到第一个引用