অবাক করে দিয়েছি যে গ্লোবাল ভেরিয়েবলের জাভাস্ক্রিপ্টে অপরিবর্তিত মান রয়েছে


89

একটি গ্লোবাল ভেরিয়েবলের undefinedএকটি নির্দিষ্ট ক্ষেত্রে মূল্য রয়েছে বলে আমি যখন আজকে পুরোপুরি অবাক হয়েছি ।

উদাহরণ:

var value = 10;
function test() {
    //A
    console.log(value);
    var value = 20;

    //B
    console.log(value);
}
test();

হিসাবে আউটপুট দেয়

undefined
20

এখানে, জাভাস্ক্রিপ্ট ইঞ্জিন কেন বিশ্বব্যাপী মান হিসাবে বিবেচনা করছে undefined? আমি জানি যে জাভাস্ক্রিপ্ট একটি ব্যাখ্যামূলক ভাষা। এটি কীভাবে ফাংশনে ভেরিয়েবল বিবেচনা করতে সক্ষম?

এটি কি জাভাস্ক্রিপ্ট ইঞ্জিনের কোনও সমস্যা?

উত্তর:


177

এই ঘটনাটি হিসাবে পরিচিত: জাভাস্ক্রিপ্ট ভেরিয়েবল উত্তোলন

কোনও বিন্দুতে আপনি আপনার ফাংশনে গ্লোবাল ভেরিয়েবল অ্যাক্সেস করছেন না; আপনি কেবল স্থানীয় valueভেরিয়েবল অ্যাক্সেস করছেন ।

আপনার কোডটি নিম্নলিখিতগুলির সমতুল্য:

var value = 10;

function test() {
    var value;
    console.log(value);

    value = 20;
    console.log(value);
}

test();

তবুও অবাক হচ্ছেন আপনি পাচ্ছেন undefined?


ব্যাখ্যা:

এটি এমন কিছু যা প্রতিটি জাভাস্ক্রিপ্ট প্রোগ্রামার শীঘ্রই বা পরে প্রবেশ করে into সহজ কথায় বলতে গেলে, আপনি যে পরিবর্তনশীল ঘোষণা করেন তা সর্বদা আপনার স্থানীয় বন্ধের শীর্ষে উত্তোলন করা হয়। সুতরাং, প্রথম console.logকলের পরেও আপনি আপনার ভেরিয়েবল ঘোষণা করলেও , এখনও এটি বিবেচনা করা হয়েছিল যেন আপনি তার আগে এটি ঘোষণা করেছিলেন।
তবে, কেবল ঘোষণার অংশটি উত্তোলন করা হচ্ছে; অন্যদিকে, অ্যাসাইনমেন্টটি নয়।

সুতরাং, যখন আপনি প্রথম কল করেছিলেন console.log(value), আপনি স্থানীয়ভাবে ঘোষিত ভেরিয়েবলটি উল্লেখ করছেন, যা এখনও এর কাছে নির্ধারিত কিছুই পায় নি; অত: পর undefined

এখানে আরও একটি উদাহরণ :

var test = 'start';

function end() {
    test = 'end';
    var test = 'local';
}

end();
alert(test);

আপনি কি মনে করেন এটি কি সতর্ক করবে? না, শুধু পড়ুন না, এটি সম্পর্কে চিন্তা করুন। এর মান কী test?

আপনি ব্যতীত অন্য কিছু বললে start, আপনি ভুল ছিল। উপরের কোডটি এর সমতুল্য:

var test = 'start';

function end() {
    var test;
    test = 'end';
    test = 'local';
}

end();
alert(test);

যাতে বিশ্বব্যাপী পরিবর্তনশীল কখনই প্রভাবিত না হয়।

আপনি দেখতে পাচ্ছেন, আপনি যেখানে আপনার পরিবর্তনশীল ঘোষণা রেখেছেন তা বিবেচনা না করেই এটি আপনার স্থানীয় বন্ধের শীর্ষে সর্বদা উত্তোলন করা হয়।


সাইড নোট:

এটি ফাংশনগুলির ক্ষেত্রেও প্রযোজ্য।

কোডের এই অংশটি বিবেচনা করুন :

test("Won't work!");

test = function(text) { alert(text); }

যা আপনাকে একটি রেফারেন্স ত্রুটি দেবে:

আনকড রেফারেন্স এরির: পরীক্ষা সংজ্ঞায়িত করা হয় নি

কোডটির এই অংশটি সূক্ষ্মভাবে কাজ করে বলে এটি অনেকগুলি বিকাশকারীকে ছুঁড়ে দেয় :

test("Works!");

function test(text) { alert(text); }

এই জন্য কারণ, যেমন বিবৃত কারণ নিয়োগ অংশ হয় না উত্তোলন করেন। সুতরাং প্রথম উদাহরণে, কখন test("Won't work!")চালানো হয়েছিল, testভেরিয়েবলটি ইতিমধ্যে ঘোষিত হয়েছে, তবে এখনও এটি কার্য সম্পাদন করতে পারে নি।

দ্বিতীয় উদাহরণে, আমরা ভেরিয়েবল অ্যাসাইনমেন্ট ব্যবহার করছি না। এর পরিবর্তে, আমরা সঠিক ফাংশন ঘোষণা সিনট্যাক্স, যা ব্যবহার করছেন না ফাংশন সম্পূর্ণরূপে উত্তোলন পেতে।


বেন চেরি এ সম্পর্কে একটি দুর্দান্ত নিবন্ধ লিখেছেন, যথাযথভাবে শিরোনামে জাভাস্ক্রিপ্ট স্কোপিং এবং হোস্টিং
এটি পড়ুন। এটি পুরো বিবরণ আপনাকে পুরো ছবি দেবে।


27
এটি একটি ভাল ব্যাখ্যা। তবে, আমি একটি সমাধান মিস করছি যেখানে আপনি কোনও ফাংশনের অভ্যন্তরে গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে পারেন।
ডুকেস0 মি ই

4
@ ডুকেস0 এমই - আপনি কোনও ফাংশনের অভ্যন্তরে সর্বদা গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে পারেন।
জোসেফ সিলবার

4
হ্যাঁ, এবং কেন খোলার পোস্ট থেকে কেস কাজ করছে না এবং এর অপরিজ্ঞাত বলছে? আমি বুঝতে পারি, এটি গ্লোবালের পরিবর্তে স্থানীয় বর্ণ হিসাবে ব্যাখ্যা করা হবে, তবে কীভাবে এটি বিশ্বব্যাপী হবে?
ডুকস0 মি ই

4
বিশ্বব্যাপী পরিবর্তনযোগ্য ব্যবহারের উইন্ডো.ভ্যালু অ্যাক্সেস করতে
ভেঙ্কট রেড্ডি

4
পরিবর্তনশীল উত্তোলনের এই স্টাইলটি কখন কার্যকর করা হয়েছিল? এটি কি সর্বদা জাভাস্ক্রিপ্টে স্ট্যান্ডার্ড হয়েছে?
ডিস্কিম

55

আমি কিছুটা হতাশ হয়েছি যে এখানে সমস্যাটি ব্যাখ্যা করা হয়েছে, তবে কেউই এর সমাধানের প্রস্তাব দেননি। আপনি যদি প্রথমে কোনও অপরিজ্ঞাত স্থানীয় ভের্ক তৈরি না করে ফাংশন স্কোপে কোনও বৈশ্বিক পরিবর্তনশীল অ্যাক্সেস করতে চান তবে ভের হিসাবে উল্লেখ করুনwindow.varName


8
হ্যাঁ, এটি চুষে পায় যে অন্যান্য ছেলেরা কোনও সমাধান প্রস্তাব করেনি কারণ গুগলের ফলাফলের মধ্যে এটিই প্রথম ফলাফল। তারা
জেএস

4
তাত্ত্বিক জ্ঞান এবং শি .. পাওয়ার মধ্যে পার্থক্য Tha এই উত্তরের জন্য ধন্যবাদ!
hansTheFranz

আমার জন্য, এটি একটি ভুল যে আমি যে কোনও কার্যক্রমে যে কোনও জায়গায় বিশ্বব্যাপী নামটি আলাদা করে নিয়েছি। কমপক্ষে বিভ্রান্তির জন্য তোলে। সবচেয়ে খারাপভাবে গুগল অনুসন্ধানের প্রয়োজন হয়। ধন্যবাদ
dcromley

জাভাস্ক্রিপ্ট আমাকে প্রতিদিন অবাক করে দেয় যা কেটে যায়। ধন্যবাদ মানুষ, উত্তরটি সহায়ক ছিল।
রাফ

সমাধানের জন্য ধন্যবাদ, আমি একটি বৈশ্বিক ভার অপরিবর্তিত পরে কেবল এটি সাফারিতেই পেয়েছি। অন্যান্য 'অন্তর্ভুক্ত' ফাইল এবং গ্লোবাল ওয়ারগুলি যেমন 'গুগল' দেখানো হয়েছে, তাই আমি ব্যবহৃত গুগলটি অনুলিপি করেছিলাম: উইন্ডো.globalVarFromJS = window.globalVarFromJS || {}; তারপরে আমি আপনার সমাধানটি পেয়েছি তাই ভেবেছিলাম আমি এটিতে যুক্ত করব।
রাল্ফ হিঙ্কলে 14

10

জাভাস্ক্রিপ্টের ভেরিয়েবলগুলির সর্বদা ফাংশন-বিস্তৃত সুযোগ থাকে। এমনকি যদি সেগুলি ফাংশনের মাঝখানে সংজ্ঞায়িত করা হয় তবে তারা আগে দৃশ্যমান। অনুরূপ ঘটনা ফাংশন উত্তোলন সঙ্গে পালন করা যেতে পারে।

বলা হচ্ছে, প্রথমটি পরিবর্তনশীলটি console.log(value)দেখায় value(অভ্যন্তরীণ যা বাহ্যকে ছায়া দেয় value) তবে এটি এখনও আরম্ভ করা হয়নি। আপনি এটা মনে করতে পারেন হিসাবে যদি সব পরিবর্তনশীল ঘোষণা পরোক্ষভাবে ফাংশন (শুরুতে সরানো হয়েছে না ভিতরের-পূর্বের কোড ব্লক) করার সময় সংজ্ঞা একই স্থানে রেখে করা হয়।

আরো দেখুন


আমি সবসময় সহজ শব্দ পছন্দ করি +1 :)
যশবন্ত

3

একটি গ্লোবাল ভেরিয়েবল আছে value, কিন্তু যখন নিয়ন্ত্রণটি testফাংশনে প্রবেশ করে , তখন আরেকটি valueভেরিয়েবল ঘোষণা করা হয়, যা বিশ্বব্যাপীকে ছায়া দেয়। যেহেতু জাভাস্ক্রিপ্টে ভেরিয়েবল ডিক্লেয়ারেশন ( তবে অ্যাসাইনমেন্ট নয় ) যেগুলি সুযোগ হিসাবে ঘোষণা করা হয়েছে তার শীর্ষে উঠানো হয়েছে:

//value == undefined (global)
var value = 10;
//value == 10 (global)

function test() {
    //value == undefined (local)
    var value = 20;
    //value == 20 (local)
}
//value == 10 (global)

নোট করুন যে ফাংশন ঘোষণার ক্ষেত্রেও এটি একই সত্য, যার অর্থ আপনার কোডটিতে সংজ্ঞায়িত হওয়ার আগে কোনও ফাংশনটি কল করতে পারেন:

test(); //Call the function before it appears in the source
function test() {
    //Do stuff
}

এটাও লক্ষণীয় যে আপনি যখন দুটোকে একটি ফাংশন এক্সপ্রেশনে একত্রিত করেন undefinedতখন অ্যাসাইনমেন্টটি না হওয়া পর্যন্ত চলকটি হয়ে থাকে , সুতরাং যতক্ষণ না ঘটে আপনি ফাংশনটিতে কল করতে পারবেন না:

var test = function() {
    //Do stuff
};
test(); //Have to call the function after the assignment

