参数 e(事件)到底是什么,为什么将它传递给 JavaScript 函数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35936365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:23:50  来源:igfitidea点击:

What exactly is the parameter e (event) and why pass it to JavaScript functions?

javascripteventsjavascript-events

提问by Lord Yggdrasill

Well, when I learned JavaScript, all the books and Internet articles I read showed code passing a parameter eto functions that handle JavaScript events, such as the code block below:

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

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

I've always accepted that as being the way it is, but now I have some questions (this is very confusing to me):

我一直接受事实就是这样,但现在我有一些问题(这让我很困惑):

  1. Where does this ecome from? When I look at the entire JavaScript file, edoes not seem to exist at all.
  2. Why pass this parameter eto functions? Will functions stop working if I do not pass eto them?
  3. Consider the code block below. There is an event variable (e) passed to an anonymous inner function. Let's say I want to use an event object outside of the anonymous function (maybe in a line above/below the element.onkeypressline). How can I do this?

    element.onkeypress = function(e) {
        if(e.keyCode) {
            element.keyCode = e.keyCode;
        } else {
            element.keyCode = e.charCode;
        }
    };
    
  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;
        }
    };
    

回答by Dimitris Karagiannis

The eis short for event

e缩写event

The simplest way to create an event is to click somewhere on the page.

创建事件的最简单方法是单击页面上的某处。

When you click, a clickevent is triggered. This eventis actually an object containing information about the action that just happened. In this example's case, the event would have info such as the coordinates of the click (event.screenXfor example), the element on which you clicked (event.target), and much more.

当您单击时,click会触发一个事件。这event实际上是一个包含有关刚刚发生的操作的信息的对象。在本例中,事件将包含诸如点击坐标(event.screenX例如)、您点击的元素 ( event.target) 等信息。

Now, events happen all the time, however you are not interested in all the events that happen. When you areinterested in some event however, it's when you add an event listener to the element you know will create events[1]. For example you are interested in knowing when the user clicks on a 'Subscribe' buttonand you want to do somethingwhen this event happens.

现在,事件一直在发生,但是您对发生的所有事件并不感兴趣。当你正在感兴趣然而,在一些情况下,当你添加一个事件监听器,你知道会创建活动[1]的元素。例如,您想知道用户何时单击“订阅”按钮,并且您想在此事件发生时执行某些操作

In order to do something about this event you bind an event handlerto the button you are interested in. The way to bind the handler to the element is by doing element.addEventListener(eventName, handler).

为了对此事件做一些事情,您将事件处理程序绑定到您感兴趣的按钮。将处理程序绑定到元素的方法是执行element.addEventListener(eventName, handler)

eventNameis a string and it's the name of the event you are interested in, in this case that would be 'click'(for the clickevent).

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

The handler is simply a functionwhich does something (it's executed) when the event happens. The handler function, by default, when executed is passed the eventobject(that was created when the event/action you are interested in happened) as an argument.

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

Defining the eventas a parameter of your handler function is optional but, sometimes (most times), it is useful for the handler function to know about the event that happened. When you dodefine it this is the eyou see in the functions like the ones you mentioned. Remember, the eventis just a regular javascript object, with lots of properties on it.

将 定义event为处理程序函数的参数是可选的,但有时(大多数情况下),处理程序函数了解发生的事件很有用。当你定义它,这是e你在像你提到的那些功能见。请记住,event它只是一个普通的 javascript 对象,上面有很多属性。

Hope that helped.

希望有所帮助。

For more info read Creating and Triggering Events

有关更多信息,请阅读创建和触发事件

As for your 3rd question, now you should know you cannot do that, because eonly exists when an event happens. You could have the handler function, which has access to the eobject when it gets executed, to store it in some global variable and work on that.

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

[1] That is not exactly correct, but it's simpler to understand. The more correct thing to say there is "add an event listener to the element you know will have events flow through it". See thisfor more information

[1] 这并不完全正确,但更容易理解。更正确的说法是“向您知道将有事件流过的元素添加一个事件侦听器”。请参阅了解更多信息

回答by Arnelle Balane

The parameter ethat you are asking about is an Eventobject, and it represents the event being fired which caused your function to be executed. It doesnt really have to be e, you can name it anything you want just like all other function parameters.

e您所询问的参数是一个Event对象,它表示导致您的函数被执行的正在触发的事件。它e并不是必须的,您可以像所有其他函数参数一样将其命名为任何您想要的名称。

  1. Where does this e come from? When I look at the entire javascript file, e does not seem to exist at all.
  1. 这个e来自哪里?当我查看整个 javascript 文件时,e 似乎根本不存在。

You won't be able to find this evariable in your javascript file because it's really not there at all, but comes from the javascript engine executing your callback function.

您将无法e在 javascript 文件中找到此变量,因为它实际上根本不存在,而是来自执行回调函数的 javascript 引擎。

When you give a callback function for some event (e.g. element.onkeypress = function(e) { ... }), you are giving the javascript engine a function to execute/call when that event fires, and when it executes/calls your callback function it passes along an Eventobject representing the event that just happened. Javascript could be doing something like this to call your callback function:

当您为某个事件(例如element.onkeypress = function(e) { ... })提供回调函数时,您是在为 javascript 引擎提供一个函数以在该事件触发时执行/调用,并且当它执行/调用您的回调函数时,它会传递一个Event表示刚刚发生的事件的对象. Javascript 可能会做这样的事情来调用你的回调函数:

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

and that's where the Eventobject ecomes from.

这就是Event对象的e来源。

  1. Why pass this parameter e to functions? Will the function stop working if I do not pass e to it?
  1. 为什么将此参数 e 传递给函数?如果我不将 e 传递给它,该功能会停止工作吗?

The function will not stop working if you don't have the eparameter in it. But if you need to access some details about the event that caused your function to be executed, you are going to need the eparameter to get them.

如果您没有e参数,该函数将不会停止工作。但是如果您需要访问有关导致您的函数执行的事件的一些详细信息,您将需要e参数来获取它们。

  1. Consider the code block below, there is an event variable(e) passed to an anonymous inner function. Lets say I want to use event object outside of the anonymous function(maybe in a line above/below the element.onkeypress line), how can I do this?
  1. 考虑下面的代码块,有一个事件变量(e)传递给匿名内部函数。假设我想在匿名函数之外使用事件对象(可能在 element.onkeypress 行上方/下方的一行中),我该怎么做?

I dont think you can do this, even if you store it in a variable outside the scope of your callback function. This is because your function is not executed right away when you declare it, but instead only when the event is fired (e.g. a key is pressed, firing the 'keypress' event).

我不认为你可以这样做,即使你将它存储在回调函数范围之外的变量中。这是因为您的函数不会在您声明时立即执行,而是仅在触发事件时执行(例如,按下某个键,触发 'keypress' 事件)。

var event;

element.onkeypress = function(e) {
    event = e;
    ...
};

console.log(event); // => undefined

The only way this could work is when the code that uses the eventvariable also gets executed later, specifically after the anonymous function given to onkeypressgets executed. So the code below could work:

唯一可行的方法是使用该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

回答by Haris Ghauri

I will try my best to explain in the most abstract way possible. The real implementation is probably a lot more complex. Therefore, the names that I am about to use are hypothetical but they do serve a good purpose for explaining things, I hope ;)

