জাভাস্ক্রিপ্ট "নতুন অ্যারে (এন)" এবং "অ্যারে.প্রোটোটাইপ.ম্যাপ" অদ্ভুততা


209

আমি এটি ফায়ারফক্স -৩..7..7 / ফায়ারবগ -১.৩.৩ এবং ফায়ারফক্স -৩.6.১6 / ফায়ারব্যাগ -১.6.২ এ পর্যবেক্ষণ করেছি

আমি যখন ফায়ারব্যাগ জ্বালিয়ে দেই:

var x = new Array(3)
console.log(x) 
// [undefined, undefined, undefined]

var y = [undefined, undefined, undefined]
console.log(y) 
// [undefined, undefined, undefined]

console.log( x.constructor == y.constructor) // true

console.log( 
  x.map(function() { return 0; })
)
// [undefined, undefined, undefined]

console.log(
  y.map(function() { return 0; })
)
// [0, 0, 0]

এখানে কি হচ্ছে? এটি কি কোনও বাগ, বা কীভাবে ব্যবহার করব তা আমি ভুল বোঝাবুঝি করছি new Array(3)?


অ্যারে আক্ষরিক স্বরলিপি থেকে আপনি একই ফলাফল পান না। আমি এখনও 0 এর পরিবর্তে অপরিজ্ঞাত হয়ে পড়েছি তবে আমি 0 ফলাফলটি পেয়েছি যদি আমি এর মতো কিছু সেট করি তবে আমি var y = x.map(function(){return 0; });নতুন অ্যারে () পদ্ধতি এবং অ্যারে আক্ষরিক উভয়ের জন্যই এটি পেয়েছি। আমি ফায়ারফক্স 4 এবং ক্রোমে পরীক্ষা করেছি।
রাসেলউরেস্তি

এছাড়াও ক্রোমে
ফাঁসানো হয়েছে

উত্তর:


125

এটি প্রদর্শিত হয় প্রথম উদাহরণ

x = new Array(3);

অপরিবর্তিত পয়েন্টার সহ একটি অ্যারে তৈরি করে।

এবং দ্বিতীয়টি 3 অপরিবর্তিত বস্তুগুলিতে পয়েন্টার সহ একটি অ্যারে তৈরি করে, এক্ষেত্রে পয়েন্টারগুলি তাদের স্ব-পরিজ্ঞাত হয় না, কেবলমাত্র তারা যে বস্তুগুলিতে নির্দেশ করে।

y = [undefined, undefined, undefined]
// The following is not equivalent to the above, it's the same as new Array(3)
y = [,,,];

অ্যারেতে থাকা অবজেক্টের প্রসঙ্গে মানচিত্রটি চালিত হওয়ার সাথে সাথে আমি বিশ্বাস করি যে প্রথম মানচিত্রটি দ্বিতীয় চালানো পরিচালনা করার সময় ফাংশনটি চালাতে মোটেই ব্যর্থ হয়।


86
থেকে এমডিসি (জোর খনি): " mapএকটি অ্যারের প্রতিটি উপাদান, যাতে একবার একটি প্রদত্ত কলব্যাক ফাংশন কল, এবং ফলাফল থেকে একটি নতুন অ্যারে নির্মান। callbackশুধুমাত্র অ্যারে যা মান নির্ধারিত করেছেন ইনডেক্স জন্য প্রার্থনা করা হয় এটা প্রার্থনা করা হয় না মুছে ফেলা হয়েছে এমন বা সূচকগুলির জন্য যা কখনও মূল্য নির্ধারণ করা হয়নি for " এই ক্ষেত্রে, xএর মানগুলি স্পষ্টভাবে মান নির্ধারণ করে না, যেখানে yএটি নির্ধারিত হলেও এটি মান হলেও undefined
মার্টিজন

2
তাহলে এটি কি জাভাস্ক্রিপ্ট ব্যর্থ হচ্ছে যে এটি অনির্ধারিত পয়েন্টার, বা অপরিবর্তিত পয়েন্টার কিনা তা যাচাই করা অসম্ভব? মানে (new Array(1))[0] === [undefined][0]
ট্রেভর নরিস

