参数e(事件)究竟是什么以及为什么将它传递给JavaScript函数?

时间:2016-03-11 09:24:09

标签: javascript events javascript-events

好吧,当我学习JavaScript时,我读过的所有书籍和互联网文章都显示了将参数e传递给处理JavaScript事件的函数的代码,例如下面的代码块:

function myEvent(e) {
    var evtType = e.type
    alert(evtType)
    // displays click, or whatever the event type was
}

我总是接受它的方式,但现在我有一些问题(这对我来说非常混乱):

  1. 这个e来自哪里?当我查看整个JavaScript文件时,e似乎根本不存在。
  2. 为什么将此参数e传递给函数?如果我没有将e传递给他们,函数是否会停止工作?
  3. 考虑下面的代码块。传递给匿名内部函数的事件变量(e)。让我们说我想在匿名函数之外使用一个事件对象(可能在element.onkeypress行上方/下方的行中)。我怎么能这样做?

    element.onkeypress = function(e) {
        if(e.keyCode) {
            element.keyCode = e.keyCode;
        } else {
            element.keyCode = e.charCode;
        }
    };
    

5 个答案:

答案 0 :(得分:47)

eevent

的缩写

创建活动的最简单方法是单击页面上的某个位置。

单击时,会触发click事件。此event实际上是一个对象,其中包含有关刚刚发生的操作的信息。在此示例的情况下,事件将包含诸如点击的坐标(例如event.screenX),您单击的元素(event.target)等信息。 / p>

现在,事件一直在发生,但是你对所发生的所有事件都不感兴趣。当你 对某些事件感兴趣时,当你向你知道会创建事件的元素添加一个事件监听器时就会这样[1]。例如,当用户点击“订阅”时,您有兴趣知道。按钮,您希望在此事件发生时执行某些操作

为了对此事件执行某些操作,您将事件处理程序绑定到您感兴趣的按钮。将处理程序绑定到元素的方法是执行element.addEventListener(eventName, handler)。< / p>

eventName是一个字符串,它是您感兴趣的事件的名称,在这种情况下是'click'(对于click事件)。

处理程序只是一个函数,它在事件发生时执行某些操作(它已被执行)。默认情况下,处理程序函数在执行时传递event对象(在您感兴趣的事件/操作发生时创建)作为参数

event定义为处理函数的参数是可选的,但有时(大多数情况下),处理程序函数可以了解发生的事件。当您执行定义时,您在功能中看到的e就像您提到的那样。请记住,event只是一个常规的javascript对象,上面有很多属性。

希望有所帮助。

有关详细信息,请参阅Creating and Triggering Events

关于你的第3个问题,现在你应该知道你不能这样做,因为e仅在事件发生时存在。您可以拥有处理程序函数,该函数在执行时可以访问e对象,将其存储在某个全局变量中并对其进行处理。

[1]这不完全正确,但理解起来比较简单。更正确的说法就是&#34;为你知道会让事件流经它的元素添加一个事件监听器&#34;。有关详细信息,请参阅this

答案 1 :(得分:8)

您要询问的参数eEvent对象 表示被触发的事件导致您的函数被执行。它实际上不必是e,你可以像所有其他函数参数一样命名它。

  1. 这个e来自哪里?当我查看整个javascript文件时,e 似乎根本不存在。
  2. 您无法在javascript文件中找到此e变量,因为 它根本不存在,但来自javascript引擎执行 你的回调函数。

    当您为某个事件提供回调函数时 (例如element.onkeypress = function(e) { ... }),你正在给予 javascript引擎在该事件触发时执行/调用的函数,以及何时触发 它执行/调用它传递给Event对象的回调函数 代表刚刚发生的事件。 Javascript可能正在做点什么 像这样调用你的回调函数:

    var e = new Event();
    callbackFunction(e);
    

    以及Event对象e来自的地方。

    1. 为什么将此参数e传递给函数?如果,该功能是否会停止工作 我没有把它传给它?
    2. 如果您没有e参数,该功能将不会停止工作。 但是,如果您需要访问导致您的事件的一些细节 要执行的函数,您将需要e参数来获取它们。

      1. 考虑下面的代码块,有一个事件变量(e)传递给 匿名内功能。让我们说我想在之外使用事件对象 匿名函数(可能在element.onkeypress行上方/下方的行中), 我怎么能这样做?
      2. 我不认为你可以做到这一点,即使你将它存储在一个变量之外 回调函数的范围。这是因为您的功能未执行 当你声明它时立即,但只有当事件被触发时 (例如按下一个键,触发&#39;按键事件)。

        var event;
        
        element.onkeypress = function(e) {
            event = e;
            ...
        };
        
        console.log(event); // => undefined
        

        这可行的唯一方法是使用event变量的代码 也会在稍后执行,特别是在给出的匿名函数之后 onkeypress被执行。所以下面的代码可以工作:

        var event;
        
        element.onkeypress = function(e) {
            event = e;
            ...
        };
        
        setTimeout(function() {
            console.log(event); // => the event object, if the `keypress` event
                                //    fired before `setTimeout` calls this function
        }, 100000); // <= set to very large value so that it gets run way way later
        

答案 2 :(得分:1)

我将尽最大可能以最抽象的方式进行解释。实际的实现可能要复杂得多。因此,我希望使用的名称是假设的,但我希望它们确实可以很好地解释事物。)


