Adding the event-listener inside, or outside, a loop doesn't really matter what tends to be the problem is creating a function multiple times within the loop, as you are with your anonymous function:
for (var i = 0; i < fruits.length; i++) {
var fruit = fruits[i];
fruit.addEventListener('click', function() {
fruit_basket.appendChild(this)
});
}
The 'better' way, which avoids the recreation of the anonymous function on each loop would be to use a named function and assign that function as the event-handler within the loop:
// declaring the variables using let,
// first we retrieve all of the <li> elements held
// inside of an ancestor element with the class of
// 'list':
let fruits = document.querySelectorAll('.list li'),
// retrieving only the first - if any - element with
// the class of 'fruit-basket':
fruit_basket = document.querySelector('.fruit-basket');
// creating a named-function, to avoid re-recreating
// an anonymous function, which will be bound as the
// event-handler later:
function addToBasket(event) {
// the 'event' object, as well as the 'this'
// is passed automatically from the
// EventTarget.addEventListener() method,
// the event.target is the element upon
// which the listened-for event was first
// triggered (here the <li> or a descendant
// of that <li>):
fruit_basket.appendChild(event.target);
}
for (let i = 0; i < fruits.length; i++) {
// iterating through the NodeList returned
// by document.querySelectorAll() and binding
// the addToBasket function as the event-handler
// for the 'click' event:
fruits[i].addEventListener('click', addToBasket);
}
let fruits = document.querySelectorAll('.list li'),
fruit_basket = document.querySelector('.fruit-basket');
function addToBasket(event) {
fruit_basket.appendChild(event.target);
}
for (let i = 0; i < fruits.length; i++) {
fruits[i].addEventListener('click', addToBasket);
}
ul {
border: 1px solid #f90;
width: 80%;
margin: 0 auto 1em auto;
border-radius: 0.5em;
min-height: 6em;
line-height: 2em;
}
<ul class="list">
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
<ul class="fruit-basket">
</ul>
JS Fiddle demo.
Incidentally there is an alternative means, using the <ul> elements:
// again, creating a named-function to act as the
// event-handler:
function addToBasket(event) {
// finding the relevant element to which
// the event.target should be appended as
// a child, and appending the event.target:
document.querySelector('.fruit-basket').appendChild(event.target);
}
// here we create an Array from the Array-like
// NodeList returned by document.querySelectorAll:
Array.from(
document.querySelectorAll('ul')
// iterating over that Array of nodes:
).forEach(
// we use an Arrow function to bind the addToBasket
// function as the event-handler for the 'click'
// event on each of the <ul> elements:
list => list.addEventListener('click', addToBasket)
);
let fruits = document.querySelectorAll('.list li'),
fruit_basket = document.querySelector('.fruit-basket');
function addToBasket(event) {
document.querySelector('.fruit-basket').appendChild(event.target);
}
Array.from(
document.querySelectorAll('ul')
).forEach(
list => list.addEventListener('click', addToBasket)
);
ul {
border: 1px solid #f90;
width: 80%;
margin: 0 auto 1em auto;
border-radius: 0.5em;
min-height: 6em;
line-height: 2em;
}
<ul class="list">
<li>Apple</li>
<li>Banana</li>
<li>Orange</li>
</ul>
<ul class="fruit-basket">
</ul>
JS Fiddle demo.
References: