2012-04-19 5 views
66

क्या हम एक चर के संदर्भ को पारित कर सकते हैं जो फ़ंक्शन में तर्क के रूप में अपरिवर्तनीय है?जावास्क्रिप्ट में पॉइंटर्स?

उदाहरण:

var x = 0; 
function a(x) 
{ 
    x++; 
} 
a(x); 
alert(x); //Here I want to have 1 instead of 0 
+0

तर्कसंगत यह खराब शैली है क्योंकि आप उत्परिवर्तन के कारण किसी फ़ंक्शन के दुष्प्रभावों का उपयोग करने का इरादा रखते हैं। यह आपके कोड को पालन करने के लिए कठिन बना सकता है। – spex

उत्तर

107

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

var x = {Value: 0}; 
 

 
function a(obj) 
 
{ 
 
    obj.Value++; 
 
} 
 

 
a(x); 
 
document.write(x.Value); //Here i want to have 1 instead of 0

इस मामले में, x एक वस्तु के लिए एक संदर्भ है। जब x फ़ंक्शन a पर पास किया जाता है, तो उस संदर्भ को obj पर कॉपी किया गया है। इस प्रकार, obj और x स्मृति में एक ही चीज़ का संदर्भ लें। Valueobj की संपत्ति Valuex की संपत्ति को प्रभावित करती है।

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

+0

क्या ऐसा करने का कोई तरीका है इसलिए कोई अन्य व्यक्ति बस करेगा: var x = 0; a (x); और यह कि फ़ंक्शन एक्स के मान के साथ एक ऑब्जेक्ट सेट करता है? (या ऐसा कुछ) – user1342369

+5

