Soru Javascript - Kapanışları idareli olarak mı kullanıyorsunuz?


izliyorum http://www.youtube.com/watch?v=mHtdZgou0qUve yaklaşık 13: 37'de (hehe), kapsam zincirine yeni bir nesnenin eklenmesi nedeniyle kaçınılması gereken şeylerin bir listesini gösteren bir slayt gösterir.

Onun ne dediğini anlıyorum using ve try-catch ifadeler, kapsam dışı değişkenlere erişmenin yanı sıra, neden kapanmaların önlenmesi gerektiğini anlamıyorum. Kapağın yerel değişkenleri kapsam zincirinin en üstünde olacaksa, performans kaybı nerede?


21
2018-03-19 00:56


Menşei


Sadece hatırla: Prematüre optimizasyon tüm kötülüklerin köküdür. Video, JavaScript'i daha performanslı hale getirmeyi tartışıyor, ancak çoğu JavaScript'in hiçbir zaman optimize edilmesine gerek yoktur. Bir kullanıcı bir düğmeyi tıkladıktan sonra eşzamansız olarak ayarlanan bir işlevi çağırdıysanız, kullanıcı 30ms yanıt oranı ile 40 ms yanıt oranı arasındaki farkı asla fark etmez. - zzzzBov
Buradaki cevaplar iyi. Ancak, videonun birkaç yaşında olduğunu ve bir zamanlar kadar alakalı olmayabileceğini unutmayın. - Dave Newton


Cevaplar:


Çünkü, yerel olmayan değişkenlere bakmak için, VM onları bulmak için kapsam zincirini yukarı doğru kaydırmak zorunda. Öte yandan yerel değişkenler önbelleğe alınır, bu nedenle yerel bir değişken araması daha hızlıdır. Bir fonksiyonun daha iç içe geçmiş olması, kapsam zincirinin ne kadar uzun olduğu ve potansiyel performans etkisinin ne kadar artacağıdır.

Bu kısmen, popüler JS kitaplıklarında bu gibi kodları sık sık görüyorsunuz:

(function(window, document, undefined) {
  // ...
})(window, document);

İşte, window ve document Yerel değişkenler haline gelir, bu yüzden onlara bakmak çok daha hızlı olur; bu, bu nesneleri kodunuzun içinden binlerce kez referans alırsanız oldukça fark edilir hale gelir.

Bu sayfa kapsam zincirleri ve yürütme bağlamları hakkında gerçekten derin bir açıklamaya sahiptir. (Okumak için zamanınız varsa, tüm makale ilginçtir.)

Genel olarak, modern tarayıcılar tüm bu şeyleri temelde ihmal edilebilir olan noktaya kadar optimize eder, bu yüzden endişeleneceğim bir şey değildir.


20
2018-03-19 01:06



Bu doğrudur, çünkü Kapanışlar yerel değişkenlere referanslar kopyalamak yerine kopyalar, bu yüzden yerel bir arama yerine yığın yürüyüşünü zorlar. - Russ Clarke
Kapsam dışı değişkenlere erişmeyen bir kapatma demek istiyorum. Kapsam dışı değişkenlere erişmekten kaçınmak için onun için biraz fazla yeterli göründü ve açık bir şekilde kapanmaları önlemek için söyleyin. Yerel değişkenleri kullanmanın yanı sıra, kapanmaları da engellemeniz gerektiği ima edilmektedir. Ne dediğini yanlış yorumlu muyum? - mowwwalker
@Walkerneo: Yerel olmayan değişkenlere başvurmuyorsanız, bu bir kapatma değildir. Söylediği şey, mümkün olduğunda kapamalardan kaçınmalısın, ama sen var Kapsam dışı bir değişkene başvurmak için, aramayı daha hızlı yapmak için yerel bir değişken kullanmalısınız (bu işlevi genellikle bu işlevin içinden kullanırsanız - aksi takdirde çok fazla işlem yapmaz). - Sasha Chedygov
@musicfreak, !! Korku veren !! Javascript kütüphaneleri hakkında konuştuğunuz için teşekkür ederiz. Birkaç kez merak ettim ama hiç sormadım ve videoyu izlemeden anlayacağımı emin değilim. Bu çok şeyleri temizler! Çok teşekkürler! - mowwwalker
Gösterdiğin modelin, aptalca bir kullanıcının önemli global sabitlerin üzerine yazmasını önlemek için ve performans sorunları için daha az olduğunu düşünüyorum. - hugomg


Bağlantılı video, kapanışın neden 11:08'den başlayarak bazı performans isabetlerine neden olabileceğini açıklıyor.

