David Posin helps you land that next programming position by understanding important JavaScript fundamentals.

JavaScript is a fun, powerful, and important language with a low barrier of entry. People from all kinds of backgrounds and careers find themselves choosing to wrestle with the chaos that is JavaScript programming. With such a varied set of backgrounds, not everyone has the same broad knowledge of JavaScript and its fundamentals. Often, it’s not until you find yourself interviewing for a job that you really stop to consider why, or how, the stuff that usually just works, works.

The goal of this series will be to delve into the concepts and theories that make up JavaScript. The topics will come from Darcy Clarke’s awesome list of typical JS interview questions. Hopefully, you will finish the article with more than just an answer to the question. Each article will leave you with a new understanding, or a brush-up from your past learnings, that will help in all of your interactions with JavaScript.

Explain event delegation

Event delegation is the idea that something other than the target of an action resolves the event raised by that action. An example of event delegation would be having the document element handle the click action of a button. A fairly common occurrence, is to have a “ul” element handle the events raised by its children “li” elements.

Event delegation can be handled in several ways. The standard way is derived from native browser functionality. Browsers are programmed to handle events in a particular work flow. They are designed to support event capturing and event bubbling. The W3C documentation on how browsers are to support events can be found here:W3C DOM Level 3 Events. Some JS libraries and frameworks expose additional options such as the pub/sub model (which we will look at below).

Event capturing and event bubbling are two phases in a three phase flow. Any event that occurs, such as clicking a button, starts at the topmost container (which usually is the html root node). The browser moves down the DOM hierarchy until it finds the element raising the event. Once the browser finds the element that caused the event, it enters the targeting phase. Once targeting is complete, the browser bubbles up the DOM back to the topmost container to see if anything else needs to use the same event.

The fiddle below illustrates the process. Clicking on either button will cause the event flow to identify itself in the text below the container box. Each element receives the same click listener code. The click event first fires at the html node with the capturing phase, and then returns to the top at the end of the bubble phase.

<div id="containerOuter" style="border: 1px solid black; width: 100px; padding: 20px">
<div id="containerInner" style="border: 1px solid black; width:80px; padding: 10px">
<button id="button1">1</button>
<button id="button2">2</button>
</div>
</div>
<br/>
<div id="EventListing"></div>
ar nodes = $('*'),
node = {};
for (var i = 0; i < nodes.length; i++) {
node = nodes[i]; node.addEventListener('click', function (event) {
$('#EventListing').append('Bubble ' + (event.currentTarget.id || event.currentTarget.tagName) + '<br/>');
}); node.addEventListener('click', function (event) {
if (event.currentTarget != event.target) {
$('#EventListing ').append('Capture ' + (event.currentTarget.id || event.currentTarget.tagName) + ' <br/>');
}
}, true);
}

View this on JSFiddle

Fiddle Code Explanation
The code starts by grabbing all nodes in the window. After getting a handle to all nodes, the code loops through the each node and attaches a click handler to each element. Event though only the button can invoke a click event by default, the click event still follows the expected capture (down) and bubbling (up) event flow. The addEventListener with the true parameter is the one setting up the capture listener, and the one without the extra parameter sets the bubbling listener.

Most modern libraries use the bubble phase for listener handling over the capture phase. Browsers include a way to manage how high we want the event to bubble. An event handler can call stopPropagation to tell the event to cease bubbling up the DOM. There is a second option called stopImmediatePropagation. This method stops the bubbling, and will also stop any other listeners for this event on this element from firing. However, be careful when stopping propagation since you don’t really know if there is anything else up the DOM that might want to be aware of the event.

There is a third function worth knowing that can be called to control how elements react to events. All modern browsers support the preventDefault function. This function prevents the browser from using its native operations to handle the event. A common use case is the link. Using links to perform UI operations is a common practice. However, we don’t want that link to try activating the regular link function of opening the page to a new page. Using preventDefault stops the browser from trying to follow an href tag.

There are other delegation methods to consider as well. One worth mentioning here is the pub/sub model. The publication/subscription model, also called a radio model, involves two participants. Usually, the two participants are not closely connected in the DOM, and may actually be derived from sibling containers. One could put a listener on the element they both ultimately descend from, but if the shared ancestor element is very high then you could end up listening for too many events at that level and create the dreaded monolith mentioned earlier. Also, there may be logically or architectural reasons to keep the two elements separate.

