0

I'm learning about using keyword "this" with DOM manipulation in JavaScript and I have a missunderstand. Maybe someone can help me to understand it.

For example I have this simple program:

<!DOCTYPE html>
<html>
<head>
    <title>JavaScript + DOM</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <h1>Shopping List</h1>
    <p id="first">Get it done today</p>
    <p class="second">No excuses</p>
    <input id="userinput" type="text" placeholder="enter items">
    <button id="enter">Enter</button>
    <ul>
        <li class="three">Notebook</li>
        <li>Jello</li>
        <li>Spinach</li>
        <li>Rice</li>
        <li>Birthday</li>
        <li>Candles</li>
    </ul>
    <script type="text/javascript" src="script.js"></script>
</body>
</html>

style.css:

.done {
    text-decoration: line-through;
}

script.js:

var button = document.getElementById("enter");
var input = document.getElementById("userinput");
var ul = document.querySelector("ul");
var li = document.getElementsByTagName("li"); 

console.log("This 1 = " + this);

function inputLength() {
    return input.value.length;
}

function createListElement() {
        var li = document.createElement("li");
        li.appendChild(document.createTextNode(input.value));
        ul.appendChild(li);
        console.log("This 2 = " + this);
        input.value = "";
}

function addListAfterClick() {
    if (inputLength() > 0) {
        createListElement();
    } 
}

function addListAfterKeypress(event) {
    if (inputLength() > 0 && event.keyCode === 13) {
        createListElement();
    }
}

function changeClass() {
        this.classList.toggle("done");
        console.log("This 3 = " + this);
}

for (var i = 0; i < li.length; i++) {
    li[i].addEventListener("click", changeClass)
}

button.addEventListener("click", addListAfterClick)

input.addEventListener("keypress", addListAfterKeypress)

It is a simple list, and you can add new elements in the list, also you can change the class of an element when you click on an element of the list.

When I refresh the browser I get in the console: This 1 = [object Window]

After that I type a letter in the box and click the "Enter" button and I get in the console: This 2 = [object Window]. So, the object is still "Window".

After that I click on an element from the list and I get in the console: This 3 = [object HTMLLIElement]. I see that the object is changed from Window to HTMLLIElement.

I don't understand when the object is changed from Window to HTMLLIElement. Why the object for This 2 is Window and the object for This 3 is HTMLLIElement. Thank you!

  • You're calling the function like `createListElement();`, there's no context involved in the function invocation, i.e. you're not calling a method, you're calling a function. – Teemu Oct 16 '18 at 11:01
  • 1
    @HMR—that's unnecessary. Functions added as listeners with *addEventListener* have the element set to *this* by the handler by default. – RobG Oct 16 '18 at 11:05

1 Answers1

2

When I refresh the browser I get in the console: This 1 = [object Window]

In global code, this is set to the global (window in a browser) object.

After that I type a letter in the box and click the "Enter" button and I get in the console: This 2 = [object Window]. So, the object is still "Window".

When the function is called, this is not set in the call so it defaults to the global/window object. In strict mode code, it would be undefined.

After that I click on an element from the list and I get in the console: This 3 = [object HTMLLIElement]. I see that the object is changed from Window to HTMLLIElement.

When a function added as a listener by addEventListener is called, its this is set to the element the listener is set on, as if by:

changeClass.call(element, event)

The related event is passed as the first argument.

I don't understand when the object is changed from Window to HTMLLIElement. Why the object for This 2 is Window and the object for This 3 is HTMLLIElement.

this is a parameter of an execution context that is set when the context is created. It can be set in the call or using bind, or lexically in arrow functions (i.e. adopted from the outer execution context). See How does the “this” keyword work?

RobG
  • 124,520
  • 28
  • 153
  • 188
  • Thans for reply! You said that: “When a function added as a listener by addEventListener is called, its this is set to the element the listener is set on”.. so it’s this is set to “li” element… but I want to ask you something, in the other case, when I type a letter and click the “Enter” button, so the addListAfterClick function is called and it is also a function added as a listener by addEventListener.. why its this isn’t set to “button” element? –  Oct 16 '18 at 11:57
  • @gaby—I've updated your post to change the code to a runnable snippet and added a console.log to *addListAfterClick*. As you can see, its *this* is the button when called from the button's listener. – RobG Oct 16 '18 at 13:02