Bu JavaScript deyiminin altında yatan nedir: var self = this?


357

WebKit HTML 5 SQL Depolama Notları Demosu kaynağında aşağıdakileri gördüm :

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

Yazar kendini bazı yerlerde (işlev gövdesi) ve bunu başka yerlerde (yöntemlerin argüman listesinde tanımlanan işlev gövdeleri) kullanır. Neler oluyor? Şimdi bir kez fark ettiğime göre, her yerde görmeye başlayacak mıyım?


4
Bu, "sözcüksel kapatma" olarak adlandırılan bir JS dil özelliğidir
subZero

2
Olası kopya: var self = this? .
DavidRR

BU kavram açıkça burada açıklanmıştır scotch.io/@alZami/understanding-this-in-javascript
AL-zami

Bu this
yanıttaki

Yanıtlar:


431

Alistapart.com adresindeki bu makaleye bakın . (Ed: Makale ilk bağlandığından beri güncellendi)

selfthisbağlam değişse bile orijinaline bir referans sağlamak için kullanılıyor . Olay işleyicilerinde (özellikle kapaklarda) sıklıkla kullanılan bir tekniktir.

Düzenleme: Kullanmanın selfartık olduğu gibi kullanılmaması window.selfve dikkatli değilseniz hatalara neden olma potansiyeli olduğunu unutmayın.

Değişken dediğiniz şey özellikle önemli değil. var that = this;iyi, ama isimle ilgili hiçbir sihir yok.

Bir bağlam içinde bildirilen işlevler (örneğin, geri aramalar, kapanışlar) aynı kapsamda veya üstünde bildirilen değişkenlere / işleve erişebilir.

Örneğin, basit bir olay geri araması:

function MyConstructor(options) {
  let that = this;

  this.someprop = options.someprop || 'defaultprop';

  document.addEventListener('click', (event) => {
    alert(that.someprop);
  });
}

new MyConstructor({
  someprop: "Hello World"
});


Görünüyor makale olduğunu kullanılarak dönüştüvar that = this;
Bob Stein

@BobStein Teşekkürler. Cevabı buna göre güncelleyeceğim.
Jonathan Fingland

96

Modern tarayıcılar, normal bir pencerenin veya bir WebWorker'ın global nesnesine işaret eden küresel bir değişkenself sağladığı için, değişken adı 'self' artık bu şekilde kullanılmamalıdır .

Önlemek karışıklık ve potansiyel çatışmaları için, yazabilir var thiz = thisveya var that = thisonun yerine.


43
Genellikle kullanıyorum_this
djheru

6
@djheru +1. " that" dan çok daha güzel (beynim asla alışmayacak).
o_o_o--

9
"Ben" kullanmaya başladım :)
Mopparthy Ravindranath

3
Modern tarayıcılar küresel bir değişken sağlamaya başlayana kadar, bu, o ya da ben.
Beejor

10
selfEğer bir varmable olarak ilan sürece adı kullanmak kesinlikle hiçbir sorun , küresel gölgeli olacaktır. Tabii ki unutursanız, varo zaman başka bir adla da işe yaramazdı.
Bergi

34

Evet, her yerde göreceksiniz. Sık sık that = this;.

selfOlaylar tarafından çağrılan fonksiyonların içinde nasıl kullanıldığını görün ? Bunlar kendi bağlamlarına sahip olacaklardı, bu yüzden içine girenleri selftutmak için kullanılır .thisNote()

Bunun nedeni self, işlevlerin ancak Note()işlev yürütülmesi bittikten sonra çalıştırılabilmelerine rağmen, işlevlerin hala kullanılabilir olması, iç işlevlerin, kapanma nedeniyle dış işlev bağlamını almasıdır .


12
Benim için ortak nokta, bunun selfözel bir anlamı yok. Ben şahsen self'kendim' in ayrılmış bir kelime olmasını beklediğim için kişisel olarak beni sık sık karıştırdığı için başka bir adda bir değişken kullanmayı tercih ediyorum . Bu yüzden cevabınızı seviyorum. Ve OP örneğinde, tercih ederim var thisNote = thisya da benzeri.
steve

@steve kabul etti, ancak genel olarak bu / öz referanslarını sürdürülebilirlik açısından çok kırılgan oldukları için kullanmaktan kaçınmaya çalışıyorum.
mattLummus

28

thisEğer var self = thisdeyimden hoşlanmıyorsanız, geri aramada orijinalin referansını korumak için alternatif bir Proxy kalıbı olduğu da not edilmelidir .

