javascript - क्या जावास्क्रिप्ट संदर्भ से गुजरता है?




reference pass-by-reference (7)

"ग्लोबल" जावास्क्रिप्ट वैरिएबल विंडो ऑब्जेक्ट के सदस्य हैं। आप विंडो ऑब्जेक्ट के सदस्य के रूप में संदर्भ का उपयोग कर सकते हैं।

var v = "initialized";
function byref(ref) {
 window[ref] = "changed by ref";
}
byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// could also be called like... byref('v');
console.log(v); // outputs changed by ref

नोट, उपरोक्त उदाहरण फ़ंक्शन के भीतर घोषित चर के लिए काम नहीं करेगा।

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

क्या यह बंद है? लेकिन कोई समारोह वापस नहीं किया जाता है।

var shape = function (config) {
    var that = {};
    that.name = config.name || "";
    that.area = function () {
        return 0;
    };
    return that;
};
var rectangle = function (config, my) {
    my = my || {};
    my.l = config.length || 1;
    my.w = config.width || 1;
    var that = shape(config);
    that.area = function () {
        return my.l * my.w;
    };
    return that;
};
myShape = shape({
    name: "Unhnown"
});
myRec = rectangle({
    name: "Rectangle",
    length: 4,
    width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());

Primitives मूल्य से पारित कर रहे हैं, वस्तुओं "संदर्भ की प्रति" द्वारा पारित किया जाता है।

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

function replace(ref) {
    ref = {};           // this code does _not_ affect the object passed
}

function update(ref) {
    ref.key = 'newvalue';  // this code _does_ affect the _contents_ of the object
}

var a = { key: 'value' };
replace(a);  // a still has its original value - it's unmodfied
update(a);   // the _contents_ of 'a' are changed

सी ++ के साथ तुलना करें जहां एक संदर्भ प्रकार बदलना पूरी तरह से कॉलर द्वारा पारित वस्तु को प्रतिस्थापित कर सकता है:

void replace(mytype& ref) {
    ref = *new mytype();  // ignoring the memory leak for the purposes of this example
}

mytype a;
replace(a);   // a is now a _different_ object

इसके बारे में इस तरह से सोचें:

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

var obj = { };

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


एक सरल उदाहरण बनाने के हित में जो const का उपयोग करता है ...

const myRef = { foo: 'bar' };
const myVal = true;

function passes(r, v) {
  r.foo = 'baz';
  v = false;
}

passes(myRef, myVal);

console.log(myRef, myVal); // Object {foo: "baz"} true

फ़ंक्शन तर्क या तो मूल्य-दर-या साझाकरण द्वारा पारित किए जाते हैं लेकिन कभी भी जावास्क्रिप्ट में संदर्भ द्वारा कभी नहीं !

कॉल-टू-मान के आधार पर

आदिम प्रकार मूल्य से पारित होते हैं:

var num = 123, str = "foo";

function f(num, str) {
  num += 1;
  str += "bar";
  console.log("inside of f:", num, str);
}

f(num, str);
console.log("outside of f:", num, str);

फ़ंक्शन स्कोप के अंदर पुन: असाइनमेंट आसपास के दायरे में दिखाई नहीं दे रहे हैं।

यह String एस पर भी लागू होता है, जो एक समग्र डेटा प्रकार हैं और फिर भी अपरिवर्तनीय हैं:

var str = "foo";

function f(str) {
  str[0] = "b"; // doesn't work, because strings are immutable
  console.log("inside of f:", str);
}

f(str);
console.log("outside of f:", str);

कॉल-टू-शेयरिंग द्वारा

ऑब्जेक्ट्स, जो कि उन सभी प्रकारों को कहना है जो प्राइमेटिव नहीं हैं, साझा करके पास किए जाते हैं। एक चर जो किसी ऑब्जेक्ट का संदर्भ रखता है वास्तव में केवल इस संदर्भ की एक प्रति रखता है। यदि जावास्क्रिप्ट कॉल-बाय-रेफरेंस मूल्यांकन रणनीति का पीछा करेगा, तो चर मूल संदर्भ रखेगा। यह साझाकरण और संदर्भ के बीच महत्वपूर्ण अंतर है।

इस भेद के व्यावहारिक परिणाम क्या हैं?

var o = {x: "foo"}, p = {y: 123};

function f(o, p) {
  o.x = "bar"; // mutation
  p = {x: 456}; // reassignment
  console.log("o inside of f:", o);
  console.log("p inside of f:", p);
}

f(o, p);

console.log("o outside of f:", o);
console.log("p outside of f:", p);

उत्परिवर्तन का मतलब किसी मौजूदा Object कुछ गुणों को संशोधित करना है। संदर्भ प्रतिलिपि जो एक चर के लिए बाध्य है और यह इस वस्तु को संदर्भित करता है वही रहता है। इस प्रकार कॉलर के दायरे में उत्परिवर्तन दिखाई देते हैं।

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

Ecmascript में मूल्यांकन रणनीतियों पर और जानकारी।


मेरे 2 सेंट .... यह अप्रासंगिक है कि जावास्क्रिप्ट संदर्भ या मूल्य द्वारा पैरामीटर पास करता है या नहीं। असाइनमेंट बनाम उत्परिवर्तन वास्तव में मायने रखता है।

मैंने यहां एक लंबा, अधिक विस्तृत स्पष्टीकरण लिखा है ( क्या जावास्क्रिप्ट एक पास-दर-संदर्भ या पास-दर-मूल्य भाषा है? )

जब आप कुछ भी पास करते हैं (चाहे वह ऑब्जेक्ट या आदिम हो), सभी जावास्क्रिप्ट फ़ंक्शन के अंदर एक नया चर निर्दिष्ट करता है ... बराबर चिह्न (=) का उपयोग करने की तरह

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

var myString = 'Test string 1';

// Assignment - A link to the same place as myString
var sameString = myString;

// If I change sameString, it will not modify myString, 
// it just re-assigns it to a whole new string
sameString = 'New string';

console.log(myString); // logs 'Test string 1';
console.log(sameString); // logs 'New string';

अगर मैं किसी फ़ंक्शन के पैरामीटर के रूप में myString को पास करना चाहता था, तो ऐसा लगता है जैसे मैंने इसे एक नए चर के लिए असाइन किया था। अब, एक ही काम करते हैं, लेकिन एक साधारण असाइनमेंट के बजाय फ़ंक्शन के साथ

function myFunc(sameString) {

    // Re assignment.. again, it will not modify myString
    sameString = 'New string';
}

var myString = 'Test string 1';

// This behaves the same as if we said sameString = myString
myFunc(myString);

console.log(myString); // Again, logs 'Test string 1';

एकमात्र कारण है कि जब आप किसी फ़ंक्शन में पास करते हैं तो आप वस्तुओं को संशोधित कर सकते हैं क्योंकि आप पुन: असाइन नहीं कर रहे हैं ... इसके बजाय, ऑब्जेक्ट्स को बदला या बदला जा सकता है .... फिर, यह वैसे ही काम करता है।

var myObject = { name: 'Joe'; }

// Assignment - We simply link to the same object
var sameObject = myObject;

// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'

sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'

// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'

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

function myFunc(sameObject) {

    // We mutate the object, so the myObject gets the change too... just like before.
    sameObject.name = 'Jill';

    // But, if we re-assign it, the link is lost
    sameObject = { name: 'Howard' };
}

var myObject = { name: 'Joe'; }

// This behaves the same as if we said sameObject = myObject;
myFunc(myObject);
console.log(myObject.name); // Logs 'Jill'

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

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

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

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


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

और यह सब कुछ वस्तुओं के लिए refernces, चर नहीं है। एक ही परिणाम प्राप्त करने के कई तरीके हैं, लेकिन उन्हें कॉल या घोषणा साइट पर केवल एक कीवर्ड जोड़ने के बजाय हाथ से किया जाना है।






pass-by-value