क्या जावास्क्रिप्ट पास-दर-संदर्भ या पास-पास-मूल्य भाषा है?


1403

आदिम प्रकार (संख्या, स्ट्रिंग, आदि) मूल्य द्वारा पारित किए जाते हैं, लेकिन वस्तुएं अज्ञात हैं, क्योंकि वे दोनों पारित-दर-मूल्य हो सकते हैं (यदि हम मानते हैं कि एक वस्तु को रखने वाला चर वास्तव में वस्तु का संदर्भ है ) और पास-बाय-रेफरेंस (जब हम मानते हैं कि ऑब्जेक्ट के लिए वैरिएबल ऑब्जेक्ट को खुद रखता है)।

यद्यपि यह वास्तव में अंत में मायने नहीं रखता है, मैं जानना चाहता हूं कि सम्मेलनों को पारित करने वाले तर्कों को प्रस्तुत करने का सही तरीका क्या है। क्या जावास्क्रिप्ट विनिर्देश से एक अंश है, जो परिभाषित करता है कि इस बारे में शब्दार्थ क्या होना चाहिए?


2
मुझे लगता है कि आपने गलती से पास-बाय-वैल्यू और पास-बाय-रेफरेंस की अपनी परिभाषा को फ़्लिप कर दिया है ... "पास-बाय-वैल्यू (यदि हम मानते हैं कि एक वस्तु को पकड़े हुए एक चर वास्तव में ऑब्जेक्ट का एक संदर्भ है) और पारित हो गया है -by-reference (जब हम मानते हैं कि ऑब्जेक्ट के लिए चर ही वस्तु को रखता है) "
निको बेलिक

5
हाँ। सिंटैक्स के बावजूद, किसी भी प्रोग्रामिंग भाषा में किसी भी फ़ंक्शन कॉल में, पास-बाय-रेफरेंस का अर्थ है कि पास किए गए वेरिएबल से जुड़े डेटा को फ़ंक्शन में पास होने पर कॉपी नहीं किया जाता है, और इस प्रकार फ़ंक्शन द्वारा किए गए किसी भी संशोधन को पास किए गए वेरिएबल में रखा जाएगा। फ़ंक्शन कॉल समाप्त होने के बाद प्रोग्राम में। पास-दर-मूल्य का मतलब है कि फ़ंक्शन से जुड़े डेटा को वास्तव में कॉपी किया जाता है जब फ़ंक्शन को पास किया जाता है और ऐसे फ़ंक्शन द्वारा ऐसे वेरिएबल में किए गए किसी भी संशोधन को तब खो दिया जाएगा जब फ़ंक्शन वापस आने पर वेरिएबल फ़ंक्शन के कार्यक्षेत्र से बाहर चला जाता है।
जॉन सोंडरसन

5
यह पुराना सवाल कुछ विषैला है क्योंकि इसका भारी-भरकम उत्तर गलत है। जावास्क्रिप्ट सख्ती से पास-बाय-वैल्यू है
पॉंच

6
@DanailNachev शब्दावली अफसोसजनक रूप से भ्रमित करने वाली है। बात यह है, "पास वैल्यू बाय" और "पास बाय रेफरेंस" ऐसे शब्द हैं जो बहुत अधिक आधुनिक प्रोग्रामिंग लैंग्वेज फीचर्स का अनुमान लगाते हैं। शब्द "मान" और "संदर्भ" विशेष रूप से पैरामीटर को संदर्भित करते हैं क्योंकि यह फ़ंक्शन कॉल अभिव्यक्ति में प्रकट होता है। जावास्क्रिप्ट हमेशा फ़ंक्शन को कॉल करने से पहले फ़ंक्शन कॉल पैरामीटर सूची में प्रत्येक अभिव्यक्ति का मूल्यांकन करता है, इसलिए पैरामीटर हमेशा मान हैं। भ्रामक हिस्सा यह है कि वस्तुओं के संदर्भ सामान्य जावास्क्रिप्ट मूल्य हैं। हालांकि, यह "संदर्भ द्वारा पास" भाषा नहीं बनाता है।
नुकीले

2
@DanailNachev "संदर्भ द्वारा पास" विशेष रूप से इसका मतलब है कि यदि आपके पास है var x=3, y=x; f(x); alert(y === x);तो फ़ंक्शन f()अलर्ट रिपोर्ट बना सकता है falseऔर नहीं true। जावास्क्रिप्ट में, यह संभव नहीं है, इसलिए यह पास-पास-संदर्भ नहीं है। यह अच्छा है कि परिवर्तनीय वस्तुओं के संदर्भ पास करना संभव है, लेकिन ऐसा नहीं है कि "संदर्भ से गुजरें" का अर्थ है। जैसा कि मैंने कहा, यह शर्म की बात है कि शब्दावली इतनी भ्रामक है।
नुकीले

जवाबों:


1596

यह जावास्क्रिप्ट में दिलचस्प है। इस उदाहरण पर विचार करें:

function changeStuff(a, b, c)
{
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);
console.log(obj1.item);
console.log(obj2.item);

यह उत्पादन का उत्पादन करता है:

10
changed
unchanged
  • यदि obj1एक संदर्भ नहीं था, तो फ़ंक्शन obj1.itemके obj1बाहर पर परिवर्तन का कोई प्रभाव नहीं होगा ।
  • यदि तर्क एक उचित संदर्भ होता, तो सब कुछ बदल जाता। numहोगा 100, और obj2.itemपढ़ेगा "changed"

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

व्यावहारिक रूप से, इसका मतलब यह है कि यदि आप पैरामीटर को (जैसा कि numऔर obj2) बदल देते हैं, तो वह उस आइटम को प्रभावित नहीं करेगा जो पैरामीटर में खिलाया गया था। लेकिन अगर आप पैरामीटर के इंटर्नशिप को बदलते हैं , तो यह वापस ऊपर (जैसे के साथ obj1) प्रचार करेगा ।


32
यह सी # के समान (या कम से कम शब्दार्थ) है। ऑब्जेक्ट के दो प्रकार हैं: मान (आदिम प्रकार) और संदर्भ।
पीटर ली

53
मुझे लगता है कि यह जावा में भी उपयोग किया जाता है: संदर्भ-दर-मूल्य।
जपन

295
वास्तविक कारण यह है कि changeStuff, संख्या, obj1 और obj2 के संदर्भ हैं। जब आप itemobj1 द्वारा संदर्भित ऑब्जेक्ट की संपत्ति को बदलते हैं, तो आप उस आइटम संपत्ति के मूल्य को बदल रहे हैं जो मूल रूप से "अपरिवर्तित" पर सेट किया गया था। जब आप obj2 को {item: "परिवर्तित"} का मान असाइन करते हैं, तो आप एक नई ऑब्जेक्ट के संदर्भ को बदल रहे हैं (जो फ़ंक्शन के बाहर निकलने पर तुरंत दायरे से बाहर हो जाता है)। यह अधिक स्पष्ट हो जाता है कि अगर आप फ़ंक्शन को नाम सुन्न, obj1f और obj2f जैसी चीजों को नाम दें। फिर आप देखते हैं कि परम बाहरी संस्करण नाम छिपा रहे थे।
जिंगलेथुला

