Czy łatwo ustawić „tę” zmienną?

139

Dobrze rozumiem JavaScript, poza tym, że nie mogę znaleźć dobrego sposobu na ustawienie zmiennej „this”. Rozważać:

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

Czy można to zrobić bez ostatnich 4 wierszy? To dość denerwujące ... Próbowałem przypisać anonimową funkcję, którą uważałem za piękną i sprytną, ale bezskutecznie:

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.

Oczywiście przekazanie zmiennej do myFunction jest opcją ... ale nie o to chodzi w tym pytaniu.

Dzięki.

Erik Philips
źródło

Odpowiedzi:

221

Istnieją dwie metody zdefiniowane dla wszystkich funkcji w JavaScript call(), i apply(). Składnia funkcji wygląda następująco:

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

Co te funkcje zrobić, to wywołać funkcję oni powoływać na przypisanie wartości obiektu parametr do tego .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Dla Twojego dobra
źródło
3
Ponadto, jeśli używasz jQuery, możesz użyć $.proxy(function, element)tak, aby za każdym razem, gdy ta funkcja była wywoływana, była w kontekście elementu. api.jquery.com/jquery.proxy
Trevin Avery
Inną przydatną metodą jest.bind()
Soroush Falahati
55

Myślę, że szukasz call:

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

To wywołuje myFunctionz thisustawionym na obj.

Istnieje również nieco inna metoda apply, która przyjmuje parametry funkcji jako tablicę:

myFunction.apply(obj, [arg1, arg2, ...]);
sth
źródło
1
Zobacz sekcje 15.3.4.3, 15.3.4.4 i 10.1.8 w specyfikacji języka ECMAScript: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
około
18

Jeśli chcesz `` przechowywać '' thiswartość w funkcji, aby móc ją później bezproblemowo wywołać (np. Gdy nie masz już dostępu do tej wartości), możesz to bindzrobić (jednak nie we wszystkich przeglądarkach):

var bound = func.bind(someThisValue);

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

bound(); // will call with someThisValue as 'this'
pimvdb
źródło
7
FYI bindjest najwyraźniej dostępne w IE9 +, FF4 +, Safari 5.1.4+ i Chrome 7+ (źródło) . Możesz również wywołać bind bezpośrednio na anonimowej funkcji:var myFunction = function(){ /* this = something */ }.bind(something);
Adam
1

Moje poszukiwanie sposobu wiązania thisdoprowadziło mnie tutaj, więc publikuję swoje wyniki: W 'ECMAScript 2015' możemy również ustawić to leksykalnie za pomocą funkcji strzałek na.

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

Zamiast:

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);
}

Teraz możemy:

function Person(){
  this.age = 0;

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

var p = new Person();
Daniela Sokołowskiego
źródło
0

Ustawienie thissłowa kluczowego w javascript.

Javascript ma 3 wbudowane metody do thiswygodnego ustawiania słowa kluczowego. Wszystkie znajdują się na Function.prototypeobiekcie, więc każda funkcja może z nich korzystać (ponieważ każda funkcja dziedziczy po tym prototypie poprzez dziedziczenie prototypowe). Te funkcje są następujące:

  1. Function.prototype.call(): Ta funkcja przyjmuje obiekt, którego chcesz użyć jako thispierwszego argumentu. Wówczas pozostałe argumenty są odpowiednimi argumentami wywoływanej funkcji.
  2. Function.prototype.apply(): Ta funkcja przyjmuje obiekt, którego chcesz użyć jako thispierwszego argumentu. Wtedy drugim argumentem jest tablica zawierająca wartości argumentów wywoływanej funkcji (pierwszy element tablicy to pierwszy argument funkcji, drugi argument tablicy to drugi argument funkcji itd.).
  3. Function.prototype.bind(): Ta funkcja zwraca nową funkcję, która ma inną wartość this. Pobiera obiekt, który chcesz ustawić jako thiswartość jako pierwszy argument, a następnie zwraca nowy obiekt funkcji.

Różnica między zadzwoń / zastosuj i połącz:

  • calli applysą podobne w tym, że natychmiast wywołują funkcję (z predefiniowaną wartością this)
  • bindróżni się calli applytym, że ta funkcja zwraca nową funkcję z innym powiązaniem thiswartości.

Przykłady:

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
źródło