Pertanyaan Bagaimana cara kerja kata kunci “ini”?


Saya perhatikan bahwa sepertinya tidak ada penjelasan yang jelas tentang apa itu this kata kunci dan bagaimana itu benar (dan salah) digunakan dalam JavaScript di situs Stack Overflow.

Saya telah menyaksikan beberapa perilaku yang sangat aneh dengannya dan telah gagal memahami mengapa hal itu terjadi.

Bagaimana this bekerja dan kapan harus digunakan?


1071
2018-06-27 13:12


asal


Jawaban:


Saya merekomendasikan membaca Mike Westartikel Cakupan dalam JavaScript (cermin) pertama. Ini adalah pengenalan yang sangat baik dan ramah terhadap konsep-konsep this dan rantai lingkup di JavaScript.

Setelah Anda mulai terbiasa thisAturannya sebenarnya cukup sederhana. Itu ECMAScript 5.1 Standar mendefinisikan this:

§11.1.1 Itu this kata kunci

Itu this kata kunci mengevaluasi nilai dari Pengikatan ini dari konteks eksekusi saat ini

ThisBinding adalah sesuatu yang dijaga oleh juru bahasa JavaScript karena mengevaluasi kode JavaScript, seperti register CPU khusus yang menyimpan referensi ke objek. Penerjemah memperbarui Pemblokiran ini setiap kali membuat konteks eksekusi di salah satu dari hanya tiga kasus yang berbeda:

1. Konteks pelaksanaan global awal

Ini adalah kasus untuk kode JavaScript yang dievaluasi pada tingkat teratas, mis. saat langsung di dalam <script>:

<script>
  alert("I'm evaluated in the initial global execution context!");

  setTimeout(function () {
      alert("I'm NOT evaluated in the initial global execution context.");
  }, 1);
</script>

Saat mengevaluasi kode dalam konteks pelaksanaan global awal, Penyatuan Ini diatur ke objek global, window (§10.4.1.1).

Memasukkan kode eval

  • ... dengan panggilan langsung ke eval() ThisBinding dibiarkan tidak berubah; itu adalah nilai yang sama seperti Pemancaran konteks eksekusi panggilan (§10.4.2 (2) (a)).

  • ... jika tidak dengan panggilan langsung ke eval()
    ThisBinding diatur ke objek global seolah-olah mengeksekusi dalam konteks eksekusi global awal (§10.4.2 (1)).

§15.1.2.1.1 mendefinisikan panggilan langsung ke eval() aku s. Pada dasarnya, eval(...) adalah panggilan langsung sedangkan sesuatu seperti (0, eval)(...) atau var indirectEval = eval; indirectEval(...); adalah panggilan tidak langsung ke eval(). Lihat jawaban chuckj untuk (1, eval) ('this') vs eval ('this') di JavaScript? dan Dmitry Soshnikov's ECMA-262-5 secara detail. Bab 2. Mode Ketat. karena ketika Anda mungkin menggunakan tidak langsung eval() panggilan.

Memasukkan kode fungsi

Ini terjadi ketika memanggil suatu fungsi. Jika suatu fungsi dipanggil pada objek, seperti di obj.myMethod() atau yang setara obj["myMethod"](), maka ThisBinding diatur ke objek (obj dalam contoh; §13.2.1). Dalam kebanyakan kasus lain, Penjilidan ini diatur ke objek global (§10.4.3).

Alasan untuk menulis "dalam banyak kasus lain" adalah karena ada delapan fungsi built-in ECMAScript 5 yang memungkinkan Penjilidan untuk ditentukan dalam daftar argumen. Fungsi-fungsi khusus ini mengambil apa yang disebut thisArg yang menjadi Binding Ini saat memanggil fungsi (§10.4.3).

Fungsi-fungsi bawaan khusus ini adalah:

  • Function.prototype.apply( thisArg, argArray )
  • Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
  • Array.prototype.every( callbackfn [ , thisArg ] )
  • Array.prototype.some( callbackfn [ , thisArg ] )
  • Array.prototype.forEach( callbackfn [ , thisArg ] )
  • Array.prototype.map( callbackfn [ , thisArg ] )
  • Array.prototype.filter( callbackfn [ , thisArg ] )

Dalam hal ini Function.prototype fungsi, mereka dipanggil pada objek fungsi, tetapi daripada pengaturan iniBerpisah ke objek fungsi, Mengikat ini diatur ke thisArg.

Dalam hal ini Array.prototype fungsi, yang diberikan callbackfn disebut dalam konteks eksekusi di mana ThisBinding diatur ke thisArg jika disediakan; jika tidak, ke objek global.

Itu adalah aturan untuk JavaScript biasa. Ketika Anda mulai menggunakan pustaka JavaScript (misalnya jQuery), Anda mungkin menemukan bahwa fungsi pustaka tertentu memanipulasi nilai this. Pengembang dari pustaka JavaScript melakukan ini karena cenderung mendukung kasus penggunaan yang paling umum, dan pengguna pustaka biasanya menganggap perilaku ini lebih nyaman. Ketika melewati fungsi callback referensi this untuk fungsi perpustakaan, Anda harus merujuk ke dokumentasi untuk jaminan apa pun tentang nilai dari this adalah ketika fungsi tersebut dipanggil.

Jika Anda bertanya-tanya bagaimana perpustakaan JavaScript memanipulasi nilai this, perpustakaan hanya menggunakan salah satu fungsi JavaScript built-in yang menerima a thisArg. Anda juga dapat menulis fungsi Anda sendiri mengambil fungsi panggilan balik dan thisArg:

function doWork(callbackfn, thisArg) {
    //...
    if (callbackfn != null) callbackfn.call(thisArg);
}

Ada kasus khusus yang belum saya sebutkan. Saat membangun objek baru melalui new operator, juru bahasa JavaScript membuat objek kosong baru, menyetel beberapa properti internal, dan kemudian memanggil fungsi konstruktor pada objek baru. Jadi, ketika suatu fungsi dipanggil dalam konteks konstruktor, nilai dari this adalah objek baru yang dibuat oleh interpreter:

function MyType() {
    this.someData = "a string";
}

var instance = new MyType();
// Kind of like the following, but there are more steps involved:
// var instance = {};
// MyType.call(instance);

Hanya untuk bersenang-senang, uji pemahaman Anda dengan beberapa contoh

Untuk mengungkapkan jawabannya, arahkan mouse ke kotak kuning muda.

  1. Berapa nilai dari this di garis yang ditandai? Mengapa?

      window - Garis yang ditandai dievaluasi dalam konteks pelaksanaan global awal.

    if (true) {
        // What is `this` here?
    }
    
  2. Berapa nilai dari this di garis yang ditandai kapan obj.staticFunction() dieksekusi? Mengapa?

      obj - Saat memanggil fungsi pada objek, ThisBinding diatur ke objek.

    var obj = {
        someData: "a string"
    };
    
    function myFun() {
        return this // What is `this` here?
    }
    
    obj.staticFunction = myFun;
    
    console.log("this is window:", obj.staticFunction() == window);
    console.log("this is obj:", obj.staticFunction() == obj);
      

  3. Berapa nilai dari this di garis yang ditandai? Mengapa?

      window

    Dalam contoh ini, interpreter JavaScript memasukkan kode fungsi, tetapi karena myFun/obj.myMethod tidak dipanggil pada objek, ThisBinding diatur ke window.  

    Ini berbeda dengan Python, di mana mengakses metode (obj.myMethod) membuat a objek metode terikat.

    var obj = {
        myMethod: function () {
            return this; // What is `this` here?
        }
    };
    var myFun = obj.myMethod;
    console.log("this is window:", myFun() == window);
    console.log("this is obj:", myFun() == obj);
      

  4. Berapa nilai dari this di garis yang ditandai? Mengapa?

      window

    Yang ini rumit. Saat mengevaluasi kode eval, this aku s obj. Namun, dalam kode eval, myFun tidak dipanggil pada objek, jadi ThisBinding diatur ke window untuk panggilan.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        myMethod: function () {
            eval("myFun()");
        }
    };
    
  5. Berapa nilai dari this di garis yang ditandai? Mengapa?

      obj

    Garis myFun.call(obj); sedang menjalankan fungsi built-in khusus Function.prototype.call(), yang menerima thisArg sebagai argumen pertama.

    function myFun() {
        return this; // What is `this` here?
    }
    var obj = {
        someData: "a string"
    };
    console.log("this is window:", myFun.call(obj) == window);
    console.log("this is obj:", myFun.call(obj) == obj);
      


1150
2017-07-07 17:32



