ডকুমেন্ট.কোয়ারিসিলিেক্টর সমস্ত আসল অ্যারের পরিবর্তে স্ট্যাটিকনোডলিস্টটি কেন ফিরিয়ে দেয়?


103

এটি আমাকে বাগ করেছে যে আমি কেবল document.querySelectorAll(...).map(...)ফায়ারফক্স ৩. in-তেও করতে পারি না এবং আমি এখনও কোনও উত্তর পাই না, তাই আমি ভেবেছিলাম যে আমি এই ব্লগ থেকে এই প্রশ্নটি ক্রস-পোস্ট করব:

http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/

আপনি অ্যারে না পাওয়ার কারিগরি কারণ সম্পর্কে কেউ কি জানেন? অথবা কেন একটি StaticNodeList যা আপনি ব্যবহার করতে পারে এমনভাবে একটি অ্যারে থেকে উত্তরাধিকারী নেই map, concat, ইত্যাদি?

(বিটিডাব্লু যদি এটি কেবল একটি ফাংশন আপনি চান তবে আপনি এর মতো কিছু করতে পারেন NodeList.prototype.map = Array.prototype.map;... তবে আবার, কেন এই কার্যকারিতাটি (ইচ্ছাকৃতভাবে?) প্রথম স্থানে অবরুদ্ধ করা হয়েছে?)


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

উত্তর:


81

আমি বিশ্বাস করি এটি ডাব্লু 3 সি এর দার্শনিক সিদ্ধান্ত decision যেমন করে DOM হয় W3C এর করে DOM [বৈশিষ্ট] নকশা, জাভাস্ক্রিপ্ট নকশা বেশ লম্ব হয় অভিপ্রেত প্ল্যাটফর্ম এবং নিরপেক্ষ ভাষা যাবে।

মত সিদ্ধান্ত " getElementsByFoo()আয় একটি আদেশ NodeList" বা " querySelectorAll()আয় একটি StaticNodeList" হয় খুব ইচ্ছাকৃত, তাই বাস্তবায়নের মত ভাষা নির্ভর বাস্তবায়ন (উপর ভিত্তি করে তাদের ফিরে ডাটা স্ট্রাকচার সমতলতা সম্পর্কে চিন্তা করতে হবে না যে .mapজাভাস্ক্রিপ্ট এবং রুবি ক্ষেত্রে বিন্যাসগুলির প্রাপ্তিসাধ্য ছিলেন, কিন্তু না C # তালিকাসমূহ তে) খুলুন।

W3C এর লক্ষ্য কম: তারা বলবো একটি NodeListএকটি থাকা উচিত কেবলমাত্র .lengthধরনের সম্পত্তি দীর্ঘ স্বাক্ষরবিহীন কারণ তারা যে বাস্তবায়ন করতে পারেন অন্তত সমর্থন বিশ্বাস যে , কিন্তু তারা কি বলবে না স্পষ্টভাবে []সূচক অপারেটর অবস্থানগত উপাদান পেয়ে সমর্থন করার জন্য ওভারলোড করা উচিত, কারণ তারা কার্যকর করতে চায় এমন কিছু দুর্বল ছোট্ট ভাষা স্টিমি করতে চায় getElementsByFoo()না তবে অপারেটর ওভারলোডিংকে সমর্থন করতে পারে না। এটি অনুমানের বেশিরভাগ অংশ জুড়ে একটি প্রচলিত দর্শন।

জন রেসিগ আপনার মতো একই বিকল্পের কথা বলেছেন , এতে তিনি যুক্ত করেছেন :

আমার যুক্তিটি এতটা নয় যে NodeIteratorএটি খুব বেশি ডোম-জাতীয় নয় যা এটি খুব জাভাস্ক্রিপ্ট-জাতীয় নয়। এটি জাভাস্ক্রিপ্ট ভাষায় উপস্থিত বৈশিষ্ট্যগুলির সদ্ব্যবহার করে না এবং এটিকে তার দক্ষতার সর্বোত্তম ব্যবহার করে ...

আমি কিছুটা সহানুভূতি করি। DOM যদি জাভাস্ক্রিপ্ট বৈশিষ্ট্যগুলি মাথায় রেখে বিশেষভাবে লেখা থাকে তবে এটি ব্যবহার করা অনেক কম বিশ্রী এবং আরও স্বজ্ঞাত। একই সাথে আমি ডাব্লু 3 সি এর ডিজাইনের সিদ্ধান্তগুলিও বুঝতে পারি।


ধন্যবাদ, এটি আমাকে পরিস্থিতি অনুধাবন করতে সহায়তা করে।
কেভ

@ কেভ: আপনি কীভাবে StaticNodeListঅ্যারেতে রূপান্তর করতে যাবেন সে প্রশ্নে সেই ব্লগ নিবন্ধ পৃষ্ঠায় আপনার মন্তব্য আমি দেখেছি । আমি @ mck89 এর উত্তরটিকে NodeList/ / StaticNodeListনেটিভ অ্যারেতে রূপান্তর করার উপায় হিসাবে সমর্থন করব তবে এটি একটি জেএসক্রিপ্ট ত্রুটির সাথে IE (8 obv) এ ব্যর্থ হবে, যেহেতু এই বিষয়গুলি হোস্ট করা হয়েছে / "বিশেষ"।
ক্রিসেন্ট ফ্রেশ

সত্য, এ কারণেই আমি তাকে উড়িয়ে দিয়েছি। যদিও অন্য কেউ আমার +1 বাতিল করেছেন। হোস্ট / স্পেশাল বলতে কী বোঝ?
কেভ

1
@ কেভ: হোস্ট করা ভেরিয়েবলগুলি "হোস্ট" পরিবেশ (যেমন একটি ওয়েব ব্রাউজার) দ্বারা সরবরাহিত কোনও পরিবর্তনশীল। উদাহরণস্বরূপ document, windowইত্যাদি ইত্যাদি প্রায়শই এই "বিশেষ" প্রয়োগ করে (উদাহরণস্বরূপ সিওএম অবজেক্টস) যা কখনও কখনও সাধারণ ব্যবহারের সাথে সামঞ্জস্য হয় না, ছোট এবং সূক্ষ্ম উপায়ে যেমন Array.prototype.slice.callবোমা দেওয়ার সময় একটি দেওয়া হয় StaticNodeList;)
ক্রিসেন্ট ফ্রেশ

