【问题标题】:Reference to Object Within Closure引用闭包内的对象
【发布时间】:2017-11-02 13:25:13
【问题描述】:

我正在使用 React,对于有 React 经验的人来说,下面的代码会更容易理解,但是,这是一个 javascript 问题。组件(对象)是使用新的 es2015 类语法创建的。

在下面的代码中,一旦对象被渲染(在 DOM 中),我就会绑定 onmousemove 处理程序(React 特定信息:在方法 componentDidMount 中)。

classSVGParent extends Component{
     ...

     componentDidMount(){
        ....
        this.mainSVGEle.onmousemove = this.throttledMouseMoveHandler();
        // one specific detail for non-react devs : the method above 
        // 'componentDidMount' is called only once the component renders.
     }

     // the purpose of below func is to localise & create closure for the
     // actual handler function (which is returned by this method to the
     // 'onmousemove' event listener we appended above).
     throttledMouseMoveHandler(){
        let { svgState,
              ... } = this.props;
        return( function( e ){
          // when this func actually runs, it always returns `false`
          // even when the actual svgState.mousemoveState is `true`
          console.log( svgState.mousemoveState );
        });
        ...
     }

根据上面的代码,在我的代码中,我在组件渲染时立即调用函数throttledMouseMoveHandler。这个函数的目的是创建一个闭包,其中包含每次后续mousemove 调用所需的信息。

我的预期:我希望 svgState(我在 'throttledMouseMoveHandler' 中本地化)将 reference 保存到 prop 'svgState',并且当调用 mousemove 时,svgState.mousemoveState 的 prop 值将从保存值的原始 obj。

我所经历的: svgState.mousemoveState 永远不会改变。即使我可以看到原始对象 svgState.mousemoveState 是 true,我仍然得到 false 作为返回值。这让我很惊讶。

抱歉,我的问题很开放,这是什么原因。当然,状态对象的副本没有存储在闭包中,连接是live,对吗?

我在下面做了一个简单的例子来说明我的理解。

var aobj = { a : 1 }

var bobj = function(){
 var aref = aobj;
 return( function(){
  console.log( "aref is...", aref.a);
 });
}

var bfunc = bobj();
bfunc(); // returns `aref is... 1`, which is expected

aobj.a = 2

bfunc() // returns `aref is... 2`, which is also expected
        // so clearly the reference to external obj is live 

【问题讨论】:

  • 主要问题是事件处理程序中的this 不会是对您的对象的引用;它将是对 DOM 元素的引用。设置事件处理程序时可以使用.bind()。
  • @Pointy this 仅用于throttledMouseMoveHandler。这只会创建实际的事件处理程序return(function( e ){ ... }),它不使用this
  • this 会不会更像是您声明的示例代码?
  • Kayote,这不取决于道具本身会发生什么吗?例如,我提供的示例代码更改了道具,这意味着只保留旧对象,我更新了jsfiddle 以反映这一点。你有没有机会告诉我们更多关于你的道具背后的状态管理?如果调用 shouldComponentUpdate 或类似的方法?
  • 是的,当我提到示例代码与实时代码不同时,这就是我的意思:) 但是,您可以将我的示例代码添加到您的问题中,但这会否定实时参考事实:)

标签: javascript reactjs scope closures


【解决方案1】:

我预计 svgState 会引用 prop 'svgState'

没有。 svgState 保存this.props.svgState 在调用throttledMouseMoveHandler 时的值。 (当然,该值是一个引用其.mousemoveState 属性的对象)

...当onmousemove 被调用时,svgState.mousemoveState 的 prop 值将从保存值的原始 obj 中检索。

是的。它将获取对象的.mousemoveState 属性的当前值。

但是,如果您说记录 this.props.svgState.mousemoveState 产生 true 而闭包产生 false,则似乎有人确实将 .props 或 .svgState 属性更改为与闭包记忆不同的对象。

【讨论】:

  • No. The svgState holds the value that this.props.svgState had at the time of calling throttledMouseMoveHandler 澄清一下,您是说在闭包内let { svgState } = this.props 持有this.props.svgState 的值,而不是存储对this.props.svgState 的引用。我就是这么读的,我认为这是不正确的。如果我错了,请澄清。
  • @Kayote 它确实保存了该属性的值,但它不保存对该属性的实时引用。
  • 这不是部分取决于道具的管理方式吗?我的意思是,只要 props 和对象本身保持不变,它仍然会引用相同的引用,一旦它没有,它就有点泄漏? :)
  • @Icepickle 是的,这正是我的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
相关资源
最近更新 更多