首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当不同的事件发生时,JavaScript如何在不同的时间查找函数名和变量?

当不同的事件发生时,JavaScript如何在不同的时间查找函数名和变量?
EN

Stack Overflow用户
提问于 2021-02-27 02:07:15
回答 1查看 53关注 0票数 0

我正在为SVG元素创建一个可拖动的函数。它完全按照我想要的那样工作,但我想知道是否有人可以帮助解释我有几个关于函数如何工作的问题。

这个简化的示例显示了我的函数,其中:

橙色线本身是可拖动的。

红色圆圈不可拖动。

蓝色正方形和绿色三角形可拖动在一起。

代码语言:javascript
运行
复制
"use strict"

/* Make an SVG element dragable using the translate transfrom. */
const makeDraggable = (el) => {

    /* Pointer SVG coordinates */
    const getPointerPosition = (e) => {
        if (e.touches) e = e.touches[0];
        return new DOMPoint(e.clientX, e.clientY).matrixTransform(svg.getScreenCTM().inverse());
    }

    /* Mouse down / touch start event */
    const dragStart = (e) => {
        /* Add event listeners. */
        root.addEventListener('mousemove', dragMove);
        root.addEventListener('touchmove', dragMove);
        root.addEventListener('mouseup', dragEnd);
        root.addEventListener('mouseleave', dragEnd);
        root.addEventListener('touchend', dragEnd);
        root.addEventListener('touchleave', dragEnd);
        root.addEventListener('touchcancel', dragEnd);

        /* Recursive check to find first parent group.  If found, apply transform to group. */
        let g = el;
        while (g && g.tagName !== 'g') g = g.parentNode;
        if (g) el = g;

        /* Check if element already has a translate as it's first transform.  If not, add it. */
        const transforms = el.transform.baseVal;
        if (transforms.length === 0 || transforms.getItem(0).type !== SVGTransform.SVG_TRANSFORM_TRANSLATE)
            translate = transforms.insertItemBefore(svg.createSVGTransform(), 0);
        else translate = transforms.getItem(0);

        /* Get pointer position during initial down/touch and offset the difference to the element translate origin. */
        offset = getPointerPosition(e);
        offset.x -= translate.matrix.e;
        offset.y -= translate.matrix.f;
    }

    /* Mouse move / touch move event */
    const dragMove = (e) => {
        /* Get pointer position of move, apply difference from initial pointer position to translate transform. */
        const point = getPointerPosition(e);
        translate.setTranslate(point.x -= offset.x, point.y -= offset.y);
    }

    /* Mouse up / leave / touch end / leave / cancel event */
    const dragEnd = () => {
        /* Remove inactive event listeners. */
        root.removeEventListener('mousemove', dragMove);
        root.removeEventListener('touchmove', dragMove);
        root.removeEventListener('mouseup', dragEnd);
        root.removeEventListener('mouseleave', dragEnd);
        root.removeEventListener('touchend', dragEnd);
        root.removeEventListener('touchleave', dragEnd);
        root.removeEventListener('touchcancel', dragEnd);
    }

    /* Attach event listeners to dragable element. */
    el.addEventListener('mousedown', dragStart);
    el.addEventListener('touchstart', dragStart);

    /* Set variables. */
    let svg = el;
    while (svg && svg.tagName !== 'svg') svg = svg.parentNode;
    const doc = svg.ownerDocument;
    const root = doc.documentElement || doc.body || svg;
    let translate, offset;

}

const loadSVG = () => {
    document.querySelectorAll(".draggable").forEach(el => makeDraggable(el))
}
代码语言:javascript
运行
复制
* {
    margin: 0;
}

svg {
    background-color: lightblue;
    width: 200px;
    height: 200px;
}

.draggable {
    cursor: move;
}

.notdraggable {
    cursor: not-allowed;
}
代码语言:javascript
运行
复制
Drag Test

我的问题是:

当SVG元素加载时,调用loadSVG函数,该函数对每个可拖动元素执行makeDraggable函数。该函数添加mousedown & touchstart事件侦听器,并将它们分配给每个可拖动元素的dragStart函数。

后来,当所有的加载函数都完成后,在其中一个可拖动元素上发生了mousedown/touchstart事件,它去调用dragStart函数,它如何找到dragStart函数,因为这个函数是在makeDraggable函数中找到的?

类似地,makeDraggble函数还创建变量translate & offset,用于存储dragStart函数(在mousedown/touchstart事件上调用)和dragMove (在mousemove/touchmove事件上调用)之间使用的信息值。但我只看到只有在调用makeDraggable函数时才会创建这些变量,只有在加载SVG时才会调用loadSVG函数。

所以,在运行完所有的load函数,并触发mousedown/touchstart & mousemove/touchmove事件之后,它如何仍然能找到这些变量呢?

我看到了另一个例子。el变量来自makeDraggable函数的一个参数,同样,该函数仅在加载期间调用。但是el变量是在dragStart (mousedown/touchstart)函数期间使用的,该函数是在不同的时间调用的。那么dragStart函数如何仍然使用这个变量呢?它不是一个全局变量,它的用法根据所单击的元素而变化。

我怀疑所有这些问题的答案可能是相同的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-27 03:02:30

向对象添加事件侦听器时,所添加的函数(以及在事件上执行)具有一定的封闭作用域。该作用域包括变量和函数。

function和箭头函数的不同之处在于它们的封闭范围,我认为对您的问题的答案是,dragStart,它确实是在makeDraggable被“绑定”到el通过事件侦听器。

el不仅仅是像这样的值1或者true而是对对象的引用。在此之后,该对象将继续存在makeDraggable

被处死。

本例中的浏览器“存储”了对dragStart它同样包含对其他函数和对象的引用。当您注销事件侦听器时,浏览器只会“忘记”这些事件。

这里有比我所描述的更多的细节。

如果您想了解更多信息,可以查看

  • 封闭函数/箭头函数的作用域
  • JavaScript事件循环
  • 通过值传递与通过引用传递
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66390783

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档