0
  1. বাইরের ভেরিয়েবলগুলি অ্যাক্সেস রাখার সহজ উপায় (কেবলমাত্র বিশ্বব্যাপী সুযোগ নয়) কার্যাবলীতে একই নামে তাদের পুনরায় ঘোষণা না করার চেষ্টা করা; শুধু সেখানে var ব্যবহার করবেন না । ব্যবহারের সঠিক বর্ণনামূলক নামকরণ নিয়ম পরামর্শ দেওয়া হয়। সেই সঙ্গে, এটা মত নামে ভেরিয়েবল দিয়ে শেষ করা কঠিন হতে হবে মান (এই দৃষ্টিভঙ্গি অগত্যা প্রশ্নে উদাহরণ এর সাথে সম্পর্কিত নয় যেমন এই পরিবর্তনশীল নাম সরলীকরণের জন্য দেওয়া হয়েছে পারে)।

  2. যদি ফাংশনটি অন্য কোথাও পুনরায় ব্যবহার করা হয় এবং তাই বাইরের ভেরিয়েবলটি সেই নতুন প্রসঙ্গে প্রকৃতপক্ষে সংজ্ঞায়িত হওয়ার কোনও গ্যারান্টি নেই তবে এভাল ফাংশনটি ব্যবহার করা যেতে পারে। এটি এই ক্রিয়াকলাপে ধীরে ধীরে তাই কর্মক্ষমতা-দাবীকারী ফাংশনগুলির জন্য এটি প্রস্তাবিত নয়:

    if (typeof variable === "undefined")
    {
        eval("var variable = 'Some value';");
    }
    
  3. আপনি যে বাইরের স্কোপ ভেরিয়েবলটি অ্যাক্সেস করতে চান তা যদি কোনও নামযুক্ত ফাংশনে সংজ্ঞায়িত করা হয় তবে এটি প্রথমে নিজেই ফাংশনটির সাথে সংযুক্ত থাকতে পারে এবং তারপরে কোডের যে কোনও জায়গা থেকে অ্যাক্সেস করা যেতে পারে - এটি গভীরভাবে নেস্টেড ফাংশনগুলি বা ইভেন্ট হ্যান্ডলারের বাইরে থেকে হোক অন্য সব কিছুর. লক্ষ্য করুন যে বৈশিষ্ট্যগুলিতে অ্যাক্সেস করা ধীরে ধীরে এবং আপনার প্রোগ্রামের পদ্ধতিটি পরিবর্তন করা প্রয়োজন, সুতরাং এটি প্রয়োজনীয় না হলে সুপারিশ করা হয় না: ফাংশনগুলির বৈশিষ্ট্য হিসাবে ভেরিয়েবল (জেএসফিডাল) :

    // (the wrapper-binder is only necessary for using variables-properties
    // via "this"instead of the function's name)
    var functionAsImplicitObjectBody = function()
    {
        function someNestedFunction()
        {
            var redefinableVariable = "redefinableVariable's value from someNestedFunction";
            console.log('--> functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
            console.log('--> redefinableVariable: ', redefinableVariable);
        }
        var redefinableVariable = "redefinableVariable's value from someFunctionBody";
        console.log('this.variableAsProperty: ', this.variableAsProperty);
        console.log('functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
        console.log('redefinableVariable: ', redefinableVariable);
        someNestedFunction();
    },
    functionAsImplicitObject = functionAsImplicitObjectBody.bind(functionAsImplicitObjectBody);
    functionAsImplicitObjectBody.variableAsProperty = "variableAsProperty's value, set at time stamp: " + (new Date()).getTime();
    functionAsImplicitObject();
    
    // (spread-like operator "..." provides passing of any number of arguments to
    // the target internal "func" function in as many steps as necessary)
    var functionAsExplicitObject = function(...arguments)
    {
        var functionAsExplicitObjectBody = {
            variableAsProperty: "variableAsProperty's value",
            func: function(argument1, argument2)
            {
                function someNestedFunction()
                {
                    console.log('--> functionAsExplicitObjectBody.variableAsProperty: ',
                        functionAsExplicitObjectBody.variableAsProperty);
                }
                console.log("argument1: ", argument1);
                console.log("argument2: ", argument2);
                console.log("this.variableAsProperty: ", this.variableAsProperty);
                someNestedFunction();
            }    
        };
        return functionAsExplicitObjectBody.func(...arguments);
    };
    functionAsExplicitObject("argument1's value", "argument2's value");
    

0

এমনকি বিশ্বব্যাপী ভেরিয়েবলগুলি নিয়েও আমি একই সমস্যায় পড়ছিলাম। আমার সমস্যা, আমি আবিষ্কার করেছি যে, বিশ্বব্যাপী পরিবর্তনশীল এইচটিএমএল ফাইলগুলির মধ্যে স্থির থাকে না।

<script>
    window.myVar = 'foo';
    window.myVarTwo = 'bar';
</script>
<object type="text/html" data="/myDataSource.html"></object>

আমি লোড হওয়া এইচটিএমএল ফাইলে মাইওয়ার এবং মাইভার্টও দুটি উল্লেখ করার চেষ্টা করেছি, তবে অপরিবর্তিত ত্রুটি পেয়েছি। দীর্ঘ গল্প / দিন সংক্ষিপ্ত, আমি আবিষ্কার করেছি আমি ব্যবহার করে চলকগুলি উল্লেখ করতে পারি:

<!DOCTYPE html>
<html lang="en">
    <!! other stuff here !!>
    <script>

        var myHTMLVar = this.parent.myVar

        /* other stuff here */
    </script>
</html>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.