Bir işlev belirli bir bağlamda function.applyveya kullanılarak çağrılabilir olarak function.call, işlevinizi belirtilen bağlamla applyveya callkullanarak çağıran bir işlev döndüren bir sarıcı yazabilirsiniz . proxyBu modelin uygulanması için jQuery işlevine bakın . İşte buna bir örnek:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFuncdaha sonra çağrılabilir ve thisbağlam olarak sürümünüze sahip olur .


10

Diğerlerinin açıkladığı gibi, var self = this;bir kapaktaki kodun ana kapsama geri dönmesini sağlar.

Ancak, şimdi 2018 ve ES6 tüm büyük web tarayıcıları tarafından yaygın olarak desteklenmektedir. var self = this;Deyim bir zamanlar olduğu gibi çok da gerekli değildir.

Artık ok fonksiyonlarınıvar self = this; kullanmaktan kaçınmak mümkün .

Kullanacağımız durumlarda var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

Artık bir ok fonksiyonunu kullanmadan kullanabiliriz var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

Ok işlevlerinin kendi işlevleri yoktur thisve sadece kapalı kapsamı varsayarlar.


Veya - şok, korku! - neden gerçek ilgili şeyi işlevinize bir argüman olarak (kapanış) geçirmiyorsunuz? Neden cehennem kapsamından bahsediyorsun, neden böyle bir programlama var? Bunu yapmak için hiçbir zaman gerçek bir neden yoktur. Bunun yerine .addEventListender("click", (x) => { console.log(x); });, nasıl ve neden çok açık bir şekilde açıkladınız ve ok işlevlerini kullanmanın daha mantıklı olduğunu kabul ediyorum, ama yine de ... bu sadece korkunç, tembel, dağınık, programlama.
Benjamin R

2
JavaScript'te, üst kapsama geri dönmek son derece yaygın ve gereklidir. Dilin temel bir parçası. Olay işleyicisinde bir bağımsız değişken olarak üst kapsamı iletme öneriniz aslında mümkün değildir. Ayrıca, ES6'da, ok işlevleri sözcüksel kapsam belirlemeyi kullanır - 'bu' geçerli çevredeki kapsamı ifade eder ve daha fazla değil - "kapsam durumundan referans alma" veya bunun gibi bir şey değildir.
Elliot

9

Değişken, yöntemde tanımlanan satır içi işlevlerle yakalanır. thisişlevde başka bir nesneye atıfta bulunacaktır. Bu şekilde, işlevin thisdış kapsamdaki bir referansı tutmasını sağlayabilirsiniz .


9

Bu bir JavaScript tuhaflığı. Bir işlev, daha uygun bir şekilde yöntem olarak adlandırılan bir nesnenin bir özelliğiyse, bu nesneyi ifade eder. Olay işleyici örneğinde, içeren nesne olayı tetikleyen öğedir. Standart bir işlev çağrıldığında, bu genel nesneye işaret eder. Örneğinizde olduğu gibi yuvalanmış işlevlere sahip olduğunuzda, bu , dış işlevin bağlamıyla hiç ilgili değildir. Geliştiriciler varyasyonları kullanacak böylece İç fonksiyonlar içeren fonksiyonu ile pay kapsamını yapmak var that = thiskorumak amacıyla bu onlar iç fonksiyonunda gerekir.


5

Aslında self, window ( window.self) öğesine yapılan bir referanstır, bu nedenle var self = 'something'kendi kendine bir pencere referansını geçersiz kıldığınızı söylediğinizde - çünkü window nesnesinde self vardır.

Çoğu geliştirici tercih nedeni budur var that = thisüzerindevar self = this;

Neyse; var that = this;iyi uygulama ile uyumlu değil ... kodunuzun daha sonra diğer geliştiriciler tarafından revize edileceğini / değiştirileceğini varsayarak geliştirici topluluğuna ilişkin en yaygın programlama standartlarını kullanmalısınız.

Bu nedenle var oldThis/ var oThis/ etc gibi bir şey kullanmalısınız - kapsamınızda net olmak için // .. o kadar değil ama birkaç saniye ve birkaç beyin döngüsü kazandıracak


2
@prior Sanırım son paragrafa kadar mantıklı geliyor.
14'te

0

Yukarıda birkaç kez bahsedildiği gibi, 'benlik', fonksiyona girmeden önce 'buna' atıfta bulunmak için kullanılır. Bir kez 'bu' fonksiyonunda başka bir şey ifade eder.


@JohnPaul ... Bu does bir cevap sağlamaktadır. Doğru cevap olmayabilir, ancak "alışkın ..." ın "bunu neden yaptı" cevabı olmadığını nasıl söyleyebilirsiniz?
GreenAsJade

-1
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call (thatt);


1
Özel yaptığınız kodla ilgili bazı açıklamalar eklemelisiniz.
Farhana
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.