Itu this kata kunci berperilaku berbeda dalam JavaScript dibandingkan dengan bahasa lain. Dalam bahasa Berorientasi Objek, this kata kunci mengacu pada contoh kelas saat ini. Di JavaScript nilai dari this sebagian besar ditentukan oleh konteks fungsi pemanggilan (context.function()) dan di mana namanya.

1. Saat digunakan dalam konteks global

Ketika Anda menggunakan this dalam konteks global, ia terikat pada objek global (windowdi browser)

document.write(this);  //[object Window]

Ketika Anda menggunakan this di dalam fungsi yang didefinisikan dalam konteks global, this masih terikat pada objek global karena fungsinya sebenarnya dijadikan metode konteks global.

function f1()
{
   return this;
}
document.write(f1());  //[object Window]

Atas f1 dibuat metode objek global. Jadi kita juga bisa menyebutnya window objek sebagai berikut:

function f()
{
    return this;
}

document.write(window.f()); //[object Window]

2. Saat digunakan di dalam metode objek

Ketika Anda menggunakan this kata kunci di dalam metode objek, this terikat ke objek melampirkan "langsung".

var obj = {
    name: "obj",
    f: function () {
        return this + ":" + this.name;
    }
};
document.write(obj.f());  //[object Object]:obj

Di atas saya telah menempatkan kata itu langsung dalam tanda kutip ganda. Ini adalah untuk membuat titik bahwa jika Anda bersarang objek di dalam objek lain, lalu this terikat pada orang tua langsung.

var obj = {
    name: "obj1",
    nestedobj: {
        name:"nestedobj",
        f: function () {
            return this + ":" + this.name;
        }
    }            
}

document.write(obj.nestedobj.f()); //[object Object]:nestedobj

Bahkan jika Anda menambahkan fungsi secara eksplisit ke objek sebagai metode, itu masih mengikuti aturan di atas, yaitu this masih menunjuk ke objek induk langsung.

var obj1 = {
    name: "obj1",
}

function returnName() {
    return this + ":" + this.name;
}

obj1.f = returnName; //add method to object
document.write(obj1.f()); //[object Object]:obj1

3. Saat memohon fungsi tanpa konteks

Ketika Anda menggunakan this di dalam fungsi yang dipanggil tanpa konteks apa pun (yaitu bukan pada objek apa pun), ia terikat ke objek global (window di browser) (bahkan jika fungsi didefinisikan di dalam objek).

var context = "global";

var obj = {  
    context: "object",
    method: function () {                  
        function f() {
            var context = "function";
            return this + ":" +this.context; 
        };
        return f(); //invoked without context
    }
};

document.write(obj.method()); //[object Window]:global 

Mencoba semuanya dengan fungsi

Kita dapat mencoba poin di atas dengan fungsi juga. Namun ada beberapa perbedaan.

  • Di atas kami menambahkan anggota ke objek menggunakan objek notasi literal. Kita dapat menambahkan anggota ke fungsi dengan menggunakan this. untuk menentukannya.
  • Notasi literal objek menciptakan sebuah instance objek yang dapat kita gunakan dengan segera. Dengan fungsi kita mungkin perlu terlebih dahulu membuat instance-nya menggunakan new operator.
  • Juga dalam pendekatan literal objek, kita dapat secara eksplisit menambahkan anggota ke objek yang sudah didefinisikan menggunakan operator dot. Ini ditambahkan ke contoh spesifik saja. Namun saya telah menambahkan variabel ke prototipe fungsi sehingga itu tercermin dalam semua contoh fungsi.

Di bawah ini saya mencoba semua hal yang kami lakukan dengan Object dan this di atas, tetapi dengan terlebih dahulu membuat fungsi alih-alih langsung menulis objek.

/********************************************************************* 
  1. When you add variable to the function using this keyword, it 
     gets added to the function prototype, thus allowing all function 
     instances to have their own copy of the variables added.
*********************************************************************/
function functionDef()
{
    this.name = "ObjDefinition";
    this.getName = function(){                
        return this+":"+this.name;
    }
}        

obj1 = new functionDef();
document.write(obj1.getName() + "<br />"); //[object Object]:ObjDefinition   

/********************************************************************* 
   2. Members explicitly added to the function protorype also behave 
      as above: all function instances have their own copy of the 
      variable added.
*********************************************************************/
functionDef.prototype.version = 1;
functionDef.prototype.getVersion = function(){
    return "v"+this.version; //see how this.version refers to the
                             //version variable added through 
                             //prototype
}
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   3. Illustrating that the function variables added by both above 
      ways have their own copies across function instances
*********************************************************************/
functionDef.prototype.incrementVersion = function(){
    this.version = this.version + 1;
}
var obj2 = new functionDef();
document.write(obj2.getVersion() + "<br />"); //v1

obj2.incrementVersion();      //incrementing version in obj2
                              //does not affect obj1 version

document.write(obj2.getVersion() + "<br />"); //v2
document.write(obj1.getVersion() + "<br />"); //v1

/********************************************************************* 
   4. `this` keyword refers to the immediate parent object. If you 
       nest the object through function prototype, then `this` inside 
       object refers to the nested object not the function instance
*********************************************************************/
functionDef.prototype.nestedObj = { name: 'nestedObj', 
                                    getName1 : function(){
                                        return this+":"+this.name;
                                    }                            
                                  };

document.write(obj2.nestedObj.getName1() + "<br />"); //[object Object]:nestedObj

/********************************************************************* 
   5. If the method is on an object's prototype chain, `this` refers 
      to the object the method was called on, as if the method was on 
      the object.
*********************************************************************/
var ProtoObj = { fun: function () { return this.a } };
var obj3 = Object.create(ProtoObj); //creating an object setting ProtoObj
                                    //as its prototype
obj3.a = 999;                       //adding instance member to obj3
document.write(obj3.fun()+"<br />");//999
                                    //calling obj3.fun() makes 
                                    //ProtoObj.fun() to access obj3.a as 
                                    //if fun() is defined on obj3

4. Saat digunakan di dalam fungsi konstruktor.

Ketika fungsi digunakan sebagai konstruktor (saat itulah disebut dengan new kata kunci), this dalam tubuh fungsi menunjuk ke objek baru sedang dibangun.

var myname = "global context";
function SimpleFun()
{
    this.myname = "simple function";
}

var obj1 = new SimpleFun(); //adds myname to obj1
//1. `new` causes `this` inside the SimpleFun() to point to the
//   object being constructed thus adding any member
//   created inside SimipleFun() using this.membername to the
//   object being constructed
//2. And by default `new` makes function to return newly 
//   constructed object if no explicit return value is specified

document.write(obj1.myname); //simple function

5. Ketika digunakan fungsi dalam didefinisikan pada rantai prototipe

Jika metodenya ada pada rantai prototipe objek, this di dalam metode tersebut mengacu pada objek metode dipanggil, seolah-olah metode tersebut didefinisikan pada objek.

var ProtoObj = {
    fun: function () {
        return this.a;
    }
};
//Object.create() creates object with ProtoObj as its
//prototype and assigns it to obj3, thus making fun() 
//to be the method on its prototype chain

var obj3 = Object.create(ProtoObj);
obj3.a = 999;
document.write(obj3.fun()); //999

//Notice that fun() is defined on obj3's prototype but 
//`this.a` inside fun() retrieves obj3.a   

6. Fungsi Inside call (), apply () dan bind ()

  • Semua metode ini didefinisikan pada Function.prototype.
  • Metode-metode ini memungkinkan untuk menulis suatu fungsi sekali dan memohonnya dalam konteks yang berbeda. Dengan kata lain, mereka memungkinkan untuk menentukan nilai this yang akan digunakan saat fungsi sedang dijalankan. Mereka juga mengambil parameter apa pun untuk diteruskan ke fungsi semula saat dipanggil.
  • fun.apply(obj1 [, argsArray]) Set obj1 sebagai nilai dari this dalam fun() dan panggilan fun() lewat elemen argsArray sebagai argumennya.
  • fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - Set obj1 sebagai nilai dari this dalam fun() dan panggilan fun() lewat arg1, arg2, arg3, ... sebagai argumennya.
  • fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]]) - Mengembalikan referensi ke fungsi fun dengan thisdalam kesenangan terikat obj1 dan parameter fun terikat ke parameter yang ditentukan arg1, arg2, arg3,....
  • Sekarang perbedaannya apply, call dan bind harus menjadi jelas. apply memungkinkan untuk menentukan argumen untuk berfungsi sebagai objek seperti larik sebuah objek dengan numerik length properti dan properti bilangan bulat non-negatif yang sesuai. Sedangkan call memungkinkan untuk menentukan argumen ke fungsi secara langsung. Kedua apply dan call segera memanggil fungsi dalam konteks yang ditentukan dan dengan argumen yang ditentukan. Di samping itu, bind hanya mengembalikan fungsi yang terikat ke yang ditentukan this nilai dan argumennya. Kita dapat menangkap referensi ke fungsi yang dikembalikan ini dengan menugaskannya ke variabel dan kemudian kita dapat memanggilnya kapan saja.