199

আপনি ES2015 (ES6) স্প্রেড অপারেটরটি ব্যবহার করতে পারেন :

[...document.querySelectorAll('div')]

স্ট্যাটিকনোডলিস্টকে আইটেমির অ্যারেতে রূপান্তর করবে।

এটি কীভাবে ব্যবহার করতে হয় তার একটি উদাহরণ এখানে।

[...document.querySelectorAll('div')].map(x => console.log(x.innerHTML))
<div>Text 1</div>
<div>Text 2</div>


24
আর একটি উপায় হ'ল অ্যারে.ফ্রোম () ব্যবহার করুন :Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
মাইকেল বার্ডিশেভ

42

আমি জানি না কেন এটি অ্যারের পরিবর্তে নোডের তালিকাটি দেয়, কারণ কারণ getElementsByTagName এর মত এটি DOM আপডেট করার সময় ফলাফলটি আপডেট করবে। যাইহোক, ফলাফলকে একটি সাধারণ অ্যারে রূপান্তরিত করার জন্য একটি খুব সহজ পদ্ধতি হ'ল:

Array.prototype.slice.call(document.querySelectorAll(...));

এবং তারপরে আপনি এটি করতে পারেন:

Array.prototype.slice.call(document.querySelectorAll(...)).map(...);

3
আসলে আপনি যখন ডোম আপডেট করেন তখন ফলাফলটি আপডেট হয় না - সুতরাং 'স্থিতিশীল'। ফলাফল আপডেট করতে আপনাকে আবার ম্যানুয়ালি qSA কল করতে হবে। sliceলাইনের জন্য যদিও +1 ।
কেভ

1
হ্যাঁ, কেভের মতো বলেছিলেন: কিউএসএ রেজাল্টটি স্থিতিশীল, getElementsByTagName () রেজাল্টটি গতিশীল।
junas.fi

আইই 8 কেবল মানদণ্ডের মোডে ক্লেইকলেটর সমস্ত () সমর্থন করে
এমবোকিল

13

ক্রিসেন্ট যা বলেছিল তা যুক্ত করার জন্য,

যদি এটি কেবলমাত্র একটি ফাংশন আপনি চান তবে আপনি নোডলিস্ট.প্রোটোটাইপ.ম্যাপ = অ্যারে.প্রোটোটাইপ.ম্যাপের মতো কিছু করতে পারেন

এই না! এটি কাজ করার কোনও গ্যারান্টিযুক্ত নয়।

কোনও জাভাস্ক্রিপ্ট বা ডোম / বিওএম স্ট্যান্ডার্ড নির্দিষ্ট করে না যে NodeList কনস্ট্রাক্টর-ফাংশন এমনকি বৈশ্বিক / windowসম্পত্তি হিসাবে উপস্থিত রয়েছে , বা NodeListফিরে querySelectorAllআসা ব্যক্তিরা এটির উত্তরাধিকারী হবে, বা এর প্রোটোটাইপটি Array.prototype.mapলিখিতযোগ্য , বা ফাংশনটি আসলে নোডলিস্টে কাজ করবে।