13
@BartoNaz वास्तव में नहीं। आप जो चाहते हैं वह संदर्भ द्वारा संदर्भ को पारित करना है, इसके बजाय संदर्भ को मूल्य से पारित करना है। लेकिन जावास्क्रिप्ट हमेशा संदर्भ को मूल्य से गुजारता है, जैसे यह मूल्य के अलावा बाकी सब कुछ गुजरता है। (तुलना के लिए, C # में जावास्क्रिप्ट और जावा के समान पास-रेफरेंस-बाइ-वैल्यू व्यवहार है, लेकिन आपको refकीवर्ड के साथ पास-रेफरेंस-बाय-रेफरेंस निर्दिष्ट करने देता है ।) आमतौर पर आपके पास फ़ंक्शन नया ऑब्जेक्ट लौटाता है, और करते हैं। उस बिंदु पर असाइनमेंट जहां आप फ़ंक्शन को कॉल करते हैं। जैसे, की foo = GetNewFoo();जगहGetNewFoo(foo);
टिम गुडमैन

55
यद्यपि यह उत्तर सबसे लोकप्रिय है, यह थोड़ा भ्रमित हो सकता है क्योंकि यह बताता है कि "यदि यह मूल्य से शुद्ध पास था"। जावास्क्रिप्ट है शुद्ध पास-दर-मूल्य। लेकिन जो मूल्य पारित किया जाता है वह एक संदर्भ है। यह पैरामीटर से गुजरने के लिए विवश नहीं है। आप बस चर की प्रतिलिपि बना सकते हैं var obj1 = { item: 'unchanged' }; var obj2 = obj1; obj2.item = 'changed';और अपने उदाहरण में उसी प्रभाव का निरीक्षण करेंगे। इसलिए मैं व्यक्तिगत रूप से टिम गुडमैन के उत्तर का उल्लेख करता हूं
chiccodoro

475

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

उदाहरण:

function changeObject(x) {
  x = { member: "bar" };
  console.log("in changeObject: " + x.member);
}

function changeMember(x) {
  x.member = "bar";
  console.log("in changeMember: " + x.member);
}

var x = { member: "foo" };

console.log("before changeObject: " + x.member);
changeObject(x);
console.log("after changeObject: " + x.member); /* change did not persist */

console.log("before changeMember: " + x.member);
changeMember(x);
console.log("after changeMember: " + x.member); /* change persists */

आउटपुट:

before changeObject: foo
in changeObject: bar
after changeObject: foo

before changeMember: foo
in changeMember: bar
after changeMember: bar

14
@ दिन का उजाला: वास्तव में, आप गलत हैं; यदि इसे कॉन्स्ट रे द्वारा पारित किया गया था तो परिवर्तन करने की कोशिश कर रहा था। केवल एक असफलता के बजाय एक त्रुटि का कारण होगा। C ++ में एक कॉस्ट रेफरेंस को एक नया मान असाइन करने का प्रयास करें और कंपाइलर इसे अस्वीकार कर देता है। उपयोगकर्ता के संदर्भ में, यह मान और पास संदर्भ के बीच अंतर है।
डेवार्डे

5
@ दिन का उजाला: यह निरंतर रेफरी नहीं है। में changeObject, मैं xनई वस्तु का संदर्भ शामिल करने के लिए बदल गया हूँ । मैं जो कह रहा हूं, वह C # के सच होने के x = {member:"bar"};बराबर है x = new Object(); x.member = "bar";
टिम गुडमैन

2
@daylight: सी # के लिए, आप समारोह बाहर से देख सकते हैं, अगर आप का उपयोग refकीवर्ड आप संदर्भ (मूल्य द्वारा संदर्भ में उत्तीर्ण होने की डिफ़ॉल्ट के बजाय) द्वारा संदर्भ पारित कर सकते हैं, और फिर एक के लिए बात करने के लिए परिवर्तन new Object() होगा जारी रहती है ।
टिम गुडमैन

11
@adityamenon "क्यों" का उत्तर देना कठिन है, लेकिन मैं ध्यान दूंगा कि जावा और C # के डिजाइनरों ने एक समान विकल्प बनाया है; यह सिर्फ कुछ जावास्क्रिप्ट विचित्रता नहीं है। वास्तव में, यह बहुत लगातार पास-बाय-वैल्यू है, जो चीज इसे लोगों के लिए भ्रमित करती है वह यह है कि एक मान एक संदर्भ हो सकता है। यह C ++ में एक पॉइंटर के आसपास (मान से) पास करने से ज्यादा अलग नहीं है और फिर सदस्यों को सेट करने के लिए इसे डीफ्रार्फिन कर रहा है। किसी को आश्चर्य नहीं होगा कि यह बदलाव कायम है। लेकिन क्योंकि ये भाषाएं सूचक को दूर करती हैं और चुपचाप आपके लिए डीफ्रेंसिंग करती हैं, इसलिए लोग भ्रमित हो जाते हैं।
टिम गुडमैन

41
दूसरे शब्दों में, यहाँ भ्रमित करने वाली बात पास-बाय-वैल्यू / पास-बाय-रेफरेंस नहीं है। सब कुछ पास-बाय-वैल्यू, फुल स्टॉप। भ्रामक बात यह है कि आप किसी ऑब्जेक्ट को पास नहीं कर सकते हैं, और न ही किसी ऑब्जेक्ट को वेरिएबल में स्टोर कर सकते हैं। हर बार जब आप सोचते हैं कि आप ऐसा कर रहे हैं, तो आप वास्तव में उस वस्तु का संदर्भ दे रहे हैं । लेकिन जब आप इसके सदस्यों को एक्सेस करने जाते हैं, तो एक मूक डीरेफ्रेंसिंग होती है, जो कि आपके वैरिएबल को वास्तविक वस्तु रखने वाले फिक्शन को नष्ट कर देती है।
टिम गुडमैन

150

चर वस्तु को "पकड़" नहीं करता है; यह एक संदर्भ रखता है। आप उस संदर्भ को किसी अन्य चर में निर्दिष्ट कर सकते हैं, और अब दोनों एक ही वस्तु को संदर्भित करते हैं। यह हमेशा मान से गुजरता है (भले ही वह मूल्य एक संदर्भ हो ...)।

एक पैरामीटर के रूप में पारित चर द्वारा आयोजित मूल्य को बदलने का कोई तरीका नहीं है, जो कि जावास्क्रिप्ट द्वारा संदर्भ के माध्यम से पारित होने पर संभव होगा।


2
यह मुझे थोड़ा भ्रमित करता है। क्या संदर्भ-दर-संदर्भ पास नहीं हो रहा है?

8
लेखक का मतलब है कि एक संदर्भ पारित करके, आप एक संदर्भ मान पारित कर रहे हैं (यह सोचने का दूसरा तरीका स्मृति पते के मूल्य को पारित कर रहा है)। इसीलिए यदि आप ऑब्जेक्ट को पुनः लोड करते हैं, तो मूल नहीं बदलता है, क्योंकि आप एक अलग मेमोरी स्थान पर एक नई ऑब्जेक्ट बना रहे हैं। यदि आप एक संपत्ति बदलते हैं, तो मूल ऑब्जेक्ट बदल जाता है क्योंकि आपने इसे मूल मेमोरी स्थान पर बदल दिया था (जो पुन: असाइन नहीं किया गया था)।
-अन्ह होआंग

113

मेरे दो सेंट ... यह मुझे समझने का तरीका है। (अगर मैं गलत हूं तो मुझे सुधारने के लिए स्वतंत्र महसूस करें)

मान / संदर्भ द्वारा पास के बारे में सब कुछ जानने का समय है।

क्योंकि जावास्क्रिप्ट में, यह मायने नहीं रखता है कि यह मूल्य से या संदर्भ से या जो भी हो। एक मामले में पारित मापदंडों के असाइनमेंट बनाम असाइनमेंट क्या मायने रखता है।

ठीक है, मुझे समझाने की पूरी कोशिश करें कि मेरा क्या मतलब है। मान लीजिए कि आपके पास कुछ वस्तुएं हैं।

var object1 = {};
var object2 = {};

हमने जो किया है वह "असाइनमेंट" है ... हमने चर "ऑब्जेक्ट 1" और "ऑब्जेक्ट 2" के लिए 2 अलग-अलग खाली वस्तुओं को सौंपा है।

अब, मान लें कि हम ऑब्जेक्ट 1 को बेहतर पसंद करते हैं ... इसलिए, हम एक नया वेरिएबल "असाइन" करते हैं।

var favoriteObject = object1;

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

favoriteObject = object2;

ऑब्जेक्ट 1 या ऑब्जेक्ट 2 के लिए कुछ भी नहीं हुआ। हमने कोई डेटा नहीं बदला है। हमने जो कुछ किया था, वह हमारी पसंदीदा वस्तु है। यह जानना महत्वपूर्ण है कि ऑब्जेक्ट 2 और पसंदीदा ऑबजेक्ट दोनों एक ही ऑब्जेक्ट को सौंपे गए हैं। हम उस वस्तु को उन चरों में से किसी के माध्यम से बदल सकते हैं।

object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe

ठीक है, अब उदाहरण के लिए स्ट्रिंग की तरह आदिमों को देखें

var string1 = 'Hello world';
var string2 = 'Goodbye world';

फिर, हम एक पसंदीदा चुनते हैं।

var favoriteString = string1;

हमारे पसंदीदा स्ट्रींग और स्ट्रिंग 1 चर दोनों को 'हैलो वर्ल्ड' में सौंपा गया है। अब, क्या होगा अगर हम अपनी पसंद को बदलना चाहते हैं ??? क्या होगा???

favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'

उह ओह .... क्या हुआ है। हम पसंदीदा बदलकर string1 को बदल नहीं सकते ... क्यों ?? क्योंकि हमने अपना स्ट्रिंग ऑब्जेक्ट नहीं बदला । सभी हमने किया "आरई असाइन करें" favoriteString था चर एक नया स्ट्रिंग के लिए। यह अनिवार्य रूप से इसे string1 से काट दिया। पिछले उदाहरण में, जब हमने अपनी वस्तु का नाम बदला, तो हमने कुछ भी निर्दिष्ट नहीं किया। (ठीक है, चर के लिए ही नहीं , ... हमने किया था, हालांकि, नाम संपत्ति को एक नए स्ट्रिंग में असाइन करें।) इसके बजाय, हमने केवल उस वस्तु को उत्परिवर्तित किया जो 2 चर और अंतर्निहित वस्तुओं के बीच संबंध रखता है। (भले ही हम स्ट्रिंग ऑब्जेक्ट को स्वयं संशोधित या म्यूट करना चाहते थे, हम नहीं कर सकते थे, क्योंकि तार वास्तव में जावास्क्रिप्ट में अपरिवर्तनीय हैं।)

अब, फ़ंक्शंस और पासिंग पैरामीटर्स पर .... जब आप किसी फ़ंक्शन को कॉल करते हैं, और एक पैरामीटर पास करते हैं, तो आप जो अनिवार्य रूप से कर रहे हैं, वह एक नए वेरिएबल के लिए "असाइनमेंट" है, और यह ठीक उसी तरह काम करता है जैसे कि आप बस उपयोग करके असाइन करते हैं बराबर (=) चिह्न।

इन उदाहरणों को लें।

var myString = 'hello';

// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment

console.log(myString); // Logs 'hello'
console.log(param1);   // Logs 'world'

अब, एक ही बात है, लेकिन एक समारोह के साथ

function myFunc(param1) {
    param1 = 'world';

    console.log(param1);   // Logs 'world'
}

var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);

console.log(myString); // logs 'hello'

ठीक है, अब चलिए कुछ उदाहरण देते हैं इसके बजाय वस्तुओं का उपयोग करते हैं ... पहला, फ़ंक्शन के बिना।

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;

// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl

console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'

// Now, let's reassign the variable
otherObj = {
    firstName: 'Jack',
    lastName: 'Frost'
};

// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';

अब, एक ही बात है, लेकिन एक फ़ंक्शन कॉल के साथ

function myFunc(otherObj) {

    // Let's mutate our object
    otherObj.firstName = 'Sue';
    console.log(otherObj.firstName); // Logs 'Sue'

    // Now let's re-assign
    otherObj = {
        firstName: 'Jack',
        lastName: 'Frost'
    };
    console.log(otherObj.firstName); // Logs 'Jack'

    // Again, otherObj and myObject are assigned to 2 very different objects
    // And mutating one object doesn't magically mutate the other
}

var myObject = {
    firstName: 'Joe',
    lastName: 'Smith'
};

// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);

console.log(myObject.firstName); // Logs 'Sue', just like before

ठीक है, यदि आप इस पूरी पोस्ट को पढ़ते हैं, तो शायद अब आपको बेहतर समझ है कि जावास्क्रिप्ट में फ़ंक्शन कैसे काम करते हैं। इससे कोई फर्क नहीं पड़ता कि कुछ संदर्भ से या मूल्य से पारित किया गया है ... क्या मामलों में असाइनमेंट बनाम म्यूटेशन है।

हर बार जब आप किसी फ़ंक्शन के लिए एक चर पास करते हैं, तो आप पैरामीटर चर का नाम जो भी हो, "असाइन करना" है, जैसे कि यदि आपने बराबर (=) चिह्न का उपयोग किया है।

हमेशा याद रखें कि बराबर चिह्न (=) का अर्थ है असाइनमेंट। हमेशा याद रखें कि जावास्क्रिप्ट में एक फ़ंक्शन के पैरामीटर को पास करने का अर्थ असाइनमेंट भी है। वे समान हैं और 2 चर बिल्कुल उसी तरह से जुड़े हुए हैं (जो यह कहना है कि वे नहीं हैं, जब तक कि आप यह न गिनें कि वे एक ही वस्तु को सौंपे गए हैं)।

एकमात्र समय जो "चर को संशोधित करता है" एक अलग चर को प्रभावित करता है, जब अंतर्निहित वस्तु उत्परिवर्तित होती है (जिस स्थिति में आपने चर को संशोधित नहीं किया है, लेकिन वस्तु ही।

वस्तुओं और आदिमों के बीच अंतर करने का कोई मतलब नहीं है, क्योंकि यह उसी तरह से काम करता है जैसे कि आपके पास कोई फ़ंक्शन नहीं था और नए चर को असाइन करने के लिए समान चिह्न का उपयोग किया गया था।

एकमात्र गोचा तब होता है जब आप फ़ंक्शन में आने वाले चर का नाम फ़ंक्शन पैरामीटर के नाम के समान होता है। जब ऐसा होता है, तो आपको फ़ंक्शन के अंदर पैरामीटर का इलाज करना होगा जैसे कि यह फ़ंक्शन के लिए एक नया चर है (क्योंकि यह है)

function myFunc(myString) {
    // myString is private and does not affect the outer variable
    myString = 'hello';
}

var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';

myFunc(myString);
console.log(myString); // Logs 'test'

2
किसी भी सी प्रोग्रामर के लिए, सोचो *। foo(char *a){a="hello";} कुछ भी नहीं करता है, लेकिन अगर आप foo(char *a){a[0]='h';a[1]='i';a[2]=0;}इसे करते हैं तो इसे बाहर बदल दिया जाता है क्योंकि aएक स्मृति स्थान है जो एक स्ट्रिंग (चार सरणी) को संदर्भित करता है। C में मान के अनुसार पासिंग स्ट्रक्चर (js ऑब्जेक्ट्स के समान) की अनुमति है, लेकिन अनुशंसित नहीं है। जावास्क्रिप्ट बस इन सर्वोत्तम प्रथाओं को लागू करता है और अनावश्यक और आमतौर पर अवांछित cruft छुपाता है ... और यह सुनिश्चित करता है कि यह आसान पढ़ने के लिए है।
टेक्नोसॉरस

2
यह सही है - शब्दों के पास-दर-मूल्य और पास-दर-संदर्भ प्रोग्रामिंग भाषा डिजाइन में अर्थ हैं, और उन अर्थों का ऑब्जेक्ट म्यूटेशन के साथ कुछ भी नहीं करना है। यह सभी के बारे में है कि फ़ंक्शन पैरामीटर कैसे काम करते हैं।
नुकीले

2
अब जब मैं समझता हूं कि obj1 = obj2 का अर्थ है कि obj1 और obj2 दोनों अब एक ही संदर्भ स्थान की ओर इशारा कर रहे हैं, और अगर मैं obj2 के आंतरिक को संशोधित करता हूं, तो obj1 का संदर्भ देना एक ही आंतरिक को उजागर करेगा। मैं किसी वस्तु की प्रतिलिपि कैसे बनाऊं कि जब मैं source = { "id":"1"}; copy = source /*this is wrong*/; copy.id="2"वह स्रोत करता हूं तब भी {"id": "1"}?
माचेटी

1
मैंने भ्रम को कम करने के लिए पारंपरिक परिभाषाओं के साथ एक और उत्तर पोस्ट किया। "पास-बाय-वैल्यू" और "पास-बाय-रेफरेंस" की पारंपरिक परिभाषाओं को स्वचालित डीरेफेरिंग से पहले मेमोरी पॉइंटर्स के दिन में वापस परिभाषित किया गया था। यह पूरी तरह से अच्छी तरह से समझा गया था कि ऑब्जेक्ट चर का मूल्य वास्तव में मेमोरी पॉइंटर स्थान था, वस्तु नहीं। यद्यपि आपकी असाइनमेंट बनाम म्यूटेशन की चर्चा संभवत: उपयोगी है, परम्परागत शब्दों को और न ही उनकी परिभाषाओं को फेंकना आवश्यक नहीं है। म्यूटेशन, असाइनमेंट, पास-बाय-वैल्यू, पास-बाय-रेफरेंस आदि को एक-दूसरे का विरोध नहीं करना चाहिए।
सी पर्किंस

क्या "संख्या" एक "अपरिवर्तनीय" भी है?
ईब्रम खलील

72

निम्नलिखित को धयान मे रखते हुए:

  1. चर स्मृति में मूल्यों के संकेत हैं ।
  2. एक चर को फिर से इंगित करना केवल एक नए मूल्य पर सूचक को इंगित करता है।
  3. वैरिएबल को पुन: असाइन करने से अन्य वैरिएबल कभी प्रभावित नहीं होंगे जो उसी ऑब्जेक्ट पर इंगित कर रहे थे

तो, "संदर्भ / मूल्य से गुजारें" के बारे में भूल जाओ , "संदर्भ / मूल्य से पारित" पर लटका न दें क्योंकि:

  1. शब्दों का उपयोग केवल एक भाषा के व्यवहार का वर्णन करने के लिए किया जाता है , जरूरी नहीं कि वास्तविक अंतर्निहित कार्यान्वयन। इस अमूर्त के परिणामस्वरूप, महत्वपूर्ण विवरण जो एक सभ्य विवरण के लिए आवश्यक हैं, खो जाते हैं, जो अनिवार्य रूप से वर्तमान स्थिति की ओर जाता है जहां एक शब्द पर्याप्त रूप से वास्तविक व्यवहार का वर्णन नहीं करता है और पूरक जानकारी प्रदान करनी होती है
  2. इन अवधारणाओं को मूल रूप से विशेष रूप से जावास्क्रिप्ट का वर्णन करने के इरादे से परिभाषित नहीं किया गया था और इसलिए जब मैं केवल भ्रम में जोड़ता हूं तो मुझे उनका उपयोग करने के लिए मजबूर नहीं होना चाहिए।

आपके प्रश्न का उत्तर देने के लिए: संकेत पारित किए जाते हैं।


// code
var obj = {
    name: 'Fred',
    num: 1
};

// illustration
               'Fred'
              /
             /
(obj) ---- {}
             \
              \
               1


// code
obj.name = 'George';


// illustration
                 'Fred'


(obj) ---- {} ----- 'George'
             \
              \
               1


// code
obj = {};

// illustration
                 'Fred'


(obj)      {} ----- 'George'
  |          \
  |           \
 { }            1


// code
var obj = {
    text: 'Hello world!'
};

/* function parameters get their own pointer to 
 * the arguments that are passed in, just like any other variable */
someFunc(obj);


// illustration
(caller scope)        (someFunc scope)
           \             /
            \           /
             \         /
              \       /
               \     /
                 { }
                  |
                  |
                  |
            'Hello world'

कुछ अंतिम टिप्पणियां:

  • ऐसा सोचना ललचाता है विशेष नियमों द्वारा आदिमता को लागू किया जाता है जबकि वस्तुएं नहीं हैं, लेकिन आदिमता केवल सूचक श्रृंखला का अंत है।
  • अंतिम उदाहरण के रूप में, विचार करें कि किसी सरणी को खाली करने का एक सामान्य प्रयास अपेक्षा के अनुरूप काम क्यों नहीं करता है।


var a = [1,2];
var b = a;

a = [];
console.log(b); // [1,2]
// doesn't work because `b` is still pointing at the original array

अतिरिक्त क्रेडिट के लिए अनुवर्ती प्रश्न;) कचरा संग्रहण कैसे काम करता है? यदि मैं एक लाख {'George', 1}मान के माध्यम से एक चर का चक्र करता हूं , लेकिन एक समय में उनमें से केवल एक का उपयोग करता हूं, तो अन्य कैसे प्रबंधित होते हैं? और क्या होता है जब मैं एक चर को दूसरे चर के मूल्य पर असाइन करता हूं? क्या मैं फिर एक पॉइंटर की ओर इशारा करता हूं, या सही ऑपरेंड के पॉइंटर की ओर इशारा करता हूं? करता है var myExistingVar = {"blah", 42}; var obj = myExistingVar;में परिणाम objकी ओर इशारा करते {"blah", 42}हैं, या करने के लिए myExistingVar?
माइकल हॉफमैन

@MichaelHoffmann ये अपने स्वयं के SO प्रश्नों के पात्र हैं और संभवतः पहले से ही बेहतर तरीके से उत्तर दिए गए हैं जो मैं प्रबंधित कर सकता हूं। कहा जा रहा है, 1)मैंने लूप फ़ंक्शन के लिए ब्राउज़र डे टूल्स में एक मेमोरी प्रोफ़ाइल चलाई , जैसे कि आपने वर्णित किया और स्पाइक को लूपिंग प्रक्रिया में मेमोरी उपयोग में देखा। यह इंगित करने लगता है कि नई समान वस्तुएं वास्तव में लूप के प्रत्येक पुनरावृत्ति में बनाई जा रही हैं। जब स्पाइक्स अचानक गिर जाते हैं, तो कचरा कलेक्टर ने इन अप्रयुक्त वस्तुओं के एक समूह को साफ कर दिया।
भू

1
@MichaelHoffmann 2)जैसे कुछ के बारे में var a = b, जावास्क्रिप्ट पॉइंटर्स का उपयोग करने के लिए एक तंत्र प्रदान नहीं करता है और इसलिए एक चर एक पॉइंटर को इंगित नहीं कर सकता (जैसा कि आप सी में कर सकते हैं), हालांकि अंतर्निहित जावास्क्रिप्ट इंजन निस्संदेह उन्हें प्रदान करता है। तो ... "सही संचालक के नुमाइंदे को var a = bइंगित करेगा a"
जॉर्ज

मैंने यहां # 1 प्रश्न पूछा (विशेष रूप से क्रोम के बारे में क्योंकि कार्यान्वयन हर ब्राउज़र में अलग-अलग होने की संभावना है) stackoverflow.com/q/42778439/539997 और मैं अभी भी यह सोचने की कोशिश कर रहा हूं कि कैसे प्रश्न # 2 का उपयोग करें। किसी भी मदद की सराहना की है।
माइकल हॉफमैन

1
"संदर्भ / मूल्य द्वारा पास" के बारे में भूलने की कोई आवश्यकता नहीं है ! इन शब्दों के ऐतिहासिक अर्थ हैं जो वर्णन करने का प्रयास करते हैं। यदि हम ऐतिहासिक शब्दों और परिभाषाओं को बाहर फेंक देते हैं और यह जानने के लिए बहुत आलसी हो जाते हैं कि मूल रूप से उनका क्या मतलब है, तो हम पीढ़ियों के बीच प्रभावी ढंग से संवाद करने की क्षमता खो देते हैं। विभिन्न भाषाओं और प्रणालियों के बीच अंतर पर चर्चा करने का कोई अच्छा तरीका नहीं होगा। इसके बजाय, नए प्रोग्रामर्स को पारंपरिक शब्दों को सीखने और समझने की जरूरत है और वे क्यों और कैसे आए थे। अन्यथा, हम सामूहिक रूप से ज्ञान और समझ खो देते हैं।
सी पर्किंस

24

किसी फ़ंक्शन के बाहर की वस्तु को फ़ंक्शन में बाहरी वस्तु का संदर्भ देकर पारित किया जाता है।

जब आप उस संदर्भ का उपयोग उसकी वस्तु में हेरफेर करने के लिए करते हैं, तो बाहर की वस्तु इस प्रकार प्रभावित होती है। हालाँकि, यदि फ़ंक्शन के अंदर आपने किसी और चीज़ के संदर्भ को इंगित करने का निर्णय लिया है, तो आपने बाहर की वस्तु को बिल्कुल भी प्रभावित नहीं किया है, क्योंकि आपने जो कुछ किया था, वह किसी और चीज़ के संदर्भ को फिर से निर्देशित करता है।


20

इसे ऐसे समझें: यह हमेशा मूल्य से गुजरता है। हालाँकि, किसी वस्तु का मूल्य स्वयं वस्तु नहीं है, बल्कि उस वस्तु का संदर्भ है।

यहाँ एक उदाहरण है, एक संख्या को पार करना (एक आदिम प्रकार)

function changePrimitive(val) {
    // At this point there are two '10's in memory.
    // Changing one won't affect the other
    val = val * 10;
}
var x = 10;
changePrimitive(x);
// x === 10

किसी वस्तु के साथ इसे दोहराने से विभिन्न परिणाम मिलते हैं:

function changeObject(obj) {
    // At this point there are two references (x and obj) in memory,
    // but these both point to the same object.
    // changing the object will change the underlying object that
    // x and obj both hold a reference to.
    obj.val = obj.val * 10;
}
var x = { val: 10 };
changeObject(x);
// x === { val: 100 }

एक और उदाहरण:

function changeObject(obj) {
    // Again there are two references (x and obj) in memory,
    // these both point to the same object.
    // now we create a completely new object and assign it.
    // obj's reference now points to the new object.
    // x's reference doesn't change.
    obj = { val: 100 };
}
var x = { val: 10 };
changeObject(x);
// x === { val: 10}

19

मूल्य और संदर्भ द्वारा प्रतिलिपि बनाने, पास करने और तुलना करने के बारे में एक बहुत विस्तृत विवरण "जावास्क्रिप्ट: द डेफिनिटिव गाइड" पुस्तक के इस अध्याय में है ।

इससे पहले कि हम संदर्भ द्वारा वस्तुओं और सरणियों में हेरफेर करने के विषय को छोड़ दें, हमें नामकरण के एक बिंदु को स्पष्ट करने की आवश्यकता है।

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

यहाँ, हमारा तात्पर्य यह है कि किसी वस्तु या सरणी का सन्दर्भ - न कि स्वयं वस्तु - किसी फंक्शन को पास किया जाता है। एक फ़ंक्शन ऑब्जेक्ट के गुणों या सरणी के तत्वों को संशोधित करने के लिए संदर्भ का उपयोग कर सकता है। लेकिन अगर फ़ंक्शन एक नई वस्तु या सरणी के संदर्भ के साथ संदर्भ को अधिलेखित करता है, तो यह फ़ंक्शन फ़ंक्शन के बाहर दिखाई नहीं देता है।

इस शब्द के अन्य अर्थ से परिचित पाठक यह कहना पसंद कर सकते हैं कि ऑब्जेक्ट और सरणियाँ मान द्वारा पारित किए जाते हैं, लेकिन जो मान पास किया जाता है वह वास्तव में ऑब्जेक्ट के बजाय एक संदर्भ है।


वाह, यह अविश्वसनीय रूप से भ्रामक है। उनके दाहिने दिमाग में कौन ठीक विपरीत का अर्थ करने के लिए एक अच्छी तरह से स्थापित शब्द को परिभाषित करेगा और फिर इसका उपयोग करेगा? कोई आश्चर्य नहीं कि इस सवाल पर यहाँ इतने सारे उत्तर इतने भ्रमित हैं।
जार्ज डब्ल्यू मित्तग

16

जावास्क्रिप्ट हमेशा पास-पास-मूल्य है ; सब कुछ मूल्य प्रकार का है।

ऑब्जेक्ट्स मान हैं, और ऑब्जेक्ट्स के सदस्य फ़ंक्शन स्वयं मान हैं (याद रखें कि फ़ंक्शन जावास्क्रिप्ट में प्रथम श्रेणी के ऑब्जेक्ट हैं)। इसके अलावा, इस अवधारणा के बारे में कि जावास्क्रिप्ट में सब कुछ एक वस्तु है ; ये गलत है। स्ट्रिंग्स, प्रतीक, संख्या, बूलियन, नल, और अपरिभाषित आदिम हैं

इस अवसर पर वे कुछ सदस्य कार्यों और संपत्तियों को अपने आधार प्रोटोटाइप से विरासत में प्राप्त कर सकते हैं, लेकिन यह केवल सुविधा के लिए है। इसका मतलब यह नहीं है कि वे स्वयं वस्तु हैं। संदर्भ के लिए निम्नलिखित प्रयास करें:

x = "test";
alert(x.foo);
x.foo = 12;
alert(x.foo);

दोनों अलर्ट में आपको अपरिभाषित मान मिलेगा।


12
-1, यह हमेशा मान से पास नहीं होता है। MDC से: "यदि आप एक ऑब्जेक्ट (यानी एक गैर-आदिम मान, जैसे कि ऐरे या उपयोगकर्ता-परिभाषित ऑब्जेक्ट) को एक पैरामीटर के रूप में पास करते हैं, तो फ़ंक्शन का एक संदर्भ फ़ंक्शन को दिया जाता है।"
निक

37
@ निक: यह हमेशा मूल्य से गुजरता है। अवधि। फ़ंक्शन के लिए ऑब्जेक्ट द्वारा ऑब्जेक्ट का संदर्भ पास किया जाता है। वह संदर्भ से नहीं गुजर रहा है। "पास से संदर्भ" लगभग वैरिएबल को पारित करने के रूप में सोचा जा सकता है, इसके मूल्य के बजाय; फ़ंक्शन में कोई भी परिवर्तन तर्क को करता है (पूरी तरह से एक अलग वस्तु के साथ बदलने के सहित!) कॉलर में परिलक्षित होगा। जेएस में अंतिम बिट संभव नहीं है, क्योंकि जेएस संदर्भ से नहीं गुजरता है - यह मूल्य से संदर्भ गुजरता है। भेद सूक्ष्म है, लेकिन इसकी सीमाओं को समझने के लिए महत्वपूर्ण है।
cHao

1
भविष्य के स्टैकर्स के लिए ... आपके इस संदर्भ के बारे में: x = "teste"; x.foo = 12;आदि। क्योंकि एक संपत्ति लगातार नहीं है इसका मतलब यह नहीं है कि यह एक वस्तु नहीं है। जैसा कि एमडीएन कहता है: जावास्क्रिप्ट में, लगभग सब कुछ एक वस्तु है। अशक्त और अपरिभाषित को छोड़कर सभी आदिम प्रकारों को वस्तुओं के रूप में माना जाता है। उन्हें असाइन किए गए गुण (कुछ प्रकार के निर्दिष्ट गुण स्थिर नहीं हैं), और उनके पास वस्तुओं की सभी विशेषताएं हैं। लिंक
slacktracer

9
MDN एक उपयोगकर्ता-संपादित विकी है और यह वहां गलत है। मानक संदर्भ ECMA-262 है। एस। 8 "संदर्भ विनिर्देश प्रकार" देखें, जो बताता है कि संदर्भ कैसे हल किए जाते हैं, और 8.12.5 भी "[[पुट]]", जिसका उपयोग संदर्भ के लिए असाइनमेंट एक्सप्रेशन को समझाने के लिए किया जाता है, और ऑब्जेक्ट के लिए 9.9 टोबेबजेक्ट। आदिम मूल्यों के लिए, माइकल ने पहले ही समझाया कि ToObject क्या करता है, जैसा कि विनिर्देश में है। लेकिन एस भी देखें। 4.3.2 आदिम मूल्य।
गैरेट

1
@WonderLand: नहीं, वह नहीं है। जो लोग संदर्भ से कभी नहीं गुजर पाए, वे संदर्भ से गुजरने और मूल्य द्वारा संदर्भ को पारित करने के बीच के अंतर को कभी नहीं समझ सकते हैं। लेकिन वे वहाँ हैं, और वे मायने रखते हैं। मैं लोगों को गलत जानकारी देने की परवाह नहीं करता क्योंकि यह आसान लगता है।
cHao

12

जावास्क्रिप्ट में, मान का प्रकार पूरी तरह से नियंत्रित करता है कि क्या मान मूल्य-प्रति या संदर्भ-प्रतिलिपि द्वारा निर्दिष्ट किया जाएगा ।

आदिम मान हमेशा असाइन / वैल्यू-कॉपी द्वारा पास किए जाते हैं :

  • null
  • undefined
  • तार
  • संख्या
  • बूलियन
  • में प्रतीक ES6

यौगिक मूल्यों को हमेशा संदर्भ-प्रति द्वारा सौंपा / पास किया जाता है

  • वस्तुओं
  • सरणियों
  • समारोह

उदाहरण के लिए

var a = 2;
var b = a; // `b` is always a copy of the value in `a`
b++;
a; // 2
b; // 3

var c = [1,2,3];
var d = c; // `d` is a reference to the shared `[1,2,3]` value
d.push( 4 );
c; // [1,2,3,4]
d; // [1,2,3,4]

उपरोक्त स्निपेट में, क्योंकि 2एक स्केलर आदिम है, aउस मूल्य की एक प्रारंभिक प्रति रखता है, और bउसे मूल्य की एक और प्रतिलिपि सौंपी जाती है। बदलते समय b, आप किसी भी तरह से मूल्य में बदलाव नहीं कर रहे हैं a

लेकिन दोनों cऔर dएक ही साझा मूल्य के लिए अलग-अलग संदर्भों हैं [1,2,3], जो एक यौगिक मूल्य है। यह ध्यान रखना महत्वपूर्ण है कि मूल्य का cन तो dअधिक और न ही "मालिक" है [1,2,3]- दोनों मूल्य के लिए समान समकक्ष संदर्भ हैं। इसलिए, जब .push(4)वास्तविक साझा arrayमूल्य को संशोधित करने के लिए (या तो ) का उपयोग करते हुए , यह सिर्फ एक साझा मूल्य को प्रभावित कर रहा है, और दोनों संदर्भ नए संशोधित मूल्य को संदर्भित करेंगे [1,2,3,4]

var a = [1,2,3];
var b = a;
a; // [1,2,3]
b; // [1,2,3]

// later
b = [4,5,6];
a; // [1,2,3]
b; // [4,5,6]

जब हम असाइनमेंट b = [4,5,6]करते हैं, तो हम प्रभावित करने के लिए बिल्कुल कुछ नहीं कर रहे हैं जहां aअभी भी संदर्भित है ( [1,2,3])। ऐसा करने के लिए, एक संदर्भ के बजाय bएक सूचक होना चाहिए - लेकिन जेएस में ऐसी कोई क्षमता मौजूद नहीं है!aarray

function foo(x) {
    x.push( 4 );
    x; // [1,2,3,4]

    // later
    x = [4,5,6];
    x.push( 7 );
    x; // [4,5,6,7]
}

var a = [1,2,3];

foo( a );

a; // [1,2,3,4]  not  [4,5,6,7]

जब हम तर्क में पास होते हैं a, तो यह aसंदर्भ की एक प्रति प्रदान करता है xxऔर aएक ही [1,2,3]मूल्य पर इंगित अलग संदर्भ हैं । अब, फ़ंक्शन के अंदर, हम उस संदर्भ का उपयोग स्वयं मान को बदलने के लिए कर सकते हैं ( push(4))। लेकिन जब हम असाइनमेंट बनाते हैं x = [4,5,6], तो यह किसी भी तरह से प्रभावित नहीं होता है जहां प्रारंभिक संदर्भ aइंगित कर रहा है - अभी भी बिंदुओं पर (अब संशोधित)[1,2,3,4] मान ।

arrayमूल्य-प्रति द्वारा एक यौगिक मूल्य (जैसे ) को प्रभावी ढंग से पारित करने के लिए , आपको मैन्युअल रूप से इसकी एक प्रतिलिपि बनाने की आवश्यकता है, ताकि पारित किए गए संदर्भ अभी भी मूल को इंगित न करें। उदाहरण के लिए:

foo( a.slice() );

यौगिक मान (ऑब्जेक्ट, एरे, आदि) जो संदर्भ-कॉपी द्वारा पारित किया जा सकता है

function foo(wrapper) {
    wrapper.a = 42;
}

var obj = {
    a: 2
};

foo( obj );

obj.a; // 42

यहाँ, objअदिश आदिम संपत्ति के लिए एक आवरण के रूप में कार्य करता है a। जब पास किया जाता है foo(..), तो objसंदर्भ की एक प्रति को wrapperपैरामीटर में सेट किया जाता है। अब हम wrapperसाझा किए गए ऑब्जेक्ट तक पहुंचने के लिए संदर्भ का उपयोग कर सकते हैं , और इसकी संपत्ति को अपडेट कर सकते हैं। फ़ंक्शन समाप्त होने के बाद, obj.aअपडेट किया गया मान देखेंगे 42

स्रोत


आप पहली बार "यौगिक मान हमेशा संदर्भ-प्रतिलिपि द्वारा असाइन / पास" करते हैं, और फिर आप " x के संदर्भ में" संदर्भ की एक प्रति प्रदान करते हैं। जिसे आप "यौगिक मान" कहते हैं, के मामले में वास्तविक चर मान संदर्भ (यानी मेमोरी पॉइंटर) है। जैसा आपने समझाया था, संदर्भ की प्रतिलिपि बनाई गई है ... इसलिए चर मान की प्रतिलिपि बनाई गई है , फिर से जोर देकर कहा गया है कि संदर्भ मूल्य है। इसका मतलब है कि जावास्क्रिप्ट सभी प्रकारों के लिए पास-बाय-वैल्यू है। पास-दर-मूल्य का मतलब चर मानों की एक प्रति से गुजरना है। इससे कोई फर्क नहीं पड़ता कि मूल्य किसी वस्तु / सरणी का संदर्भ है।
सी पर्किंस

आप नई शब्दावली (मूल्य-प्रति / संदर्भ-प्रति) पेश करते हैं और यह बस चीजों को और अधिक जटिल बनाती है। केवल प्रतियां हैं, अवधि। यदि आप एक आदिम उत्तीर्ण करते हैं, तो आप वास्तविक आदिम डेटा की एक प्रति पारित करते हैं, यदि आप एक ऑब्जेक्ट पास करते हैं, तो आप ऑब्जेक्ट की मेमोरी लोकेशन की एक प्रति पास करते हैं। आपको बस इतना ही कहना है। और कुछ भी बस लोगों को भ्रमित करता है।
स्कॉट मार्कस

9

खैर, यह 'प्रदर्शन' और 'गति' के बारे में है और एक प्रोग्रामिंग भाषा में सरल शब्द 'मेमोरी मैनेजमेंट' में।

जावास्क्रिप्ट में हम दो परत में मान रख सकते हैं: type1 - objectsऔर type2 -all अन्य प्रकार के मूल्य जैसे string&boolean और आदि

यदि आप स्मृति की कल्पना नीचे वर्गों के रूप में करते हैं जो उनमें से हर एक में सिर्फ एक टाइप 2-मूल्य को बचाया जा सकता है:

यहां छवि विवरण दर्ज करें

प्रत्येक टाइप 2 -मूल्य (हरा) एक एकल वर्ग है जबकि टाइप 1-मूल्य (नीला) उनमें से एक समूह है :

यहां छवि विवरण दर्ज करें

मुद्दा यह है कि यदि आप टाइप 2-मूल्य को इंगित करना चाहते हैं, तो पता स्पष्ट है लेकिन यदि आप टाइप 1-मूल्य के लिए एक ही काम करना चाहते हैं तो यह आसान नहीं है! :

यहां छवि विवरण दर्ज करें

और अधिक जटिल कहानी में:

यहां छवि विवरण दर्ज करें

इसलिए यहाँ संदर्भ हमें बचा सकते हैं: यहां छवि विवरण दर्ज करें

जबकि यहाँ हरे रंग का तीर एक विशिष्ट चर है, बैंगनी वाला एक वस्तु चर है, इसलिए क्योंकि हरे तीर (विशिष्ट चर) में केवल एक ही कार्य है (और यह एक विशिष्ट मूल्य का संकेत है) हमें इसे अलग करने की आवश्यकता नहीं है। इसलिए हम हरे तीर को उस मूल्य के साथ स्थानांतरित करते हैं जहां यह जाता है और सभी असाइनमेंट, फ़ंक्शन और इतने पर ...

लेकिन हम बैंगनी तीर के साथ एक ही काम नहीं कर सकते हैं, हम 'जॉन' सेल को यहां या कई अन्य चीजों में स्थानांतरित करना चाह सकते हैं ..., इसलिए बैंगनी तीर अपनी जगह पर चिपक जाएगा और केवल विशिष्ट तीर जो इसे सौंपा गया था, वह आगे बढ़ जाएगा ...

एक बहुत ही भ्रामक स्थिति यह है कि आप महसूस नहीं कर सकते हैं कि आपके संदर्भित चर कैसे बदलते हैं, आइए एक बहुत अच्छे उदाहरण पर एक नज़र डालें:

let arr = [1, 2, 3, 4, 5]; //arr is an object now and a purple arrow is indicating it
let obj2 = arr; // now, obj2 is another purple arrow that is indicating the value of arr obj
let obj3 = ['a', 'b', 'c'];
obj2.push(6); // first pic below - making a new hand for the blue circle to point the 6
//obj2 = [1, 2, 3, 4, 5, 6]
//arr = [1, 2, 3, 4, 5, 6]
//we changed the blue circle object value (type1-value) and due to arr and obj2 are indicating that so both of them changed
obj2 = obj3; //next pic below - changing the direction of obj2 array from blue circle to orange circle so obj2 is no more [1,2,3,4,5,6] and it's no more about changing anything in it but we completely changed its direction and now obj2 is pointing to obj3
//obj2 = ['a', 'b', 'c'];
//obj3 = ['a', 'b', 'c'];

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें


8

यह मान के पास और संदर्भ (जावास्क्रिप्ट) द्वारा पारित करने के लिए थोड़ा अधिक स्पष्टीकरण है। इस अवधारणा में, वे संदर्भ द्वारा चर को पारित करने और संदर्भ द्वारा चर को पारित करने के बारे में बात कर रहे हैं।

मान से गुजरें (आदिम प्रकार)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
  • जावास्क्रिप्ट (स्ट्रिंग, संख्या, बूलियन, अपरिभाषित और अशक्त) में सभी आदिम प्रकार पर लागू होता है।
  • a को एक मेमोरी आवंटित की जाती है (0x001 कहते हैं) और b मेमोरी में मान की एक प्रति बनाता है (0x002 कहते हैं)।
  • इसलिए एक चर का मूल्य बदलना दूसरे को प्रभावित नहीं करता है, क्योंकि वे दोनों दो अलग-अलग स्थानों में रहते हैं।

संदर्भ (ऑब्जेक्ट) द्वारा पास

var c = { "name" : "john" };
var d = c;

console.log(c); // { "name" : "john" }
console.log(d); // { "name" : "john" }

c.name = "doe";

console.log(c); // { "name" : "doe" }
console.log(d); // { "name" : "doe" }
  • जावास्क्रिप्ट इंजन चर के लिए वस्तु प्रदान करता है c , और यह कुछ स्मृति को इंगित करता है, कहते हैं (0x012)।
  • जब डी = सी, इस चरण में d में समान स्थान (0x012) की ओर इशारा करता है।
  • दोनों चर के लिए किसी भी परिवर्तन मूल्य का मूल्य बदलना।
  • कार्य वस्तुएं हैं

विशेष मामला, संदर्भ (वस्तुओं) द्वारा पारित

c = {"name" : "jane"};
console.log(c); // { "name" : "jane" }
console.log(d); // { "name" : "doe" }
  • बराबर (=) ऑपरेटर नया मेमोरी स्पेस या पता सेट करता है

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

6

जावास्क्रिप्ट में संदर्भों के बारे में मुझे जो पता है उसे साझा करना

जावास्क्रिप्ट में, जब किसी वस्तु को किसी चर के लिए निर्दिष्ट किया जाता है, तो चर को दिया गया मान वस्तु का संदर्भ होता है:

var a = {
  a: 1,
  b: 2,
  c: 3
};
var b = a;

// b.c is referencing to a.c value
console.log(b.c) // Output: 3
// Changing value of b.c
b.c = 4
// Also changes the value of a.c
console.log(a.c) // Output: 4


1
यह एक अति सरल उत्तर है जो कुछ भी नहीं कहता है कि पहले के उत्तर बेहतर नहीं बताए गए हैं। मैं उलझन में हूं कि आप विशेष मामले के रूप में सरणियों को क्यों कहते हैं।
क्वेंटिन

1
" वस्तुओं को संदर्भ के रूप में संग्रहीत किया जाता है " भ्रामक है। मेरे विचार से आपका मतलब यह है कि किसी वस्तु को किसी चर में निर्दिष्ट करते समय, चर को दिया गया मान वस्तु का संदर्भ है।
रॉब जूल

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

@amaster उस ओर इशारा करने के लिए धन्यवाद! क्या आप कृपया एक संपादन का सुझाव दे
xameeramir

हाहा, मैंने कोशिश की ... मेरे सुझाए गए एडिट में बहुत ज्यादा बदलाव आया, इसकी अनुमति नहीं थी
अमस्टर

4

शब्दार्थ !! ठोस परिभाषाएँ निर्धारित करने से जरूरी कुछ उत्तर और टिप्पणियाँ असंगत हो जाएंगी क्योंकि वे एक ही शब्द और वाक्यांशों का उपयोग करते समय भी एक ही चीज़ का वर्णन नहीं कर रहे हैं, लेकिन भ्रम (विशेष रूप से नए प्रोग्रामर) के लिए पिछले करना महत्वपूर्ण है।

