जावास्क्रिप्ट में संकेत?


81

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

उदाहरण:

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

तर्क यह बुरी शैली है क्योंकि आप एक समारोह के साइड-इफेक्ट का उपयोग करने के लिए उत्परिवर्तन का कारण बन रहे हैं। इससे आपका कोड अनुसरण करने में कठिन हो सकता है।
— 12

जवाबों:


140

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

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स्मृति में एक ही बात को देखें। की Valueसंपत्ति को objप्रभावित करने वाली Valueसंपत्ति को बदलना x।

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


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

6
हे, मुझे एसओ पर कोड स्निपेट पेश करने के लिए धन्यवाद । इससे पहले कि मैंने आपके उत्तर में इसका इस्तेमाल किया, मैंने उन्हें नहीं सुना।
— Joeytje50

@ Joeytje50 - हाँ, यह सुविधा अभी सितंबर में वापस जोड़ी गई थी। बेहद सुविधाजनक!
— माइक क्रिस्टीनसेन

क्या होगा यदि आप उदाहरण के लिए obj प्रॉपर्टी के लिए नाम नहीं जानते हैं अगर यह obj.name था तो अगली बार आप obj.surname अपडेट करना चाहते हैं? आप उस प्रकार के लचीलेपन के लिए एक फ़ंक्शन को कैसे अनुकूल बना सकते हैं?
— सर

1
@ यह एक देर से जवाब हो सकता है, लेकिन आप अपने फ़ंक्शन को 3 मापदंडों, obj, संपत्ति के नाम और मूल्य के लिए उम्मीद कर सकते हैं। याद रखें कि आप obj.propertyname या obj ['propertyname'] कर के किसी वस्तु की संपत्ति तक पहुँच सकते हैं, जो कि आप लचीलेपन के समय चाहते हैं। 3 पैरामीटर पास करें और obj करें ['propertyname'] = value और वह पुन: प्रयोज्य होगी।
— कार्लोस कैला

19

यह प्रश्न मदद कर सकता है: जावास्क्रिप्ट में संदर्भ द्वारा चर कैसे पारित करें? ActiveX फ़ंक्शन से डेटा पढ़ें जो एक से अधिक मान लौटाता है

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

var myobj = {x:0};

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

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

  


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

जबकि वस्तुओं को संदर्भ द्वारा पारित किया जाता है, केवल सच नहीं है। जावास्क्रिप्ट में कुछ भी संदर्भ से पारित नहीं है।
— माइक क्रिस्टेन्सन

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

14

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

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

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

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

var _x = [ 10 ];

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

foo(_x);

console.log(_x[0]);

पैदावार

output: 20

8

आप विंडो ऑब्जेक्ट से 'x' को देखें

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

जावास्क्रिप्ट में जो एक वैश्विक होगा। हालाँकि, आपका कार्य इस तरह दिखाई देगा:

function a(){
   x++;
};

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


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

1

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

यह वही है जो मैं निकटतम के रूप में देखता हूं आप व्यवहार में सी पॉइंटर्स पर आ सकते हैं

js में:

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

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

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


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

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

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

इसका कष्टप्रद हिस्सा तब होता है जब आप साझा राज्य का एक बैग बनाना चाहते हैं, जैसे "window.sared" जो कि वर्तमान में अशक्त / अपरिभाषित हैं, जिन्हें आप बाद में सेट कर देंगे। इस स्थिति में, जैसा कि आप उस स्थिति का मान सेट करते हैं जो वर्तमान में अशक्त / अपरिभाषित है, "window.sared" चर परिवर्तनों को नहीं पहचान पाएगा, भले ही वे ऑब्जेक्ट प्रकार में संग्रहीत हों, लेकिन यह पहले से ही बहुत देर हो चुकी है; "शून्य / अपरिभाषित" मानों को कार्य के लिए शुरू करने के लिए ऑब्जेक्ट प्रकारों के अंदर होना चाहिए, उदाहरण के लिए [अशक्त] [अपरिभाषित]।
— दिमित्री

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

0

मैं सोच रहा हूँ कि सी के विपरीत या संकेत के साथ किसी भी भाषा:

/** Javascript **/
var o = {x:10,y:20};
var o2 = {z:50,w:200};
  • जाहिर है कि जावास्क्रिप्ट में आप ऑब्जेक्ट्स ओ और ओ 2 पतों को मेमोरी में एक्सेस नहीं कर सकते हैं
  • लेकिन आप न तो उनके पते की तुलना कर सकते हैं : (न ही उन्हें छांटने की कोई तुच्छ संभावना , और फिर डाइकोटॉमी द्वारा पहुंच )

।

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

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

  • इसका मतलब है कि आप अपने आवेदन द्वारा बनाई गई (आवंटित) हर वस्तु को सूचीबद्ध / प्रबंधित कर सकते हैं,

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

  • लेकिन जब आप किसी विशिष्ट वस्तु के बारे में आपके द्वारा बनाई गई जानकारी को पुनः प्राप्त करना चाहते हैं, तो आप इसे अपनी विशाल सूची में डाइकोटॉमी द्वारा नहीं पा सकते हैं : प्रति ऑब्जेक्ट में कोई विशिष्ट पहचानकर्ता नहीं है जिसे वास्तविक स्मृति पते के प्रतिस्थापन के रूप में इस्तेमाल किया जा सकता है

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

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

0

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

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

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


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

यह केवल एक ब्राउज़र वातावरण में काम करता है और windowऑब्जेक्ट के लिए विशिष्ट है । इसके अलावा, वैश्विक चर का उपयोग करने की सिफारिश कम है, क्योंकि पहले से ही एक ही नाम के साथ एक चर हो सकता है।
— JayJay

0

यह सिर्फ संकेत का समर्थन नहीं करता है, कहानी का अंत :-(।

मैं यह जोड़ना चाहूंगा, जबकि मैं बिल्कुल नया हूं और C बैकग्राउंड से आ रहा हूं, जो मैं इवेंट लूप और स्टैक के बारे में पढ़ रहा हूं, आपको जो भी संभव हो, उसके कॉलर को जितना संभव हो उतना पास रखना चाहिए। जैसा कि मैं बिल्कुल नया हूं, मुझे यह गलत लग सकता है।

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

इसके अलावा, किसी भी उदाहरण ने यह संकेत दिया है कि एक ही काम करने के लिए कई तरीकों से सिर्फ 1 संकेत मिलता है, जो कि सूचक नहीं होगा।


-1

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

यह संभवत: सुरक्षित नहीं है कि जावास्क्रिप्ट हमेशा इस तरह से व्यवहार करेगा ...

चियर्स!


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

-1

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

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