2013-05-01 15 views
7

Così ho un metodo semplice isPlainObject che uso per testare letterali oggetto JavaScript:Perché l'aggiunta di una proprietà al prototipo di un oggetto letterale cambia il suo "tipo"?

var isPlainObject = function (obj) { 
    return typeof obj === "object" && {}.toString.call(obj) === "[object Object]"; 
}; 

Ora ho un oggetto semplice:

var obj = {'one': 1, 'two': 2, 'three': 3}; 

Quando eseguo attraverso la funzione isPlainObject(obj) funziona come previsto e restituisce true. La mia domanda arriva da l'aggiunta di una proprietà per il prototipo dell'oggetto:

obj.constructor.prototype.four = 4; 

Ora, quando corro isPlainObject(obj) su obj restituisce false. typeof obj restituisce object in entrambi i casi. Lo toString restituisce [object Number] nella seconda istanza dopo aver aggiunto una proprietà al prototipo.

Che cosa è successo esattamente per cambiare obj? Cosa sta succedendo?

MODIFICA: Questo accade solo se testato entro i confini di una chiamata di funzione QUnit.

test("each", function() { 

    _.each([1, 2, 3], function(i,v) { 
     equal(v, i + 1, 'each iterator provided index and value from array'); 
    }); 

    var obj = {'one': 1, 'two': 2, 'three': 3}; 
    console.log(_.isPlainObject(obj)); // => true 
    obj.constructor.prototype.four = 4; 
    console.log(_.isPlainObject(obj)); // => false 

}); 

EDIT: Questa è la console.log ottengo quando accede l'oggetto arguments array simile ai isPlainObject.

Logging out the <code>arguments</code> object

Guardando il registro sembrerebbe indicare la matrice ha ora due argomenti. Ma la lunghezza continua a leggere 1.

+9

Quale browser (strano) stai usando? [Mostra 'true' per me ...?] (Http://jsfiddle.net/mattlunn/bR7PX/) – Matt

+0

Sto testando una chiamata a QUnit test(). E hai ragione, ho appena eseguito il test nella console e tutto funziona come previsto. Perché eseguire questo test in QUnit ha questo effetto. Una sorta di problema di ambito? – Xaxis

+4

È vero anche per me. Cosa restituiscono per te 'typeof obj' e' {} .toString.call (obj) '? – Barmar

risposta

1

Chiamando

({}).constructor.prototype 

si sta accedendo il prototipo di tutti gli oggetti. Quindi essenzialmente stai aggiungendo una proprietà "quattro" ad ogni oggetto nativo.

Se si voleva estendere la vostra istanza di un oggetto si avrebbe idealmente bisogno di una nuova funzione di costruzione, come:

var Count = function() { 
    this.one = 1; 
    this.two = 2; 
    this.three = 3; 
} 

var obj = new Count(); 
obj.four = 4; 

O per estendere la funzione di costruzione:

Count.prototype.four = 4; 

Indipendentemente ... Non è sicuro che questo avrebbe rotto QUnit, ma come un altro poster suggeriva hasOwnProperty dovrebbe fare il trucco. Ecco uno similar question

Problemi correlati