function add(inc1, inc2)
{
    return this.a + inc1 + inc2;
}

var o = { a : 4 };
document.write(add.call(o, 5, 6)+"<br />"); //15
      //above add.call(o,5,6) sets `this` inside
      //add() to `o` and calls add() resulting:
      // this.a + inc1 + inc2 = 
      // `o.a` i.e. 4 + 5 + 6 = 15
document.write(add.apply(o, [5, 6]) + "<br />"); //15
      // `o.a` i.e. 4 + 5 + 6 = 15

var g = add.bind(o, 5, 6);       //g: `o.a` i.e. 4 + 5 + 6
document.write(g()+"<br />");    //15

var h = add.bind(o, 5);          //h: `o.a` i.e. 4 + 5 + ?
document.write(h(6) + "<br />"); //15
      // 4 + 5 + 6 = 15
document.write(h() + "<br />");  //NaN
      //no parameter is passed to h()
      //thus inc2 inside add() is `undefined`
      //4 + 5 + undefined = NaN</code>

7 this di dalam penangan acara

  • Saat Anda menetapkan fungsi secara langsung ke penangan peristiwa elemen, gunakan this langsung di dalam fungsi penanganan peristiwa mengacu pada elemen yang sesuai. Penugasan fungsi langsung seperti itu dapat dilakukan dengan menggunakan addeventListener metode atau melalui metode pendaftaran acara tradisional seperti onclick.
  • Begitu pula saat Anda menggunakan this langsung di dalam properti acara (seperti <button onclick="...this..." >) dari elemen, ini mengacu pada elemen.
  • Namun penggunaan this secara tidak langsung melalui fungsi lain yang disebut di dalam fungsi penanganan acara atau properti acara yang diselesaikan ke objek global window.
  • Perilaku yang sama di atas tercapai ketika kita melampirkan fungsi ke pengendali event menggunakan metode metode Pendaftaran Acara Microsoft attachEvent. Alih-alih menetapkan fungsi ke pengendali event (dan dengan demikian membuat metode fungsi elemen), itu memanggil fungsi pada acara (secara efektif menyebutnya dalam konteks global).

Saya sarankan untuk lebih baik mencoba ini JSFiddle.

<script> 
    function clickedMe() {
       alert(this + " : " + this.tagName + " : " + this.id);
    } 
    document.getElementById("button1").addEventListener("click", clickedMe, false);
    document.getElementById("button2").onclick = clickedMe;
    document.getElementById("button5").attachEvent('onclick', clickedMe);   
</script>

<h3>Using `this` "directly" inside event handler or event property</h3>
<button id="button1">click() "assigned" using addEventListner() </button><br />
<button id="button2">click() "assigned" using click() </button><br />
<button id="button3" onclick="alert(this+ ' : ' + this.tagName + ' : ' + this.id);">used `this` directly in click event property</button>

<h3>Using `this` "indirectly" inside event handler or event property</h3>
<button onclick="alert((function(){return this + ' : ' + this.tagName + ' : ' + this.id;})());">`this` used indirectly, inside function <br /> defined & called inside event property</button><br />

<button id="button4" onclick="clickedMe()">`this` used indirectly, inside function <br /> called inside event property</button> <br />

IE only: <button id="button5">click() "attached" using attachEvent() </button>

122
2017-10-26 15:07



Javascript this

Doa fungsi sederhana

Pertimbangkan fungsi berikut:

function foo() {
    console.log("bar");
    console.log(this);
}
foo(); // calling the function

Perhatikan bahwa kami menjalankan ini dalam mode normal, yaitu mode ketat tidak digunakan.

Saat dijalankan di browser, nilai dari this akan dicatat sebagai window. Hal ini karena window adalah variabel global dalam lingkup browser web.

Jika Anda menjalankan kode yang sama ini di lingkungan seperti node.js, this akan mengacu pada variabel global di aplikasi Anda.

