为什么VueUse里的useIntersectionObserver函数的回调函数内部可以调用stop()方法?

新手上路,请多包涵

前端小菜鸟一只,今天遇到了个大难题。业务需求是利用VueUse的useIntersectionObserver函数实现图片资源懒加载,但我比较困惑的地方是useIntersectionObserver函数的第二个参数是一个回调函数,为什么可以在这个回调函数里调用 stop() 来停止监听呢?
我困惑的地方在于:赋值语句从右到左进行,先得到等号右边的结果再赋值给左边,调用stop()的时候等号左边还没有解构出 stop 这个方法呀。我在解构时尝试重新命名为 abc,回调函数内部调用 abc()程序仍正常运作,说明回调函数内调用的就是等号左边解构出的结果。虽然业务功能可以实现,但我不明白为什么可以这样写,希望好心人能指点一下

我可以理解下面这种,返回值赋值给stop后调用stop()函数。(图片来自VueUse官网)

阅读 2.5k
2 个回答

简单构建一下模拟的代码,就会发现,并不是所有情况下,都可以这样用。

比如下面的代码中,如果你把 setTimeout 换成同步的方式去调用(直接调用 cb),那就会出现两种情况。

  • 1、如果下面的解构获取是使用的 const,那就会报 “不能在变量初始化之前进行使用”
  • 2、如果下面的解构获取是使用的 var,那就会报 “abc 不是一个函数”

重要的点就在于,在执行这个 abc 时,这个变量是否已经拿到了值。

当使用同步执行的时候,实际上要走到后面的 return 才能把这里的 stop 给出去,这时候才有 stop 函数。

而当这个回调函数作为异步执行时,就不一样了,异步时,这里的函数已经执行完了,外面已经拿到返回值并解构赋值给了 abc。

在调用时,就会跟随其声明的域开始向上查找,找到对应的方法进行调用。

!(function () {
  function foo (el, cb) {
    setTimeout(cb) // 重要

    return {
      stop () {
        console.log('stop')
      },
    }
  }

  const { stop: abc } = foo('#app', () => {
    console.log(this)
    abc()
  })
})()

就是基础的变量作用域的问题,跟 IntersectionObserver 无关,跟 VueUse 也无关。

你在内部作用域里访问 abc(),会先从当前作用域开始找,没找到有这个变量,就会向上层作用域找,直到全局作用域为止。要是中间找到了,那就是它了;要是到最后也没找到,在严格模式下那就抛变量未定义的异常了。


const { foo: bar } = (function () {
   setTimeout(() => bar(), 1000);
   return {
      foo: () => console.log('bingo!')
   };
})();

如果你能明白这段代码里内部是怎么访问到 bar() 的,也就能明白前面是怎么访问到 abc() 的了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