क्या जावास्क्रिप्ट में फ़ॉरचिंग करते समय सरणी के मूल्यों को बदलना संभव है?


300

उदाहरण:

var arr = ["one","two","three"];

arr.forEach(function(part){
  part = "four";
  return "four";
})

alert(arr);

सरणी अभी भी मूल मूल्यों के साथ है, क्या एररिंग फ़ंक्शन से सरणी के तत्वों तक पहुंच लिखने का कोई तरीका है?



मानचित्र आज़माएं ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ):x=[2,3,4]; x=x.map(n=>n*2); // [4,6,8]
जस्टिन

जवाबों:


468

कॉलबैक तत्व, सूचकांक और सरणी को स्वयं पारित किया जाता है।

arr.forEach(function(part, index, theArray) {
  theArray[index] = "hello world";
});

संपादित करें - जैसा कि एक टिप्पणी में कहा गया है, .forEach()फ़ंक्शन एक दूसरा तर्क ले सकता है, जिसका उपयोग thisकॉल करने के लिए प्रत्येक कॉल के मूल्य के रूप में किया जाएगा :

arr.forEach(function(part, index) {
  this[index] = "hello world";
}, arr); // use arr as this

यह दूसरा उदाहरण कॉलबैक के arrरूप thisमें खुद को स्थापित करने से पता चलता है। कोई सोच सकता है कि .forEach()कॉल में शामिल सरणी का डिफ़ॉल्ट मान हो सकता है this, लेकिन जो भी कारण यह नहीं है; thisयह होगा कि undefinedयदि दूसरा तर्क प्रदान नहीं किया गया है।

(ध्यान दें: thisयदि कॉलबैक एक =>फ़ंक्शन है, तो इसके बारे में उपरोक्त सामग्री लागू नहीं होती है , क्योंकि thisइस तरह के कार्यों को लागू किए जाने पर किसी भी चीज के लिए बाध्य नहीं होता है।)

यह भी याद रखना महत्वपूर्ण है कि ऐरे प्रोटोटाइप पर प्रदान की गई समान उपयोगिताओं का एक पूरा परिवार है, और कई प्रश्न स्टैकओवरफ़्लो पर एक फ़ंक्शन या किसी अन्य के बारे में पॉप अप करते हैं जैसे कि सबसे अच्छा समाधान बस एक अलग टूल चुनना है। तुम्हें मिल गया है:

  • forEach एक सरणी में या हर प्रविष्टि के साथ एक काम करने के लिए;
  • filter केवल अर्हक प्रविष्टियों वाले एक नए सरणी के निर्माण के लिए;
  • map मौजूदा सरणी को परिवर्तित करके एक-से-एक नए सरणी बनाने के लिए;
  • some यह जाँचने के लिए कि किसी सरणी में कम से कम एक तत्व कुछ वर्णन के लिए उपयुक्त है या नहीं;
  • everyयह जाँचने के लिए कि किसी सरणी में सभी प्रविष्टियाँ विवरण से मेल खाती हैं या नहीं;
  • find किसी सरणी में मान देखने के लिए

और इसी तरह। MDN लिंक


34
धन्यवाद! ES6: arr.forEach ((o, i, a) => a [i] = myNewVal)
DiegoRBaquero

क्यों part(या oes6 में भी ) अपरिभाषित है? कैसे iterated मूल्य पाने के लिए?
डेनियल मशकिन

@DaniilMashkin partहोगा undefinedयदि सरणी का एक तत्व undefinedस्पष्ट रूप से सौंपा गया है । एक सरणी के "खाली" स्लॉट (एक सरणी प्रविष्टि जिसे कभी भी कोई मान नहीं सौंपा गया है) .forEach()सबसे अधिक और अन्य सरणी पुनरावृत्ति विधियों द्वारा छोड़ दिया जाता है ।
पोइंट्टी

2
पूर्णता के लिए, .forEach()एक दूसरा तर्क भी लेता है thisArg, जिसे आप thisकॉलबैक के अंदर उपयोग कर सकते हैं । नोट: यह .forEachकॉलबैक का तर्क नहीं है।
मोहम्मदी ऊँट ऊँट

3
thisपास किए गए दूसरे तर्क के रूप में उपयोग करने के लिए .forEach(), आपको सिंटैक्स का उपयोग करके कॉलबैक फ़ंक्शन को पास करने की आवश्यकता है function(), क्योंकि ES6 के तीर फ़ंक्शन का उपयोग () => {}संदर्भ को बाध्य नहीं करता है।
जपना

131

आइए इसे सरल रखने की कोशिश करें और चर्चा करें कि यह वास्तव में कैसे काम कर रहा है। यह चर प्रकार और फ़ंक्शन मापदंडों के साथ करना है।

आपका कोड हम यहां बता रहे हैं:

var arr = ["one","two","three"];

arr.forEach(function(part) {
  part = "four";
  return "four";
})

alert(arr);

सबसे पहले, यहाँ है जहाँ आपको Array.prototype.forEach () के बारे में पढ़ना चाहिए:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

दूसरा, आइए जावास्क्रिप्ट में मूल्य प्रकारों के बारे में संक्षेप में बात करते हैं।

आदिम (अपरिभाषित, अशक्त, स्ट्रिंग, बुलियन, संख्या) एक वास्तविक मूल्य संग्रहीत करते हैं।

उदाहरण के लिए: var x = 5;

संदर्भ प्रकार (कस्टम ऑब्जेक्ट) ऑब्जेक्ट के मेमोरी स्थान को संग्रहीत करते हैं।

उदाहरण के लिए: var xObj = { x : 5 };

और तीसरा, फ़ंक्शन पैरामीटर कैसे काम करते हैं।

फ़ंक्शंस में, पैरामीटर हमेशा मूल्य द्वारा पारित किए जाते हैं ।

क्योंकि arrस्ट्रिंग्स की एक सरणी है, यह आदिम वस्तुओं का एक सरणी है , जिसका अर्थ है कि वे मूल्य द्वारा संग्रहीत किए जाते हैं।

तो ऊपर दिए गए आपके कोड के लिए, इसका मतलब यह है कि हर बार forEach () पुनरावृत्ति partकरता है arr[index], लेकिन समान ऑब्जेक्ट के समान मूल्य के बराबर है ।

part = "four";partचर को बदल देगा , लेकिन arrअकेला छोड़ देगा ।

निम्नलिखित कोड आपकी इच्छा के मूल्यों को बदल देगा:

var arr = ["one","two","three"];

arr.forEach(function(part, index) {
  arr[index] = "four";
});

alert(arr);

अब यदि सरणी संदर्भ प्रकारोंarr की एक सरणी थी , तो निम्न कोड काम करेगा क्योंकि संदर्भ प्रकार वास्तविक ऑब्जेक्ट के बजाय किसी ऑब्जेक्ट का मेमोरी स्थान संग्रहीत करते हैं।

var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];

arr.forEach(function(part, index) {
  // part and arr[index] point to the same object
  // so changing the object that part points to changes the object that arr[index] points to

  part.num = "four";
});

alert(arr[0].num);
alert(arr[1].num);
alert(arr[2].num);

निम्नलिखित दर्शाता है कि आप अकेले partमें संग्रहीत वस्तुओं को छोड़ते हुए एक नई वस्तु की ओर संकेत कर सकते arrहैं:

var arr = [{ num : "one" }, { num : "two"}, { num : "three"}];

arr.forEach(function(part, index) {
  // the following will not change the object that arr[index] points to because part now points at a new object
  part = 5;
});

alert(arr[0].num);
alert(arr[1].num);
alert(arr[2].num);

2
वास्तव में, महान व्याख्या! यह बेहतर होगा कि अन्य पुनरावृति के तरीकों पर स्पष्टीकरण का विस्तार किया जाए ... के लिए, ..., ... के लिए नया ... ऐसे मामलों के लिए बहुत ही समान तरीके से काम करता है, सिवाय इसके कि " सूचकांक "मूल सरणी (जैसे कि forEach) में परिवर्तन के लिए गायब है। इसके अलावा ES5 का नक्शा forEach के समान लगता है, हो सकता है कि मानचित्र से मानों को वापस करने की संभावना सूचकांक के उपयोग की तुलना में चीजों को वाक्यविन्यास के दृष्टिकोण से स्पष्ट करती है।
क्रिस्टोफ विडाल

