1

I was given this code:

if (num == 100 && num== 200 && num==300) {
  console.log('it works!');
}

the condition needs to be true so that it prints "It works!" in the console.

I got these codes here and would really like to know how it works. Also, what's the difference between valueOf and toString?

Any explanation would be much appreciated. Thanks!

const num = {
  value: 0,
  valueOf: function() {
    this.value += 100;
    return this.value;
  }
}
if (num == 100 && num== 200 && num==300) {
  console.log('it works!');
}

-

const num = {
  value: 0,
  toString: function() {
    this.value += 100;
    return this.value;
  }
}
if (num == 100 && num== 200 && num==300) {
  console.log('it works!');
}
R3tep
  • 12,512
  • 10
  • 48
  • 75
Senjiro
  • 31
  • 4
  • 1
    @ilkerkaran But this expression is true in this case – R3tep Sep 26 '19 at 14:49
  • 5
    Possible duplicate of [Can (a== 1 && a ==2 && a==3) ever evaluate to true?](https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true) – James Coyle Sep 26 '19 at 14:51
  • 2
    whenever u call any object with the operator. It calls valueOf to get the primitive value. Whatever return, the operation performs in that value. This is why it is working. Please read here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf – xdeepakv Sep 26 '19 at 14:51
  • @xdeepakv Thanks for the explanation. Also the link is very helpful, thank you so much. – Senjiro Sep 26 '19 at 14:56

2 Answers2

1

Well this is kind of tricky.... but

if (num == 100 && num== 200 && num==300) 

This line will evaluate 'num' each time a comparison is made with it.

Now these lines :

  value: 0,
  toString: function() { // valueOf is the 'same' almost
    this.value += 100;
    return this.value;
  }

define your object, with a value property and a method on them. Each time your object is to be compared, and BECAUSE its not a value type, the engine will look for a 'valueOf' method, if it is not found it will try to call the object's 'toString' method. This takes place 'behind the scenes' for you as the developer.

Now since your evaluator function, and your toString actually increment the "real" value of the object by 100 each time you see the num in the if statement you are incrementing it by 100. So when the first statement is checked num gets its value field +=100, the comparison is made and it passes. Next again when its time for num == 200 it is again increased by 100 ( during evaluation) BEFORE returning control to the comparison execution, so when the time comes to compare the values, it is also true. The third time is again the same concept.

Hope you get what i mean.

TLDR: because num is not a 'value type' the comparator will look for a valueOf or a toString (depending on what type it tries to match on the statement) and your evaluators are incrementing the value behind the scenes!

MKougiouris
  • 2,821
  • 1
  • 16
  • 19
  • i understand this.value +=100 and return this.value but value:0 and toString or valueOf: function() still confuses me. sorry for my slow understanding, i'm new to programming. – Senjiro Sep 26 '19 at 15:04
  • The important missing information, in my opinion, is that `toString` in the second example is invoked because, when evaluating an object, if `valueOf` doesn't return a primitive, `toString` is invoked instead, unless the comparison is hinted against a string, where, in that case, `toString` is invoked first instead. You should add a link to the ECMAScript specification, these informations are deeply written there. – briosheje Sep 26 '19 at 15:22
1

If you add both functions into const, you'll see, that only valueOf is called. If you remove the valueOf than toString will be called. That means, that every time, when you try to compare the object num with some value, javascript tries to

  • find a method valueOf of the object and call it
  • if valueOf method is not found, than call the toString method of the object and then compare it with the scalar value
const num = {
    value: 0,
    valueOf: function () {
        console.log('Called valueOf');
        this.value += 100;
        return this.value;
    },
    toString: function () {
        console.log('Called toString');
        this.value += 100;
        return this.value;
    }
}
if (num == 100 && num == 200 && num == 300) {
    console.log('it works!');
}
Alexey Zelenin
  • 710
  • 4
  • 10