Sekarang jika kita menjalankan ini dalam mode ketat dengan menambahkan pernyataan "use strict"; ke awal deklarasi fungsi, this tidak akan lagi mengacu pada variabel global di salah satu envirnoments. Ini dilakukan untuk menghindari kebingungan dalam mode ketat. this akan, dalam hal ini hanya log undefined, karena memang begitu, itu tidak didefinisikan.

Dalam kasus-kasus berikut, kita akan melihat bagaimana memanipulasi nilai this.

Memanggil fungsi pada objek

Ada berbagai cara untuk melakukan ini. Jika Anda telah memanggil metode asli di Javascript suka forEach dan slice, Anda seharusnya sudah tahu bahwa this variabel dalam hal ini mengacu pada Object di mana Anda memanggil fungsi itu (Perhatikan bahwa dalam javascript, hampir semuanya adalah sebuah Object, termasuk Arrays dan Functions). Ambil kode berikut misalnya.

var myObj = {key: "Obj"};
myObj.logThis = function () {
    // I am a method
    console.log(this);
}
myObj.logThis(); // myObj is logged

Jika Object mengandung properti yang memegang Function, properti disebut metode. Metode ini, saat dipanggil, akan selalu memilikinya this variabel ditetapkan ke Object itu terkait dengan. Ini berlaku untuk mode ketat dan non-ketat.

Perhatikan bahwa jika suatu metode disimpan (atau lebih tepatnya, disalin) dalam variabel lain, referensi ke this tidak lagi dipertahankan dalam variabel baru. Sebagai contoh:

// continuing with the previous code snippet

var myVar = myObj.thisMethod;
myVar();
// logs either of window/global/undefined based on mode of operation

Mempertimbangkan skenario yang lebih umum praktis:

var el = document.getElementById('idOfEl');
el.addEventListener('click', function() { console.log(this) });
// the function called by addEventListener contains this as the reference to the element
// so clicking on our element would log that element itself

Itu new kata kunci

Pertimbangkan fungsi konstruktor di Javascript:

function Person (name) {
    this.name = name;
    this.sayHello = function () {
        console.log ("Hello", this);
    }
}

var awal = new Person("Awal");
awal.sayHello();
// In `awal.sayHello`, `this` contains the reference to the variable `awal`

Bagaimana cara kerjanya? Nah, mari kita lihat apa yang terjadi ketika kita menggunakan new kata kunci.

  1. Memanggil fungsi dengan new kata kunci akan segera memulainya Object tipe Person.
  2. Konstruktor ini Object memiliki konstruktor diatur ke Person. Juga, perhatikan itu typeof awal akan kembali Object hanya.
  3. Ini baru Object akan diberi protoype Person.prototype. Ini berarti bahwa setiap metode atau properti di dalam Person prototipe akan tersedia untuk semua contoh Person, termasuk awal.
  4. Fungsi itu Person sendiri sekarang dipanggil; this menjadi referensi ke objek yang baru dibangun awal.

Cukup berani, eh?

Perhatikan bahwa ECMAScript resmi tidak menetapkan di mana menyatakan bahwa jenis fungsi semacam itu adalah aktual constructor fungsi. Mereka hanya fungsi normal, dan new dapat digunakan pada fungsi apa pun. Hanya saja kami menggunakannya seperti itu, jadi kami hanya menyebutnya.

Memanggil fungsi pada Fungsi: call dan apply

Jadi ya, sejak itu functions juga Objects (dan sebenarnya variabel kelas pertama dalam Javascript), bahkan fungsi memiliki metode yang ... yah, fungsi-fungsi itu dipilih.

Semua fungsi mewarisi dari global Function, dan dua dari banyak metodenya call dan apply, dan keduanya dapat digunakan untuk memanipulasi nilai this dalam fungsi di mana mereka dipanggil.

function foo () { console.log (this, arguments); }
var thisArg = {myObj: "is cool"};
foo.call(thisArg, 1, 2, 3);

Ini adalah contoh penggunaan yang khas call. Ini pada dasarnya mengambil parameter dan set pertama this dalam fungsi foo sebagai referensi untuk thisArg. Semua parameter lainnya diteruskan ke call dilewatkan ke fungsi foo sebagai argumen.
Jadi kode di atas akan masuk {myObj: "is cool"}, [1, 2, 3] di konsol. Cara yang cukup bagus untuk mengubah nilai this dalam fungsi apa pun.

