When is toString() get called implicitly in javascript? - Stack Overflow

With reference to below code written in Javascript.let a = {value: 2,toString: function() {return ++thi

With reference to below code written in Javascript.

let a = {
    value: 2,
    toString: function() {
        return ++this.value;
    }
}
if (a == 3 && a == 4) {
    console.log('Condition is true');
}

With reference to below code written in Javascript.

let a = {
    value: 2,
    toString: function() {
        return ++this.value;
    }
}
if (a == 3 && a == 4) {
    console.log('Condition is true');
}

The output is "Condition is true". Looks like it invokes toString() function. But how?

When I replace "==" with "===", condition does not evaluates to true and it does not invoke toString() function this time?

Can someone explain me in detail what's going under the hood?

Share Improve this question edited Apr 26, 2018 at 6:52 Durga 15.6k2 gold badges30 silver badges54 bronze badges asked Apr 26, 2018 at 6:44 NaveenNaveen 3713 silver badges9 bronze badges 4
  • stackoverflow./questions/359494/… – gvmani Commented Apr 26, 2018 at 6:45
  • 1 Possible duplicate of Which equals operator (== vs ===) should be used in JavaScript parisons? – user9420984 Commented Apr 26, 2018 at 6:46
  • 1 Doesn't print anything for me – Jagdeep Singh Commented Apr 26, 2018 at 6:46
  • 2 I don't think that would be evaluated to true. – Jai Commented Apr 26, 2018 at 6:49
Add a ment  | 

7 Answers 7

Reset to default 2

Happen to notice that toString is invoked in interpolated string, executed prioritized than valueOf

var a = {
    value: 1000,
    toString: () => 'call toString method',
    valueOf: () => 'call valueOf method'
};

console.log(`interpreted value: ${a}`); // interpreted value: call toString method

When you do == it is not a strict parison so what it does for the condition a == 3 && a == 4, is that first it pares a == 3. Since, it is not a strict parison, it will change a to string. And since you have toString() in a, that will increment the value of a from 2 to 3 and hence a == 3 result in true. Then, a == 4 checks the same way and this time the value of a is 3 so when it checks for a == 4 it results in true by invoking the toString() function of a.

let a = {
  value: 2,
  toString: function() {
    return ++this.value;
  }
}
if (a == 3 && a == 4) {
    console.log('Condition is true');
}

However, when you use ===, it works as a strict parison and the type of LHS should match RHS. Thus, a is a object in LHS and there is a number type in RHS, so it results false for a == 3 and hence, a == 3 && a == 4

let a = {
  value: 2,
  toString: function() {
    return ++this.value;
  }
}
if (a === 3 && a === 4) {
  console.log('Condition is true');
} else {
  console.log('Condition is false');
}

The output is "Condition is true". Looks like it invokes 'toString()' function.

Everytime you use == operator between two variables with different types it is invoked internally toString method which will coerce one member. Have a look at type coercion

But how?

You're creating a custom toString function for your a object that changes what it returns each time it is used such that it satisfies all two conditions. You can also use valueOf method.

How about === operator ?

Otherwise, the === operator will not do the conversion.

What means this ?

If you're using === operator with two values with different type === will simply return false.

In addition to Mihai's answer, === is a strict typechecking equality operator which checks for the type of the operands and the values as well.

In your case, the type of a is an object, whereas 3 and 4 are numbers. So the condition doesn't evaluate to true.

it checks whether object has falsy value or not when you use == thats why you get true from a == 4 and a == 3. Have a look at type coercion. It does not coerce variables when paring them and thats why you cannot get into the block statement

You can find detail information of how '==' and '===' works in javascript from link below: Equality parisons and sameness

In this URL refer 'Loose equality using ==' section.

In you case your parison as a == 3. a is object and 3 is number. So parison will take place as ToPrimitive(a) == 3. What ToPrimitive(a) do is it attempting to invoke varying sequences of a.toString and a.valueOf methods on A. This is how your toString function is called.

On the surface your question looks like the sheer difference between == and === operators, but in fact there is bit more to it.

For your first question, since javascript is not strictly typed language, there is 2 operators, == will try to convert the left operand to right ones type if possible whereas === will give false if the types are different with the exception of NaN.

A more interesting question is when toString method gets called. Normally when you create an object, either by typing an object literal or through a constructor, it will inherit toString from the Object, you easily check this:

var u = function(){};
var w = {};
u.prototype.toString === Object.prototype.toString //true
w.toString === Object.prototype.toString //true as well

Now what you might forget is that there is also a valueOf method:

u.prototype.valueOf === Object.prototype.valueOf //true
w.valueOf === Object.prototype.valueOf //true as well

But what does it do? I points to itself:

w.valueOf === w //true
u.prototype.valueOf() === u.prototype //true as well

So when an object is given, the first choice is to use the toString becuae valueOf will result in the object itself. What does toString give by default? it can depend on what is there on its prototype chain:

w.toString() //"[object Object]"
u.toString() //"function (){}"
u.prototype.toString.call(u) //"[object Function]"

So by default the first choice is to use the nearest toString method of the object. Now to see what happens if we override BOTH valueOf and toString, let me construct this object:

 var x = {
    inner:10,
    ledger:[],
    result:[],
    timeout:0,
    toString:function(){
        console.log("String");
        clearTimeout(this.timeout);
        this.timeout = setTimeout((function(){
            this.result = this.ledger;
            this.ledger = []}).bind(this)
        ,0) ;
        this.ledger.push("toString");
        this.ledger.slice(-2);
        return String(this.inner);
    },
    valueOf:function(){
        console.log("Valueof");
        clearTimeout(this.timeout);
        this.timeout = setTimeout((function(){
            this.result = this.ledger;
            this.ledger = []}).bind(this)
        ,0) ;
        this.ledger.push("valueOf");
        this.ledger.slice(-2);
        return this.inner;
    }
}

This object will keep a "ledger", an array of valueOf or toString or both called during type conversion. It will also console.log. So,here are some operations that will trigger type conversion just like ==:

 +x //10
//ValueOf

"5" + x //"510"
//ValueOf

x + [] //10
//ValueOf

x + "str"//"10str"
//ValueOf

x.toString() //"10"
//String

String(x) //"10"
//String

x + {u:""} //"10[object Object]"
//valueOf

So in many cases if a non-default valueOf is found that is used. If the right operand is a string, then the returned value from valueOf is converted to string rather than toString on the object. To override default behavior you can force call to string by using toString or String( as shown in the examples. So the priority list goes as:

Custom valueOf >> custom toString >> default toString >>>> default valueOf

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744717816a4589725.html

相关推荐

  • When is toString() get called implicitly in javascript? - Stack Overflow

    With reference to below code written in Javascript.let a = {value: 2,toString: function() {return ++thi

    1天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信