我会尽量用最抽象的方式来解释。真正的实现可能要复杂得多。因此,我将要使用的名称是假设性的,但它们确实有助于解释事物,我希望 ;)



Every node in the browser is an implementation of EventEmitterclass. This class maintains an object eventsthat contains key:valuepairs of eventType(the key) : an Array containing listenerfunctions (the value).

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

The two functions defined in the EventEmitter class are addEventListenerand fire.

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));
    }
  }
}


addEventListeneris used by the programmer to register their desired listenerfunctions to be fired upon the execution of their desired eventType.

addEventListener程序员使用它来注册他们想要的listener函数,以便在执行他们想要的eventType.

Note that for each distinct eventType, there is a distinct array. This array can hold multiple listenerfunctions for the same eventType.

请注意,对于每个 distinct eventType,都有一个不同的数组。该数组可以listener为同一个eventType.



fireis invoked by the browser in response to user interactions. The browser knows what kind of interaction has been performed and on what node it has been performed. It uses that knowledge to invoke fireon the appropriate node with the appropriate parameters which are eventTypeand eventProperties.

fire由浏览器调用以响应用户交互。浏览器知道执行了哪种交互以及在哪个节点上执行。它使用该知识fire在适当的节点上调用适当的参数,即eventTypeeventProperties

fireloops through the array associated with the specific eventType. Going through the array, it invokes every listenerfunction inside the array while passing eventPropertiesto it.

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

This is how the listenerfunctions, registered only with the particular eventType, are invoked once fireis called.

这就是listener仅使用特定 eventType 注册的函数被调用一次的fire方式。



Following is a demonstration. There are 3 Actors in this demonstration. Programmer, Browser and the User.

下面是一个演示。在这个演示中有 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

After the user clicks on button, Browser invokes fireon button passing "click" as an eventTypeand the object holding eventProperties. This causes all the registered listenerfunctions under "click" eventTypeto be invoked.

用户点击按钮后,浏览器调用fire按钮,将“click”作为 aneventType和持有eventProperties. 这会导致调用listener“click”下的所有注册函数eventType

As you can see, the Browser ALWAYSputs eventPropertieson fire. As a programmer, you may or may not use those properties in your listenerfunctions.

正如你所看到的,浏览器总是eventProperties着火。作为程序员,您可能会也可能不会在您的listener函数中使用这些属性。



Some answers that I found helpful on stackoveflow:

我发现对 stackoveflow 有帮助的一些答案:

Where is an event registered with addEventListener stored?

使用 addEventListener 注册的事件存储在哪里?

Where are Javascript event handlers stored?

Javascript 事件处理程序存储在哪里?

回答by RobG

When a listener is added using addEventListener, the first argument passed to the function is an Event object, so it will be assigned to the eparameter (or whatever name is given to the function's first parameter).

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

回答by Bata

  1. It's just how JS works, you get event object in every event callback. It contains a lot of info about the event.
  2. Function will not stop working if you do not pass it, it is optional. Go on and console.log the event (e) and see the event object and its properties. It will be more clear when you see what it has.
  3. You can use it outside of that anonymous function by storing it, example:

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

    but you should know that the event object is relative only to that specific event that happened, and considering that you should decide if you really need to do that.

  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);
    

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