apply hampir sama dengan call menerima bahwa hanya dibutuhkan dua parameter: thisArg dan larik yang berisi argumen yang akan diteruskan ke fungsi. Demikian hal di atas call panggilan dapat diterjemahkan ke apply seperti ini:

foo.apply(thisArg, [1,2,3])

Perhatikan itu call dan apply dapat menggantikan nilai this diatur oleh pemanggilan metode dot kita bahas dalam peluru kedua. Cukup sederhana :)

Menyajikan .... bind!

bind adalah saudara laki-laki call dan apply. Ini juga merupakan metode yang diwarisi oleh semua fungsi dari global Function konstruktor dalam Javascript. Perbedaan antara bind dan call/apply adalah keduanya call dan apply akan benar-benar memanggil fungsi. bind, di sisi lain, mengembalikan fungsi baru dengan thisArg dan arguments sudah diatur sebelumnya. Mari kita ambil contoh untuk lebih memahami ini:

function foo (a, b) {
    console.log (this, arguments);
}
var thisArg = {myObj: "even more cool now"};
var bound = foo.bind(thisArg, 1, 2);
console.log (typeof bound); // logs `function`
console.log (bound);
/* logs `function () { native code }` */

bound(); // calling the function returned by `.bind`
// logs `{myObj: "even more cool now"}, [1, 2]`

Lihat perbedaan antara ketiganya? Ini halus, tetapi mereka digunakan secara berbeda. Seperti call dan apply, bind juga akan over-naik nilai this diatur oleh pemanggilan metode-titik.

Juga perhatikan bahwa kedua fungsi ini tidak mengubah fungsi aslinya. call dan apply akan mengembalikan nilai dari fungsi yang baru dibangun sementara bind akan mengembalikan fungsi yang baru dibangun itu sendiri, siap dipanggil.

Barang ekstra, salin ini

Terkadang, Anda tidak menyukai kenyataan itu this perubahan dengan ruang lingkup, khususnya lingkup bersarang. Lihatlah contoh berikut.

var myObj = {
    hello: function () {
        return "world"
        },
    myMethod: function () {
        // copy this, variable names are case-sensitive
        var that = this;
        // callbacks ftw \o/
        foo.bar("args", function () {
            // I want to call `hello` here
            this.hello(); // error
            // but `this` references to `foo` damn!
            // oh wait we have a backup \o/
            that.hello(); // "world"
        });
    }
  };

Dalam kode di atas, kita melihat bahwa nilai dari this berubah dengan lingkup bersarang, tetapi kami menginginkan nilai this dari ruang lingkup aslinya. Jadi kami 'menyalin' this untuk that dan menggunakan salinannya sebagai gantinya this. Pintar, ya?

Indeks:

  1. Apa yang diadakan di this secara default?
  2. Bagaimana jika kita memanggil fungsi sebagai metode dengan notasi Object-dot?
  3. Bagaimana jika kita menggunakan new kata kunci?
  4. Bagaimana kita memanipulasi this dengan call dan apply?
  5. Menggunakan bind.
  6. Penyalinan this untuk menyelesaikan masalah ruang bersarang.

46
2018-06-27 14:10



"ini" adalah semua tentang ruang lingkup. Setiap fungsi memiliki ruang lingkup sendiri, dan karena segala sesuatu di JS adalah objek, bahkan fungsi dapat menyimpan beberapa nilai ke dalam dirinya sendiri menggunakan "ini". OOP 101 mengajarkan bahwa "ini" hanya berlaku untuk contoh suatu objek. Oleh karena itu, setiap kali fungsi dijalankan, "contoh" baru dari fungsi itu memiliki arti baru "ini".

Kebanyakan orang bingung ketika mereka mencoba menggunakan "ini" di dalam fungsi penutupan anonim seperti:

(fungsi (nilai) {
    this.value = value;
    $ ('. some-elements'). masing-masing (function (elt) {
        elt.innerHTML = this.value; // uh oh!! mungkin tidak terdefinisi
    });
}) (2);

Jadi di sini, di dalam setiap (), "ini" tidak memiliki "nilai" yang Anda harapkan dari (dari

this.value = value;
 di atasnya). Jadi, untuk mengatasi masalah ini (tidak ada yang dimaksudkan), pengembang dapat:

(fungsi (nilai) {
    var self = ini; // perubahan kecil
    nilai self.value =;
    $ ('. some-elements'). masing-masing (function (elt) {
        elt.innerHTML = self.value; // phew !! == 2
    });
}) (2);