ওয়েল, অপরিজ্ঞাতকৃত একটি অ্যারে পয়েন্টারগুলির অ্যারে থেকে অপরিজ্ঞাপিত অবজেক্টগুলিতে পৃথক। অপরিজ্ঞানের একটি অ্যারে নাল মানগুলির একটি অ্যারের মতো হবে, [নাল, নাল, নাল] অপরিজ্ঞায়িত পয়েন্টারের একটি অ্যারে [343423, 343424, 343425] নাল এবং নাল এবং শূন্যের মতো হবে। দ্বিতীয় সমাধানগুলিতে সত্যিকারের পয়েন্টারগুলি মেমোরি অ্যাড্রেসের দিকে নির্দেশ করে যখন প্রথমটি কোথাও নির্দেশ করে না। যদি এটি জেএসের ব্যর্থতা হয় তবে সম্ভবত এটি আলোচনার বিষয়, তবে এখানে নয়;)
ডেভিড মার্টেনসন

4
@TrevNorris, আপনি সহজেই পরীক্ষা করতে পারেন যে hasOwnProperty, যদি না hasOwnPropertyনিজেই একটি বাগ আছে: (new Array(1)).hasOwnProperty(0) === falseএবং [undefined].hasOwnProperty(0) === true। বাস্তবে, আপনি in: 0 in [undefined] === trueএবং এর সাথে ঠিক একই কাজটি করতে পারেন 0 in new Array(0) === false
squid314

3
জাভাস্ক্রিপ্টে "অপরিজ্ঞাত পয়েন্টার" সম্পর্কে কথা বলা বিষয়টি বিভ্রান্ত করে। আপনি যে শব্দটির সন্ধান করছেন তা হ'ল এলিজেন্সসx = new Array(3);সমান x = [,,,];, না x = [undefined, undefined, undefined]
ম্যাট ক্যান্টর

118

আমার একটি টাস্ক ছিল যা আমি কেবল অ্যারের দৈর্ঘ্য জানতাম এবং আইটেমগুলিকে রূপান্তর করতে হবে। আমি এরকম কিছু করতে চেয়েছিলাম:

let arr = new Array(10).map((val,idx) => idx);

এটির মতো দ্রুত অ্যারে তৈরি করতে:

[0,1,2,3,4,5,6,7,8,9]

তবে এটি কার্যকর হয়নি কারণ: (জোনাথন লোনস্কির উত্তর উপরে কয়েকটি উত্তর দেখুন)

সমাধানটি অ্যারে.প্রোটোটাইপ.ফিল () ব্যবহার করে কোনও মান (এমনকি অপরিজ্ঞাতকৃত ) দিয়ে অ্যারে আইটেমগুলি পূরণ করা হতে পারে

let arr = new Array(10).fill(undefined).map((val,idx) => idx);

হালনাগাদ

আর একটি সমাধান হতে পারে:

let arr = Array.apply(null, Array(10)).map((val, idx) => idx);

console.log(Array.apply(null, Array(10)).map((val, idx) => idx));


28
আপনি টুকুনি রাষ্ট্র প্রয়োজন হবে না undefinedযে .fill(), এর খুব সামান্য কোড সরল পদ্ধতিlet arr = new Array(10).fill().map((val,idx) => idx);
Yann Eves

একইভাবে আপনি ব্যবহার করতে পারেনArray.from(Array(10))

84

ES6 এর সাহায্যে আপনি [...Array(10)].map((a, b) => a)তাড়াতাড়ি এবং সহজেই করতে পারেন !


9
প্রাক ES6 আপনি ব্যবহার করতে পারেন new Array(10).fill()। একই ফলাফল[...Array(10)]
মলম্বি

বড় অ্যারে দিয়ে বিস্তার সিনট্যাক্স সমস্যা সৃষ্টি তাই এটি এড়াতে ভালো

বা[...Array(10).keys()]
চুংজুওয়ালা


19

অ্যারেগুলি আলাদা। পার্থক্যটি হ'ল new Array(3)তিনটি দৈর্ঘ্যের সাহায্যে অ্যারে তৈরি করে তবে কোনও বৈশিষ্ট্য নেই, যখন [undefined, undefined, undefined]তিন এবং তিনটি বৈশিষ্ট্যের দৈর্ঘ্য সহ "0", "1" এবং "2" নামে একটি অ্যারে তৈরি করে, যার প্রতিটি মূল্য রয়েছে undefinedinঅপারেটরটি ব্যবহার করে আপনি পার্থক্যটি দেখতে পাবেন :

