是否可以在JavaScript中更改对象类型的名称?

时间:2015-12-04 22:13:51

标签: javascript oop

例如:

Object.prototype.toString.call(new Date); // [object Date]
Object.prototype.toString.call(new Array); // [object Array]
Object.prototype.toString.call(new Object); // [object Object]

现在考虑一下:

var PhoneNumber = function(number) {
    this.number = number;
}

我可以覆盖toString()方法,但它不会真正重命名对象类型。它只是假装它:

PhoneNumber.prototype.toString = function() {
    return '[object PhoneNumber]';
}

new PhoneNumber().toString(); // [object PhoneNumber]

然而,l33t h4x0rs知道我的toString()方法是谎言而且我是n00b:

Object.prototype.toString.call(new PhoneNumber); // [object Object]

无论在原型上覆盖toString()方法,我希望得到的结果是什么:

 Object.prototype.toString.call(new PhoneNumber); // [object PhoneNumber]

这可能吗?

3 个答案:

答案 0 :(得分:6)

ECMAScript 2015规范定义了一个众所周知的Symbol,可用于控制此行为:Symbol.toStringTag。不幸的是no browser currently support it

支持后,您就可以像这样使用它:

PhoneNumber.prototype[Symbol.toStringTag] = 'PhoneNumber';

这将产生您预期的行为:

new PhoneNumber().toString(); // [object PhoneNumber]
Object.prototype.toString.call(new PhoneNumber); // [object PhoneNumber]

答案 1 :(得分:2)

是。但是,让我先解释一下这个问题:你没有使用你班级的.toString(),但是toString() Object的{​​{1}}有它自己的定义并且没有返回toString()你的对象。

我有两个解决方案* :(两者均在Edge,Chrome,Firefox,IE9-11中测试过)

解决方案A

Object.prototype.toString = (function(f) {
  return function() {
    return (this.toString === Object.prototype.toString
            || /\{\s*\[native code\]\s*\}/.test(this.toString.toString())
           ) ? f.call(this) : this.toString()
  }
})(Object.prototype.toString) // or just {}.toString


var PhoneNumber = function(number) {
  this.number = number;
}

PhoneNumber.prototype.toString = function() {
  return '[object PhoneNumber]';
}

document.writeln(Object.prototype.toString.call(new PhoneNumber))
document.writeln(Object.prototype.toString.call(Function()))
document.writeln(Object.prototype.toString.call(Array()))
document.writeln(Object.prototype.toString.call(window))
document.writeln(Object.prototype.toString.call(new Date))
document.writeln(Object.prototype.toString.call(1))
document.writeln(Object.prototype.toString.call(null))
document.writeln(Object.prototype.toString.call(""))
document.writeln(Object.prototype.toString.call(document))
document.writeln(Object.prototype.toString.call(document.createElement("div")))
document.writeln(Object.prototype.toString.call(Object()))
document.writeln(({}).toString()) // check

解决方案B

Object.prototype.toString = (function(f) {
  return function() {
    return (typeof this._toString ===  'undefined') ? f.call(this) : this._toString()
  }
})(Object.prototype.toString)


var PhoneNumber = function(number) {
  this.number = number;
}

PhoneNumber.prototype._toString = function() {
  return '[object PhoneNumber]';
}

document.writeln(Object.prototype.toString.call(new PhoneNumber))
document.writeln(Object.prototype.toString.call(Function()))
document.writeln(Object.prototype.toString.call(Array()))
document.writeln(Object.prototype.toString.call(window))
document.writeln(Object.prototype.toString.call(new Date))
document.writeln(Object.prototype.toString.call(1))
document.writeln(Object.prototype.toString.call(null))
document.writeln(Object.prototype.toString.call(""))
document.writeln(Object.prototype.toString.call(document))
document.writeln(Object.prototype.toString.call(document.createElement("div")))
document.writeln(Object.prototype.toString.call(Object()))
document.writeln(({}).toString()) // check

  • 我只花了两个小时来弄明白

答案 2 :(得分:0)

因为Object.prototype.toString返回类的[[Class]]内部属性,[[Class]]内部属性的值由es5规范定义,用于每种内置对象,如Date,Regexp。 。 在规范中,您找不到任何方法来访问此属性。 此属性用于设置内置对象之间的差异,因此重写toString不能更改[[Class]]属性,结果始终为[object Object]。 更详细的解决方法如何工作http://es5.github.io/#x15.2.4.2