0

box = {
  curBox: 0,
  boxes: document.getElementsByClassName('box'),
  size: this.boxes.length, //this one won't work
  orSize: Object.keys(this.boxes).length, //as well as this one
  preBox: function() {
    curBox -= 1
  },
  nexBox: function() {
    curBox += 1
  }
}

console.log(box.boxes.length); //This one works well!!!
<div class='active box BG_blue'>
  <meta name='title' content='Overview' /> ...
</div>

<div class='inactive box BG_orange'>
  <meta name='title' content='Career' /> ...
</div>

<div class='inactive box BG_red'>
  <meta name='title' content='Skills' /> ...
</div>

<div class='inactive box BG_awesome'>
  <meta name='title' content='Hobbies' /> ...
</div>

I tried to get the length of an array returned from getElementsByClassName. If I put it outside the object range, it work. But inside the object range, it won't. Right now, I would like to know a reason how come. I've test on other site (such as Mozilla) code editor but it only return the same result.

Star Light
  • 154
  • 2
  • 8
  • 19

3 Answers3

2

this in javascript has only function scope, i.e, it points to the object where the currently executing function resides. If you do not have such an object, i.e. you are at the top level, then this, in a browser, generally points to the window object.

So, while your object is being constructed, this is not actually your object, but something else.

Code like this will work:

const person = {
  name: "Wekoslav",
  surname: "Stefanovski",
  getName: function(){
    return this.name + " " + this.surname;
  }
}

console.log(person.getName());

because I'm calling the getName function only after I've defined it, and within that function, this is bound to person. However, this code:

const person = {
  name: "Wekoslav",
  surname: "Stefanovski",
  fullName: this.name + " " + this.surname;
}

console.log(person.fullName);

won't work, because this is bound to whatever it was before the const person line got executed.

SWeko
  • 30,434
  • 10
  • 71
  • 106
0

document.getElementsByClassName('box') is incorrect and return null in this case. That function returns elements which have all of the classes specified in the first argument as a space-separated string. You can use document.querySelectorAll('.box').

Ali Soltani
  • 9,589
  • 5
  • 30
  • 55
  • dude, it returns an HTML collection and it's an object, so there's nothing wrong with what he's doing, only that he's calling `this` inside the object initialization – Roljhon Feb 06 '18 at 08:51
  • @Roljhon Did you test `document.getElementsByClassName('box')` in console? It returns null. – Ali Soltani Feb 06 '18 at 08:53
  • dude, it didn't :) probably you're executing the code outside of the iframe if you're testing it from the fiddle above. – Roljhon Feb 06 '18 at 08:55
0

main reson is you are still initializing you Box object hence you can't access this. In other words your object is not fully formed at the time you are using this.

what you can do is create a function and return it.

boxes: function() {
  return function() { return this.boxes.length; },
}

I created a jsfiddle with improvements. https://jsfiddle.net/jz1thu26/.

also note that you need to run your method when DOM is ready.

Ryxle
  • 880
  • 7
  • 21
  • this is not going to work. again `this` will not point to the box object, it will likely be undefined or the Window object, if you tried it then you will know Edited: Sweko was right – Roljhon Feb 06 '18 at 08:56
  • 2
    Yes, you will need a regular function, as the fat arrow does not define its own `this` – SWeko Feb 06 '18 at 08:58
  • @SWeko forgot about that :) awesome! – Roljhon Feb 06 '18 at 08:59