2016-03-22 19 views
3

Ben underscorejs itibaren, bu düşündüğünü oldum:underscorejs'deki optimizasyon nasıl çalışır?

var optimizeCb = function(func, context, argCount) { 
    if (context === void 0) return func; 
    switch (argCount == null ? 3 : argCount) { 
     case 1: return function(value) { 
     return func.call(context, value); 
     }; 
     case 2: return function(value, other) { 
     return func.call(context, value, other); 
     }; 
     case 3: return function(value, index, collection) { 
     return func.call(context, value, index, collection); 
     }; 
     case 4: return function(accumulator, value, index, collection) { 
     return func.call(context, accumulator, value, index, collection); 
     }; 
    } 
    return function() { 
     return func.apply(context, arguments); 
    }; 
    }; 

Yani, görünüşe göre bu optimizasyon sadece (burada context denir) this değerini ayarlar geri arama için de geçerlidir. Bu farklı, geri arama için doğrudan call'u nasıl arayabilir? Bu, performansı nasıl geliştirebilir?

Optimizasyon yalnızca eski JS motorları için geçerliyse sorun değil. Sadece bilmek için ölüyorum.

Düzenleme

muhtemelen söz konusu belli değildi. Demek istediğim bu. optimizeCb kullanıldığı Bir örnek verelim:

_.each = _.forEach = function(obj, iteratee, context) { 
    iteratee = optimizeCb(iteratee, context); //REMOVE this 
    var i, length; 
    if (isArrayLike(obj)) { 
     for (i = 0, length = obj.length; i < length; i++) { 
     iteratee(obj[i], i, obj); 
     //REPLACE with iteratee.call(context, obj[i], i, obj); 
     } 
    } else { 
     var keys = _.keys(obj); 
     for (i = 0, length = keys.length; i < length; i++) { 
     iteratee(obj[keys[i]], keys[i], obj); 
     } 
    } 
    return obj; 
    }; 

2 yorumları görüntüle: iteratee = optimizeCb(iteratee, context); //REMOVE this ve iteratee(obj[i], i, obj); //REPLACE with iteratee.call(context, obj[i], i, obj);. Tartışmaların yavaş olduğunu ve başvuruda yavaş olduğunu anlıyorum. Ama benve vs argümanları çağrıları nasıl görüyorsunuz? 2 yaklaşım arasında fark görmüyorum.

Anahtar sorun, geri arama belirli bir alt çizgi yöntemine geçirilirse, imzanın zaten bilindiğini düşünüyorum. Örneğin, geri arama _.each'a geçirildiğinde function(value, index, collection) olmalıdır. Bu gözlem, optimizCb'nin çağrıldığı şekilde onaylanır: optimizeCb'nin arayanı argCount parametresini sağlayabilirse (boş bırakın, 3 demektir), hangi imzanın olduğunu bilir.

Birisi daha ayrıntılı olabilir mi? Çok teşekkürler!

+1

'call', https://jsperf.com/call-apply-segu adresinden çok daha hızlıdır. Düşünüyorum çünkü argüman dizisine erişmek zorunda değil. –

+0

@Moogs: Bağlandığınız test elmaları-elmaları karşılaştırmıyor; Sanırım bunu yapıyor: http://jsperf.com/call-apply-segu/53 Yine de 'apply' üzerinden 'call' için hala belli bir avantaj var. –

cevap

2

Üç onlar yapıyor olabilir nedenler: arguments sözde diziye erişim

  1. eski JavaScript motorlarına pahalıya mal oldu. Gerçekten pahalı. Mesela, birkaç emir büyüklüğü.

    Modern motorlarda, özellikle sıkı modda değil, arguments ve biçimsel işlev argümanları arasındaki canlı bağlantıyı kaldıran büyük bir maliyet olduğunu düşünmüyorum. Bir comment içinde

  2. Moogs zamanda noktalarını, applycall daha yavaştır. this test dayanarak, yarısı tekrar ve iki katı arasında bir yerde olduğu gibi görünüyor. Yani arguments (gün içinde) büyüklük-or-ikisinin büyüklüğü ile aynı ligde değil, ama yine de, daha hızlı.

  3. contextundefined ise, bunlar değişmeden fonksiyonunu (yani başlangıçtaki if (context == void 0) return func; var) iade, bu yüzden çağrılırken de tüm ilgili hiçbir .callveya.apply var.

Peki yapar ikilidir:

A) geri arama belirli this gerektirmiyorsa, bu basit işlev çağrısı ile doğrudan geri arama kullanır.Geri arama , this belirli bir this gerekiyorsa, onlar, context bağımsız değişkeni geçirerek kaydeder ve çağrı kodunu basitleştirir, doğru this kullanacak şekilde aynı şekilde çağırabilirler.

B) Bu arguments erişmek ve özel dikiş sarıcı fonksiyonu ile argümanların ortak sayılar için apply kullanmaz: 1-4 argümanlar alır geri aramalar maliyeti önlemek için olsun, geri aramalar, 0 ya da en fazla 4 bağımsız değişken ile maliyet yol açar.

+0

Merhaba, lütfen benim düzenle – Boyang

+0

@CharlesW .: Yukarıda # 3 eklendi. –

+0

Ah, bağlamdaki nokta çok doğrudur. Mükemmel cevap – Boyang