_.Each (सूची, पुनरावृत्ति, [संदर्भ]) में संदर्भ क्या है?


162

मैं अंडरस्कोर।जेएस के लिए नया हूं। का उद्देश्य क्या है [context]में _.each()? इसका उपयोग कैसे किया जाना चाहिए?

जवाबों:


220

संदर्भ पैरामीटर सिर्फ 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


7
उसका क्या फायदा? क्यों नहीं someOtherArray[num]बल्कि संदर्भित करते हैं this[num]?
csjacobs24

3
@ csjacobs24: पुन: प्रयोज्य कार्यों का एक सेट होना आम है जो स्थानीय चर दायरे तक नहीं पहुंच पाएंगे। यहाँ एक सरल उदाहरण है: jsfiddle.net/a6Rx4/745

1
यह उत्तर प्रश्न का उत्तर देता है, लेकिन यह बेहतर होगा यदि यह उदाहरण प्रदान करता है कि यह कैसे उपयोगी हो सकता है।
temporary_user_name

50

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);

7

संदर्भ आपको कॉल-टाइम पर तर्क प्रदान करने देता है, जिससे जेनेरिक पूर्व-निर्मित सहायक कार्यों के आसान अनुकूलन की अनुमति मिलती है।

कुछ उदाहरण:

// 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()संगतता प्रदान करने के लिए मैं हमेशा सहायकों को जोड़ता हूं । अन्यथा, उन्हें वस्तुओं में ले जाया जाता है, जो आमतौर पर अभी भी काम करता है, लेकिन यह तेजी से और सुरक्षित-विशिष्ट है।


5

_.Each का सरल उपयोग

_.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);

पूर्ण उदाहरण जो _.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();
_.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]पैरामीटर के रूप में पास कर सकते हैं और प्राथमिक इरादा। और अंडरस्कोरजेस डॉक्यूमेंटेशन में सबसे ऊपर, यही वे कहते हैं: इट्रैट संदर्भ ऑब्जेक्ट से जुड़ा होता है, यदि कोई पास हो जाता है


4

जैसा कि अन्य उत्तरों में बताया गया है, 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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.