अरे, मुझे [एसओ पर कोड स्निपेट] (http://meta.stackoverflow.com/q/269753/1256925) शुरू करने के लिए धन्यवाद। इससे पहले कि मैंने इसे आपके उत्तर में इस्तेमाल किया, इससे पहले मैंने उनके बारे में नहीं सुना था। – Joeytje50

+0

@ जोएटेजे 50 - यूप, [यह सुविधा] (http://blog.stackoverflow.com/2014/09/introducing-runnable-javascript-css-and-html-code-snippets/) सितंबर में वापस जोड़ा गया था। बेहद सुविधाजनक! –

19

यह सवाल मदद मिल सकती है: How to pass variable by reference in javascript? Read data from ActiveX function which returns more than one value

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

var myobj = {x:0}; 
 

 
function a(obj) 
 
{ 
 
    obj.x++; 
 
} 
 

 
a(myobj); 
 
alert(myobj.x); // returns 1 
 

 

+2

ऑब्जेक्ट वेरिएबल्स हमेशा मूल्य के आधार पर पारित होते हैं - यह केवल यह है कि * ऑब्जेक्ट का मान * संदर्भ है। * संदर्भ द्वारा गुजरने * और * मूल्य * के संदर्भ में गुजरने के बीच एक अंतर है। अर्थात्, जब आप मान द्वारा 'x' पास करते हैं, चाहे' x' एक ऑब्जेक्ट है या नहीं, तो आप कॉलर को किसी भी तरह से किसी अन्य तरीके से प्रतिस्थापित नहीं कर सकते हैं। – cHao

+0

* जबकि वस्तुओं संदर्भ द्वारा पारित किया जाता है * बस सच नहीं है। जावास्क्रिप्ट में कुछ भी संदर्भ द्वारा पारित नहीं किया गया है। –

+0

यदि आप मान द्वारा प्राइमेट प्रकार पास करते हैं (x द्वारा संदर्भित किया जाता है), एक्स क्यों नहीं बदलता है, जब तक कि आप ऑब्जेक्ट – SuperUberDuper

1

जावास्क्रिप्ट में है कि एक वैश्विक होगा। हालांकि, अपने समारोह और अधिक इस प्रकार दिखाई देगा:

function a(){ 
    x++; 
}; 

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

+1

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

+0

यह एक अच्छा मुद्दा है। – Maess

0

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

+3

बस सच नहीं है। आप जावास्क्रिप्ट में संदर्भ द्वारा कुछ भी पास नहीं कर सकते हैं। –

+1

ऑब्जेक्ट संदर्भ मान के रूप में पारित किया गया है, इसलिए सब कुछ मान के रूप में पारित किया जाता है। –

+0

दिलचस्प अवलोकन; यह जावास्क्रिप्ट में मौजूदा आदिम के संदर्भ बनाने के लिए असंभव प्रतीत होता है; एक बार जब आदिम बाध्य हो जाता है, तो इस आदिम में किसी भी बदलाव को अपने बेवकूफ संदर्भकों द्वारा कभी नहीं देखा जा सकता है क्योंकि रेफरेंट वैल्यू को इंगित करते हैं जो परिवर्तनीय है, जो एक आदिम होता है; इसलिए एक आदिम को "बिंदु" का एकमात्र तरीका यह है कि यदि आदिम एक चर में लपेटा जाता है जिसका प्रकार "ऑब्जेक्ट" होता है; क्योंकि कोई अन्य प्रकार संदर्भ को स्टोर नहीं कर सकता है। TLDR; जावास्क्रिप्ट में कोई पर्ल "\" ऑपरेटर नहीं है; यह या तो शुरू करने का संदर्भ है, या आप इसे कभी भी इंगित नहीं कर सकते हैं। – Dmitry

11

मुझे एक अलग तरीके से लागू करने वाले पॉइंटर्स मिल गए हैं जो सी परिप्रेक्ष्य से समझने के लिए शायद अधिक सामान्य और आसान है (और इस प्रकार उपयोगकर्ताओं के उदाहरण के प्रारूप में अधिक फिट बैठता है)।

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

यह पॉइंटर के पते और पॉइंटर के पते पर क्या संदर्भित करता है, यह दो अलग-अलग नोटेशन का उपयोग करने की अनुमति देता है।

यहाँ एक उदाहरण (मैं अंडरस्कोर का उपयोग एक सूचक निरूपित करने के लिए) है:

var _x = [ 10 ]; 

function foo(_a){ 
    _a[0] += 10; 
} 

foo(_x); 

console.log(_x[0]); 

पैदावार

output: 20 
8

आप विंडो वस्तु से 'एक्स' का उल्लेख

var x = 0; 

function a(key, ref) { 
    ref = ref || window; // object reference - default window 
    ref[key]++; 
} 

a('x');     // string 
alert(x); 
3

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

function ptr(get, set) { 
    return { get: get, set: set }; 
} 

function helloWorld(namePtr) { 
    console.log(namePtr.get()); 
    namePtr.set('jack'); 
    console.log(namePtr.get()) 
} 

var myName = 'joe'; 
var myNamePtr = ptr(
    function() { return myName; }, 
    function (value) { myName = value; } 
); 

helloWorld(myNamePtr); // joe, jack 
console.log(myName); // jack 

ES6 में, कोड लैम्ब्डा एक्सप्रेशन का उपयोग करने छोटा किया जा सकता:

var myName = 'joe'; 
var myNamePtr = ptr(=> myName, v => myName = v); 

helloWorld(myNamePtr); // joe, jack 
console.log(myName); // jack 
-1

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

यह शायद जावास्क्रिप्ट अनुमान हमेशा ऐसा व्यवहार करे सुरक्षित नहीं है ...

चीयर्स!

+0

यह उत्तर इस पोस्ट के लिए कोई मूल्य नहीं जोड़ता है। @ माइक क्रिस्टेंसेन का जवाब अधिक विस्तृत और पहले से ही स्वीकार किया गया है। – Alexander

0

मैं सोच रहा हूँ कि सी के विपरीत या संकेत के साथ किसी भी भाषा में: आप स्मृति में ओ और o2पतों वस्तुओं को एक्सेस नहीं कर सकता जावास्क्रिप्ट में

/** Javascript **/ 
var o = {x:10,y:20}; 
var o2 = {z:50,w:200}; 
  • स्पष्ट रूप से
  • लेकिन आप से उनके पते की तुलना नहीं कर सकते हैं: (कोई मामूली संभावना नहीं है तरह उन्हें को ity, और फिर विरोधाभास)

द्वारा उपयोग।

o == o2 // obviously false : not the same address in memory 
o <= o2 // true ! 
o >= o2 // also true !! 

कि एक बड़ी समस्या है:

  • इसका मतलब है कि आप सूची/अपने आवेदन के द्वारा,

  • वस्तुओं की कि विशाल सूची से हर वस्तुओं (आवंटित) बनाया प्रबंधन कर सकते हैं , इनके बारे में कुछ जानकारी की गणना करें (उदाहरण के लिए वे एक साथ कैसे जुड़े हुए हैं)

  • बी ut जब आप जानकारी आप एक विशिष्ट वस्तु के बारे में बनाई प्राप्त करना चाहते हैं, तो आप नहीं यह आपके विशाल सूची में विरोधाभास से पा सकते हैं: है कि वास्तविक स्मृति पता

    की एक स्थानापन्न के रूप में इस्तेमाल किया जा सकता वस्तु प्रति कोई अद्वितीय पहचानकर्ता है

इस अंत में इसका मतलब है कि यह एक बहुत बड़ा समस्या है, यदि आप जावास्क्रिप्ट में लिखना चाहते हैं:

  • एक javaScript डीबगर/आईडीई
  • या एक विशेष रूप से अनुकूलित कचरा कलेक्टर
  • एक डेटा संरचना दराज/विश्लेषक
1

जावास्क्रिप्ट बस coz यह समस्याओं का एक बहुत हल करती है मिश्रण में संकेत दिए गए रखना चाहिए। इसका मतलब है कि कोड एक अज्ञात परिवर्तनीय नाम या चर को संदर्भित कर सकता है जो गतिशील रूप से बनाए गए थे। यह मॉड्यूलर कोडिंग और इंजेक्शन को भी आसान बनाता है।

var a = 78;  // creates a var with integer value of 78 
var pointer = 'a' // note it is a string representation of the var name 
eval (pointer + ' = 12'); // equivalent to: eval ('a = 12'); but changes value of a to 12 
ग में

:

int a = 78;  // creates a var with integer value of 78 
int pointer = &a; // makes pointer to refer to the same address mem as a 
*pointer = 12; // changes the value of a to 12 
0

जावास्क्रिप्ट गुजर का समर्थन नहीं करता

यह क्या मैं सबसे करीब के रूप में देखते हैं आप js में अभ्यास

में ग संकेत करने के लिए आ सकते हैं संदर्भ द्वारा आदिम प्रकार। हालांकि, एक कामकाज है।

किसी ऑब्जेक्ट में पास करने के लिए आवश्यक सभी चर रखें। इस मामले में, केवल एक चर है, x। चर को पारित करने के बजाय, वैरिएबल नाम को एक स्ट्रिंग के रूप में पास करें, जो "x" है।

var variables = {x:0}; 
 
function a(x) 
 
{ 
 
    variables[x]++; 
 
} 
 
a("x"); 
 
alert(variables.x);

1

इसके बाद से जावास्क्रिप्ट पर्ल के "\" ऑपरेटर एक संदर्भ द्वारा आदिम प्राप्त करने के लिए नहीं है असंभव हो सकता है, लेकिन वहाँ एक "प्रभावी रूप से एक सूचक" वस्तु के लिए बनाने के लिए एक रास्ता है इस पैटर्न का उपयोग कर एक आदिम।

यह समाधान सबसे अधिक समझ में आता है जब आपके पास पहले से ही आदिम है (इसलिए आप इसे किसी अन्य ऑब्जेक्ट को संशोधित किए बिना किसी ऑब्जेक्ट में नहीं डाल सकते हैं), लेकिन फिर भी इसके अन्य हिस्सों के लिए पॉइंटर पास करने की आवश्यकता है अपने राज्य के साथ टिंकर करने के लिए आपका कोड; तो आप अभी भी एक निर्बाध प्रॉक्सी का उपयोग कर अपने राज्य के साथ टिंकर कर सकते हैं जो एक सूचक की तरह व्यवहार करता है।

var proxyContainer = {}; 

// | attaches a pointer-lookalike getter/setter pair 
// | to the container object. 
var connect = function(container) { 
    // | primitive, can't create a reference to it anymore 
    var cant_touch_this = 1337; 

    // | we know where to bind our accessor/mutator 
    // | so we can bind the pair to effectively behave 
    // | like a pointer in most common use cases. 
    Object.defineProperty(container, 'cant_touch_this', { 
     'get': function() { 
      return cant_touch_this; 
     },     
     'set': function(val) { 
      cant_touch_this = val; 
     } 
    }); 
}; 

// | not quite direct, but still "touchable" 
var f = function(x) { 
    x.cant_touch_this += 1; 
}; 

connect(proxyContainer); 

// | looks like we're just getting cant_touch_this 
// | but we're actually calling the accessor. 
console.log(proxyContainer.cant_touch_this); 

// | looks like we're touching cant_touch_this 
// | but we're actually calling the mutator. 
proxyContainer.cant_touch_this = 90; 

// | looks like we touched cant_touch_this 
// | but we actually called a mutator which touched it for us. 
console.log(proxyContainer.cant_touch_this); 

f(proxyContainer); 

// | we kinda did it! :) 
console.log(proxyContainer.cant_touch_this); 
0

आप करना चाहते हैं क्या पर निर्भर करता है, तो आप बस चर नाम को बचा सकता है, और उसके बाद तो जैसे बाद में पर इस तक पहुंच:

function toAccessMyVariable(variableName){ 
    alert(window[variableName]); 
} 

var myFavoriteNumber = 6; 

toAccessMyVariable("myFavoriteNumber"); 

अपने विशिष्ट उदाहरण के लिए लागू करने के लिए, तुम कर सकते हो इस तरह कुछ:

var x = 0; 
var pointerToX = "x"; 

function a(variableName) 
{ 
    window[variableName]++; 
} 
a(pointerToX); 
alert(x); //Here I want to have 1 instead of 0 
संबंधित मुद्दे