Considérez le code suivant:
function A() {} A.prototype.go = function() { console.log(this); //A { go=function()} var f = function() { console.log(this); //Window }; f(); } var a = new A(); a.go();
Pourquoi '' cette 'dans la fonction' f 'se réfère à la portée globale? Pourquoi ce n'est pas la portée de la fonction 'A'?
JavaScript a un concept différent de ce que le nom spécial se réfère à la plupart des autres langages de programmation. Il existe exactement cinq façons différentes dans lesquelles la valeur de this
peut être liée dans la langue.
this;
Lorsque vous utilisez this
dans une portée globale, il se référera simplement à l'objet global .
foo();
Ici, this
se référera à nouveau à l'objet global .
ES5 Remarque: En mode strict, l'affaire globale n'existe plus .
this
aura plutôt la valeur d'undefined
dans ce cas.
test.foo();
Dans cet exemple, this
se référera au test
.
new foo();
Un appel de fonction qui est précédé par le new
mot-clé agit comme un constructeur. À l'intérieur de la fonction, this
se référera à un nouvel Object
créé .
this
function foo(a, b, c) {} var bar = {}; foo.apply(bar, [1, 2, 3]); // array will expand to the below foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
Lorsque vous utilisez l' call
ou apply
méthodes de Function.prototype
, la valeur de this
valeur dans la fonction appelée est explicitement définie sur le premier argument de l'appel de fonction correspondant.
En conséquence, dans l'exemple ci-dessus, le cas de la méthode ne s'applique pas , et this
intérieur de foo
sera mis en bar
.
Remarque:
this
ne peut pas être utilisé pour désigner l'objet à l'intérieur d'unObject
littéral. Donc,var obj = {me: this}
ne me fera pas référence àobj
, carthis
ne relève que de l'un des cinq cas listés.
Bien que la plupart de ces cas aient du sens, le premier doit être considéré comme une autre mauvaise conception de la langue car il n'a jamais d'utilisation pratique.
Foo.method = function() { function test() { // this is set to the global object } test(); }
Une idée fausse commune est que this
de test
réfère à Foo
; Alors qu'en fait, ce n'est pas le cas .
Afin d'accéder à Foo
partir du test
interne, il est nécessaire de créer une variable locale dans la method
qui se réfère à Foo
.
Foo.method = function() { var that = this; function test() { // Use that instead of this here } test(); }
C'est juste un nom de variable normal, mais il est couramment utilisé pour la référence à un externe. En combinaison avec des fermetures, il peut également être utilisé pour passer this
valeurs autour.
Une autre chose qui ne fonctionne pas dans JavaScript est l'aliasing de la fonction, qui affecte une méthode à une variable.
var test = someObject.methodTest; test();
En raison du premier cas, le test
maintenant comme un appel de fonction simple; Par conséquent, this
ne se rapportera plus à someObject
.
Bien que la contraction tardive de this
puisse sembler une mauvaise idée au début, en fait, c'est ce qui fait que les héritages prototypiques fonctionnent.
function Foo() {} Foo.prototype.method = function() {}; function Bar() {} Bar.prototype = Foo.prototype; new Bar().method();
Lorsque la method
est appelée sur une instance de Bar
, this
se référera maintenant à cette instance même.
Disclaimer: Shamelessy volé de mes propres ressources à http://bonsaiden.github.com/JavaScript-Garden/#function.this
La raison pour laquelle vous appelez f
comme une function
et non comme une method
. Lorsqu'elle est appelée comme une fonction, this
est définie sur la window
lors de l'exécution de la cible
// Method invocation. Invoking a member (go) of an object (a). Hence // inside "go" this === a a.go(); // Function invocation. Invoking a function directly and not as a member // of an object. Hence inside "f" this === window f(); // Function invocation. var example = a.go; example();
La portée de toutes les fonctions est la window
.
Pour contourner cela, vous pouvez le faire:
function A() {} A.prototype.go = function() { var self = this; console.log(self); //A { go=function()} var f = function() { console.log(self); //A { go=function()} }; f(); }
Parce que la fonction f()
n'est pas appelée sans référence d'objet. Essayer,
f.apply(this);