ক্রমের জাভাস্ক্রিপ্ট কনসোলটি কী অ্যারেগুলি মূল্যায়ন করতে অলস?


126

আমি কোড দিয়ে শুরু করব:

var s = ["hi"];
console.log(s);
s[0] = "bye";
console.log(s);

সরল, তাই না? এর জবাবে ফায়ারব্যাগ বলেছেন:

["hi"]
["bye"]

আশ্চর্যজনক, তবে Chrome এর জাভাস্ক্রিপ্ট কনসোল (7.0.517.41 বিটা) বলেছেন:

["bye"]
["bye"]

আমি কি কিছু ভুল করেছি, বা Chrome এর জাভাস্ক্রিপ্ট কনসোলটি আমার অ্যারের মূল্যায়ন সম্পর্কে ব্যতিক্রমীভাবে অলস হচ্ছে?

এখানে চিত্র বর্ণনা লিখুন


1
আমি সাফারিতে একই আচরণ পর্যবেক্ষণ করি - সুতরাং এটি সম্ভবত ওয়েবকিট জিনিস। খুব অবাক। আমি এটিকে বাগ বলি।
লি

@ এমপ্লুংজন - এটি সত্য নয়। প্রথম লাইনটি সূচক 0-এ একটি একক উপাদান সহ "সমতল পুরাতন" অ্যারে ঘোষণা করে The তৃতীয় লাইনটি সেই উপাদানটির জন্য একটি নতুন মান নির্ধারণ করে। উভয় ক্ষেত্রেই একটি সাধারণ সংখ্যাযুক্ত সূচক অ্যারে নিয়ে কাজ করা হয়।
লি

যদি এটি কোনও বাগ হয় তবে কেন এই ত্রুটিটি খুঁজে পাওয়া যায় নি এবং স্থির করা আমার বোধগম্য beyond
nonopolarity

7
আমার কাছে এটি একটি বাগের মতো দেখাচ্ছে। লিনাক্স অপেরা এবং ফায়ারফক্সে প্রত্যাশিত ফলাফল প্রদর্শন করে, ক্রোম এবং অন্যান্য ওয়েবকিট-ভিত্তিক ব্রাউজারগুলি তা করে না। আপনি ওয়েবকিট ডেভস
tec

2
মার্চ ২০১ 2016 পর্যন্ত, এই সমস্যাটি আর নেই।
kmonsoor

উত্তর:


69

মন্তব্য, ধন্যবাদ জন্য ধন্যবাদ। আমি একটি বিদ্যমান অসমর্থিত ওয়েবকিট বাগ খুঁজে পেতে সক্ষম হয়েছি যা এই সমস্যাটি ব্যাখ্যা করে: https://bugs.webkit.org/show_bug.cgi?id=35801 (EDIT: এখন ঠিক আছে!)

এটি ঠিক কতটা বাগ এবং এটি স্থিরযোগ্য কিনা তা নিয়ে কিছু বিতর্ক রয়েছে বলে মনে হয়। এটি আমার কাছে খারাপ আচরণ বলে মনে হচ্ছে। এটি আমার কাছে বিশেষত বিরক্তিকর ছিল কারণ কমপক্ষে, ক্রোমে, কোডটি তত্ক্ষণাত কার্যকর হয়ে যাওয়া স্ক্রিপ্টগুলিতে উপস্থিত হয় (পৃষ্ঠাটি লোড হওয়ার আগে), কনসোলটি খোলা থাকলেও, যখনই পৃষ্ঠাটি রিফ্রেশ হয়। কনসোল.লগকে কল করা যখন কনসোলটি এখনও সক্রিয় নেই কেবলমাত্র রেখায় থাকা বস্তুর রেফারেন্সের ফলস্বরূপ, কনসোল আউটপুট নয় not সুতরাং, কনসোল প্রস্তুত না হওয়া অবধি অ্যারে (বা কোনও বস্তু) মূল্যায়ন করা হবে না। এটি সত্যই অলস মূল্যায়নের একটি ঘটনা।

তবে আপনার কোডে এটি এড়ানোর একটি সহজ উপায় রয়েছে:

var s = ["hi"];
console.log(s.toString());
s[0] = "bye";
console.log(s.toString());

টু স্ট্রিংকে কল করে আপনি মেমরিতে এমন একটি প্রতিনিধিত্ব তৈরি করেন যা নিম্নলিখিত বিবৃতিগুলির দ্বারা পরিবর্তন করা হবে না, এটি কনসোল প্রস্তুত হওয়ার পরে পড়বে। কনসোল আউটপুট সরাসরি বস্তুটি পাস করার থেকে কিছুটা আলাদা তবে এটি গ্রহণযোগ্য বলে মনে হয়:

