2010-06-12 15 views
0

Je suis très confus avec les méthodes javascript définies dans les objets et le mot clé "this".objet littéral de la fonction constructeur renvoie la méthode toString() mais aucune autre méthode

Dans l'exemple ci-dessous, la méthode toString() est appelée lorsque l'objet des mammifères instancié:

function Mammal(name){ 
this.name=name; 
this.toString = function(){ 
    return '[Mammal "'+this.name+'"]'; 

} 
} 

var someAnimal = new Mammal('Mr. Biggles'); 
alert('someAnimal is '+someAnimal); 

Malgré le fait que la méthode toString() n'est pas invoqué le someAnimal objet comme celui-ci:

alert('someAnimal is '+someAnimal.toString()); 

Il retourne toujours 'someAnimal is [Mammal "M. Biggles"]'. Cela n'a aucun sens car la fonction toString() n'est appelée nulle part.

Puis pour ajouter encore plus de confusion, si je change la méthode toString() à une méthode que je me maquille comme le hasard():

function Mammal(name){ 
this.name=name; 
this.random = function(){ 
    return Math.floor(Math.random() * 15); 
} 
} 

var someAnimal = new Mammal('Mr. Biggles'); 
alert(someAnimal); 

Il ignore complètement la méthode aléatoire (en dépit du fait que est défini de la même manière que la méthode toString() était) et retourne: [object object]

Un autre problème que j'ai de la difficulté à comprendre avec l'héritage est la valeur de "this". Par exemple, dans l'exemple ci-dessous

function person(w,h){ 
    width.width = w; 
    width.height = h; 
} 

function man(w,h,s) { 
person.call(this, w, h); 
    this.sex = s; 
} 

Ce mot clé est envoyé clairement à l'objet Personne. Cependant, est-ce que "ceci" fait référence à la sous-classe (homme) ou à la super classe (personne) quand l'objet personne la reçoit?

Merci d'avoir éliminé la confusion que j'ai avec l'héritage et les littéraux d'objets en javascript.

+0

'toString' est une méthode spéciale. Il est implicitement appelé pour obtenir une représentation sous forme de chaîne de l'objet lorsque cela est requis comme dans l'appel 'alert'. 'random 'est juste une méthode que vous avez créée et qui n'a pas de sens ou de traitement particulier, donc rien n'est fait. – Anurag

Répondre

3

Le comportement que vous rencontrez avec la méthode toString est causée parce que quand vous faites une concaténation de chaîne , l'objet est converti implicitement à la chaîne (par le fonctionnement interne ToPrimitive, en utilisant le type d'indice « String »). Cette méthode appelle une autre opération interne, [[DefaultValue]](hint).

Si le indice de type est String, cette opération obtient explicitement la propriété toString et l'invoque.

Si votre objet ne définit pas explicitement une méthode toString, la méthode sera toujours résolue plus haut dans la chaîne prototype, "[object Object]" est le résultat de la méthode Object.prototype.toString.

Par exemple:

var obj = { 
    toString:function() { 
    return "hello"; 
    } 
}; 

alert(obj + ' world'); 
// will alert "hello world" 

Maintenant, à propos de la valeur this:

La façon dont vous construisez vos objets est également connu comme constructeur enchaînant, la valeur this se référera à un nouvel objet qui hérite du prototype du constructeur que vous avez appelé avec l'opérateur new.

L'invocation de l'autre constructeur avec call fera juste que toutes les affectations de propriétés faites à la valeur this dans la fonction appelée, sont en fait sur le nouvel objet à partir du premier constructeur, qui ne touche pas vraiment le prototype chaîne, par exemple:

function Person(w,h){ 
    this.width = w; 
    this.height = h; 
} 

function Man(w,h,s) { 
    Person.call(this, w, h); // will just apply the width and height assignments 
    this.sex = s; 
} 

var person = new Person(1,2); 
person instanceof Person; // true 
person instanceof Man; // false 

var man = new Man(1,2,3); 
person instanceof Person; // false 
person instanceof Man; // true 

Edit: pour clarifier plus, lorsque vous invoquez Person.call(this, ...); il appelle simplement cette fonction pour les cessions de propriétés de la valeur this (this.width et this.height sur votre exemple) sur cette fonction , à l'objet passé comme premier argument de call, un exemple simplifié:

function Test() { 
    this.foo = 1; 
    this.bar = 2; 
    this.baz = 3; 
} 

var obj = { foo: 0 }; // a simple object 
Test.call(obj); 
// now obj looks like this: {foo: 1, bar: 2,baz: 3} 
+0

Merci, savez-vous si "ceci" fait référence à l'objet man ou à l'objet personne dans l'exemple ci-dessus, où l'homme est hérité de la personne (man.prototype = new person(); man.prototype.constructor = man;)? – JohnMerlino

+0

@John: 'man' n'hérite pas de' Person.prototype', lorsque vous appelez 'Person.call (this, ...);' les affectations ('this.width = w;' et 'this.height = h; ') sont faites à la valeur' this' dans le constructeur 'Man', comme je l'ai dit, cela n'affecte pas la chaîne du prototype (regardez la sortie de l'opérateur' instanceof' que j'inclus). – CMS