1
महान व्याख्या। धन्यवाद। आखिरकार मुझे यह कथन नहीं मिल सकता है: In functions, parameters are always passed by value. दूसरे उदाहरण के बारे में क्या?
एलेक्स

@ 7sides, यह कथन वर्णन कर रहा है कि फ़ंक्शन पैरामीटर हमेशा मान द्वारा पारित किए जाएंगे। इसलिए आदिम के लिए, यह वह मूल्य होगा जो आदिम को इंगित करता है। ऑब्जेक्ट के लिए, वह स्थान होगा जिसे ऑब्जेक्ट इंगित कर रहा है। इस w3schools पृष्ठ की अच्छी व्याख्या है। देखें कि खंड मूल्य द्वारा पास किए गए हैं और ऑब्जेक्ट्स संदर्भ द्वारा पारित किए गए हैं
डेव

फ़ंक्शंस में, पैरामीटर हमेशा मूल्य द्वारा पारित किए जाते हैं। BAM। धन्यवाद। +1
राडारोब

92

सरणी: [1, 2, 3, 4]
परिणाम:["foo1", "foo2", "foo3", "foo4"]

Array.prototype.map() मूल सरणी रखें

const originalArr = ["Iron", "Super", "Ant", "Aqua"];
const modifiedArr = originalArr.map(name => `${name}man`);

console.log( "Original: %s", originalArr );
console.log( "Modified: %s", modifiedArr );

Array.prototype.forEach() मूल सरणी को ओवरराइड करें

const originalArr = ["Iron", "Super", "Ant", "Aqua"];
originalArr.forEach((name, index) => originalArr[index] = `${name}man`);

console.log( "Overridden: %s", originalArr );


3
"Array.prototyp.map () मूल सरणी को संशोधित करें, गिरफ्तार चर को पुन: असाइन करके हासिल किया गया" .map () मूल सरणी को कभी भी संशोधित नहीं करता है, यह एक नया बनाता है। चर का पुनर्मूल्यांकन मूल वस्तु को नहीं बदलता है।
vadkou

1
let arr1 = ["1", 2, 3, 4]; arr1.map(function(v) { return "foo"+ v; }); console.log( arr ); Array.prototyp.map () मूल सरणी को कभी संशोधित न करें, म्यूट करें।
अनुपम मौर्य

@ अनुपममौर्या यह बिल्कुल भी सच नहीं है। mapनिश्चित रूप से इसके सरणी को बदल सकते हैं forEach, और सामान्य तौर पर, नहीं।
user4642212

@SebastianSimon, उत्तर के लिए धन्यवाद। सभी मैं जोड़ना चाहता हूं, सभी डेटा को ओवरराइड करते हैं, लेकिन एक नक्शा, नहीं कर सकता, यह एक नई प्रतिलिपि बनाता है।
अनुपम मौर्य

14

जावास्क्रिप्ट को मान से पास किया जाता है, और जो अनिवार्य रूप से मतलब partहै वह सरणी में मूल्य की एक प्रति है।

मान बदलने के लिए, सरणी को अपने लूप में ही एक्सेस करें।

arr[index] = 'new value';


यह इस बात पर निर्भर करता है partकि क्या इसकी प्रतिलिपि बनाई गई है - हालांकि आप सही हैं कि चर एक सूचक नहीं है, लेकिन एक मान है
बर्गी

8
"जावास्क्रिप्ट पास मूल्य से है" कहना एक सामान्य सामान्यीकरण है। जावास्क्रिप्ट में संदर्भ प्रकार हैं। मूल्य प्रकार मूल्य द्वारा पारित किए जाते हैं।
एलेक्स टर्पिन

9
स्थूल सामान्यीकरण नहीं। पूरी तरह से सही और निरपेक्ष कथन। जावास्क्रिप्ट मूल्य से संदर्भ गुजरता है। जावास्क्रिप्ट को मान से पास किया जाता है, हमेशा।
hvgotcodes

