2010-11-23 8 views
2

Pourquoi la fonction d'auto-invocation dans une fonction n'obtient pas la portée de la fonction externe dans JavaScript?Portée de la fonction d'auto-invocation dans Javascript

var prop = "global"; 

var hash = { 
    prop: "hash prop", 
    foo: function(){ 
     console.log(this.prop); 
     (function bar(){ 
      console.log(this.prop); 
     })(); 
    } 
}; 

var literal = { 
    prop: "object" 
}; 

hash.foo(); 
// hash prop 
// global 

hash.foo.call(literal); 
// object 
// global 

On dirait que la modification de la portée de la fonction externe n'a aucun effet sur la portée de la fonction d'auto-invocation interne. PS: La question n'est pas de savoir comment modifier la portée de la fonction interne. Mais quelle est la bonne explication dans la perspective "langage Javascript"? Toutes les fonctions auto-exécutables ont-elles une portée "globale" par défaut? Si oui, pourquoi?

Répondre

1

Vous n'appliquez aucun objet au contexte this lorsque vous appelez la fonction interne. Par conséquent, le this est défini sur window par défaut. Si vous vouliez appeler la fermeture avec le même this que la fonction externe, vous devez faire:

(function bar(){ 
    console.log(this.prop); 
}).call(this); 

Ou:

var that = this; 
(function bar(){ 
    console.log(that.prop); 
})(); 
+0

+1 pour la première solution! –

7

Votre problème est le this et ce qu'il Références:

foo: function(){ 
    console.log(this.prop); 
    (function bar(){ 
     console.log(this.prop); <--- this does not reference to foo here, but instead it refers to the window object 
    })(); 
} 

Vous devez conserver une référence à l'extérieur this:

foo: function(){ 
    console.log(this.prop); 

    var that = this; 
    (function bar(){ 
     console.log(that.prop); <--- tada! 
    })(); 
} 

Mise à jour
Quelques explications. Tout dépend de la façon dont JavaScript détermine le contexte lors de l'appel d'une fonction.

function Test() { 
    this.name = "Test"; 
    this.bar = function() { console.log("My name is: "+ this.name);} 
} 

function Blub() { 
    this.name = "Blub"; 
    this.foo = function() { console.log("My name is: " + this.name);} 
} 

var a = new Test(); 
var b = new Blub(); 

// this works as expected 
a.bar(); // My name is: Test 
b.foo(); // My name is: Blub 

// let's do something fun 
a.foo = b.foo; // make an educated guess what that does... 

a.foo() // My name is: Test 

Huh? Ne faisons-nous pas référence au method de Blub? Non, nous ne sommes pas. Nous référons le function non lié de Blub.

JavaScript lie sur . (points) et sur la base de cela, il décide waht la valeur de this devrait être.

Puisque vous n'appelez pas votre fonction anonyme sur un objet (donc pas .) il fera this référence à l'objet global, qui est - dans le cas du navigateur - l'objet fenêtre.

Un autre exemple (on pourrait penser que cela fonctionnerait):

var str = "Hello World"; 
var ord = str.charCodeAt; // let's make a little shortcut here.... bad idea 

ord(0) // no dot... 

au lieu des codes char qui sont str nous obtenons ceux qui sont l'objet global, bien sûr ce n'est pas une chaîne si charCodeAt appelle toString sur lequel résulte "[object DOMWindow]"

+1

'this' se référera à l'objet global, pas à' bar'. [Plus d'info] (http://stackoverflow.com/questions/4223001/what-does-this-refer-to/4223037#4223037). – CMS

+0

@CMS Ouais petit black out ici, il est assez tard, réparé. –

+0

Dans votre premier exemple, cela ne fait pas référence à "barre". Il référence votre objet racine (l'objet fenêtre si vous êtes dans un navigateur Web) –

Questions connexes