浏览器中的每个节点都是EventEmitter类的实现。此类维护一个对象events,该对象包含eventType(密钥)的 key:value 对:一个包含listener函数(值)的数组。

EventEmitter类中定义的两个函数是addEventListenerfire

class EventEmitter {
  constructor(id) {
    this.events = {};
    this.id = id;
  }

  addEventListener(eventType, listener) {
    if (!this.events[eventType]) {
      this.events[eventType] = [];
    }

    this.events[eventType].push(listener);
  }

  fire(eventType, eventProperties) {
    if (this.events[eventType]) {
      this.events[eventType].forEach(listener => listener(eventProperties));
    }
  }
}

程序员使用

addEventListener来注册其所需的listener函数,以在执行其所需的eventType时触发。

请注意,对于每个不同的eventType,都有一个不同的数组。该数组可以为同一listener保留多个eventType函数。


fire由浏览器响应用户交互而调用。浏览器知道已经执行了哪种类型的交互以及在哪个节点上进行了交互。它使用该知识在具有适当参数fireeventType的适当节点上调用eventProperties

fire遍历与特定eventType相关联的数组。遍历数组时,它将调用数组中的每个listener函数,同时将eventProperties传递给它。

一旦调用listener,就会调用仅注册到特定eventType的fire函数。


以下为演示。此演示中有3个演员。程序员,浏览器和用户。

let button = document.getElementById("myButton"); // Done by the Programmer
let button = new EventEmitter("myButton"); // Done by the Browser somewhere in the background. 


button.addEventListener("click", () =>
  console.log("This is one of the listeners for the click event. But it DOES NOT need the event details.")
); // Done By the Programmer


button.addEventListener("click", e => {
  console.log(
    "This is another listener for the click event! However this DOES need the event details."
  );
  console.log(e);
}); // Done By the Programmer


//User clicks the button


button.fire("click", {
  type: "click",
  clientX: 47,
  clientY: 18,
  bubbles: true,
  manyOthers: "etc"
}); // Done By the Browser in the background

用户单击按钮后,浏览器将在按钮上调用fire,并将“ click”作为eventType传递给持有eventProperties的对象。这将导致调用“点击” listener下所有已注册的eventType函数。

如您所见,浏览器总是使eventProperties着火。作为程序员,您可以在listener函数中使用或不使用这些属性。


一些我认为对stackoveflow有用的答案

Where is an event registered with addEventListener stored?

Where are Javascript event handlers stored?

答案 3 :(得分:0)

使用 addEventListener 添加侦听器时,传递给该函数的第一个参数是一个Event对象,因此它将被分配给 e 参数(或任何名称)赋予函数的第一个参数)。

答案 4 :(得分:0)

  1. 这就是JS的工作原理,你在每个事件回调中得到事件对象。它包含大量有关该事件的信息。
  2. 如果您没有通过它,功能将不会停止工作,它是可选的。继续和console.log事件(e)并查看事件对象及其属性。当你看到它有什么时,它会更清楚。
  3. 您可以通过存储它来在匿名函数之外使用它,例如:

    var myEvent;
    
    element.onkeypress = function(e) {
        myEvent = e;
        if(e.keyCode) {
            element.keyCode = e.keyCode;
        } else {
            element.keyCode = e.charCode;
        }
    };
    
    console.log(myEvent);
    

    但你应该知道事件对象只与发生的特定事件有关,并且考虑到你应该决定是否真的需要这样做。