"0" in new Array(3); // false
"0" in [undefined, undefined, undefined]; // true

এটি কিছুটা বিভ্রান্তিকর সত্য থেকে উদ্ভূত হয়েছে যে আপনি যদি জাভাস্ক্রিপ্টে কোনও নেটিভ অবজেক্টের অস্তিত্বহীন সম্পত্তির মূল্য পাওয়ার চেষ্টা করেন তবে এটি ফিরে আসে undefined(কোনও ত্রুটি ছোঁড়ার পরিবর্তে ঘটবে, যখন আপনি অস্তিত্বহীন ভেরিয়েবলটি উল্লেখ করার চেষ্টা করবেন) ), যা সম্পত্তিটি পূর্বে স্পষ্টভাবে সেট করা থাকলে আপনি যা পান তার সমান undefined


17

এর জন্য এমডিসি পৃষ্ঠা থেকে map:

[...] callbackকেবলমাত্র নির্ধারিত অ্যারের সূচকগুলির জন্য অনুরোধ করা হয়; [...]

[undefined]প্রকৃতপক্ষে সূচক (এস)-তে সেটার প্রয়োগ করে যাতে mapপুনরাবৃত্তি হয়, যেখানে new Array(1)সূচীটি (এস) শুরু করে undefinedতাই mapএটির এড়াতে কোনও ডিফল্ট মান থাকে।

আমি বিশ্বাস করি সমস্ত পুনরাবৃত্তি পদ্ধতির ক্ষেত্রে এটি একই ।


8

ইসমাস্ক্রিপ্টে 6th ষ্ঠ সংস্করণের স্পেসিফিকেশন।

new Array(3)শুধুমাত্র সম্পত্তি সংজ্ঞায়িত করুন lengthএবং সূচক বৈশিষ্ট্যগুলি যেমন সংজ্ঞায়িত করবেন না {length: 3}। দেখতে https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len ধাপ 9।

[undefined, undefined, undefined]সূচক বৈশিষ্ট্য এবং দৈর্ঘ্যের সম্পত্তি যেমন পছন্দ করবে {0: undefined, 1: undefined, 2: undefined, length: 3}। দেখতে https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulation ElementList পদক্ষেপ 5।

পদ্ধতি map, every, some, forEach, slice, reduce, reduceRight, filterএরে দ্বারা সূচক সম্পত্তি পরীক্ষা হবে HasPropertyঅভ্যন্তরীণ পদ্ধতি, তাই new Array(3).map(v => 1)হবে না কলব্যাক ডাকা।

আরও তথ্যের জন্য https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map দেখুন

কিভাবে ঠিক করবো?

let a = new Array(3);
a.join('.').split('.').map(v => 1);

let a = new Array(3);
a.fill(1);

let a = new Array(3);
a.fill(undefined).map(v => 1);

let a = new Array(3);
[...a].map(v => 1);

খুব সুন্দর ব্যাখ্যা।
ধীররাজ রাও

7

আমি মনে করি এটি ব্যাখ্যা করার সর্বোত্তম উপায় হ'ল ক্রোম কীভাবে এটি পরিচালনা করে।

>>> x = new Array(3)
[]
>>> x.length
3

সুতরাং আসলে যা ঘটছে তা হ'ল নতুন অ্যারে () একটি খালি অ্যারে ফিরিয়ে দিচ্ছে যার দৈর্ঘ্য 3, তবে কোনও মান নেই। অতএব, যখন আপনি চালাতে x.mapএকটি উপর টেকনিক্যালি খালি অ্যারে, সেখানে সেট হওয়ার কিছুই নেই।

ফায়ারফক্সের undefinedকোনও মূল্য নেই যদিও এই শূন্য স্লটগুলি কেবল 'পূরণ করে' ।

আমি মনে করি না এটি স্পষ্টতই একটি বাগ, যা চলছে তা উপস্থাপনের একটি দরিদ্র উপায়। আমি মনে করি Chrome এর "আরও সঠিক" কারণ এটি দেখায় যে অ্যারেতে আসলে কিছুই নেই।


