जवाबों:
संदर्भ पैरामीटर सिर्फ this
इट्रेटर फ़ंक्शन में मान सेट करता है।
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);
काम करने का उदाहरण: http://jsfiddle.net/a6Rx4/
यह एरे के प्रत्येक सदस्य की संख्या का उपयोग उस इंडेक्स के आइटम को प्राप्त करने के लिए पुनरावृत्त someOtherArray
करता है, जिसका प्रतिनिधित्व this
हम संदर्भ पैरामीटर के रूप में करते हैं।
यदि आप संदर्भ सेट नहीं करते हैं, तो ऑब्जेक्ट this
को संदर्भित करेगा window
।
context
वह है जहाँ this
आपके पुनरावृत्त समारोह में संदर्भित किया जाता है। उदाहरण के लिए:
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);
संदर्भ आपको कॉल-टाइम पर तर्क प्रदान करने देता है, जिससे जेनेरिक पूर्व-निर्मित सहायक कार्यों के आसान अनुकूलन की अनुमति मिलती है।
कुछ उदाहरण:
// 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);
सीमित उदाहरणों से भी, आप देख सकते हैं कि पुन: प्रयोज्य कोड बनाने के लिए एक "अतिरिक्त तर्क" कितना शक्तिशाली हो सकता है। प्रत्येक स्थिति के लिए एक अलग कॉलबैक फ़ंक्शन करने के बजाय, आप आमतौर पर एक निम्न-स्तरीय सहायक को अनुकूलित कर सकते हैं। लक्ष्य आपके कस्टम लॉजिक को न्यूनतम बायलरप्लेट के साथ एक क्रिया और दो संज्ञाओं को बांधना है।
बेशक, तीर के कार्यों ने सामान्य शुद्ध कार्यों के बहुत सारे "कोड गोल्फ" लाभों को समाप्त कर दिया है, लेकिन सिमेंटिक और संगति लाभ बने हुए हैं।
प्राथमिकताओं को पार "use strict"
करते समय मूल [].map()
संगतता प्रदान करने के लिए मैं हमेशा सहायकों को जोड़ता हूं । अन्यथा, उन्हें वस्तुओं में ले जाया जाता है, जो आमतौर पर अभी भी काम करता है, लेकिन यह तेजी से और सुरक्षित-विशिष्ट है।
_.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>
यहाँ सरल उदाहरण है जो उपयोग कर सकता है _.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();
आउटपुट:
items: [ 'banana', 'apple', 'kiwi' ]
addItem
कई बार कॉल करने के बजाय आप इस तरह से अंडरस्कोर का उपयोग कर सकते हैं :
_.each(['banana', 'apple', 'kiwi'], function(item) { x.addItem(item); });
जो addItem
इन वस्तुओं के साथ क्रमिक रूप से तीन बार कॉल करने के समान है । मूल रूप से यह आपके सरणी को पुनरावृत्त करता है और प्रत्येक आइटम के लिए आपके अनाम कॉलबैक फ़ंक्शन को कॉल करता है x.addItem(item)
। अनाम कॉलबैक फ़ंक्शन addItem
सदस्य फ़ंक्शन के समान है (जैसे यह एक आइटम लेता है) और व्यर्थ की तरह है। इसलिए, अनाम फ़ंक्शन के माध्यम से जाने के बजाय यह बेहतर है कि _.each
इस अप्रत्यक्ष से बचा जाए और addItem
सीधे कॉल करें:
_.each(['banana', 'apple', 'kiwi'], x.addItem);
लेकिन यह काम नहीं करेगा, क्योंकि टोकरी के addItem
सदस्य फ़ंक्शन के अंदर this
आपकी x
टोकरी को संदर्भित नहीं किया जाएगा जो आपने बनाई थी। यही कारण है कि आपके पास अपनी टोकरी x
को पास करने का एक विकल्प है [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>
संक्षेप में, यदि आप _.each
किसी भी तरह से पास होने वाले कॉलबैक फ़ंक्शन का उपयोग करते हैं, this
तो आपको यह निर्दिष्ट this
करना होगा कि आपके कॉलबैक फ़ंक्शन के अंदर क्या होना चाहिए। ऐसा लगता है जैसे x
मेरी उदाहरण में अनावश्यक है, लेकिन x.addItem
सिर्फ एक समारोह है और पूरी तरह से से संबंधित नहीं हो सकता है x
या basket
या किसी अन्य वस्तु, उदाहरण के लिए :
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>
दूसरे शब्दों में, आप this
अपने कॉलबैक के अंदर कुछ मूल्य बांधते हैं , या आप सीधे इस तरह से बाइंड का उपयोग कर सकते हैं :
_.each(['banana', 'apple', 'kiwi'], addItem.bind(x));
यह सुविधा कुछ अलग अंडरस्कोर तरीकों से कैसे उपयोगी हो सकती है?
सामान्य तौर पर, यदि कोई underscorejs
विधि कॉलबैक फ़ंक्शन लेती है और यदि आप चाहते हैं कि कॉलबैक को किसी ऑब्जेक्ट के कुछ सदस्य फ़ंक्शन (जैसे कोई फ़ंक्शन जो उपयोग करता है this
) पर कॉल किया जाए, तो आप उस फ़ंक्शन को किसी ऑब्जेक्ट में बाँध सकते हैं या उस ऑब्जेक्ट को [context]
पैरामीटर के रूप में पास कर सकते हैं और प्राथमिक इरादा। और अंडरस्कोरजेस डॉक्यूमेंटेशन में सबसे ऊपर, यही वे कहते हैं: इट्रैट संदर्भ ऑब्जेक्ट से जुड़ा होता है, यदि कोई पास हो जाता है
जैसा कि अन्य उत्तरों में बताया गया है, context
क्या this
कॉलबैक के अंदर इस्तेमाल किया जाने वाला संदर्भ है each
।
मैं इसे अंडरस्कोर स्रोत कोड से प्रासंगिक तरीकों के स्रोत कोड की मदद से समझाऊंगा
की परिभाषा _.each
या _.forEach
इस प्रकार है:
_.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;
};
यहां ध्यान देने के लिए दूसरा कथन महत्वपूर्ण है
iteratee = optimizeCb(iteratee, context);
यहां, context
एक अन्य विधि में पारित किया जाता है optimizeCb
और इसमें से लौटाया गया कार्य फिर सौंपा iteratee
जाता है जिसे बाद में कहा जाता है।
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);
};
};
जैसा कि उपरोक्त विधि परिभाषा से देखा जा सकता है optimizeCb
, यदि context
पारित नहीं हुआ है तो func
जैसा है वैसा ही लौटा दिया जाता है। यदि context
पारित हो जाता है, तो कॉलबैक फ़ंक्शन को कहा जाता है
func.call(context, other_parameters);
^^^^^^^
func
कहा जाता है call()
जिसके साथ this
इसका संदर्भ सेट करके किसी विधि को लागू करने के लिए उपयोग किया जाता है। इसलिए, जब this
अंदर उपयोग किया जाता है func
, तो यह संदर्भित करेगा 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>
आप जावास्क्रिप्ट में context
अंतिम वैकल्पिक पैरामीटर के रूप में विचार कर सकते हैं forEach
।
someOtherArray[num]
बल्कि संदर्भित करते हैंthis[num]
?