सबसे पहले, अमूर्तता के कई स्तर हैं जो हर किसी को समझ में नहीं आते हैं। 4 या 5 वीं पीढ़ी की भाषाओं पर सीखने वाले नए प्रोग्रामर को असेंबली या सी प्रोग्रामर से परिचित अवधारणाओं के आसपास अपने दिमाग को लपेटने में कठिनाई हो सकती है, जो पॉइंटर्स टू पॉइंटर्स टू पॉइंटर्स से चरणबद्ध नहीं होते हैं। पास-दर-संदर्भ का अर्थ केवल फ़ंक्शन पैरामीटर चर का उपयोग करके संदर्भित ऑब्जेक्ट को बदलने की क्षमता नहीं है।

परिवर्तनीय : एक प्रतीक की संयुक्त अवधारणा जो स्मृति में किसी विशेष स्थान पर एक मूल्य का संदर्भ देती है। यह शब्द आमतौर पर विवरणों पर चर्चा करने के लिए अकेले उपयोग किए जाने के लिए बहुत अधिक भरा हुआ है।

प्रतीक : पाठ स्ट्रिंग जिसका उपयोग चर (यानी चर का नाम) को संदर्भित करने के लिए किया जाता है।

मान : विशेष रूप से बिट मेमोरी में संग्रहीत और चर के प्रतीक का उपयोग करके संदर्भित।

मेमोरी लोकेशन : जहां एक वैरिएबल की वैल्यू स्टोर होती है। (स्थान खुद को स्थान पर संग्रहीत मूल्य से अलग एक संख्या द्वारा दर्शाया जाता है।)

फ़ंक्शन पैरामीटर : फ़ंक्शन में दी गई चर को संदर्भित करने के लिए उपयोग की जाने वाली फ़ंक्शन परिभाषा में घोषित चर।

फ़ंक्शन तर्क : फ़ंक्शन के बाहर चर जो कॉलर द्वारा फ़ंक्शन को पास किया जाता है।

ऑब्जेक्ट वैरिएबल : वैरिएबल जिसका मूल अंतर्निहित मूल्य स्वयं "ऑब्जेक्ट" नहीं है, बल्कि इसकी वैल्यू एक पॉइंटर (मेमोरी लोकेशन वैल्यू) है जो मेमोरी में किसी अन्य स्थान पर होती है जहां ऑब्जेक्ट का वास्तविक डेटा संग्रहीत होता है। अधिकांश उच्च-पीढ़ी की भाषाओं में, "सूचक" पहलू स्वचालित रूप से विभिन्न संदर्भों में स्वचालित डी-संदर्भ द्वारा छिपा हुआ है।

आदिम चर : चर जिसका मूल्य वास्तविक मूल्य है। यहां तक ​​कि यह अवधारणा विभिन्न भाषाओं के ऑटो-बॉक्सिंग और ऑब्जेक्ट-जैसे संदर्भों द्वारा जटिल हो सकती है, लेकिन सामान्य विचार यह है कि चर का मान किसी अन्य मेमोरी स्थान के लिए सूचक के बजाय चर के प्रतीक द्वारा दर्शाया गया वास्तविक मूल्य है।

फ़ंक्शन तर्क और पैरामीटर समान चीज़ नहीं हैं। इसके अलावा, एक चर का मूल्य चर की वस्तु नहीं है (जैसा कि पहले से ही विभिन्न लोगों द्वारा बताया गया है, लेकिन स्पष्ट रूप से अनदेखा किया गया है)। ये अंतर उचित समझ के लिए महत्वपूर्ण हैं।

पास-बाय-वैल्यू या कॉल-बाय-शेयरिंग (ऑब्जेक्ट्स के लिए): फ़ंक्शन तर्क का मान किसी अन्य मेमोरी लोकेशन पर कॉपी किया जाता है, जिसे फ़ंक्शन के पैरामीटर सिंबल (चाहे वह स्टैक या हीप पर हो) द्वारा संदर्भित किया जाता है। दूसरे शब्दों में, फ़ंक्शन पैरामीटर को पास किए गए तर्क के मान की एक प्रति मिली ... और (महत्वपूर्ण) तर्क की कीमत को कभी भी अलग नहीं किया गया है / कॉलिंग फ़ंक्शन द्वारा बदल दिया गया है। याद रखें, ऑब्जेक्ट वेरिएबल का वैल्यू खुद ऑब्जेक्ट नहीं है, बल्कि यह ऑब्जेक्ट के लिए पॉइंटर है, इसलिए वैल्यू बाय ऑब्जेक्ट वेरिएबल को पॉइंटर को फंक्शन पैरामीटर वेरिएबल पर कॉपी करता है। फ़ंक्शन पैरामीटर का मान मेमोरी में सटीक समान ऑब्जेक्ट को इंगित करता है। ऑब्जेक्ट डेटा को स्वयं फ़ंक्शन पैरामीटर के माध्यम से सीधे बदल दिया जा सकता है, लेकिन फ़ंक्शन तर्क के मान को अद्यतन नहीं किया गया है, इसलिए यह इंगित करना जारी रखेगा उसीफ़ंक्शन कॉल के बाद और उसके बाद भी ऑब्जेक्ट (भले ही इसकी ऑब्जेक्ट का डेटा बदल दिया गया हो या यदि फ़ंक्शन पैरामीटर को पूरी तरह से एक अलग ऑब्जेक्ट सौंपा गया है)। यह निष्कर्ष निकालना गलत है कि फ़ंक्शन तर्क को संदर्भ से केवल इसलिए पास किया गया क्योंकि संदर्भित ऑब्जेक्ट फ़ंक्शन पैरामीटर चर के माध्यम से अद्यतन करने योग्य है।

कॉल / पास-दर-संदर्भ : फ़ंक्शन तर्क का मान संबंधित फ़ंक्शन पैरामीटर द्वारा सीधे अपडेट / किया जा सकता है। यदि यह मदद करता है, तो फ़ंक्शन पैरामीटर तर्क के लिए एक प्रभावी "उपनाम" बन जाता है - वे प्रभावी रूप से एक ही मेमोरी स्थान पर समान मान का संदर्भ देते हैं। यदि फ़ंक्शन तर्क ऑब्जेक्ट चर है, तो ऑब्जेक्ट के डेटा को बदलने की क्षमता पास-दर-मूल्य मामले से अलग नहीं है क्योंकि फ़ंक्शन पैरामीटर अभी भी तर्क के समान ऑब्जेक्ट को इंगित करेगा। लेकिन ऑब्जेक्ट चर मामले में, यदि फ़ंक्शन पैरामीटर पूरी तरह से भिन्न ऑब्जेक्ट पर सेट है, तो तर्क भी अलग ऑब्जेक्ट को इंगित करेगा - पास-बाय-वैल्यू केस में ऐसा नहीं होता है।

जावास्क्रिप्ट संदर्भ से नहीं गुजरती है। यदि आप बारीकी से पढ़ते हैं, तो आप महसूस करेंगे कि सभी विपरीत राय पास-बाय-वैल्यू का गलत मतलब निकालते हैं और वे गलत तरीके से निष्कर्ष निकालते हैं कि फ़ंक्शन पैरामीटर के माध्यम से किसी ऑब्जेक्ट के डेटा को अपडेट करने की क्षमता "पास-बाय-वैल्यू" का पर्याय है।

ऑब्जेक्ट क्लोन / कॉपी : एक नई ऑब्जेक्ट बनाई जाती है और मूल ऑब्जेक्ट का डेटा कॉपी किया जाता है। यह एक गहरी प्रतिलिपि या उथली प्रतिलिपि हो सकती है, लेकिन मुद्दा यह है कि एक नई वस्तु बनाई गई है। किसी वस्तु की प्रतिलिपि बनाना पास-दर-मूल्य से एक अलग अवधारणा है। कुछ भाषाएं क्लास ऑब्जेक्ट और स्ट्रक्चर्स (या पसंद) के बीच अंतर करती हैं, और विभिन्न प्रकारों के चर को पार करने के लिए अलग व्यवहार हो सकता है। लेकिन ऑब्जेक्ट चर को पार करते समय जावास्क्रिप्ट स्वचालित रूप से ऐसा कुछ भी नहीं करता है। लेकिन स्वचालित ऑब्जेक्ट क्लोनिंग की अनुपस्थिति पास-दर-संदर्भ में अनुवाद नहीं करती है।


4

जावास्क्रिप्ट संदर्भ द्वारा मूल्य और वस्तु प्रकारों से आदिम प्रकार गुजरता है

अब, लोग इस बारे में अंतहीन बात करना पसंद करते हैं कि क्या "संदर्भ द्वारा पास" क्या जावा एट अल का वर्णन करने का सही तरीका है। वास्तव में करते हैं। मुद्दा यह है:

  1. किसी वस्तु को पास करना वस्तु की नकल नहीं करता है।
  2. किसी फ़ंक्शन को दी गई ऑब्जेक्ट में फ़ंक्शन द्वारा संशोधित किए गए सदस्य हो सकते हैं।
  3. एक समारोह में पारित एक आदिम मूल्य फ़ंक्शन द्वारा संशोधित नहीं किया जा सकता है। एक प्रति बनाई जाती है।

मेरी पुस्तक में जिसे संदर्भ से गुजरना कहा जाता है।

- ब्रायन बी - किन प्रोग्रामिंग भाषाओं को संदर्भ द्वारा पारित किया जाता है?


अपडेट करें

यहाँ इसका खंडन किया गया है:

जावास्क्रिप्ट में कोई "पास बाय रेफरेंस" उपलब्ध नहीं है।


@ एमी क्योंकि वह मूल्य द्वारा पास का वर्णन कर रहा है, संदर्भ से नहीं। यह उत्तर एक अच्छा है जो अंतर दिखाता है: stackoverflow.com/a/3638034/3307720
nasch

@ ज्ञानचंद मैं अंतर समझता हूं। # 1 और # 2 पास-दर-रिफ शब्दार्थ का वर्णन कर रहे हैं। # 3 पास-दर-मूल्य शब्दार्थ का वर्णन कर रहा है।
एमी

@ एमी 1, 2, और 3 सभी पास मूल्य के अनुरूप हैं। संदर्भ से गुजरने के लिए आपको 4 की भी आवश्यकता होगी: फ़ंक्शन के अंदर एक नए मूल्य के संदर्भ को निर्दिष्ट करना (= ऑपरेटर के साथ) फ़ंक्शन के बाहर संदर्भ को भी पुन: असाइन करता है। यह जावास्क्रिप्ट के साथ ऐसा नहीं है, यह विशेष रूप से मूल्य से गुजरता है। ऑब्जेक्ट को पास करते समय, आप ऑब्जेक्ट को एक पॉइंटर पास करते हैं, और आप उस पॉइंटर को वैल्यू से पास करते हैं।
नास

यह आमतौर पर "पास-बाय-रेफरेंस" का मतलब नहीं है। आपने मेरी क्वेरी को संतुष्ट किया है, और मैं आपसे असहमत हूं। धन्यवाद।
एमी