hi
bye

1
প্রকৃতপক্ষে, সহযোগী অ্যারে বা অন্যান্য অবজেক্টের সাথে, এটি একটি আসল সমস্যা হতে পারে, যেহেতু টস্ট্রস্ট্রিংয়ের কোনও মূল্যই উত্পাদন করে না। সাধারণভাবে অবজেক্টগুলির জন্য কি সহজ কাজ?
এরিক মিক্কেলসেন

29
JSON.stringify ()
ড্র্যাটন

1
ওয়েবকিট এর জন্য কয়েক মাস আগে একটি প্যাচ অবতরণ করেছে
antony.trupe

1
এটি করুন: কনসোল.লগ (JSON.parse (JSON.stringify (গুলি));
লি কমস্টক

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

21

এরিকের ব্যাখ্যা থেকে, এটি console.log()সারিবদ্ধ হওয়ার কারণে , এবং এটি অ্যারের (বা অবজেক্ট) এর পরবর্তী মান মুদ্রণ করে।

এখানে 5 টি সমাধান থাকতে পারে:

1. arr.toString()   // not well for [1,[2,3]] as it shows 1,2,3
2. arr.join()       // same as above
3. arr.slice(0)     // a new array is created, but if arr is [1, 2, arr2, 3] 
                    //   and arr2 changes, then later value might be shown
4. arr.concat()     // a new array is created, but same issue as slice(0)
5. JSON.stringify(arr)  // works well as it takes a snapshot of the whole array 
                        //   or object, and the format shows the exact structure

7

আপনি এখানে একটি অ্যারের ক্লোন করতে পারেন Array#slice:

console.log(s); // ["bye"], i.e. incorrect
console.log(s.slice()); // ["hi"], i.e. correct

এর পরিবর্তে আপনি যে ফাংশনটি ব্যবহার করতে পারেন console.logতাতে এই সমস্যাটি নেই:

console.logShallowCopy = function () {
    function slicedIfArray(arg) {
        return Array.isArray(arg) ? arg.slice() : arg;
    }

    var argsSnapshot = Array.prototype.map.call(arguments, slicedIfArray);
    return console.log.apply(console, argsSnapshot);
};

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

console.logSanitizedCopy = function () {
    var args = Array.prototype.slice.call(arguments);
    var sanitizedArgs = JSON.parse(JSON.stringify(args));

    return console.log.apply(console, sanitizedArgs);
};

এই সমস্ত পদ্ধতিগুলি স্পষ্টতই খুব ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে স্বাভাবিক console.log


2

এটি ওয়েবকিটে প্যাচ করা হয়েছে, তবে প্রতিক্রিয়া কাঠামোটি ব্যবহার করার সময় কিছু পরিস্থিতিতে আমার জন্য এটি ঘটে, অন্যদের পরামর্শ মতো আপনার যদি ঠিক তেমন সমস্যা হয় তবে:

console.log(JSON.stringify(the_array));

2
নিশ্চিত করতে পারেন. ReactSynthetEvents লগ আউট করার চেষ্টা করার সময় এটি আক্ষরিক অর্থেই সবচেয়ে খারাপ। এমনকি একটি JSON.parse(JSON.stringify(event))সঠিক গভীরতা / নির্ভুলতা পায় না। সঠিক অন্তর্দৃষ্টি পাওয়ার জন্য আমি খুঁজে পেয়েছি একমাত্র আসল সমাধান ডিবাগার স্টেটমেন্ট।
সিএসটাম্ফ

1

এটি ইতিমধ্যে উত্তর দেওয়া হয়েছে, তবে আমি আমার উত্তর যেভাবেই ফেলে দেব। আমি একটি সাধারণ কনসোল মোড়ক কার্যকর করেছি যা এই সমস্যাটিতে ভুগছে না। JQuery প্রয়োজন।

এটা শুধুমাত্র প্রয়োগ log, warnএবং errorপদ্ধতি, আপনি অনুক্রমে আরো কিছু যোগ করার জন্য এটি একটি নিয়মিত সঙ্গে বিনিমেয় হতে এটাতে ভুগতে হবে console

var fixedConsole;
(function($) {
    var _freezeOne = function(arg) {
        if (typeof arg === 'object') {
            return $.extend(true, {}, arg);
        } else {
            return arg;
        }
    };
    var _freezeAll = function(args) {
        var frozen = [];
        for (var i=0; i<args.length; i++) {
            frozen.push(_freezeOne(args[i]));
        }
        return frozen;
    };
    fixedConsole = {
        log: function() { console.log.apply(console, _freezeAll(arguments)); },
        warn: function() { console.warn.apply(console, _freezeAll(arguments)); },
        error: function() { console.error.apply(console, _freezeAll(arguments)); }
    };
})(jQuery);

0

দেখে মনে হচ্ছে ক্রোম তার "প্রাক সংকলন" পর্যায়ে "এস" এর যে কোনও উদাহরণকে প্রকৃত অ্যারেতে নির্দেশকের সাহায্যে প্রতিস্থাপন করছে ।

এর চারপাশে এক উপায় হ'ল অ্যারে ক্লোন করে, পরিবর্তে তাজা অনুলিপিটি লগইন করুন:

var s = ["hi"];
console.log(CloneArray(s));
s[0] = "bye";
console.log(CloneArray(s));

function CloneArray(array)
{
    var clone = new Array();
    for (var i = 0; i < array.length; i++)
        clone[clone.length] = array[i];
    return clone;
}

এটি ভাল, তবে এটি অগভীর অনুলিপি হওয়ায় আরও একটি সূক্ষ্ম সমস্যার সম্ভাবনা রয়েছে। এবং অ্যারে নয় এমন জিনিসগুলির কী হবে? (এগুলিই এখন আসল সমস্যা)) আপনি "প্রাক কম্পাইল" সম্পর্কে যা বলছেন তা সঠিক বলে আমি মনে করি না। এছাড়াও কোডটিতে একটি ত্রুটি রয়েছে: ক্লোন [ক্লোন. দৈর্ঘ্য] ক্লোন হওয়া উচিত [i]।
এরিক মিকেলসেন

