_.Each (list, iterator, [context]) içindeki bağlam nedir?


Yanıtlar:


220

Context parametresi this, yineleyici işlevindeki değerini ayarlar .

var someOtherArray = ["name","patrick","d","w"];

_.each([1, 2, 3], function(num) { 
    // In here, "this" refers to the same Array as "someOtherArray"

    alert( this[num] ); // num is the value from the array being iterated
                        //    so this[num] gets the item at the "num" index of
                        //    someOtherArray.
}, someOtherArray);

Çalışma Örneği: http://jsfiddle.net/a6Rx4/

Bu dizinde öğeyi almak için yinelenen Array öğesinin her bir üyesinden gelen sayıyı kullanır; bu, context parametresi olarak geçtiğimizden beri someOtherArraytemsil edilir this.

İçeriği ayarlamazsanız this, windownesneye başvurur .


7
Bunun avantajı nedir? Neden sadece ilgili değildir someOtherArray[num]ziyade this[num]?
csjacobs24

3
@ csjacobs24: Yerel değişken kapsamına erişimi olmayan bir dizi yeniden kullanılabilir fonksiyona sahip olmak yaygındır. İşte basit bir örnek: jsfiddle.net/a6Rx4/745

1
Bu cevap soruyu cevaplıyor, ancak bunun nasıl faydalı olabileceğine dair örnekler vermesi daha iyi olurdu.
temporary_user_name

50

contextburada thisyineleyici işlevinizde ifade edilir. Örneğin:

var person = {};
person.friends = {
  name1: true,
  name2: false,
  name3: true,
  name4: true
};

_.each(['name4', 'name2'], function(name){
  // this refers to the friends property of the person object
  alert(this[name]);
}, person.friends);

7

Bağlam, çağrı sırasında bağımsız değişkenler sağlayarak genel önceden oluşturulmuş yardımcı işlevlerin kolayca özelleştirilmesini sağlar.

bazı örnekler:

// stock footage:
function addTo(x){ "use strict"; return x + this; }
function pluck(x){ "use strict"; return x[this]; }
function lt(x){ "use strict"; return x < this; }

// production:
var r = [1,2,3,4,5,6,7,8,9];
var words = "a man a plan a canal panama".split(" ");

// filtering numbers:
_.filter(r, lt, 5); // elements less than 5
_.filter(r, lt, 3); // elements less than 3

// add 100 to the elements:
_.map(r, addTo, 100);

// encode eggy peggy:
_.map(words, addTo, "egg").join(" ");

// get length of words:
_.map(words, pluck, "length"); 

// find words starting with "e" or sooner:
_.filter(words, lt, "e"); 

// find all words with 3 or more chars:
_.filter(words, pluck, 2); 

Sınırlı örneklerden bile, yeniden kullanılabilir kod oluşturmak için bir "ekstra argüman" ın ne kadar güçlü olabileceğini görebilirsiniz. Her durum için farklı bir geri arama işlevi yapmak yerine, genellikle düşük düzey bir yardımcıyı uyarlayabilirsiniz. Amaç, özel mantığınızın asgari kaynatma plakasıyla bir fiil ve iki isim paketlemesini sağlamaktır.

Kuşkusuz, ok fonksiyonları, genel saf fonksiyonların "kod golf" avantajlarının birçoğunu ortadan kaldırmıştır, ancak semantik ve tutarlılık avantajları devam etmektedir.

İlkelleri geçerken her zaman "use strict"yerel [].map()uyumluluk sağlamak için yardımcılara ekliyorum . Aksi takdirde, genellikle hala çalışan nesnelere zorlanırlar, ancak türe özgü olmak daha hızlı ve daha güvenlidir.


5

_.Each'in basit kullanımı

