【问题标题】:Make Variables Behave Like Global Variables使变量表现得像全局变量
【发布时间】:2020-01-12 01:47:18
【问题描述】:

我想知道是否可以将一组变量从全局范围移动到嵌套范围。在以下情况下是否可以使用闭包来实现这一点?应该是吧?

let 变量可能不应该在renderInfo() 范围内,因为renderInfo() 在加载时被多次调用,这是无法避免的。每次调用renderInfo() 时,render() 都会渲染多个元素,所有元素都添加了一个click 事件监听器。因此,变量也不能以代码当前的结构方式出现。

我尝试将clickToSort() 变成闭包,但每次都会遇到问题。我不知道如何允许所有带有click 事件侦听器的元素共享 访问let 变量。

let
  sortNameAscending =
  sortFreeAscending =
  sortSizeAscending = true

// Called multiple times at load.
function renderInfo(a,b,c,d) {

  // Renders multiple elements, and adds an event listener to them, each call.
  function render(){
    // The event listener is added to multiple elements
    // that are also rendered herein.
    ele.addEventListener('click', (e)=>clickToSort(e, cls, 'aString'))
  }

  // This function is added to the click event of tons of elements.
  function clickToSort(e, cls, dataProperty) {

    // How do I move the let variables from the global
    // scope to here, so that they behave as if they
    // are in the global scope? Is it possible with a
    // closure?
    // let
    //  sortNameAscending =
    //  sortFreeAscending =
    //  sortSizeAscending = true

    // I imagine the following code should be wrapped in
    // its own scope, but the scope must have access to
    // the arguments of clickToSort(), and the let variables
    // which should behave as if they are global.
    if (cls.includes('whatever')) {
      sortNameAscending = !sortNameAscending
    } else if (cls.includes('whatever2')) {
      sortFreeAscending = !sortFreeAscending
    } else {
      sortSizeAscending = !sortSizeAscending
    }
  }
}

我已经尝试了以下方法,但它不想工作。

let
  sortNameAscending =
  sortFreeAscending =
  sortSizeAscending = true

function renderInfo(a,b,c,d) {

  function render(){
    // The event listener is added to multiple elements
    // that are also rendered herein.
    ele.addEventListener('click', (e)=>clickToSort(e, cls, 'aString'))
  }

  function clickToSort(e, cls, dataProperty) {

    let
      sortNameAscending =
      sortFreeAscending =
      sortSizeAscending = true

    ;(function whatevs(){
      if (cls.includes('whatever')) {
        sortNameAscending = !sortNameAscending
      } else if (cls.includes('whatever2')) {
        sortFreeAscending = !sortFreeAscending
      } else {
        sortSizeAscending = !sortSizeAscending
      }
    )()
  }
}

我不确定为什么,尽管这可能与我将 clickToSort() 函数绑定到元素而不是返回函数这一事实有关?

【问题讨论】:

    标签: javascript variables scope closures global-variables


    【解决方案1】:

    您可以将整个函数包装成immediately invoked function expression。这将确保关闭您的三个变量,同时让您的调用共享相同的数据。

    在您的匿名函数中,您可以声明包含的变量并返回最初称为renderInfo 的函数。当你的代码被执行时,这三个变量将被声明并保存在匿名函数的作用域内,然后renderInfo 将被赋予一个函数的值。

    // Called multiple times at load.
    const renderInfo = (function() {
    
      let
        sortNameAscending =
        sortFreeAscending =
        sortSizeAscending = true
    
      return function(a, b, c, d) {
    
        // Renders multiple elements, and adds an event listener to them, each call.
        function render() {
          // The event listener is added to multiple elements
          // that are also rendered herein.
          ele.addEventListener('click', (e) => clickToSort(e, cls, 'aString'))
        }
    
        // This function is added to the click event of tons of elements.
        function clickToSort(e, cls, dataProperty) {
    
          if (cls.includes('whatever')) {
            sortNameAscending = !sortNameAscending
          } else if (cls.includes('whatever2')) {
            sortFreeAscending = !sortFreeAscending
          } else {
            sortSizeAscending = !sortSizeAscending
          }
        }
    
      }
    
    })()

    使用 IIFE(立即调用函数表达式)创建闭包的简单示例如下:

    const add = (function() {
      let sum = 0;
      return function() {
        return ++sum;
      }
    })()
    
    console.log(add())
    console.log(add())
    console.log(add())
    console.log(add())

    【讨论】:

    • 这不会遇到问题吗?就像每次在加载时调用renderInfo() 一样,let 变量将被重置为true,如果它们已经被更改过,对吧?还是我错了,关闭时是一个巨大的n00b?是不是不能把clickToSort变成闭包?
    • @oldboy 闭包内部(即函数返回之前的匿名函数内部)只执行一次。调用renderInfo n 次不会重置这三个变量。
    • 哇,真的吗??如此反直觉。我在哪里可以阅读更多相关信息?
    • 另外,难道不能把clickToSort变成闭包吗?
    • 当你仔细想想,这并不违反直觉……但可以令人惊讶!我在回答中添加了另一个示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2019-07-24
    • 2017-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多