কোনও নোডলিস্টকে 'হোস্ট অবজেক্ট' হিসাবে অনুমোদিত (এবং এটি আই, এবং কিছু পুরানো ব্রাউজারে রয়েছে)। Arrayপদ্ধতি কোনো জাভাস্ক্রিপ্ট 'নেটিভ অবজেক্টকে অবশ্যই' যে সাংখ্যিক এবং অনাবৃত কাজ করার অনুমতি দেওয়া হচ্ছে হিসাবে সংজ্ঞায়িত করা হয় lengthবৈশিষ্ট্য, কিন্তু তারা হোস্ট বস্তুর উপর কাজ করা প্রয়োজন করছি না (এবং ইন্টারনেট, তারা হবে না)।

এটি বিরক্তিকর যে আপনি ডিওএম তালিকায় সমস্ত অ্যারে পদ্ধতিগুলি পান না (সেগুলি কেবল স্ট্যাটিকনোডলিস্ট নয়) তবে এর আশেপাশে কোনও নির্ভরযোগ্য উপায় নেই। আপনাকে ম্যানুয়ালি একটি অ্যারেতে ফিরে পেতে প্রতিটি ডিওএম তালিকা রূপান্তর করতে হবে:

Array.fromList= function(list) {
    var array= new Array(list.length);
    for (var i= 0, n= list.length; i<n; i++)
        array[i]= list[i];
    return array;
};

Array.fromList(element.childNodes).forEach(function() {
    ...
});

1
শ্যুট, আমি এটা ভাবিনি। ধন্যবাদ!
কেভ

আমি +1 সম্মত। একটি মন্তব্য, আমার মনে হয় "var অ্যারে ="] "পরিবর্তে" var অ্যারে = নতুন অ্যারে (list.leth) "এর পরিবর্তে কোডটি আরও ছোট করা হবে। তবে আমি আগ্রহী যদি আপনি জানেন তবে এটি করতে সমস্যা হতে পারে।
মার্কো ডেমাইও

@ মার্কোডেমিও: না, কোনও সমস্যা নেই। new Array(n)অ্যারে কতক্ষণ শেষ হতে চলেছে তার জন্য কেবল জেএস টের্পকে একটি ইঙ্গিত দেয়। এটি এটিকে আগাম পরিমাণ পরিমাণ বরাদ্দ দেওয়ার অনুমতি দিতে পারে, যার ফলে স্পিডআপ হওয়ার সম্ভাবনা থাকে কারণ অ্যারে বাড়ার সাথে সাথে কিছু স্মৃতি পুনর্বিবেচনাগুলি এড়ানো যেতে পারে। যদিও এটি আধুনিক ব্রাউজারগুলিতে আসলে সহায়তা করে কিনা আমি জানি না ... আমি সন্দেহ করি যে পরিমাপযোগ্য নয়।
বোবিনস


2

আমি মনে করি আপনি কেবল নিম্নলিখিতটি করতে পারেন

Array.prototype.map.call(document.querySelectorAll(...), function(...){...});

এটি আমার জন্য নিখুঁত কাজ করে


0

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


কেবল এটির মজাদার জন্য, এখানে querySelectorAllনতজানু হয়ে আপনাকে প্রণাম করার জন্য "বাধ্য" করার একটি উপায় এখানে রয়েছে :

Element.prototype.querySelectorAll = (function(QSA){
    return function(){
        return [...QSA.call(this, arguments[0])]
    }
})(Element.prototype.querySelectorAll);

এখন মনিব কে তা দেখিয়ে that ফাংশনটির পুরো পদক্ষেপটি ভাল লাগছে। এখন আমি আরও ভাল কি জানি না, পুরো নতুন নামযুক্ত ফাংশন র‌্যাপার তৈরি করে এবং তারপরে আপনার সমস্ত কোড ব্যবহার করে সেই অদ্ভুত নামটি (বেশ কিছুটা jQuery- স্টাইল) বা উপরের মতো ফাংশনটিকে ওভাররাইড করুন যাতে আপনার বাকী কোডগুলি এখনও সক্ষম হয়ে উঠবে মূল ডিওএম পদ্ধতির নাম ব্যবহার করতে querySelectorAll

  • এই জাতীয় পন্থা উপ-পদ্ধতির সম্ভাব্য ব্যবহারকে সরিয়ে ফেলবে

আমি কোনওভাবেই এটির সুপারিশ করব না, যদি না আপনি সততার সাথে একটি [আপনি কী জানেন] না দেন।

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