使用 ES5 覆盖 toString - 奇怪的行为

Overriding toString Using ES5 - Strange Behaviour

我想使用 ES5 覆盖 toString。给定以下 returns 复数的函数:

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

为了覆盖从 Object 继承的 toString,我执行了以下操作:

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

测试:

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

结果:

{ real: 1, imaginary: 1 }

我是不是漏掉了什么?

有两件事正在发生:

  1. 在很多环境中(包括大多数浏览器),console.log不使用toString,而

  2. 你的complex函数没有return一个使用complex.prototype作为原型的对象,所以它没有你的toString .您正在使用 {} 创建您 return 的对象,它会创建一个直接继承自 Object.prototype.

    的对象

如果您想在不使用 new 的情况下调用 complex,您需要在创建对象时明确使用 complex.prototype,例如通过 Object.create(complex.prototype)。 (然后在记录时,故意触发 toString,直接调用它或以其他各种方式转换为字符串。)

示例:

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));

如果愿意,您可以通过 new 调用 complex(但我猜您是故意不这样做的)。仅 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));

甚至

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));


旁注:我已将上面的“imagenary”更改为“imaginary”,这是英文的正确拼写。 (您的代码中的大部分文本似乎都是英文的,但如果您只是将问题中的代码从另一种语言翻译过来而忘记翻译“imagenary”,我们深表歉意。)