Temel olarak, her iç içe geçmiş işlev için, kapsam zincirine başka bir nesne eklediğini ve bu nedenle kapanışın dışındaki değişkenlere erişmenin daha uzun süreceğini söylüyor.

Bir değişkenle ilişkili değeri bulmak için Javascript arası bu işlemi takip eder:

  1. yerel kapsam nesnesini ara
  2. 1 çalışmadıysa, üst kapsam nesnesini arayın
  3. 2 çalışmadıysa, üst tarafın ana kapsam nesnesini arayın
  4. ana kapsamları aramaya devam et
  5. küresel kapsamı araştırıyorsunuz
  6. ve hala bulunamadıysa, tanımlanmamış bir değişken hatası atın.

Normal bir fonksiyonda, bir değişken bulmak için, sadece kapsam zincirinin üstünde arama yapmanız gerekir. Diğer taraftan, bir üst kapak, üst değişkenleri bulmak için, bazen de birkaç seviyeye kadar olan kapsam zincirini araştırmak zorunda kalacaktır. Örneğin, bunun gibi bazı kapanışlar varsa (bunun bir çok çekişmeli örnek):

function a (x) {
  function b (y) {
    return (function (z) {
      return x + y + z;
    })(y + y);
  }
  return b(x + 3);
}

En içteki işlevden, ifadeyi değerlendirmek için x + y + z, x bulmak için kapsam zincirinde üç seviyeyi geçmek zorunda, daha sonra y bulmak için tekrar iki seviye ve daha sonra bir kez z bulmak için kapsam zincirini yukarı çapraz zorunda. Toplamda, aramak zorundaydı altı nesne nihai sonucu döndürmek için kapsam zincirinde.

Bu kapanışlarda kaçınılmaz çünkü Kapılar her zaman ebeveyn değişkenlerine erişmelidir. Eğer yapmadılarsa, bir kapatma kullanmanın bir amacı olmazdı.

Ayrıca, Javascript’te, fonksiyonların, özellikle kapanışların yaratılmasında önemli bir ek yük olduğunu unutmayın. Örneğin, bu oldukça basit kapatma:

function a(x) {
  return function (y) {
    return x + y;
  }
}

Ve buna birkaç kez farklı diyorsunuz, bunun gibi

var x = a(1);
var y = a(2);
var z = a(3);
alert(x(3)); // 4
alert(y(3)); // 5
alert(z(3)); // 6

Dönen fonksiyonun a Ebeveyn işlevi zaten çağrıldıktan sonra bile üst işlevde bir argüman olarak geçirilenleri tutmak zorundadır. Bu, tercümanın, şu ana kadar aradığınız her işleve aktardığınız şeyi hafızasında tutması gerektiği anlamına gelir.


9
2018-03-19 01:13



Saklamak y ve z Üçüncü işlevdeki yerel değişkenler hala performansı düşürüyor mu? Tabii ki, bu örnekte, kapanmaları yaratmanın bir nedeni yok, ama ne zaman var? - mowwwalker
@Walkerneo Ebeveyn değişkenlerini bulmak için hala kapsam zincirine çıkmak zorunda kalacak. Ana değişkenleri iç işlevde bir kereden fazla kullanırsanız, yerel değişkenler olarak bildirmeye değerdir, ancak bunları yalnızca bir kez kullanırsanız, bunları yerel değişkenler olarak bildirmeye yardımcı olacak hiçbir şey yoktur. - Peter Olson
Pekala, kapsam zincirini geçme ile ilgili problemi anlıyorum, ama diğer cevap hakkındaki yorumumda da belirttiğim gibi, kapsam dışı değişkenler hakkında söylediklerinin hemen ardından “kapanışları kapalı bir şekilde kullan” şeklindeki yöntemi kapsama zincirine başka bir nesne eklediklerinden değil, kapaklarla doğal olarak yanlış bir şey var. - mowwwalker
@Walkerneo: Peter'ın referans aldığı videonun bir bölümünü izlerseniz, özellikle bahsettiğimiz şey hakkında konuşur: kapsam zinciri. Kapatmalarla ilgili sorun bu. Ancak, açık kodlar gerçek kodda açık bir şekilde kaçınılmazdır, bu yüzden ileriye dönük aramaları daha hızlı yapmak için referans yaptığınız her kapsam dışı değişken için yerel bir değişken bildirmeniz gerektiğini söylüyor. - Sasha Chedygov
@Walkerneo Kapanışlarla doğal olarak yanlış bir şey yok - onlar kesinlikle harika şeyler IMO'lar. Sadece bir performans yüküne maruz kalmaları sorunu var. - Peter Olson