কোনও ত্রুটি নেই, আমি এটি কার্যকর করেছি এবং এটি ঠিক আছে। ক্লোন [ক্লোন. দৈর্ঘ্য] হুবহু ক্লোন [i] এর মতো হয়, যেমন অ্যারে 0 দৈর্ঘ্যের সাথে শুরু হয় এবং লুপ পুনরুক্তিকারী "i "ও হয়। যাইহোক, জটিল বস্তুর সাথে এটি কীভাবে আচরণ করবে তা নিশ্চিত নন তবে আইএমও এটি চেষ্টা করার মতো। যেমনটি আমি বলেছিলাম, এটি কোনও সমাধান নয়, এটি সমস্যার চারপাশের উপায় ..
শ্যাডো উইজার্ড ইয়ার ফর ইয়ার ফর ইউ

@ শ্যাডো উইজার্ড: ভাল পয়েন্ট: ক্লোন. দৈর্ঘ্য সর্বদা i এর সমান হবে। এটি বস্তুর জন্য কাজ করবে না। সম্ভবত "প্রত্যেকের জন্য" দিয়ে একটি সমাধান রয়েছে।
এরিক মিক্কেলসেন

আপনি কি বোঝাতে চাইছেন? var s = {পরম 1: "হাই", প্যারাম 2: "কেমন আছেন?" }; যদি তাই হয় তবে আমি ঠিক পরীক্ষা করেছি এবং যখন আপনার এস ["param1"] = "বাই"; এটি প্রত্যাশার মতো ঠিকঠাক কাজ করছে। আপনি কি "এটি বস্তুর জন্য কাজ করবে না" উদাহরণ পোস্ট করতে পারেন? আমি দেখতে পাবো এবং সেইটিকে আরোহণের চেষ্টা করব।
শেডো উইজার্ড আপনার পক্ষে কান

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

0

এখন পর্যন্ত সংক্ষিপ্ত সমাধান হ'ল লগিংয়ের সময় হিসাবে সংরক্ষণ করা মানগুলির একটি ক্লোন পেতে অ্যারে বা অবজেক্ট স্প্রেড সিনট্যাক্স ব্যবহার করা, যেমন:

console.log({...myObject});
console.log([...myArray]);

তবে এটি অগভীর অনুলিপি হিসাবে সতর্ক হওয়া উচিত, সুতরাং যে কোনও গভীর নেস্টেড অ-আদিম মানগুলি ক্লোন করা হবে না এবং এটি কনসোলে তাদের পরিবর্তিত অবস্থায় প্রদর্শিত হবে

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