Cobalah; Anda akan mulai menyukai pola pemrograman ini


43
2017-10-06 19:46



this di Javascript selalu mengacu pada 'pemilik' dari fungsi yang ada sedang dieksekusi.

Jika tidak ada pemilik eksplisit didefinisikan, maka pemilik paling atas, objek jendela, direferensikan.

Jadi jika saya melakukannya

function someKindOfFunction() {
   this.style = 'foo';
}

element.onclick = someKindOfFunction;

this akan merujuk ke objek elemen. Tapi hati-hati, banyak orang membuat kesalahan ini

<element onclick="someKindOfFunction()">

Dalam kasus terakhir, Anda hanya mereferensikan fungsi, tidak menyerahkannya ke elemen. Untuk itu, this akan mengacu pada objek jendela.


12
2017-10-30 03:58



Karena utas ini telah naik, saya telah mengumpulkan beberapa poin untuk pembaca baru this tema. 

Bagaimana nilai dari thisbertekad?

Kami menggunakan ini serupa dengan cara kami menggunakan kata ganti dalam bahasa alami seperti bahasa Inggris: “John berlari cepat karena dia sedang mencoba untuk menangkap kereta. "Sebaliknya kita bisa menulis" ... John sedang mencoba menangkap kereta api ”.

var person = {    
    firstName: "Penelope",
    lastName: "Barrymore",
    fullName: function () {

    // We use "this" just as in the sentence above:
       console.log(this.firstName + " " + this.lastName);

    // We could have also written:
       console.log(person.firstName + " " + person.lastName);
    }
}

this  tidak diberi nilai sampai suatu objek memanggil fungsi di mana ia didefinisikan. Dalam lingkup global, semua variabel dan fungsi global didefinisikan pada window obyek. Karena itu, this dalam fungsi global mengacu pada (dan memiliki nilai) global window obyek.

Kapan use strict, this dalam fungsi global dan anonim yang tidak terikat pada objek apa pun yang memiliki nilai undefined.

Itu this kata kunci adalah paling disalahpahami ketika: 1) kami meminjam metode yang menggunakan this, 2) kami menetapkan metode yang digunakan this ke variabel, 3) fungsi yang menggunakan this dilewatkan sebagai fungsi panggilan balik, dan 4) this digunakan di dalam penutupan - fungsi batin. (2)

table

Apa yang memegang masa depan

Ditetapkan dalam Naskah ECMA 6, panah-fungsi mengadopsi this mengikat dari lingkup melampirkan (fungsi atau global).

function foo() {
     // return an arrow function
     return (a) => {
     // `this` here is lexically inherited from `foo()`
     console.log(this.a);
  };
}
var obj1 = { a: 2 };
var obj2 = { a: 3 };

var bar = foo.call(obj1);
bar.call( obj2 ); // 2, not 3!

Sementara fungsi panah menyediakan alternatif untuk menggunakan bind(), penting untuk dicatat bahwa pada dasarnya mereka melumpuhkan tradisional this mekanisme yang mendukung scoping leksikal yang lebih luas dipahami. (1)


Referensi:

  1. ini & Prototipe Objek, oleh Kyle Simpson. Solusi Getify 2014.
  2. javascriptissexy.com - http://goo.gl/pvl0GX 
  3. Angus Croll - http://goo.gl/Z2RacU 

12
2018-06-27 13:15



Setiap fungsi  konteks eksekusi di javascript memiliki cakupan  konteks  ini parameter yang diatur oleh:

  1. Bagaimana fungsi ini disebut (termasuk sebagai metode objek, penggunaan panggilan dan menerapkan, penggunaan baru)
  2. Penggunaan mengikat
  3. Secara leksikal untuk fungsi panah (mereka mengadopsi ini konteks eksekusi luar mereka)

Apa pun konteks ruang lingkup itu, direferensikan oleh "ini".

Kamu bisa ganti itu atur nilainya ini  cakupan  konteks menggunakan func.call, func.apply atau func.bind.

Secara default, dan apa yang membingungkan kebanyakan pemula, ketika a panggilan balik listener dipanggil setelah suatu peristiwa dinaikkan pada elemen DOM, konteks ruang lingkup  ini nilai fungsi adalah elemen DOM.

jQuery membuat ini sepele untuk berubah dengan jQuery.proxy.


9
2017-11-29 06:01