簡體   English   中英

如何在 JS function 中創建變量閉包?

[英]How to create closure over variables in a JS function?

假設網頁上可以存在多個滑塊,並且它們每個都需要自己的 state 用戶交互,例如觸摸啟動 X 位置和 boolean 當前是否正在處理滑動。

我正在嘗試重用一段處理滑動和鼠標拖動事件的代碼,但每個 slider 都應該有自己的 initalX 和 isInSwipe 值:

   function slideInteractions(selector, callback) {
        return function() {
            let initialX = 0;
            let isInSwipe = false;
            document.querySelector(selector).addEventListener('mousedown', (ev) => {
                startInteraction(ev);
                ev.preventDefault();
            });
            document.querySelector(selector).addEventListener('touchstart', startInteraction);
            document.addEventListener('mouseup', (ev) => {
                endInteraction(ev, callback);
            });
            document.addEventListener('touchend', (ev) => {
                endInteraction(ev, callback);
            });
        };
    }

對於頁面上的每個 slider,我會像這樣使用它,傳遞幻燈片容器和回調以調用已接受的交互:

slideInteractions('.project-slides', moveProject)();

我認為由於 initialX 和 isInSwipe 是在返回的 function 中定義的,那么這將在它們之上創建一個閉包,以便每次調用 slideInteractions() 都會創建這些變量的自己的副本,但是一旦 function,它們似乎是 scope 中的 go回報。

有沒有辦法解決這個問題,讓變量在閉包中正常運行?

編輯

這些變量在startInteraction()endInteraction()中使用,但這些函數根本看不到這些變量:它們在那些函數中未聲明,這是我感到困惑的地方,因為我假設這些函數可以訪問“已關閉” “變量沒有?

要在函數之間共享變量,它們必須位於同一塊 scope 中。這意味着您必須在定義變量的同一塊內定義 startInteraction 和 endInteraction 函數。

function slideInteractions(selector, callback) {
    return function() {

        let initialX = 0;
        let isInSwipe = false;

        function startInteraction(e,) {
          initialX = e.clientX;
        }
        function endInteraction(e, callback) { 
           console.log(initialX, e.clientX);
           if (callback) callback(initialX);
        }

        document.querySelector(selector).addEventListener('mousedown', (ev) => {
            startInteraction(ev);
            ev.preventDefault();
        });
        document.querySelector(selector).addEventListener('touchstart', startInteraction);
        document.addEventListener('mouseup', (ev) => {
            endInteraction(ev, callback);
        });
        document.addEventListener('touchend', (ev) => {
            endInteraction(ev, callback);
        });
    };
}

另一種選擇是繞過 object。函數可以在塊 scope 之外。

function startInteraction(e, data) {
  data.initialX = e.clientX;
}
function endInteraction(e, data, callback) { 
   console.log(data.initialX, e.clientX);
   if (callback) callback(data);
}

function slideInteractions(selector, callback) {
    return function() {

        const data = {
          initialX: 0,
          isInSwipe: false,
        };

        document.querySelector(selector).addEventListener('mousedown', (ev) => {
            startInteraction(ev, data);
            ev.preventDefault();
        });
        document.querySelector(selector).addEventListener('touchstart', startInteraction);
        document.addEventListener('mouseup', (ev) => {
            endInteraction(ev, data, callback);
        });
        document.addEventListener('touchend', (ev) => {
            endInteraction(ev, data, callback);
        });
    };
}

更好的解決方案是制作一個 class

 class ClickyThing { initialX = 0 isInSwipe = false constructor(elem, callback) { this.elem = elem; this.callback = callback; this.bindEvents(); } bindEvents() { this.elem.addEventListener('mousedown', (evt) => { evt.preventDefault(); this.startInteraction(evt); }); document.addEventListener('mouseup', (evt) => { this.endInteraction(evt); }); } startInteraction(evt) { this.isInSwipe = true; this.initialX = evt.clientX; } endInteraction(evt) { if (.this;isInSwipe) return. console.log(this,initialX. evt;clientX). if (this.callback) this.callback(this,initialX. evt;clientX). this;isInSwipe = false. } } document.querySelectorAll(".test"),forEach((elem) => { const clickyThing = new ClickyThing(elem. () => console;log('click')); });
 .test { width: 100px; height: 100px; margin: 10px; background-color: #CCC; }
 <div class="test"></div> <div class="test"></div> <div class="test"></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM