Définir facilement «cette» variable?

139

J'ai une assez bonne compréhension de Javascript, sauf que je ne peux pas trouver une bonne façon de définir la variable "this". Considérer:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body; //using body as example object
someObj.foo_variable = "hi"; //set foo_variable so it alerts

var old_fn = someObj.fn;   //store old value
someObj.fn = myFunction;   //bind to someObj so "this" keyword works
someObj.fn();              
someObj.fn = old_fn;       //restore old value

Y a-t-il un moyen de faire cela sans les 4 dernières lignes? C'est plutôt ennuyeux ... j'ai essayé de lier une fonction anonyme, que je trouvais belle et intelligente, mais en vain:

var myFunction = function(){
    alert(this.foo_variable);
}

var someObj = document.body;        //using body as example object
someObj.foo_variable = "hi";        //set foo_variable so it alerts
someObj.(function(){ fn(); })();    //fail.

Évidemment, passer la variable dans myFunction est une option ... mais ce n'est pas le but de cette question.

Merci.

Erik Philips
la source

Réponses:

221

Il existe deux méthodes définies pour toutes les fonctions dans JavaScript call(), et apply(). La syntaxe de la fonction ressemble à:

call( /* object */, /* arguments... */ );
apply(/* object */, /* arguments[] */);

Ce que ces fonctions font est d' appeler la fonction qu'ils ont été invoquées sur, affectant la valeur de l' objet paramètre à ce .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Pour votre propre bien
la source
3
De plus, si vous utilisez jQuery, vous pouvez l'utiliser $.proxy(function, element)pour que chaque fois que cette fonction est appelée, ce soit dans le contexte de element. api.jquery.com/jquery.proxy
Trevin Avery
Une autre méthode utile est.bind()
Soroush Falahati
55

Je pense que vous recherchez call:

myFunction.call(obj, arg1, arg2, ...);

Cela appelle myFunctionavec thisset to obj.

Il existe également la méthode légèrement différente apply, qui prend les paramètres de la fonction comme un tableau:

myFunction.apply(obj, [arg1, arg2, ...]);
qc
la source
1
Voir les sections 15.3.4.3, 15.3.4.4 et 10.1.8 dans ECMAScript Language Specification: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
certains
18

Si vous souhaitez `` stocker '' la thisvaleur dans une fonction afin de pouvoir l'appeler plus tard de manière transparente (par exemple lorsque vous n'avez plus accès à cette valeur), vous pouvez le bindfaire (pas disponible dans tous les navigateurs cependant):

var bound = func.bind(someThisValue);

// ... later on, where someThisValue is not available anymore

bound(); // will call with someThisValue as 'this'
pimvdb
la source
7
FYI bindest apparemment disponible dans IE9 +, FF4 +, Safari 5.1.4+ et Chrome 7+ (source) . Vous pouvez également appeler bind directement sur une fonction anonyme:var myFunction = function(){ /* this = something */ }.bind(something);
Adam
1

Ma recherche sur la façon de lier thism'a amené ici, donc je publie mes résultats: Dans «ECMAScript 2015», nous pouvons également définir ce lexicalement à l'aide des fonctions fléchées.

Voir: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Au lieu de:

function Person() {
  setInterval(function growUp() {
    // The callback refers to the `self` variable of which
    // the value is the expected object.
    this.age++;
  }.bind(this), 1000);
}

Nous pouvons maintenant faire:

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();
Daniel Sokolowski
la source
0

Définition du thismot - clé en javascript.

Javascript a 3 méthodes intégrées pour définir le thismot - clé de manière pratique. Ils sont tous situés sur l' Function.prototypeobjet afin que chaque fonction puisse les utiliser (puisque chaque fonction hérite de ce prototype via l'héritage prototypique). Ces fonctions sont les suivantes:

  1. Function.prototype.call(): Cette fonction prend l'objet que vous souhaitez utiliser comme thispremier argument. Ensuite, le reste des arguments sont les arguments respectifs de la fonction qui est appelée.
  2. Function.prototype.apply(): Cette fonction prend l'objet que vous souhaitez utiliser comme thispremier argument. Ensuite, le deuxième argument est un tableau qui contient les valeurs des arguments de la fonction qui est appelée (le premier élément du tableau est le premier argument de la fonction, le deuxième argument du tableau est le deuxième argument de la fonction etc.).
  3. Function.prototype.bind(): Cette fonction renvoie une nouvelle fonction qui a une valeur différente de this. Il prend l'objet que vous souhaitez définir comme thisvaleur comme premier argument, puis renvoie un nouvel objet fonction.

Différence entre call / apply et bind:

  • callet applysont similaires dans le fait qu'ils appellent immédiatement la fonction (avec une valeur prédéfinie de this)
  • bindest différent callet applydans le fait que cette fonction renvoie une nouvelle fonction avec une liaison différente de la thisvaleur.

Exemples:

const thisObj = {
  prop1: 1,
  prop2: 2,
};

function myFunc(arg1, arg2) {
  console.log(this.prop1, this.prop2);
  console.log(arg1, arg2);
}

// first arg this obj, other arguments are the  
// respective arguments of the function
myFunc.call(thisObj, 'Call_arg1', 'Call_arg2');

// first arg this obj, other argument is an array which  
// are the respective arguments of the function
myFunc.apply(thisObj, ['Apply_arg1', 'Apply_arg2']);


// the bind method returns a new function with a different
// this context which is stored in the newMyFunc variable
const newMyFunc = myFunc.bind(thisObj);

// now we can call the function like a normal function 
newMyFunc('first', 'second');

Willem van der Veen
la source