1
@ बर्गी: नहीं, इससे कोई फर्क नहीं पड़ता। सभी मूल्यों को असाइनमेंट पर कॉपी किया जाता है - जावास्क्रिप्ट में केवल मान आदिम और संदर्भ हैं। आदिम और संदर्भ दोनों को असाइनमेंट पर कॉपी किया जाता है।
newacct

6
@ बर्गी सिर्फ इसलिए कि एक भाषा में संदर्भ नामक एक चीज होती है, इसका मतलब यह नहीं है कि यह संदर्भ द्वारा पास का उपयोग करता है। संदर्भ मूल्य द्वारा पारित किए जा सकते हैं (और हैं), अर्थात संदर्भ के मूल्य की प्रतिलिपि बनाई गई है और उस प्रति का उपयोग तर्क के रूप में किया जाता है।
hvgotcodes 15


4

यहां एक =>शैली फ़ंक्शन का उपयोग करके एक समान उत्तर दिया गया है:

var data = [1,2,3,4];
data.forEach( (item, i, self) => self[i] = item + 10 );

परिणाम देता है:

[11,12,13,14]

selfपैरामीटर तीर शैली समारोह के साथ सख्ती से आवश्यक नहीं है, इसलिए

data.forEach( (item,i) => data[i] = item + 10);

भी काम करता है।


3

.ForEach फ़ंक्शन में कॉलबैक फ़ंक्शन (eachelement, elementIndex) हो सकता है, इसलिए मूल रूप से आपको क्या करना है:

arr.forEach(function(element,index){
    arr[index] = "four";   //set the value  
});
console.log(arr); //the array has been overwritten.

या यदि आप मूल सरणी रखना चाहते हैं, तो उपरोक्त प्रक्रिया करने से पहले आप इसकी एक प्रति बना सकते हैं। प्रतिलिपि बनाने के लिए, आप उपयोग कर सकते हैं:

var copy = arr.slice();

3
यदि आप सरणी की प्रतिलिपि बनाना चाहते हैं, तो map()इसके बजाय का उपयोग करें forEach()map()स्रोत सरणी पर पुनरावृत्त करता है और मूल की [संशोधित] प्रतिलिपि युक्त एक नया सरणी देता है: स्रोत सरणी अपरिवर्तित छोड़ दी जाती है।
निकोलस कैरी

2

सरणी ऑब्जेक्ट विधियों के साथ आप लूप के लिए मूल की तुलना में अभी तक ऐरे सामग्री को संशोधित कर सकते हैं, इन विधियों में एक महत्वपूर्ण कार्यक्षमता का अभाव है। आप रन पर इंडेक्स को संशोधित नहीं कर सकते।

उदाहरण के लिए यदि आप वर्तमान तत्व को निकालेंगे और इसे उसी अनुक्रमणिका में किसी अन्य अनुक्रमणिका स्थिति में रखेंगे तो आप आसानी से ऐसा कर सकते हैं। यदि आप वर्तमान तत्व को पिछली स्थिति में ले जाते हैं, तो अगले पुनरावृत्ति में कोई समस्या नहीं है, आपको वही अगला आइटम मिलेगा जैसे कि आपने कुछ भी नहीं किया था।

इस कोड पर विचार करें जहां हम आइटम को इंडेक्स स्थिति 5 से इंडेक्स पोजीशन 2 पर ले जाते हैं जब इंडेक्स 5 तक गिनता है।

var ar = [0,1,2,3,4,5,6,7,8,9];
ar.forEach((e,i,a) => {
i == 5 && a.splice(2,0,a.splice(i,1)[0])
console.log(i,e);
}); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 5 5 - 6 6 - 7 7 - 8 8 - 9 9

हालाँकि यदि हम वर्तमान तत्व को वर्तमान सूचकांक स्थिति से कहीं आगे ले जाते हैं तो चीजें थोड़ी गड़बड़ हो जाती हैं। फिर बहुत अगला आइटम स्थानांतरित वस्तुओं की स्थिति में स्थानांतरित हो जाएगा और अगले पुनरावृत्ति में हम इसे देख या मूल्यांकन नहीं कर पाएंगे।