The Pub/Sub model also opens the opportunity to create custom events. The pub/sub model works by sending a message out from one element and traveling up, and sometimes down, the DOM telling all elements along the way that the event happened. jQuery uses the trigger function to pass events up the DOM as illustrated in the fiddle below.

<br />
<div id="container" style="border: 1px solid black; width: 100px; padding: 20px">
<button id="button2">Trigger Me</button>
<div id="insertText" style="padding: 10px;"></div>
</div>
<br/>
<div id="EventListing"></div>
$('#container').on('myCustomEvent', function (e, data) {
$('#insertText').append(data);
}); $('#button2').click(function () {
$('#button2').trigger('myCustomEvent', ['I triggered']);
});

Fiddle Code Explanation
The first clause, $(‘#container’), sets a listener for the myCustomEvent event on the element. The second clause adds a click listener on the $(‘button2’) element. When the button is clicked it triggers the myCustomEvent which bubbles up the DOM.

The are several benefits of using event delegation to manage the event flow. One of the biggest is performance. Every listener attached to an element takes up some memory. If there are only a few listeners on a page then the difference won’t be noticed. However, if you have a listener on every cell of a 50 row 5 column table then your web application may begin to slow down. In the interest of making an application as fast as possible it is best to keep memory use as low as possible.

Using event delegation can reduce the number of listeners from many to a few. Placing a listener on a container above the elements firing the event means only needing one listener. The drawback to this approach is that the listener at the parent container may need to examine the event to choose the correct operation, whereas a listener on the element itself would not. The impact of that extra processing is much less than the impact of too many listeners in memory.

Fewer listeners and fewer points of DOM interaction make for easier maintenance. One listener at a container level can handle multiple different event operations. This is not an excuse for a monolithic function of titanic proportions. It is an easy way to manage related events that often perform related functions or need to share data.

If a parent container is listening then individual operations performed inside that container don’t have to add or remove listeners on their own. Operations like dynamic buttons and elements are extremely common with the increased use of single page applications. Something as simple as adding a button dynamically to a section can create a potential performance block for your application. Without proper event delegation it becomes necessary to manually add listeners to each new button, and if each listener is not cleaned up properly, it can potentially cause memory leaks. The browser does not clear the page, and therefore memory, in a single page application so everything that is not cleaned from memory properly can stick around. These fragments in memory drag down the performance of your application, like a great sponge that continues to absorb memory growing heavier and bigger and never releasing the pent-up memory.

When adding interaction to your pages, do yourself (and the person maintaining your code in the future) a favor, and carefully consider which element really needs to be listening.

Additional Articles Worth Reading
NCZOnline.com – The technical blog of Nicholas Zakas.http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/

Explain how this works in JavaScript
The “this” keyword in JavaScript is a commonly used method to refer to the code’s current context.

  • If “this” has not been set to anything then it defaults to the global object, which is usually Window.
  • If a function is running on an in-line function, such as an event listener, then “this” will refer to the source of the function. For example, when setting a click handler for a button, “this” will refer to the button inside the anonymous function.
  • If a function is a constructor for an object, then this will refer to the new object.
  • If a function is being defined on an object, then when invoked on the object, “this” will refer to the object.

In a world of asynchronous programming and the helpful existence of promises, it is easy for “this” to change in the course of one feature’s operation. One trick to keep a handle on the context that started the operation is to set it to a variable inside a closure. When you call a function where context changes, like setTimeout, you will still be able to reference the object you need through that variable.

The other way one can manipulate “this” is through the use of call, apply, and bind. All three of these methods are used to invoke a function with a specific context of “this”. Instead of relying on the browser operation to figure out what “this” is, you can tell the code to use the object you are proposing. Call, apply, and bind can be pretty sophisticated in their own right and deserve their own writeup. We will address them in a future installment. An example of the many changing ways of “this” is below:

<div id="appendHere"></div>
<button id="clickMe">Click Me</button>
var div = $('#appendHere');

$('#clickMe').on('click', function () {
var that = this;
div.append(checkForWindow(this)); setTimeout(function () {
div.append(checkForWindow(this));
div.append('<strong>that</strong> is the ' + that.tagName + '<br/>');
}, 300);
});

Fiddle Code Explanation
When the button is initially clicked, the this value is output to a div. Since click operates from the button context, “this” is the button. Using setTimeout causes the context to change to the Window. When “this” is called in the timeout function is, “this” reverts to the global context. You will notice we set a variable called “that” which we set initially to the “this” context. When invoked in the setTimeout, that still refers to the original “this”.

Event delegation and “this” are important features of modern JavaScript. Understanding how they work are critical to successful development, and almost certainly necessary to understand to get that peach position of a JavaScript Engineer.

JavaScript Interview Questions: Event Delegation and This的更多相关文章

  1. javascript事件代理(Event Delegation)

    看了几篇文章,放上来供参考 司徒正美的文章,Event Delegation Made Easy --------------------------------------------------- ...

  2. javascript 事件委托 event delegation

    事件委托 event delegation 一.概念: 假设我们有很多个子元素,每个元素被点击时都会触发相应事件,普通的做法是给每个子元素添加一个事件监听. 而,事件委托则是给它们的父元素添加一个事件 ...

  3. JavaScript Event Delegation, and event.target vs. event.currentTarget

    原文:https://medium.com/@florenceliang/javascript-event-delegation-and-event-target-vs-event-currentta ...

  4. 安卓面试题 Android interview questions

    安卓面试题 Android interview questions 作者:韩梦飞沙 ‎2017‎年‎7‎月‎3‎日,‏‎14:52:44 1.      要做一个尽可能流畅的ListView,你平时在 ...

  5. [译]Node.js Interview Questions and Answers (2017 Edition)

    原文 Node.js Interview Questions for 2017 什么是error-first callback? 如何避免无止境的callback? 什么是Promises? 用什么工 ...

  6. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  7. [转]Design Pattern Interview Questions - Part 2

    Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...

  8. JavaScript------事件委托(event delegation)

    简单的说,事件委托(event delegation)是在DOM上层(也就是在触发事件的元素的父元素上)定义事件的处理程序,而不是定义在触发事件的元素本身上. 首先我们来举这样一个例子:我有N个li元 ...

  9. jQuery Questions:Front-end Developer Interview Questions

    Explain "chaining". Chaining allows us to run multiple jQuery methods (on the same element ...

随机推荐

  1. RHEL7系统修复rm -rf /boot /etc/fstab

    RHEL7/Centos7系统发布这么长时间了,大家都知道这个系统的一个特点就是用systemctl代替了init系统守护进程,系统越来越模块化了.在新版的系统中许多的命令也发生了改变,grub也变为 ...

  2. easyui tree带checkbox实现单选

    <ul id="regionTree"></ul> $('#regionTree').tree({ cascadeCheck: false, //onlyL ...

  3. UIFont可用字体

    label.font = [UIFont fontWithName:@"Arial-BoldItalicMT" size:24]; 字体名如下: Font Family: Amer ...

  4. PHP高级教程-Data

    PHP date() 函数 PHP date() 函数用于格式化时间/日期. PHP date() 函数 PHP date() 函数可把时间戳格式化为可读性更好的日期和时间. 时间戳是一个字符序列,表 ...

  5. Java从零开始学十五(继承)

    一.继承作用 继承使用复用以前的代码非常容易,能够大大的缩短开发周期,降低开发成本,同时增加程序的易维护性 继承使重一个类A能够直接使用另外一个类B的属性和方法的一种途径 类A可以有自己的属性和方法 ...

  6. Java从零开始学十四(包和访问控制)

    一.java中的包 Java文件的组织形式Windows中的文件功能类似 在开发比较大的项目时,不可能只涉及到一个java文件,可能要创建几十,甚至几百个java文件,这个时候,我们就可以使用包,把相 ...

  7. 美国程序猿(软件project师)平均年薪状况调查

    来源站点:Indeed.com&computerengineeringsalarydata.com Average Software Engineer Salary by 50 States ...

  8. Windows 无法启动MongoDB服务 错误1067:进程意外终止

    1:Windows 无法启动MongoDB服务 错误1067:进程意外终止 2:解决方法: 进入MongoDB安装目录\data\将此文件夹下的mongod.lock删除(网友提供解决方案,实验之后貌 ...

  9. ionic 项目中 使用 sass

    注: 1.先安装node-sass  -->> npm install --save node-sass --registry=https://registry.npm.taobao.or ...

  10. 解决"libc.so.6: version `GLIBC_2.14' not found",系统的glibc版本太低 {强行安装!!}

     原创,转载请注明出处,谢谢!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 首先查看系统glibc支持的版本: strings /lib64/libc.so.6 |grep G ...