_.each(['Hello', 'World!'], function(word){
    console.log(word);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

İşte kullanabileceğiniz basit bir örnek_.each :

function basket() {
    this.items = [];
    this.addItem = function(item) {
        this.items.push(item);
    };
    this.show = function() {
        console.log('items: ', this.items);
    }
}

var x = new basket();
x.addItem('banana');
x.addItem('apple');
x.addItem('kiwi');
x.show();

Çıktı:

items:  [ 'banana', 'apple', 'kiwi' ]

addItemBirden çok kez aramak yerine alt çizgiyi şu şekilde kullanabilirsiniz :

_.each(['banana', 'apple', 'kiwi'], function(item) { x.addItem(item); });

Bu, addItembu öğelerle üç kez sırayla çağrı yapmakla aynıdır . Temel olarak dizinizi yineler ve her öğe için çağıran anonim geri arama işlevinizi çağırır x.addItem(item). Anonim geri arama işlevi addItemüye işlevine benzer (örneğin bir öğe alır) ve bir tür anlamsızdır. Bu nedenle, anonim işlevden geçmek yerine, _.eachbu dolaylı yoldan kaçınmak ve addItemdoğrudan çağrı yapmak daha iyidir :

_.each(['banana', 'apple', 'kiwi'], x.addItem);

ancak sepetin addItemüye işlevi this, xoluşturduğunuz sepetinize gönderme yapmayacağı için bu işe yaramaz . Bu nedenle, sepetinizi xşu şekilde kullanılmak üzere geçirme seçeneğiniz vardır [context]:

_.each(['banana', 'apple', 'kiwi'], x.addItem, x);

_.Each ve context kullanan tam örnek:

function basket() {
    this.items = [];
    this.addItem = function(item) {
        this.items.push(item);
    };
    this.show = function() {
        console.log('items: ', this.items);
    }
}
var x = new basket();
_.each(['banana', 'apple', 'kiwi'], x.addItem, x);
x.show();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Kısacası, _.eachherhangi bir şekilde geçtiğiniz geri arama işlevi kullanırsa , geri arama işlevinizin içinde thisneye thisatıfta bulunmanız gerektiğini belirtmeniz gerekir. Gibi görünebilir xbenim örnekte gereksiz olduğunu, ancak x.addItemsadece bir işlevdir ve tamamen ilgisiz olabilir xveya basket örneğin, ya da başka herhangi bir nesne :

function basket() {
    this.items = [];
    this.show = function() {
        console.log('items: ', this.items);
    }
}
function addItem(item) {
    this.items.push(item);
};

var x = new basket();
_.each(['banana', 'apple', 'kiwi'], addItem, x);
x.show();
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

Başka bir deyişle, thisgeri aramanızın içine bir değer bağlarsınız veya doğrudan bu şekilde bağla da kullanabilirsiniz :

_.each(['banana', 'apple', 'kiwi'], addItem.bind(x));

bu özellik bazı farklı alt çizgi yöntemleriyle nasıl yararlı olabilir?

Genel olarak, bir underscorejsyöntem bir geri çağırma işlevi alıyorsa ve bu geri çağrının bazı nesnelerin bazı üye işlevlerinde (örneğin, kullanılan bir işlev this) çağrılmasını istiyorsanız, o işlevi bir nesneye bağlayabilir veya bu nesneyi [context]parametre olarak iletebilirsiniz. birincil niyet. Ve alt çizgi belgelerinin en üstünde, tam olarak belirttikleri şey: Yinelemeden biri geçilirse bağlam nesnesine bağlıdır


4

Diğer yanıtlar açıklandığı gibi, contextolduğu thisgeçirilen callback'inde içinde kullanılacak bağlam each.

Bunu ilgili yöntemlerin kaynak kodunun yardımıyla açıklayacağım. alt çizgi kaynak kodundan

Tanımı _.eachya da _.forEachaşağıdaki gibidir:

_.each = _.forEach = function(obj, iteratee, context) {
  iteratee = optimizeCb(iteratee, context);

  var i, length;
  if (isArrayLike(obj)) {
    for (i = 0, length = obj.length; i < length; i++) {
      iteratee(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;
};

İkinci ifade burada not etmek önemlidir

iteratee = optimizeCb(iteratee, context);

Burada, contextbaşka bir yönteme geçirilir optimizeCbve bundan sonra döndürülen işlev, daha sonra iterateeçağrılı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);
  };
};

Yukarıdaki yöntem tanımından görülebileceği gibi optimizeCb, geçilmezse context, funcolduğu gibi döndürülür. Eğer contextgeçirilir, geri çağırma işlevi olarak adlandırılır

func.call(context, other_parameters);
          ^^^^^^^

func, bağlamını call()ayarlayarak bir yöntemi çağırmak için kullanılır this. Yani, thisiçeride kullanıldığında func, buna atıfta bulunacaktır context.

// Without `context`
_.each([1], function() {
  console.log(this instanceof Window);
});


// With `context` as `arr`
var arr = [1, 2, 3];
_.each([1], function() {
  console.log(this);
}, arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

JavaScript'te contextson isteğe bağlı parametre olarak düşünebilirsiniz forEach.

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.