इस कोड पर विचार करें जहां हम आइटम को इंडेक्स स्थिति 5 से इंडेक्स स्थिति 7 पर ले जाते हैं, जबकि इंडेक्स 5 तक गिना जाता है।

var a = [0,1,2,3,4,5,6,7,8,9];
a.forEach((e,i,a) => {
i == 5 && a.splice(7,0,a.splice(i,1)[0])
console.log(i,e);
}); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 5 5 - 6 7 - 7 5 - 8 8 - 9 9

इसलिए हम लूप में 6 कभी नहीं मिले। आम तौर पर एक लूप के लिए आपसे यह उम्मीद की जाती है कि जब आप ऐरे आइटम को आगे बढ़ाएंगे तो इंडेक्स वैल्यू में कमी आएगी ताकि आपका इंडेक्स अगले रन में उसी स्थिति में रहे और आप अभी भी हटाए गए आइटम के स्थान पर स्थानांतरित किए गए आइटम का मूल्यांकन कर सकें। यह ऐरे तरीकों से संभव नहीं है। आप इंडेक्स को बदल नहीं सकते। निम्नलिखित कोड की जाँच करें

var a = [0,1,2,3,4,5,6,7,8,9];
a.forEach((e,i,a) => {
i == 5 && (a.splice(7,0,a.splice(i,1)[0]), i--);
console.log(i,e);
}); // 0 0 - 1 1 - 2 2 - 3 3 - 4 4 - 4 5 - 6 7 - 7 5 - 8 8 - 9 9

जैसा कि आप देखते हैं कि जब हम घटते हैं i यह 5 नहीं बल्कि 6 से जारी रहेगा, जहां से इसे छोड़ा गया था।

इसलिए इस बात का ध्यान रखें।


1

तत्वों को पूरी तरह से जोड़ने या हटाने के लिए, जो अनुक्रमणिका में परिवर्तन करेगा, स्लाइस के (या) स्लाइस () को एक प्रतिलिपि पर पुनरावृत्त करने के सुझाव के विस्तार के माध्यम से, उन तत्वों की संख्या गिनाएं जिन्हें आपने पहले ही हटा दिया है या जोड़ा है और तदनुसार परिवर्तन करें। उदाहरण के लिए, तत्वों को हटाने के लिए:

let values = ["A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"];
let count = 0;
values.slice().forEach((value, index) => {
    if (value === "A2" || value === "A5") {
        values.splice(index - count++, 1);
    };
});
console.log(values);

// Expected: [ 'A0', 'A1', 'A3', 'A4', 'A6', 'A7', 'A8' ]

पहले तत्वों को सम्मिलित करने के लिए:

if (value === "A0" || value === "A6" || value === "A8") {
    values.splice(index - count--, 0, 'newVal');
};

// Expected: ['newVal', A0, 'A1', 'A2', 'A3', 'A4', 'A5', 'newVal', 'A6', 'A7', 'newVal', 'A8' ]

तत्वों को सम्मिलित करने के लिए:

if (value === "A0" || value === "A6" || value === "A8") {
    values.splice(index - --count, 0, 'newVal');
};

// Expected: ['A0', 'newVal', 'A1', 'A2', 'A3', 'A4', 'A5', 'A6', 'newVal', 'A7', 'A8', 'newVal']

एक तत्व को बदलने के लिए:

if (value === "A3" || value === "A4" || value === "A7") {
    values.splice(index, 1, 'newVal');
};

// Expected: [ 'A0', 'A1', 'A2', 'newVal', 'newVal', 'A5', 'A6', 'newVal', 'A8' ]

नोट: यदि आवेषण के बाद 'पहले' और 'दोनों' को लागू किया जाता है, तो कोड को पहले 'आवेषण' से पहले संभालना चाहिए।


0

यदि आप ओवरराइड करना चाहते हैं तो आप यह कोशिश कर सकते हैं

var newArray= [444,555,666];
var oldArray =[11,22,33];
oldArray.forEach((name, index) => oldArray [index] = newArray[index]);
console.log(newArray);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.