"मेरी पुस्तक में जिसे संदर्भ से गुजरना कहा जाता है।" - हर एक संकलक पुस्तक में, दुभाषिया पुस्तक, प्रोग्रामिंग भाषा सिद्धांत पुस्तक, और कंप्यूटर विज्ञान पुस्तक कभी भी लिखी गई है, यह नहीं है।
जार्ज डब्ल्यू मित्तग

3

इसे समझने का मेरा सरल तरीका ...

  • किसी फ़ंक्शन को कॉल करते समय, आप तर्क चर की सामग्री (संदर्भ या मूल्य) पास कर रहे हैं, स्वयं चर नहीं।

    var var1 = 13;
    var var2 = { prop: 2 };
    
    //13 and var2's content (reference) are being passed here
    foo(var1, var2); 
  • फ़ंक्शन के अंदर, पैरामीटर चर, inVar1और inVar2, पास होने वाली सामग्री प्राप्त करें।

    function foo(inVar1, inVar2){
        //changing contents of inVar1 and inVar2 won't affect variables outside
        inVar1 = 20;
        inVar2 = { prop: 7 };
    }
  • चूंकि inVar2संदर्भ प्राप्त हुआ है { prop: 2 }, आप ऑब्जेक्ट की संपत्ति के मूल्य को बदल सकते हैं।

    function foo(inVar1, inVar2){
        inVar2.prop = 7; 
    }

3

जावास्क्रिप्ट में एक फ़ंक्शन के लिए तर्क पास करना सी में पॉइंटर मान द्वारा पासिंग पैरामीटर के अनुरूप है:

/*
The following C program demonstrates how arguments
to JavaScript functions are passed in a way analogous
to pass-by-pointer-value in C. The original JavaScript
test case by @Shog9 follows with the translation of
the code into C. This should make things clear to
those transitioning from C to JavaScript.

function changeStuff(num, obj1, obj2)
{
    num = num * 10;
    obj1.item = "changed";
    obj2 = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);    
console.log(obj2.item);

This produces the output:

10
changed
unchanged
*/

#include <stdio.h>
#include <stdlib.h>

struct obj {
    char *item;
};

void changeStuff(int *num, struct obj *obj1, struct obj *obj2)
{
    // make pointer point to a new memory location
    // holding the new integer value
    int *old_num = num;
    num = malloc(sizeof(int));
    *num = *old_num * 10;
    // make property of structure pointed to by pointer
    // point to the new value
    obj1->item = "changed";
    // make pointer point to a new memory location
    // holding the new structure value
    obj2 = malloc(sizeof(struct obj));
    obj2->item = "changed";
    free(num); // end of scope
    free(obj2); // end of scope
}

int num = 10;
struct obj obj1 = { "unchanged" };
struct obj obj2 = { "unchanged" };

int main()
{
    // pass pointers by value: the pointers
    // will be copied into the argument list
    // of the called function and the copied
    // pointers will point to the same values
    // as the original pointers
    changeStuff(&num, &obj1, &obj2);
    printf("%d\n", num);
    puts(obj1.item);
    puts(obj2.item);
    return 0;
}

1
मुझे नहीं लगता कि जावास्क्रिप्ट में यह मामला है: `` जावास्क्रिप्ट संस्करण संख्या = 5;
डैनियल नाचेव

@DanailNachev: जबकि यह तकनीकी रूप से सच हो सकता है, अंतर केवल उन परिवर्तनशील वस्तुओं के लिए है जो ECMAScript प्राइमेटिव नहीं हैं।
जार्ज डब्ल्यू मित्तग

3

प्रोग्रामिंग लैंग्वेज वकीलों के लिए, मैं ECMAScript 5.1 (जो कि नवीनतम संस्करण की तुलना में पढ़ना आसान है) के निम्नलिखित अनुभागों से गुजरा हूं, और जहाँ तक हो सकता है ECMAScript मेलिंग सूची पर पूछ रहा हूँ

टीएल; डीआर : एवरीथिंगगेज वैल्यू द्वारा पास किया गया है, लेकिन ऑब्जेक्ट्स के गुण संदर्भ हैं, और ऑब्जेक्ट की परिभाषा मानक में कमी है।

तर्क सूची का निर्माण

धारा 11.2.4 "तर्क सूचियाँ" केवल 1 तर्क से मिलकर एक तर्क सूची तैयार करने पर निम्नलिखित कहती है:

उत्पादन तर्कवादी: असाइनमेंटएक्सप्रेशन का मूल्यांकन निम्नानुसार किया जाता है:

  1. मान लीजिए कि AssignmentExpression का मूल्यांकन करने का परिणाम है।
  2. आज्ञा देना हो GetValue (रेफरी)।
  3. वह सूची लौटाएं जिसका एकमात्र आइटम arg है।

अनुभाग उन मामलों की भी गणना करता है जहां तर्क सूची में 0 या> 1 तर्क हैं।

इस प्रकार, सब कुछ संदर्भ द्वारा पारित किया जाता है।

वस्तु के गुणों की पहुँच

धारा 11.2.1 "संपत्ति अभिदाता"

प्रोडक्शन मेम्बर एक्सप्रेशन: मेंबर एक्सप्रेशन [एक्सप्रेशन] का मूल्यांकन निम्नानुसार किया जाता है:

  1. बता दें कि BaseReference सदस्यExpression के मूल्यांकन का परिणाम है।
  2. BaseValue GetValue (BaseReference) होने दें।
  3. बता दें कि प्रॉपर्टीनामेप्रेशन एक्सप्रेशन के मूल्यांकन का परिणाम है।
  4. चलिए PropertyNameValue GetValue (संपत्तिनामप्रदर्शन) करें।
  5. CheckObjectCoercible (baseValue) को कॉल करें।
  6. चलिए PropertyNameString ToString (propertyNameValue) है।
  7. अगर वाक्य रचना का मूल्यांकन किया जा रहा है जो सख्त मोड कोड में समाहित है, तो इसे सख्त होने दें, अन्यथा कड़ाई को गलत होने दें।
  8. प्रकार का संदर्भ लौटाएं जिसका आधार मान baseValue है और जिसका संदर्भित नाम गुणनाम है, और जिसका सख्त मोड ध्वज सख्त है।

इस प्रकार, वस्तुओं के गुण हमेशा संदर्भ के रूप में उपलब्ध होते हैं।

संदर्भ पर

यह खंड 8.7 में वर्णित है "संदर्भ विनिर्देश प्रकार", कि संदर्भ भाषा में वास्तविक प्रकार नहीं हैं - वे केवल डिलीट, टाइपोफ़ और असाइनमेंट ऑपरेटरों के व्यवहार का वर्णन करने के लिए उपयोग किए जाते हैं।

"ऑब्जेक्ट" की परिभाषा

इसे 5.1 संस्करण में परिभाषित किया गया है कि "एक वस्तु गुणों का संग्रह है"। इसलिए, हम अनुमान लगा सकते हैं, कि वस्तु का मूल्य संग्रह है, लेकिन संग्रह का मूल्य क्या है, इसे कल्पना में खराब तरीके से परिभाषित किया गया है, और समझने के लिए थोड़े प्रयास की आवश्यकता होती है ।


यह कभी भी मुझे विस्मित नहीं करता है कि मूल्य द्वारा पारित तर्कों के बीच कितने लोग भ्रमित हो जाते हैं, संदर्भ द्वारा पारित तर्क, संपूर्ण वस्तुओं पर संचालन और उनके गुणों पर संचालन। 1979 में, मैंने अपने एमबीए प्रोग्राम में 15 घंटे या सीएस ऐच्छिक को जोड़ने के बजाय, कंप्यूटर विज्ञान में अपनी डिग्री प्राप्त नहीं की। फिर भी, यह जल्द ही मेरे लिए स्पष्ट हो गया कि इन अवधारणाओं की मेरी समझ कम से कम उतनी ही अच्छी थी जितनी कि मेरे किसी भी साथी के पास थी, जिसके पास कंप्यूटर विज्ञान या गणित की डिग्री थी। असेंबलर का अध्ययन करें, और यह काफी स्पष्ट हो जाएगा।
डेविड ए। ग्रे

3

MDN डॉक्स स्पष्ट रूप से समझाते हैं, बिना क्रिया के:

फ़ंक्शन कॉल के पैरामीटर फ़ंक्शन के तर्क हैंमूल्य द्वारा कार्यों को तर्क दिया जाता है । यदि फ़ंक्शन एक तर्क के मूल्य को बदलता है, तो यह परिवर्तन विश्व स्तर पर या कॉलिंग फ़ंक्शन में परिलक्षित नहीं होता है। हालाँकि, ऑब्जेक्ट संदर्भ मान हैं, भी, और वे विशेष हैं: यदि फ़ंक्शन संदर्भित ऑब्जेक्ट के गुणों को बदलता है, तो वह फ़ंक्शन फ़ंक्शन के बाहर दिखाई देता है, (...)

स्रोत: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Description


1

निम्न स्तर की भाषा में, यदि आप संदर्भ के आधार पर एक चर पास करना चाहते हैं, तो आपको फ़ंक्शन के निर्माण में एक विशिष्ट वाक्यविन्यास का उपयोग करना होगा:

int myAge = 14;
increaseAgeByRef(myAge);
function increaseAgeByRef(int &age) {
  *age = *age + 1;
}

&ageलिए एक संदर्भ है myAge, लेकिन अगर आप मूल्य चाहते हैं आप संदर्भ कन्वर्ट करने के लिए है, का उपयोग करते हुए*age

जावास्क्रिप्ट एक उच्च स्तरीय भाषा है जो आपके लिए यह रूपांतरण करती है। इसलिए, हालाँकि ऑब्जेक्ट्स संदर्भ द्वारा पारित किए जाते हैं, भाषा संदर्भ पैरामीटर को मान में परिवर्तित करती है। आपको &फ़ंक्शन परिभाषा पर, संदर्भ द्वारा इसे पास करने की आवश्यकता नहीं है , न ही *, फ़ंक्शन बॉडी पर, संदर्भ के मान को परिवर्तित करने के लिए, JS इसे आपके लिए करता है।

इसीलिए जब आप किसी फ़ंक्शन के अंदर किसी ऑब्जेक्ट को बदलने का प्रयास करते हैं, तो उसका मान (यानी age = {value:5}) बदलकर, परिवर्तन जारी नहीं रहता है, लेकिन यदि आप बदलते हैं तो यह गुण (यानी age.value = 5) है।

और अधिक जानें


1

मैंने कई बार इन उत्तरों के माध्यम से पढ़ा है, लेकिन वास्तव में इसे तब तक नहीं मिला जब तक कि मुझे बारबरा लिस्कॉव द्वारा "कॉल शेयरिंग" की तकनीकी परिभाषा के बारे में पता नहीं चला।

साझा करने से कॉल के शब्दार्थक उस संदर्भ में कॉल के संदर्भ से भिन्न होते हैं, जो फ़ंक्शन के कार्य के लिए तर्कों को कॉल करने वाले (संदर्भ शब्दार्थ द्वारा विपरीत) के लिए दृश्यमान नहीं होते हैं [उद्धरण वांछित], इसलिए यदि कोई चर पारित किया गया था, तो यह संभव नहीं है कॉलर के दायरे में उस चर पर असाइनमेंट का अनुकरण करने के लिए। हालाँकि, फ़ंक्शन के पास उसी ऑब्जेक्ट तक पहुंच है, जैसे कि कॉलर (कोई प्रतिलिपि नहीं बनाई गई है), उन ऑब्जेक्ट्स के लिए म्यूटेशन, यदि ऑब्जेक्ट्स उत्परिवर्तित होते हैं, तो फ़ंक्शन के भीतर कॉल करने वाले को दिखाई देते हैं, जो कि मूल्य से कॉल से भिन्न दिखाई दे सकता है अर्थ विज्ञान। फ़ंक्शन के भीतर एक उत्परिवर्तनीय वस्तु के म्यूटेशन कॉलर को दिखाई देते हैं क्योंकि ऑब्जेक्ट को कॉपी या क्लोन नहीं किया जाता है - इसे साझा किया जाता है।

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


नहीं, कोई वस्तु उत्परिवर्तनीय है या नहीं यह वास्तव में मुद्दा नहीं है। सब कुछ हमेशा मूल्य से पारित किया जाता है। यह सिर्फ इस बात पर निर्भर करता है कि आप क्या कर रहे हैं (एक मूल्य या एक संदर्भ)। देखें इस
स्कॉट मार्कस

वह जो वर्णन कर रही है वह BY-VALUE के संदर्भ में है। नई शब्दावली को पेश करने का कोई कारण नहीं है।
संजीव

1

ज्यादातर सरल तरीका है

// Copy JS object without reference
var first = {"a":"value1","b":"value2"};
var clone = JSON.parse( JSON.stringify( first ) ); 

var second = ["a","b","c"];
var clone = JSON.parse( JSON.stringify( second ) ); 

JSON.parse( JSON.stringify( obj ) )गहरी-क्लोन वस्तुओं के लिए एक भयानक तरीका है। न केवल यह न केवल धीमा है, बल्कि इससे डेटा हानि भी हो सकती है।
डी। परदल

0

जब मैं किसी ऑब्जेक्ट में एक पैरामीटर के रूप में पास करना चाहता हूं, जो कि या तो पूरी तरह से संशोधित किया जा सकता है या पूरी तरह से बदल दिया जा सकता है, तो मैंने अंडरस्कोरजेएस लाइब्रेरी के विस्तार का तरीका ढूंढ लिया है ।

function replaceOrModify(aObj) {
  if (modify) {

    aObj.setNewValue('foo');

  } else {

   var newObj = new MyObject();
   // _.extend(destination, *sources) 
   _.extend(newObj, aObj);
  }
}

0

सबसे अधिक स्पष्ट व्याख्या मुझे AirBNB स्टाइल गाइड में मिली थी :

  • प्रिमिटिव्स : जब आप एक आदिम प्रकार का उपयोग करते हैं तो आप सीधे उसके मूल्य पर काम करते हैं

    • तार
    • संख्या
    • बूलियन
    • शून्य
    • अपरिभाषित

उदाहरण के लिए:

var foo = 1,
    bar = foo;

bar = 9;

console.log(foo, bar); // => 1, 9
  • जटिल : जब आप एक जटिल प्रकार का उपयोग करते हैं तो आप इसके मूल्य के संदर्भ में काम करते हैं

    • वस्तु
    • सरणी
    • समारोह

उदाहरण के लिए:

var foo = [1, 2],
    bar = foo;

bar[0] = 9;

console.log(foo[0], bar[0]); // => 9, 9

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


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

-1

मैं कहूंगा कि यह पास-बाय-कॉपी है -

तर्कों और चर वस्तुओं पर विचार करें जो फ़ंक्शन मंगलाचरण की शुरुआत में बनाए गए निष्पादन संदर्भ के दौरान बनाई गई वस्तुएं हैं - और फ़ंक्शन में पारित आपका वास्तविक मूल्य / संदर्भ बस इस तर्क + चर वस्तुओं में संग्रहीत होता है।

सीधे शब्दों में, आदिम प्रकारों के लिए, फ़ंक्शन कॉल की शुरुआत में मान की प्रतिलिपि बनाई जाती है, ऑब्जेक्ट प्रकार के लिए, संदर्भ कॉपी हो जाता है।


1
"पास-बाय-कॉपी" === पास से मान
स्कॉट मार्कस

-1

यहां जावास्क्रिप्ट में "संदर्भ द्वारा पास" शब्द के उपयोग के बारे में कुछ चर्चा की गई है , लेकिन आपके प्रश्न का उत्तर देने के लिए:

एक वस्तु विशेष रूप से इसे निर्दिष्ट करने की आवश्यकता के बिना, संदर्भ द्वारा स्वचालित रूप से पारित हो जाती है

(ऊपर वर्णित लेख से)


7
लिंक किए गए लेख में अब वह कथन शामिल नहीं है और "संदर्भ द्वारा पास" का उपयोग करने से पूरी तरह से बचा जाता है।
C पर्किंस

मान एक संदर्भ है

-2

यह निर्धारित करने का एक आसान तरीका है कि क्या कुछ "संदर्भ से गुजरता है" यह है कि क्या आप "स्वैप" फ़ंक्शन लिख सकते हैं। उदाहरण के लिए, C में, आप कर सकते हैं:

void swap(int *i, int *j)
{
    int t;
    t = *i;
    *i = *j;
    *j = t;
}

यदि आप जावास्क्रिप्ट के बराबर नहीं कर सकते हैं, तो यह "संदर्भ द्वारा पास" नहीं है।


21
यह वास्तव में संदर्भ से नहीं गुजरता है। आप फ़ंक्शन में पॉइंटर्स पास कर रहे हैं, और उन पॉइंटर्स को मान से पास किया जा रहा है। एक बेहतर उदाहरण होगा C ++ का ऑपरेटर और ऑपरेटर या C # का "Ref" कीवर्ड, दोनों ही सही मायने में संदर्भ से गुजरते हैं।
मैट ग्रीर

इससे भी आसान यह है कि जावास्क्रिप्ट में सब कुछ मूल्य से पारित किया गया है।
स्कॉट मार्कस


-3
  1. स्ट्रिंग की तरह आदिम प्रकार चर, संख्या हमेशा पास पास मूल्य के रूप में होती है।
  2. ऐरे और ऑब्जेक्ट को संदर्भ के रूप में पास किया जाता है या इन दो स्थितियों के आधार पर मूल्य से पारित किया जाता है।

    • यदि आप नए ऑब्जेक्ट या एरे के साथ उस ऑब्जेक्ट या एरे का मान बदल रहे हैं तो वह वैल्यू से पास होता है।

      object1 = {item: "car"}; array1=[1,2,3];

    यहां आप पुरानी वस्तु को नई वस्तु या सरणी प्रदान कर रहे हैं। आप पुरानी वस्तु की संपत्ति के मूल्य को नहीं बदल रहे हैं। क्योंकि यह मूल्य से पास है।

    • यदि आप किसी ऑब्जेक्ट या ऐरे की प्रॉपर्टी की वैल्यू बदल रहे हैं तो उसे रेफरेंस द्वारा पास कर दिया जाता है।

      object1.key1= "car"; array1[0]=9;

    यहां आप पुरानी ऑब्जेक्ट की प्रॉपर्टी वैल्यू बदल रहे हैं। आप पुराने ऑब्जेक्ट को नई ऑब्जेक्ट या एरे को असाइन नहीं कर रहे हैं। यह संदर्भ द्वारा पास है।

कोड

    function passVar(object1, object2, number1) {

        object1.key1= "laptop";
        object2 = {
            key2: "computer"
        };
        number1 = number1 + 1;
    }

    var object1 = {
        key1: "car"
    };
    var object2 = {
        key2: "bike"
    };
    var number1 = 10;

    passVar(object1, object2, number1);
    console.log(object1.key1);
    console.log(object2.key2);
    console.log(number1);

Output: -
    laptop
    bike
    10

1
असाइनमेंट ऑपरेटर को एक फ़ंक्शन कॉल के साथ भ्रमित नहीं होना है। जब आप किसी मौजूदा वैरिएबल में नया डेटा असाइन करते हैं तो पुराने डेटा की संदर्भ संख्या कम हो जाती है और नया डेटा पुराने वैरिएबल से जुड़ा होता है। मूल रूप से, चर नए डेटा की ओर इशारा करते हुए समाप्त होता है। यह संपत्ति चर का सच है। चूंकि ये असाइनमेंट फंक्शन कॉल नहीं हैं, इसलिए उनका पास-बाय-वैल्यू या पास-बाय-रेफरेंस से कोई लेना-देना नहीं है।
जॉन सोंडरसन

1
नहीं, सब कुछ हमेशा मूल्य द्वारा पारित किया जाता है। यह सिर्फ इस बात पर निर्भर करता है कि आप क्या कर रहे हैं (एक मूल्य या एक संदर्भ)। देखें इस
स्कॉट मार्कस

-3
  1. आदिम (संख्या, बूलियन, आदि) मूल्य द्वारा पारित किए जाते हैं।
    • तार अपरिवर्तनीय हैं, इसलिए यह वास्तव में उनके लिए मायने नहीं रखता है।
  2. ऑब्जेक्ट्स संदर्भ द्वारा पारित किए जाते हैं (संदर्भ मूल्य द्वारा पारित किया जाता है)।

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

आपका दूसरा कथन स्वयं विरोधाभासी है।
जार्ज डब्ल्यू मित्तग

-5

फ़ंक्शन के अंदर सरल मान फ़ंक्शन के बाहर उन मानों को नहीं बदलेंगे (वे मूल्य द्वारा पारित किए जाते हैं), जबकि जटिल वाले (वे संदर्भ द्वारा पारित किए जाते हैं)।

function willNotChange(x) {

    x = 1;
}

var x = 1000;

willNotChange(x);

document.write('After function call, x = ' + x + '<br>'); // Still 1000

function willChange(y) {

    y.num = 2;
}

var y = {num: 2000};

willChange(y);
document.write('After function call y.num = ' + y.num + '<br>'); // Now 2, not 2000

यह हास्यास्पद है, कार्यात्मक स्तर के ढलान के कारण y बदल जाएगा, यह नहीं फहराया जाता है क्योंकि इसे संदर्भ द्वारा पारित किया जाता है।
पारिजात कालिया 19

नहीं, सब कुछ हमेशा मूल्य द्वारा पारित किया जाता है। यह सिर्फ इस बात पर निर्भर करता है कि आप क्या कर रहे हैं (एक मूल्य या एक संदर्भ)। देखें इस
स्कॉट मार्कस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.