255 votes

Comment fonctionne le mot-clé « this » dans un littéral d’objet JavaScript ?

Je viens de tomber sur une situation intéressante en Javascript. J'ai une classe avec une méthode qui définit plusieurs objets à l'aide de l'objet littéral de la notation. À l'intérieur de ces objets, l' this pointeur est utilisé. À partir du comportement du programme, j'ai déduit que l' this pointeur est en se référant à la classe pour laquelle la méthode a été appelée, et non pas de l'objet en cours de création par le littéral. Cela semble arbitraire, mais c'est la façon dont je voudrais espérer qu'il fonctionne. Est-ce comportement défini? Est-il de la croix-navigateur sécuritaire? Est-il un raisonnement sous-jacent à raison, c'est la façon dont il est au-delà de "la spec dit" (par exemple, est-ce une conséquence de quelques larges décision de conception/philosophie)? Épurée exemple de code:

// inside class definition, itself an object literal, we have this function:
onRender: function() {

	this.menuItems = this.menuItems.concat([
		{
			text: 'Group by Module',
			rptletdiv: this
		},
		{
			text: 'Group by Status',
			rptletdiv: this
		}]);
	// etc
}

Merci!

569voto

Alan Storm Points 82442

Récupérés à partir d'un autre poste de la mine, voici plus d'informations que vous avez toujours voulu savoir au sujet de cette.

Avant de commencer, voici la chose la plus importante à garder à l'esprit à propos de Javascript et de répéter à vous-même quand il ne fait pas de sens. Javascript n'ayant pas de classes. Si quelque chose ressemble à une classe, c'est une astuce. Javascript a des objets et des fonctions. (ce n'est pas précis à 100%, les fonctions sont seulement des objets, mais il peut parfois être utile de penser à eux comme à des choses distinctes)

La cette variable est attaché à des fonctions. Chaque fois que vous appelez une fonction, c' est bénéficier d'une certaine valeur, en fonction de comment vous appelez la fonction. Ceci est souvent appelé l'invocation de modèle.

Il y a quatre façons d'appeler des fonctions en javascript. Vous pouvez appeler la fonction comme une méthode, comme une fonction, en tant que constructeur, et à appliquer.

En tant que Méthode

Une méthode est une fonction qui est attachée à un objet

var foo = {};
foo.someMethod = function(){
    alert(this);
}

Lorsqu'il est invoqué comme une méthode, ce sera lié à l'objet de la fonction/méthode est une méthode de. Dans cet exemple, ce sera lié à toto.

En Fonction

Si vous avez un stand alone de la fonction, cette variable est lié à la "global" de l'objet, presque toujours la fenêtre de l' objet dans le contexte d'un navigateur.

 var foo = function(){
    alert(this);
 }
 foo();

Ce peut-être ce qui est le déclenchement de vous, mais ne vous sentez pas mal. Beaucoup de gens considèrent que cela est une mauvaise décision de conception. Depuis un callback est appelée comme une fonction et non pas comme une méthode, c'est pourquoi on voit ce qui semble être un comportement incohérent.

Beaucoup de gens contourner le problème en faisant quelque chose comme, euh, ce

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}

On définit une variable qui qui des points pour cela. Fermeture (un sujet tout propre) assure que , si vous appelez de la barre de rappel, il a encore une référence.

En tant que Constructeur

Vous pouvez également appeler une fonction en tant que constructeur. Basé sur la convention de nommage que vous utilisez (TestObject), cela aussi peut être ce que vous êtes en train de faire et c'est ce qui est le déclenchement de vous.

Vous appelez une fonction, comme un Constructeur avec le mot clé new.

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();

Lorsqu'il est invoqué comme un constructeur, un nouvel Objet sera créé, et ce sera lié à cet objet. Encore une fois, si vous avez les fonctions internes et elles sont utilisées comme des rappels, vous serez en invoquant comme des fonctions, et ce sera lié à l'objet global. Utiliser var que = ce truc/pattern.

Certaines personnes pensent que le constructeur/nouveau mot-clé d'un os jeté à Java/traditionnel de la programmation orientée objet programmeurs comme un moyen de créer quelque chose de semblable à des classes.

Avec la Méthode Appliquer.

Enfin, chaque fonction a une méthode (oui, les fonctions sont des objets en Javascript) nommé "appliquer". Appliquer vous permet de déterminer quelle est la valeur de ce sera, et vous permet aussi de passer un tableau d'arguments. Voici un exemple inutile.

function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);

36voto

insin Points 19509

Les appels de fonction

Les fonctions sont juste un type d'Objet.

Tous les objets de Fonction ont appel et appliquer des méthodes d'exécuter la Fonction de l'objet qu'ils sont appelés sur.

Lorsqu'il est appelé, le premier argument de ces méthodes spécifie l'objet qui va être référencé par l' this mot-clé lors de l'exécution de la Fonction - si c'est l' null ou undefined, l'objet global, window, est utilisé pour l' this.

Ainsi, l'appel d'une Fonction...

whereAmI = "window";

function foo()
{
    return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}

...avec des parenthèses - foo() - est équivalent à foo.call(undefined) ou foo.apply(undefined), ce qui est effectivement le même que foo.call(window) ou foo.apply(window).

>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"

Des arguments supplémentaires à l' call sont passés comme arguments à l'appel de la fonction, tandis qu'un seul argument supplémentaire pour apply pouvez spécifier les arguments de l'appel de fonction dans un Tableau comme objet.

Ainsi, foo(1, 2, 3) est équivalent à foo.call(null, 1, 2, 3) ou foo.apply(null, [1, 2, 3]).

>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"

Si une fonction est une propriété d'un objet...

var obj =
{
    whereAmI: "obj",
    foo: foo
};

...l'accès à une référence à la Fonction via l'objet et de l'appeler avec des parenthèses - obj.foo() - est équivalent à foo.call(obj) ou foo.apply(obj).

Cependant, les fonctions de tenue comme des propriétés des objets ne sont pas "liés" à ces objets. Comme vous pouvez le voir dans la définition de l' obj - dessus, car les Fonctions sont juste un type d'Objet, ils peuvent être référencés (et peut donc être transmis par référence à un appel de Fonction ou retourné par référence à partir d'un appel de Fonction). Lorsqu'une référence à une Fonction est passé, aucune information supplémentaire sur l'endroit où il était passé de est emporté avec elle, c'est pourquoi les cas suivants:

>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"

L'appel à notre Fonction de référence, baz, n'est pas de fournir un contexte pour l'appel, donc c'est effectivement la même que baz.call(undefined), alors this finit référencement window. Si nous voulons baz à savoir qu'il appartient à l' obj, nous avons besoin de quelque manière que l'information lors de l' baz est appelé, qui est l'endroit où le premier argument call ou apply et de fermetures entrent en jeu.

La portée des chaînes

function bind(func, context)
{
    return function()
    {
        func.apply(context, arguments);
    };
}

Lorsqu'une Fonction est exécuté, il crée un nouveau champ d'application et a une référence à un cadre englobant. Lorsque la fonction anonyme est créé dans l'exemple ci-dessus, il a une référence vers la portée, il a été créé, qui est - binds'portée. Ceci est connu comme une "fermeture".

[global scope (window)] - whereAmI, foo, obj, baz
    |
    [bind scope] - func, context
        |
        [anonymous scope]

Lorsque vous essayez d'accéder à une variable du champ d'application de la chaîne d'" est parcouru de trouver une variable avec le nom donné - si le champ ne contient pas la variable, vous regardez à la prochaine portée dans la chaîne, et ainsi de suite jusqu'à ce que vous atteindre une portée globale. Lorsque la fonction anonyme est retourné et bind issue de l'exécution, la fonction anonyme a encore une référence à l' binds'étendue, binds'étendue de ne pas "s'en aller".

Compte tenu de tous les ci-dessus, vous devriez maintenant être en mesure de comprendre comment étendue fonctionne dans l'exemple suivant, et pourquoi la technique pour le passage d'une fonction autour de "pré-lié" avec une valeur particulière de l' this il aura lorsqu'il est appelé œuvres:

>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"

10voto

GreenWebDev Points 450

Ce thème possède quelques grandes informations sur le mot clé « this » et son champ d’application, ainsi que quelques autres bizarreries de JavaScript et des choses à regarder dehors pour.

9voto

Rakesh Pai Points 9905

Est-ce comportement défini? Est-il croix-navigateur sécuritaire?

Oui. Et oui.

Est-il le raisonnement sous-jacent pourquoi c'est la façon dont il est...

Le sens de l' this est assez simple d'en déduire:

  1. Si this est utilisé à l'intérieur d'un constructeur de la fonction, et la fonction a été appelée avec l' new mot-clé, this fait référence à l'objet qui sera créé. this continuera à dire l'objet même dans les méthodes publiques.
  2. Si this est utilisé n'importe où ailleurs, y compris imbriquée protégé fonctions, il se réfère à la portée globale (qui, dans le cas du navigateur est l'objet de la fenêtre).

Le deuxième cas est de toute évidence un défaut de conception, mais il est assez facile de le contourner en utilisant les fermetures.

4voto

Santiago Cepas Points 2127

Dans ce cas, le cercle intérieur est lié à l’objet global au lieu de la variable de la fonction externe. C’est la façon dont le langage est conçu.

Voir « JavaScript : The Good Parts » par Douglas Crockford pour une bonne explication.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X