4

শুধু এই মধ্যে দৌড়ে। এটি নিশ্চিতভাবে ব্যবহার করতে সক্ষম হবে সুবিধাজনক Array(n).map

Array(3) মোটামুটি ফলন {length: 3}

[undefined, undefined, undefined]সৃষ্টি সংখ্যাযুক্ত বৈশিষ্ট্য:
{0: undefined, 1: undefined, 2: undefined, length: 3}

মানচিত্র () বাস্তবায়ন কেবল নির্ধারিত বৈশিষ্ট্যগুলিতে কাজ করে।


3

একটি বাগ না। অ্যারে কনস্ট্রাক্টরকে এভাবে কাজের জন্য সংজ্ঞায়িত করা হয়।

এমডিসি থেকে:

আপনি যখন অ্যারে কনস্ট্রাক্টরের সাথে একটি একক সংখ্যক প্যারামিটার নির্দিষ্ট করেন, আপনি অ্যারের প্রাথমিক দৈর্ঘ্য নির্দিষ্ট করেন। নিম্নলিখিত কোডটি পাঁচটি উপাদানের একটি অ্যারে তৈরি করে:

var billingMethod = new Array(5);

অ্যারে কনস্ট্রাক্টরের আচরণটি একক প্যারামিটারের একটি সংখ্যা কিনা তার উপর নির্ভর করে।

.map()পদ্ধতিটি কেবল অ্যারের স্পষ্টভাবে নির্ধারিত মান ছিল এর পুনরাবৃত্তির উপাদানের মধ্যে অন্তর্ভুক্ত করা হয়েছে। এমনকি একটি সুস্পষ্ট নিয়োগের undefinedকারণে মানকে পুনরাবৃত্তিতে অন্তর্ভুক্তির জন্য যোগ্য হিসাবে বিবেচনা করবে। এটি অদ্ভুত বলে মনে হচ্ছে তবে এটি মূলত কোনও জিনিসের স্পষ্ট undefinedসম্পত্তি এবং নিখোঁজ সম্পত্তির মধ্যে পার্থক্য :

var x = { }, y = { z: undefined };
if (x.z === y.z) // true

অবজেক্টটির x"z" নামক কোনও সম্পত্তি yনেই এবং অবজেক্টটি আছে। তবে উভয় ক্ষেত্রেই দেখা যায় যে সম্পত্তিটির "মান" undefined। একটি অ্যারেতে, পরিস্থিতিটি একই রকম: এর মানটি lengthশূন্য থেকে সমস্ত উপাদানকে স্পষ্টতই একটি মূল্য নির্ধারণ করে length - 1.map()ফাংশন তাই কিছু (কলব্যাক কল হবে না) যখন একটি অ্যারের সদ্য এরে কন্সট্রাকটর এবং একটি সাংখ্যিক যুক্তি দিয়ে নির্মিত আহ্বান করে দেবে না।


এটি সংশোধন করা হবে? এটি এমন তিনটি উপাদানের অ্যারে উত্পাদন করার জন্য তৈরি করা হয়েছে যা সর্বদা undefinedচিরকাল থাকবে?
অরবিটে মার্চীনতা রেস

হ্যাঁ, "চিরকাল" অংশ ব্যতীত এটি সঠিক। আপনি পরবর্তীকালে উপাদানগুলিকে মান নির্ধারণ করতে পারেন।
পয়েন্টি

3
এজন্য আপনার x = []পরিবর্তে ব্যবহার করা উচিতx = new Array()
রকেট হাজমত

3

