回调不能正确调用,如果该参数是一个绑定功能

问题描述:

当一个函数需要一个回调的PARAM,我想这是有意义的提供这样回调不能正确调用,如果该参数是一个绑定功能

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,你压抑它)

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 
+0

我相信你知道答案,你可以设计一个具体的例子来恶魔培养差异,我真的无法得到你的观点 – Guigui

+0

你是正确的,问题在于'商店。getState()'读取陈旧的数据 – Guigui

+0

@Guigui我添加了一个例子(但没有尝试) – Bergi

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

下面是代码以证明:

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它不能被改变。另一方面,当函数被直接调用时, 参数是动态,即,它可以随时得到更新的数据

结论:

NEVER绑定动态参数的函数

对我来说,情况state是每次immutablereduxstore.getState()return一个新的参考,使用bind,它总是得到第一个参考