Atur variabel "ini" dengan mudah?

139

Saya memiliki pemahaman yang cukup bagus tentang Javascript, kecuali bahwa saya tidak dapat menemukan cara yang bagus untuk mengatur variabel "ini". Mempertimbangkan:

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

Apakah ada cara untuk melakukan ini tanpa 4 baris terakhir? Agak menyebalkan ... Saya sudah mencoba mengikat fungsi anonim, yang saya pikir cantik dan pintar, tetapi tidak berhasil:

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.

Jelas, mengirimkan variabel ke fungsi saya adalah sebuah pilihan ... tapi itu bukan poin dari pertanyaan ini.

Terima kasih.

Erik Philips
sumber

Jawaban:

221

Ada dua metode yang ditentukan untuk semua fungsi dalam JavaScript call(),, dan apply(). Sintaks fungsi terlihat seperti:

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

Apa fungsi ini lakukan adalah memanggil fungsi mereka dipanggil, menugaskan nilai parameter objek untuk ini .

var myFunction = function(){
    alert(this.foo_variable);
}
myFunction.call( document.body );
Untuk kebaikan Anda
sumber
3
Selain itu, jika Anda menggunakan jQuery, Anda dapat menggunakan $.proxy(function, element)sehingga kapan pun fungsi itu dipanggil, itu akan berada dalam konteks elemen. api.jquery.com/jquery.proxy
Trevin Avery
Metode lain yang bermanfaat adalah.bind()
Soroush Falahati
55

Saya pikir Anda sedang mencari call:

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

Panggilan ini myFunctiondengan thisdiatur ke obj.

Ada juga metode yang sedikit berbeda apply, yang mengambil parameter fungsi sebagai array:

myFunction.apply(obj, [arg1, arg2, ...]);
sth
sumber
1
Lihat bagian 15.3.4.3, 15.3.4.4 dan 10.1.8 dalam Spesifikasi Bahasa ECMAScript: ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
some
18

Jika Anda ingin 'menyimpan' thisnilai ke suatu fungsi sehingga Anda dapat menyebutnya dengan mulus nanti (mis. Ketika Anda tidak memiliki akses ke nilai itu lagi), Anda bisa bind(tidak tersedia di semua browser):

var bound = func.bind(someThisValue);

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

bound(); // will call with someThisValue as 'this'
pimvdb
sumber
7
FYI bindtampaknya tersedia di IE9 +, FF4 +, Safari 5.1.4+ dan Chrome 7+ (sumber) . Anda juga dapat memanggil bind langsung pada fungsi anonim:var myFunction = function(){ /* this = something */ }.bind(something);
Adam
1

Pencarian saya tentang cara mengikat thismembawa saya ke sini sehingga saya memposting temuan saya: Dalam 'ECMAScript 2015' kita juga dapat mengatur ini secara leksikal menggunakan fungsi panah.

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

Dari pada:

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

Sekarang kita dapat melakukan:

function Person(){
  this.age = 0;

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

var p = new Person();
Daniel Sokolowski
sumber
0

Pengaturan thiskata kunci dalam javascript.

Javascript memiliki 3 metode bawaan untuk mengatur thiskata kunci dengan nyaman. Mereka semua terletak pada Function.prototypeobjek sehingga setiap fungsi dapat menggunakannya (karena setiap fungsi mewarisi dari prototipe ini melalui pewarisan prototypal). Fungsi-fungsi ini adalah sebagai berikut:

  1. Function.prototype.call(): Fungsi ini mengambil objek yang ingin Anda gunakan sebagai thisargumen pertama. Kemudian sisa argumen adalah masing-masing argumen dari fungsi yang disebut.
  2. Function.prototype.apply(): Fungsi ini mengambil objek yang ingin Anda gunakan sebagai thisargumen pertama. Kemudian argumen kedua adalah array yang berisi nilai-nilai argumen fungsi yang disebut (elemen pertama array adalah argumen pertama dari fungsi, argumen kedua array adalah argumen kedua fungsi dll).
  3. Function.prototype.bind(): Fungsi ini mengembalikan fungsi baru yang memiliki nilai berbeda this. Dibutuhkan objek yang ingin Anda tetapkan sebagai thisnilai sebagai argumen pertama dan kemudian mengembalikan objek fungsi baru.

Perbedaan antara panggilan / berlaku dan ikat:

  • calldan applyserupa dalam kenyataan bahwa mereka langsung memanggil fungsi (dengan nilai yang telah ditentukan this)
  • bindberbeda dari calldan applypada kenyataannya bahwa fungsi ini mengembalikan fungsi baru dengan pengikatan thisnilai yang berbeda.

Contoh:

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
sumber