जावास्क्रिप्ट बंद - चर के जीवनकाल

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

मैं कोड के इस छोटे स्निपेट को समझने की कोशिश कर रहा हूं

// Function which returns object with function properties
function myFunc() {

    value = 42;

    var result = {
        value: value,
        getValue: getValue,
        incrementValue: incrementValue,
        setValue: setValue,
    };
    return result; 

    function setValue(y) {
        value = y;
    };

    function getValue() {
         return value;   
    }; 

    function incrementValue() {
        value++;
    };
};

// Helper function to print out results
function printResults(m,x){
    $('#output').append(m + ': ' + x).append('
'); }; var myObject = myFunc(); //returns the object printResults('Inital call to getValue',myObject.getValue()); myObject.setValue(59); printResults('Called changeValue',myObject.getValue()); printResults('Value property of object',myObject.value); printResults('Called getValue again',myObject.getValue()); myObject.incrementValue(); printResults('Call increment value',myObject.getValue()); printResults('Value property of object',myObject.value);

JsFiddle में चलाते समय मुझे निम्न परिणाम मिलते हैं

Inital call to getValue: 42
Called changeValue: 59
Value property of object: 42
Called getValue again: 59
Call increment value: 60
Value property of object: 42

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

मुझे लगता है कि मुझे मूल बिंदु मिलता है कि कार्य को स्कोप श्रृंखला का उपयोग करके निष्पादित किया जाता है जो प्रभावी रूप से परिभाषित किए जाने पर प्रभावी था।

Questions Can I make the value property of the returned object operate in the same way - or is the only way to return it via a function, since the latter retains the variable in its closure?

And, just for confirmation, for every invocation of myFunc(), I assume I will get an object whose function properties will have their own scope chain and therefore independent of each invocation.

0
जोड़ा संपादित
विचारों: 1
यह वैसे ही सी # में वही व्यवहार करता है, अगर इससे आपको असाइनमेंट के अर्थशास्त्र और क्या नहीं लगता है।
जोड़ा लेखक Ry-, स्रोत
युक्ति: ब्लॉक के बाद कोई अर्धविराम नहीं, उदा। समारोह घोषणाओं में।
जोड़ा लेखक Ry-, स्रोत
@ डेरिजा 9 3: एर, नहीं। सख्त मोड एएसआई को प्रभावित नहीं करता है, मेरी शाश्वत निराशा के लिए।
जोड़ा लेखक Ry-, स्रोत
@ Derija93: मैं वास्तव में अर्धविराम छोड़ने के बारे में बात नहीं कर रहा हूं, मैं बहुत अधिक होने के बारे में बात कर रहा हूं, जो कि काफी स्वाभाविक रूप से गलत है। सीएफ myObject.incrementValue() ;;;;;;;;; printResults() ;;;
जोड़ा लेखक Ry-, स्रोत
@ Derija93: यह एक विशेष मामला नहीं है। अर्धविराम के साथ सभी बयान समाप्त करें। एक ब्लॉक एक बयान नहीं है।
जोड़ा लेखक Ry-, स्रोत
@ Derija93: आपके अपवाद मामले में, ब्लॉक अभी भी अर्धविराम से समाप्त नहीं होता है, लेकिन परिवर्तनीय घोषणा करता है।
जोड़ा लेखक Ry-, स्रोत
@GuilhermeSehn ठीक है कि ... इस छोटे विवाद को कम से कम कम कर सकता था।
जोड़ा लेखक Kiruse, स्रोत
@minitech वास्तव में कोई फर्क नहीं पड़ता, और यह भी पूरी तरह से सच नहीं है। var func = function() {}; को सेमी-कोलन की आवश्यकता नहीं होती है, क्योंकि सामान्य रूप से जावास्क्रिप्ट को सेमी-कोलन की आवश्यकता नहीं होती है, लेकिन लिंटर्स अभी भी इसे चिह्नित करेंगे। लेकिन यह एकमात्र मामला है जहां आपका कथन काफी सच नहीं है ... और कुछ खास है। : पी
जोड़ा लेखक Kiruse, स्रोत
@GuilhermeSehn मैं एक लाइनर के बारे में बात नहीं कर रहा था। जाहिर है उन लोगों के लिए आपको निश्चित रूप से अर्धविराम (या आपके उदाहरण में अल्पविराम) रखना होगा। मैं एक नई पंक्ति में प्रत्येक कथन लिखने के बारे में सोच रहा था।
जोड़ा लेखक Kiruse, स्रोत
@minitech ठीक है, यह भी बदतर है, जिसका अर्थ है कि यह मूल रूप से केवल अनुशंसित है ... परवाह किए बिना, यह काफी लंबा हो रहा है।
जोड़ा लेखक Kiruse, स्रोत
@minitech यह आमतौर पर सही वाक्यविन्यास है, लेकिन केवल सख्त मोड में आवश्यक है।
जोड़ा लेखक Kiruse, स्रोत
@minitech हां, लेकिन अर्धविराम छोड़ना और बहुत से होने से वास्तव में दुभाषिया से कोई फर्क नहीं पड़ता। वे अनावश्यक हैं और बहुत अधिक नो-ऑप्स हैं। कोड शायद पढ़ने के लिए मुश्किल हो जाता है और निश्चित रूप से आकार में अनावश्यक रूप से बड़ा हो जाता है। यही एकमात्र चीज है जिसके बारे में मैं बात कर रहा हूं।
जोड़ा लेखक Kiruse, स्रोत
@minitech और यह बहुत अधिक है विशेष मैं इसका जिक्र कर रहा हूं।
जोड़ा लेखक Kiruse, स्रोत
@ Derija93 मैं मानता हूं कि जब आप प्रत्येक कथन को एक नई पंक्ति में डाल रहे हैं, अर्धविराम वैकल्पिक हैं और इसकी आवश्यकता नहीं है। हालांकि, मुझे लगता है कि वह कहने की कोशिश कर रहा है कि यदि आप अर्धविरामों को वैसे भी रखना चाहते हैं, तो उन जगहों पर केवल उन जगहों पर उनका उपयोग करें जिनकी आवश्यकता होगी यदि भाषा में एएसआई नहीं है। और ब्लॉक के रूप में घोषित कार्यों की आवश्यकता नहीं होगी।
जोड़ा लेखक Guilherme Sehn, स्रोत
बस एक उदाहरण के बाद, एक कोडर फ़ंक्शन ए() {} फ़ंक्शन बी() {} लिखते समय, आपको सेमिकोलन की आवश्यकता नहीं है क्योंकि आप ब्लॉक से निपट रहे हैं, लेकिन परिवर्तनीय घोषणाओं की आवश्यकता होती है। जैसे a = function() {} b = function {} एक वाक्यविन्यास त्रुटि का कारण बनता है।
जोड़ा लेखक Guilherme Sehn, स्रोत

3 उत्तर

हाँ तुम कर सकते हो:

var result = {
    get value() {
        return value;
    },
    getValue: getValue,
    incrementValue: incrementValue,
    setValue: setValue,
};

Hooray for ECMAScript 5. Of course, this won’t work on IE < 8.

इस तरह से चर के जीवनकाल के साथ बहुत कुछ नहीं है, वैसे ही - यह असाइनमेंट कैसे काम करता है। जावास्क्रिप्ट में संदर्भ हैं, लेकिन कोई "संदर्भ चर" या "संदर्भ गुण" नहीं हैं। ऑब्जेक्ट में उस समय value की एक प्रति शामिल थी; इस तरह एक गेटटर बनाना एक ऐसा फ़ंक्शन बनाने जैसा है जिसे स्पष्ट रूप से कहा जाता है।

0
जोड़ा
मैंने उपरोक्त फ़ेलिक्स किंग का जवाब दिया है और मैं देखता हूं कि आपकी पोस्ट इसका उत्तर दे सकती है। तो, जेएस में, वेरिएबल्स ऑब्जेक्ट्स के संदर्भ नहीं हैं - वे ऑब्जेक्ट्स हैं?
जोड़ा लेखक jcaddy, स्रोत
@jcaddy: आप निश्चित रूप से उन सभी वस्तुओं के संदर्भ के रूप में सोच सकते हैं, लेकिन आप संदर्भों को ओवरराइट कर रहे हैं; मैंने फ़ेलिक्स क्लिंग के उत्तर पर अधिक जानकारी के साथ एक टिप्पणी जोड़ा। :)
जोड़ा लेखक Ry-, स्रोत

क्या मैं लौटाए गए ऑब्जेक्ट की वैल्यू प्रॉपर्टी को उसी तरह से संचालित कर सकता हूं

यदि आपका मतलब है कि यह अद्यतन मूल्य दिखाता है, हाँ, आप यह कर सकते हैं। आपको बस value प्रॉपर्टी को अपडेट करने के लिए कोड को बदलना होगा:

function myFunc() {

    var value = 42;//don't forget var!

    var result = {
        value: value,
        getValue: getValue,
        incrementValue: incrementValue,
        setValue: setValue,
    };
    return result; 

    function setValue(y) {
        result.value = value = y;
    }

    function getValue() {
         return value;   
    }

    function incrementValue() {
        value++;
        result.value = value;
    }
}

value और result.value दोनों का उपयोग करने का कारण result.value के माध्यम से मान के संशोधन को रोकने के लिए है। यदि आप देखते हैं, तो मैं result.value से आंतरिक रूप से पढ़ा नहीं करता हूं, मैं केवल इसे लिखता हूं। इसका मतलब है कि बाहरी कोड से result.value को असाइनमेंट का कोई प्रभाव नहीं पड़ता है। यह इस बात का अनुरूप है कि आपका मौजूदा कोड कैसे काम करता है।

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

हां, myFunc का प्रत्येक आमंत्रण एक नई वस्तु और नए कार्यों को बनाता है और वे पिछले आमंत्रणों द्वारा बनाई गई वस्तुओं/कार्यों से पूरी तरह से स्वतंत्र हैं।

0
जोड़ा
तो क्या इसका मतलब यह है कि परिणाम चर संदर्भित करके यह आमंत्रण के बीच आंतरिक कार्य के बंद होने के भीतर रहता है?
जोड़ा लेखक jcaddy, स्रोत
बस अपनी संतुष्टि के लिए, मैंने value प्रॉपर्टी को एक साधारण ऑब्जेक्ट var myInternalObject = {value: 42}; - कोड को थोड़ा बदल दिया, और वास्तव में मुझे मिला संपत्ति के रूप में अपेक्षित व्यवहार अब एक आदिम नहीं था।
जोड़ा लेखक jcaddy, स्रोत
मैंने इन सभी टिप्पणियों से काफी कुछ हासिल किया है - सभी को आकर्षित करने के लिए धन्यवाद। ऐसा लगता है कि, value लौटाई गई वस्तु की एक संपत्ति है - इसे एक आदिम (यानी int) असाइन किया गया है और इसके लिए (जैसे सी # में) असाइनमेंट के दौरान मान की प्रतिलिपि बनाई जाएगी। बेशक फ़ंक्शन गुणों की भी प्रतिलिपि बनाई जाती है - लेकिन चूंकि उनका मान एक संदर्भ है (जैसा सी # में है) वे एक ही कोड का संदर्भ दे रहे हैं। इस बिंदु पर आप सभी पाइप करते हैं कि मुझे अभी भी यह नहीं मिला है! सभी के लिए धन्यवाद - सभी टिप्पणियां बहुत उपयोगी - यहां तक ​​कि अर्धविराम चर्चा भी!
जोड़ा लेखक jcaddy, स्रोत
मेरे naivety के लिए माफ़ी। मैं उम्मीद करता हूं कि लौटा ऑब्जेक्ट की value प्रॉपर्टी उसी वैरिएबल का संदर्भ है जो आंतरिक फ़ंक्शंस का उपयोग कर रही है। तो जब changeValue value वैरिएबल बदलता है तो मैं उम्मीद करता हूं कि लौटाई गई वस्तु की value प्रॉपर्टी को प्रतिबिंबित किया जाए। मैं क्या खो रहा हूँ? हमें value के बजाय result.value सेट करने की आवश्यकता क्यों है - क्या वे एक ही स्थान का संदर्भ नहीं देते हैं? इसे समझने में मदद की बहुत सराहना करते हैं।
जोड़ा लेखक jcaddy, स्रोत
@ Derija93: इससे कोई फर्क नहीं पड़ता कि आप प्राइमेटिव को "मान" या "संदर्भ" के रूप में देखते हैं, या फिर उनकी प्रतिलिपि बनाई गई है या नहीं। चूंकि वे अपरिवर्तनीय हैं, व्यवहार में कोई अंतर नहीं होगा।
जोड़ा लेखक Ry-, स्रोत
@jcaddy: चाहे वे प्रारंभिक रूप से उसी स्थान का संदर्भ लें या न करें, बहुत अधिक अप्रासंगिक है - जावास्क्रिप्ट में, यह वास्तव में यह मानना ​​सुरक्षित है कि सबकुछ एक "संदर्भ" है। महत्वपूर्ण बात यह है कि, .value = कुछ नया करके, आप उस संदर्भ को ओवरराइट कर रहे हैं। यदि यह एक संदर्भ था, तो यह अब एक ही स्थान पर इंगित नहीं करता है। यहां तक ​​कि .value ++ .value = .value + 1 के लिए शॉर्टेंड है; "जगह में" कुछ भी नहीं हो रहा है।
जोड़ा लेखक Ry-, स्रोत
@minitech समझ में आता है, लेकिन यह निश्चित रूप से इसे समझने में मदद करता है।
जोड़ा लेखक Kiruse, स्रोत
@minitech मैं इसे एक छोटे से तरीके से रखूंगा: सभी वस्तुओं का संदर्भ दिया जाता है जबकि प्राइमेटिव की प्रतिलिपि बनाई जाती है। जब ओपी संपत्ति value की घोषणा करता है और शुरू करता है, तो उसे परिवर्तनीय value की एक प्रति प्राप्त होती है और तब से इसकी "उत्पत्ति" से स्वतंत्र होती है। अब मुझे यकीन नहीं है कि स्ट्रिंग्स ऑब्जेक्ट्स या प्राइमेटिव्स के रूप में जिम्मेदार हैं ...
जोड़ा लेखक Kiruse, स्रोत
@jcaddy: नहीं, यह एक संदर्भ नहीं है। मुझे सी # नहीं पता, लेकिन मुझे लगता है कि आपके पास int foo = 42; और int bar = foo; है, फिर bar </कोड> मान को foo पर असाइन नहीं करेगा, या यह होगा?
जोड़ा लेखक Felix Kling, स्रोत
@ Derija93: यह वास्तव में सही नहीं है। सभी मूल्यों की प्रतिलिपि बनाई गई है। किसी ऑब्जेक्ट का मान वास्तव में ऑब्जेक्ट का संदर्भ है और यह संदर्भ है जो प्रतिलिपि बनाई गई है। मैं इसे इस तरह देखता हूं: वेरिएबल्स स्वतंत्र मूल्य कंटेनर हैं। एक चर के लिए एक मान असाइन करना किसी अन्य चर के मान को कभी नहीं बदलता है। लेकिन दो चर एक ही मान (उदा। ऑब्जेक्ट) को संदर्भित कर सकते हैं और उस ऑब्जेक्ट को फिर वैरिएबल से बदला जा सकता है (और निश्चित रूप से वे परिवर्तन अन्य चर के माध्यम से भी दिखाई दे रहे हैं क्योंकि वे दोनों एक ही ऑब्जेक्ट को संदर्भित करते हैं)।
जोड़ा लेखक Felix Kling, स्रोत
मुझे नहीं पता तुम्हारा क्या मतलब है। myFunc के अंदर परिभाषित फ़ंक्शंस में myFunc के भीतर परिभाषित सभी अन्य चरों तक पहुंच है। इसलिए उनके पास value और परिणाम तक पहुंच है।
जोड़ा लेखक Felix Kling, स्रोत
स्ट्रिंग प्राइमेटिव हैं, जैसे शून्य, अपरिभाषित और संख्याएं।
जोड़ा लेखक Walter Macambira, स्रोत

सबसे पहले, चर घोषित करते समय var कीवर्ड को न भूलें। जब आप value = 42 को myFunc के अंदर घोषित करते हैं, तो आप वास्तव में फ़ंक्शन स्कोप के बजाय वैश्विक नामस्थान में एक चर बना रहे हैं। इसे इस तरह शुरू करना चाहिए:

function myFunc() {
    var value = 42;

अब, myObject.result 42 लौटा रहा है क्योंकि myFunc आपके result ऑब्जेक्ट को देता है जिसमें value चर की एक प्रति होती है समारोह के अंदर घोषित किया गया।

आपके फ़ंक्शन setValue , getValue और incrementValue value के मान को बदल रहे हैं, नहीं result.value । जब आप myObject.value पर कॉल करते हैं, तो आपको लौटे ऑब्जेक्ट से मूल्य मिल रहा है, न कि आपके फ़ंक्शन के आंतरिक चर।

आप इसे इस तरह कुछ उपयोग करके काम करने के लिए प्राप्त कर सकते हैं:

function myFunc() {
    var value = 42;
    var result = {
        value: value,
        getValue: getValue,
        incrementValue: incrementValue,
        setValue: setValue
    };

    return result;

    function setValue(y) {
        result.value = y;
    }

    function getValue() {
        return result.value;
    }

    function incrementValue() {
        result.value++;
    }
}

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

function myFunc() {
    this.value = 42;
}

myFunc.prototype.setValue = function(y) {
    this.value = y;
}

myFunc.prototype.getValue = function(y) {
    return this.value;
}

myFunc.prototype.incrementValue = function(y) {
    this.value++;
}

var myObject = new myFunc();
console.log(myObject.getValue());//42
myObject.setValue(30);
myObject.incrementValue();
console.log(myObject.getValue());//31
0
जोड़ा
@ वाल्टर: यह वास्तव में एक कार्यान्वयन विस्तार हो सकता है। चूंकि आदिम मान अपरिवर्तनीय हैं, आप नहीं बता सकते हैं (केवल कोड निष्पादित करके) चाहे प्राइमेटिव भी संदर्भ न हों।
जोड़ा लेखक Felix Kling, स्रोत
ध्यान दें कि दोनों उदाहरण ओपी के कोड की तुलना में एक अलग व्यवहार का पर्दाफाश करते हैं। उनमें से दोनों में आप myObject.value = newValue; ( myObject.setValue के अतिरिक्त) के माध्यम से मान भी बदल सकते हैं। मूल कोड में यह संभव नहीं था।
जोड़ा लेखक Felix Kling, स्रोत
मैं समझता हूं, मैं बस इसे इंगित करना चाहता था।
जोड़ा लेखक Felix Kling, स्रोत
@WalterMacambira: एक चर का मान या तो एक आदिम या किसी ऑब्जेक्ट के लिए सूचक है। यह मूल्य की एकमात्र औपचारिक अवधारणा है।
जोड़ा लेखक newacct, स्रोत
@ वाल्टरमैकाम्बिर: जावास्क्रिप्ट में प्रत्येक मान को पारित या असाइन किए जाने पर कॉपी किया जाता है। जावास्क्रिप्ट में "ऑब्जेक्ट्स" मान नहीं हैं। जावास्क्रिप्ट में केवल उन्हीं मानों का उपयोग कर सकते हैं जो प्राइमेटिव्स और रेफरेंस (ऑब्जेक्ट्स पॉइंटर्स) हैं, जैसे जावा में।
जोड़ा लेखक newacct, स्रोत
@newacct और मैं उस से असहमत नहीं हूं, मैंने जो कुछ कहा वह सिर्फ गलत है।
जोड़ा लेखक Walter Macambira, स्रोत
@newacct मैं चर 'मूल्य' के बारे में बात कर रहा हूँ।
जोड़ा लेखक Walter Macambira, स्रोत
इस पर ध्यान दिलाने के लिए धन्यवाद। यह निश्चित रूप से मेरी टिप्पणी से उत्पन्न होने वाले किसी भी संदेह को स्पष्ट करेगा।
जोड़ा लेखक Walter Macambira, स्रोत
माना। मेरी टिप्पणी का इरादा केवल यह स्पष्ट करना है कि वापसी वस्तु में 'मूल्य' फ़ंक्शन के अंदर घोषित नहीं किया गया है।
जोड़ा लेखक Walter Macambira, स्रोत
यह अच्छा होगा अगर आप समझाते हैं कि प्राइमेटिव की प्रतिलिपि बनाई गई है। यही कारण है कि वापसी वस्तु पर मूल्य की प्रतिलिपि बनाई गई है। दूसरी तरफ, वस्तुओं की प्रतिलिपि नहीं बनाई जाती है। उनके लिए, असाइनमेंट एक ही नियम के लिए सिर्फ एक उपनाम हैं।
जोड़ा लेखक Walter Macambira, स्रोत