2015-12-04 7 views
7

Per esempio:È possibile modificare il nome di un tipo di oggetto in JavaScript?

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

Ora considerare questo:

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

posso ignorare il metodo toString(), ma non davvero rinominare il tipo di oggetto. E 'solo un pò finge esso:

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

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

Tuttavia, h4x0rs l33t sanno il mio metodo toString() è una bugia e io sono un n00b:

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

Quello che vorrei che il risultato sia, a prescindere dal toString() metodo viene sovrascritto sul prototipo:

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

è possibile?

+0

ho fatto funzionare;) – CoderPi

risposta

6

La specifica ECMAScript 2015 definisce un noto Symbol, che può essere utilizzato per controllare questo comportamento: Symbol.toStringTag. Sfortunatamente no browser currently support it.

Una volta che è supportato, si sarà in grado di utilizzare in questo modo:

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

che produrrà il vostro comportamento previsto:

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

A partire dal [V8 rilasciare 4.9] (http://v8project.blogspot.hr /2016/01/v8-release-49.html) questa funzione è disponibile, quindi dovrebbe ridursi a Nodo e Chrome a partire da quest'anno. –

0

perché Object.prototype.toString restituisce [[Classe ]] proprietà interna della classe e il valore della proprietà interna [[Classe]] è definito dalla specifica es5 per ogni tipo di oggetto incorporato come Date, Regexp .. E nelle specifiche non è possibile trovare alcun modo per accedi a questa proprietà. Questa proprietà si utilizza per impostare la differenza tra gli oggetti incorporati, pertanto l'override di toString non può modificare la proprietà [[Classe]] e risultare sempre [oggetto oggetto]. Più dettagliato come funziona toString http://es5.github.io/#x15.2.4.2

2

Sì. Ma lasciatemi spiegare prima il problema: non stai usando lo .toString() della tua stessa classe, ma lo toString() di Object che ha la sua propria definizione e non restituisce lo toString() del tuo oggetto.

ho due soluzioni per voi *: (entrambi testate in Bordo, Chrome, Firefox, IE9-11)

Soluzione 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

Soluzione 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

  • Mi ci sono voluti solo due ore per capirlo
+2

Interrompe toString su oggetti generici: '({}). ToString()' comporterà un errore di stack di chiamate superato. –

+0

@NoahFreitas Risolto il problema – CoderPi

Problemi correlati