Ayoub Falah
Ayoub Falah

Reputation: 484

Overriding toString Using ES5 - Strange Behaviour

I would like to override toString using ES5. Given the following function which returns a complex number:

function complex(real, imaginary){
    var z = Object.create(complex.prototype);
    z.real = real;
    z.imaginary = imaginary;
    return z;
}

In order to override toString inherited from Object I do the following:

complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};

TEST:

var z = complex(1,1);
console.log(z);

RESULT:

{ real: 1, imaginary: 1 }

Do I miss something?

Upvotes: 1

Views: 271

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074435

There are two things going on:

  1. In many environments (including most browsers), console.log doesn't use toString, and

  2. Your complex function doesn't return an object that uses complex.prototype as its prototype, so it doesn't have your toString. You're creating the object you return using {}, which creates an object directly inheriting from Object.prototype.

If you want to call complex without new, you need to explicitly use complex.prototype when creating your object, for instance via Object.create(complex.prototype). (And then when logging, trigger toString on purpose, either calling it directly or converting to string in various other ways.)

Example:

function complex(real, imaginary){
    var z = Object.create(complex.prototype);
    z.real = real;
    z.imaginary = imaginary;
    return z;
}
complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};

var z = complex(1, 1);
console.log(String(z));

You could call complex via new if you like (but I'm guessing you chose not to on purpose). Just FWIW:

function Complex(real, imaginary){
    this.real = real;
    this.imaginary = imaginary;
}
Complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};

var z = new Complex(1, 1);
console.log(String(z));

or even

class Complex {
    constructor(real, imaginary) {
        this.real = real;
        this.imaginary = imaginary;
    }
    toString() {
        return this.real + " + " + this.imaginary + "*i";
    }
}

const z = new Complex(1, 1);
console.log(String(z));


Side note: I've changed "imagenary" to "imaginary" above, which is the correct spelling in English. (Most of the text in your code seemed to be in English, but apologies if it's just that you translated the code in the question from another language and just forgot to translate "imagenary".)

Upvotes: 3

Related Questions