1
<div class="range" data-max="100">0-100</li>
<div class="range" data-max="200">0-200</li>
<div class="range" data-max="300">0-300</li>

I wish to access data-max in my javascript. For example, if I click 0-200, I get 200 only. Here is my javascript.

const ranges = document.querySelectorAll(".range");
for(var i = 0; i < ranges.length; i++){
    ranges[i].addEventListener('click', function(){
        console.log(this.dataset.max);
    });
}

The output when I click 0-200 is

200 100

I'm expecting 200.

Here are my questions:
1. how to get expected value---200 as in the example.
2. What is the scope of this in this.dataset.max in my code? I thought its scope is the function.
3. When I change this to ranges[i], it seems ranges[i] is undefined. why?

guessNum.js:4 Uncaught TypeError: Cannot read property 'dataset' of undefined

I'm expecting answers in pure javascript. No jquery pls.

Musa
  • 96,336
  • 17
  • 118
  • 137
Abel Zhu
  • 27
  • 2
  • 7

2 Answers2

3

Well your html is invalid, if you fix it it will work.
What is happening is the divs become nested inside each other and the click events bubble up the divs.

const ranges = document.querySelectorAll(".range");
for(var i = 0; i < ranges.length; i++){
    ranges[i].addEventListener('click', function(){
        console.log(this.dataset.max);
    });
}
<div class="range" data-max="100">0-100</div>
<div class="range" data-max="200">0-200</div>
<div class="range" data-max="300">0-300</div>
   
Musa
  • 96,336
  • 17
  • 118
  • 137
0

Please avoid asking multiple questions, and please don't change the question to something entirely different. The original should have been closed as it was a simple typo, and the additional questions are duplicates.

  1. What is the scope of this in this.dataset.max in my code? I thought its scope is the function.

this is always scoped to the current execution context. However, it's set in a number of ways, mostly in the call. Arrow functions adopt the this of their outer context, which is arguably how it's set, not how it's scoped.

Where a listener is added using addEventListener, then this within the function references the element on which the listener was placed. That isn't about scope, it's how this is set within the function.

See How does the “this” keyword work?

  1. When I change this to ranges[i], it seems ranges[i] is undefined. why?

Because i within the listeners has a closure to the original i, which has been incremented to ranges.length and hence references a non-existent element of the collection. See JavaScript closure inside loops – simple practical example.

RobG
  • 142,382
  • 31
  • 172
  • 209