Jawaban:
Parameter konteks hanya menetapkan nilai this
dalam fungsi iterator.
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);
Contoh Kerja: http://jsfiddle.net/a6Rx4/
Ia menggunakan nomor dari setiap anggota Array yang di-iterasi untuk mendapatkan item pada indeks tersebut someOtherArray
, yang diwakili oleh this
sejak kami memberikannya sebagai parameter konteks.
Jika Anda tidak mengatur konteksnya, maka this
akan merujuk ke window
objek.
context
adalah di mana this
mengacu pada fungsi iterator Anda. Sebagai contoh:
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);
Konteksnya memungkinkan Anda memberikan argumen saat panggilan berlangsung, memungkinkan penyesuaian mudah dari fungsi pembantu umum yang dibuat sebelumnya.
beberapa contoh:
// 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);
Bahkan dari contoh terbatas, Anda dapat melihat betapa dahsyatnya "argumen tambahan" dapat untuk membuat kode yang dapat digunakan kembali. Alih-alih membuat fungsi panggilan balik yang berbeda untuk setiap situasi, Anda biasanya dapat mengadaptasi pembantu tingkat rendah. Tujuannya adalah agar logika kustom Anda menggabungkan kata kerja dan dua kata benda, dengan pelat ketel minimum.
Memang, fungsi panah telah menghilangkan banyak "kode golf" keunggulan fungsi murni generik, tetapi keunggulan semantik dan konsistensi tetap.
Saya selalu menambahkan "use strict"
bantuan untuk memberikan [].map()
kompatibilitas asli ketika melewati primitif. Kalau tidak, mereka dipaksa menjadi objek, yang biasanya masih berfungsi, tetapi lebih cepat dan aman untuk menjadi tipe spesifik.
_.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>
Inilah contoh sederhana yang dapat digunakan _.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();
Keluaran:
items: [ 'banana', 'apple', 'kiwi' ]
Alih-alih menelepon addItem
beberapa kali, Anda dapat menggunakan garis bawah dengan cara ini:
_.each(['banana', 'apple', 'kiwi'], function(item) { x.addItem(item); });
yang identik dengan memanggil addItem
tiga kali berurutan dengan barang-barang ini. Pada dasarnya itu array Anda dan untuk setiap item memanggil fungsi panggilan balik anonim Anda yang memanggil x.addItem(item)
. Fungsi panggilan balik anonim mirip dengan addItem
fungsi anggota (misalnya mengambil item) dan agak tidak berguna. Jadi, alih-alih melalui fungsi anonim, lebih baik _.each
menghindari tipuan ini dan menelepon addItem
langsung:
_.each(['banana', 'apple', 'kiwi'], x.addItem);
tetapi ini tidak akan berfungsi, karena addItem
fungsi anggota di dalam keranjang this
tidak akan merujuk ke x
keranjang yang Anda buat. Itu sebabnya Anda memiliki opsi untuk meneruskan keranjang Anda x
untuk digunakan sebagai [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>
Singkatnya, jika fungsi panggilan balik yang Anda _.each
gunakan menggunakan cara apa pun this
maka Anda perlu menentukan apa yang this
harus dirujuk di dalam fungsi panggilan balik Anda. Mungkin tampak seperti x
berlebihan dalam contoh saya, tetapi x.addItem
hanya sebuah fungsi dan bisa sama sekali tidak terkait dengan x
atau basket
atau objek lain, misalnya :
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>
Dengan kata lain, Anda mengikat beberapa nilai ke this
dalam panggilan balik Anda, atau Anda juga dapat menggunakan mengikat secara langsung seperti ini:
_.each(['banana', 'apple', 'kiwi'], addItem.bind(x));
bagaimana fitur ini dapat berguna dengan beberapa metode garis bawah yang berbeda?
Secara umum, jika beberapa underscorejs
metode mengambil fungsi panggilan balik dan jika Anda ingin panggilan balik itu dipanggil pada beberapa fungsi anggota dari beberapa objek (misalnya fungsi yang menggunakan this
) maka Anda dapat mengikat fungsi itu ke beberapa objek atau meneruskan objek itu sebagai [context]
parameter dan itu niat utama. Dan di bagian atas dokumentasi underscorejs, itulah yang mereka nyatakan: Iteratee terikat ke objek konteks, jika satu dilewatkan
Seperti yang dijelaskan dalam jawaban lain, context
apakah this
konteks yang akan digunakan dalam callback diteruskan ke each
.
Saya akan menjelaskan ini dengan bantuan kode sumber metode yang relevan dari kode sumber garis bawah
Definisi _.each
atau _.forEach
adalah sebagai berikut:
_.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;
};
Pernyataan kedua penting untuk diperhatikan di sini
iteratee = optimizeCb(iteratee, context);
Di sini, context
diteruskan ke metode lain optimizeCb
dan fungsi yang dikembalikan darinya kemudian ditugaskan iteratee
yang kemudian disebut.
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);
};
};
Seperti dapat dilihat dari definisi metode di atas optimizeCb
, jika context
tidak lulus maka func
dikembalikan sebagaimana adanya. Jika context
dilewati, fungsi panggilan balik disebut sebagai
func.call(context, other_parameters);
^^^^^^^
func
dipanggil dengan call()
yang digunakan untuk memanggil metode dengan mengatur this
konteksnya. Jadi, ketika this
digunakan di dalam func
, itu akan merujuk 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>
Anda dapat mempertimbangkan context
sebagai parameter opsional terakhir forEach
dalam JavaScript.
someOtherArray[num]
bukanthis[num]
?