আপনি যদি মানগুলি সহ সহজেই কোনও অ্যারে পূরণ করার জন্য এটি করেন তবে ব্রাউজার সমর্থনজনিত কারণে ফিল ব্যবহার করতে পারবেন না এবং সত্যই কোনও লুপ করতে চান না, আপনি এটিও করতে পারেন x = new Array(3).join(".").split(".").map(...যা আপনাকে খালি একটি অ্যারে দেবে স্ট্রিং।

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


1

যেহেতু প্রশ্নটি কেন, এটি জেএসকে কীভাবে ডিজাইন করা হয়েছিল তার সাথে সম্পর্কযুক্ত।

এই আচরণটি ব্যাখ্যা করার জন্য 2 টি মূল কারণ আমি ভাবতে পারি:

  • পারফরম্যান্স: দেওয়া হয়েছে x = 10000এবং new Array(x)নির্মাণকারীর পক্ষে 0 থেকে 10000 পর্যন্ত undefinedমানগুলি সহ অ্যারে পূরণ করা লুপিং এড়ানো বুদ্ধিমানের কাজ ।

  • পরোক্ষভাবে "undefined": দাও a = [undefined, undefined]এবং b = new Array(2), a[1]এবং b[1]উভয় প্রত্যাবর্তিত হবে undefined, কিন্তু a[8]এবং b[8]এছাড়াও ফিরে আসবে undefinedএমনকি যদি তারা সীমার শেষ হয়ে গেছে।

শেষ পর্যন্ত, স্বরলিপিটি ঘোষিত না হওয়ার কারণে মানগুলি empty x 3দীর্ঘায়িত তালিকা নির্ধারণ এবং প্রদর্শন এড়াতে স্বরলিপিটি একটি শর্টকাট ।undefinedundefined

দ্রষ্টব্য: প্রদত্ত অ্যারে a = [0]এবং a[9] = 9, console.log(a)ফিরে আসবে (10) [0, empty x 8, 9], স্পষ্টভাবে ঘোষিত দুটি মানের মধ্যে পার্থক্য ফিরিয়ে দিয়ে স্বয়ংক্রিয়ভাবে শূন্যস্থান পূরণ করবে।


1

অন্যান্য উত্তরে পুঙ্খানুপুঙ্খভাবে ব্যাখ্যা করার কারণে, Array(n).mapকাজ করে না। তবে, ES2015 এ Array.fromএকটি মানচিত্রের ফাংশন গ্রহণ করে:

let array1 = Array.from(Array(5), (_, i) => i + 1)
console.log('array1', JSON.stringify(array1)) // 1,2,3,4,5

let array2 = Array.from({length: 5}, (_, i) => (i + 1) * 2)
console.log('array2', JSON.stringify(array2)) // 2,4,6,8,10


0

কার্যকারণ হিসাবে এখানে একটি সাধারণ ইউটিলিটি পদ্ধতি:

সরল মানচিত্রের জন্য

function mapFor(toExclusive, callback) {
    callback = callback || function(){};
    var arr = [];
    for (var i = 0; i < toExclusive; i++) {
        arr.push(callback(i));
    }
    return arr;
};

var arr = mapFor(3, function(i){ return i; });
console.log(arr); // [0, 1, 2]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

সম্পূর্ণ উদাহরণ

এখানে আরও সম্পূর্ণ উদাহরণ রয়েছে (স্যানিটি চেক সহ) যা একটি startingচ্ছিক সূচনা সূচক নির্দিষ্ট করার অনুমতি দেয়:

function mapFor() {
var from, toExclusive, callback;
if (arguments.length == 3) {
    from = arguments[0];
    toExclusive = arguments[1];
    callback = arguments[2];
} else if (arguments.length == 2) {
    if (typeof arguments[1] === 'function') {
        from = 0;
        toExclusive = arguments[0];
        callback = arguments[1];
    } else {
        from = arguments[0];
        toExclusive = arguments[1];
    }
} else if (arguments.length == 1) {
    from = 0;
    toExclusive = arguments[0];
}

callback = callback || function () {};

var arr = [];
for (; from < toExclusive; from++) {
    arr.push(callback(from));
}
return arr;
}

var arr = mapFor(1, 3, function (i) { return i; });
console.log(arr); // [1, 2]
arr = mapFor(1, 3);
console.log(arr); // [undefined, undefined]
arr = mapFor(3);
console.log(arr); // [undefined, undefined, undefined]

গণনা ডাউন

কলব্যাকটিতে পাস করা সূচিটি ম্যানিপুলেট করা পিছনের দিকে গণনা করতে দেয়:

var count = 3;
var arr = arrayUtil.mapFor(count, function (i) {
    return count - 1 - i;
});
// arr = [2, 1, 0]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.