Underscore.js'de yeniyim. [context]
In amacı nedir _.each()
? Nasıl Kullanılmalı?
Underscore.js'de yeniyim. [context]
In amacı nedir _.each()
? Nasıl Kullanılmalı?
Yanıtlar:
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 someOtherArray
temsil edilir this
.
İçeriği ayarlamazsanız this
, window
nesneye başvurur .
context
burada this
yineleyici 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);
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.
_.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' ]
addItem
Birden çok kez aramak yerine alt çizgiyi şu şekilde kullanabilirsiniz :
_.each(['banana', 'apple', 'kiwi'], function(item) { x.addItem(item); });
Bu, addItem
bu öğ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, _.each
bu dolaylı yoldan kaçınmak ve addItem
doğrudan çağrı yapmak daha iyidir :
_.each(['banana', 'apple', 'kiwi'], x.addItem);
ancak sepetin addItem
üye işlevi this
, x
oluş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);
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ı, _.each
herhangi bir şekilde geçtiğiniz geri arama işlevi kullanırsa , geri arama işlevinizin içinde this
neye this
atıfta bulunmanız gerektiğini belirtmeniz gerekir. Gibi görünebilir x
benim örnekte gereksiz olduğunu, ancak x.addItem
sadece bir işlevdir ve tamamen ilgisiz olabilir x
veya 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, this
geri 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 underscorejs
yö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
Diğer yanıtlar açıklandığı gibi, context
olduğu this
geç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ı _.each
ya da _.forEach
aş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, context
başka bir yönteme geçirilir optimizeCb
ve 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
, func
olduğu gibi döndürülür. Eğer context
geç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, this
iç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 context
son isteğe bağlı parametre olarak düşünebilirsiniz forEach
.
someOtherArray[num]
ziyadethis[num]
?