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


251

পূর্বে এখানে উত্তর দেওয়া প্রশ্নগুলি বলেছিল যে এটি ছিল দ্রুততম উপায়:

//nl is a NodeList
var arr = Array.prototype.slice.call(nl);

আমার ব্রাউজারে বেঞ্চমার্কিংয়ে আমি দেখতে পেয়েছি যে এটি এর চেয়ে 3 গুণ বেশি ধীর:

var arr = [];
for(var i = 0, n; n = nl[i]; ++i) arr.push(n);

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

এটি কি আমার ব্রাউজারে ক্রিক (ক্রোমিয়াম 6)? না কোন দ্রুততর উপায় আছে?

সম্পাদনা: যে কেউ যত্ন করে তাদের জন্য আমি নিম্নলিখিতটি স্থির করেছিলাম (যা আমি পরীক্ষিত প্রতিটি ব্রাউজারে সবচেয়ে দ্রুত বলে মনে হয়):

//nl is a NodeList
var l = []; // Will hold the array of Node's
for(var i = 0, ll = nl.length; i != ll; l.push(nl[i++]));

সম্পাদনা 2: আমি আরও দ্রুততর একটি উপায় খুঁজে পেয়েছি

// nl is the nodelist
var arr = [];
for(var i = nl.length; i--; arr.unshift(nl[i]));

2
arr[arr.length] = nl[i];arr.push(nl[i]);যেহেতু এটি কোনও ফাংশন কল এড়ায় তার চেয়ে দ্রুত হতে পারে ।
Luc125

9
এই jsPerf পৃষ্ঠাটি এই পৃষ্ঠাতে সব উত্তর অবগত থাকার হয় jsperf.com/nodelist-to-array/27
পলান্ন

দয়া করে নোট করুন যে "EDIT2: আমি একটি দ্রুত পথ খুঁজে পেয়েছি" আইই 8-তে 92% ধীর।
ক্যামিলো মার্টিন

2
যেহেতু আপনি ইতিমধ্যে জানেন জানি তুমি কত নোড আছে:var i = nl.length, arr = new Array(i); for(; i--; arr[i] = nl[i]);
মেমস

@ লুক 125 এটি ব্রাউজারের উপর নির্ভর করে, যেহেতু পুশ বাস্তবায়ন অনুকূলিত হতে পারে, আমি ক্রোম সম্পর্কে ভাবছি কারণ ভি 8 এই ধরণের স্টাফের সাথে ভাল।
axelduch

উত্তর:


197

দ্বিতীয়টি কিছু ব্রাউজারে দ্রুত হতে থাকে, তবে মূল বিষয়টি হ'ল আপনাকে এটি ব্যবহার করতে হবে কারণ প্রথমটি কেবল ক্রস ব্রাউজার নয়। যদিও দ্য টাইমস তারা চ্যাঞ্জিন '

@ কংগ্যাক্স ( IE 9 পূর্বরূপ )

অ্যারে.প্রোটোটাইপ.স্লাইস এখন নির্দিষ্ট হোস্ট অবজেক্টগুলিকে (যেমন নোডলিস্টের) অ্যারে রূপান্তর করতে পারে - এমন কিছু যা আধুনিক ব্রাউজারগুলির বেশিরভাগ সময় বেশিরভাগ ক্ষেত্রে করতে সক্ষম হয়েছিল।

উদাহরণ:

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

??? উভয়ই ক্রস-ব্রাউজারের সাথে সামঞ্জস্যপূর্ণ - জাভাস্ক্রিপ্ট (এটি যদি ECMAscript স্পেসের সাথে সামঞ্জস্যপূর্ণ বলে দাবি করে) তবে জাভাস্ক্রিপ্ট; অ্যারে, প্রোটোটাইপ, স্লাইস এবং কল হ'ল মূল ভাষা + অবজেক্টের ধরণের বৈশিষ্ট্য।
জেসন এস

6
তবে এগুলি আইডিতে নোডলিস্টে ব্যবহার করা যাবে না (আমি জানি এটি চুষে গেছে, তবে ও আমার আপডেট দেখুন)
gblazex

9
নোডলিস্টগুলি ভাষার অংশ না হওয়ায় এগুলি ডিওএম এপিআইয়ের অংশ, যা বগি / অবিশ্বাস্যরূপে বিশেষত আইই
গ্যাব্লেজেক্স

3
আপনি যদি88 অ্যাকাউন্টে নেন তবে অ্যারে.প্রোটোটাইপ.স্লাইস ক্রস ব্রাউজার নয়।
লাজোস মেসারোস

1
হ্যাঁ, আমার উত্তরটি মূলত সে সম্পর্কেই ছিল :) যদিও এটি আজকের (২০১৫) এর চেয়ে ২০১০ সালে বেশি প্রাসঙ্গিক ছিল।
gblazex

224

ES6 সহ, আমাদের এখন নোডলিস্ট থেকে একটি অ্যারে তৈরি করার সহজ উপায় রয়েছে: Array.from()ফাংশন।

// nl is a NodeList
let myArray = Array.from(nl)

উপরে উল্লিখিত অন্যান্যগুলির সাথে এই নতুন ES6 পদ্ধতিটি কীভাবে গতির সাথে তুলনা করবে?
ব্যবহারকারী5508297

10
@ ব্যবহারকারী5508297 স্লাইস কল ট্রিকের চেয়ে ভাল। লুপগুলির চেয়ে ধীর গতির, তবে এটি ঠিক নয় যে আমরা এটির সন্ধান ছাড়াই কোনও অ্যারে রাখতে চাই। এবং বাক্য গঠনটি সুন্দর, সহজ এবং মনে রাখা সহজ!
ওয়েবডিফ 3'16

: Array.from সম্পর্কে চমৎকার ব্যাপার হল আপনি মানচিত্র যুক্তি ব্যবহার করতে পারেনconsole.log(Array.from([1, 2, 3], x => x + x)); // expected output: Array [2, 4, 6]
honzajde

103

ES6 স্প্রেড অপারেটরটি ব্যবহার করে এটি করার জন্য এখানে একটি নতুন দুর্দান্ত উপায় :

let arr = [...nl];

7
টাইপ স্ক্রিপ্টে আমার পক্ষে কাজ করেনি। ERROR TypeError: el.querySelectorAll(...).slice is not a function
আলিরেজা মিরিয়ান


19

কিছু অপ্টিমাইজেশন:

  • একটি চলক মধ্যে নোডলিস্ট দৈর্ঘ্য সংরক্ষণ করুন
  • সেট করার আগে স্পষ্টতই নতুন অ্যারের দৈর্ঘ্য সেট করুন।
  • চাপ বা উত্তোলন না করে সূচকগুলিতে অ্যাক্সেস করুন।

কোড ( jscreen ):

var arr = [];
for (var i = 0, ref = arr.length = nl.length; i < ref; i++) {
 arr[i] = nl[i];
}

আপনি একটি শেভ করতে সামান্য এরে (দৈর্ঘ্য) ব্যবহার বদলে অ্যারে তৈরি এবং তারপর আলাদাভাবে এটা নির্ধারন করে আরও সময়। আপনি যদি লুপের ভিতরে একটি লেট দিয়ে অ্যারে এবং এর দৈর্ঘ্য ঘোষণার জন্য কনস্ট ব্যবহার করেন তবে এটি উপরের পদ্ধতির তুলনায় প্রায় 1.5% দ্রুত শেষ হবে: কনস্ট এ = অ্যারে (এনএল. দৈর্ঘ্য), সি = a.leth; (যাক বি = 0; বি <সি; বি ++)) এ [বি] = এনএল [বি]; } দেখুন jsperf.com/nodelist-to-array/93
BrianFreud

15

ফলাফলগুলি সম্পূর্ণরূপে ব্রাউজারের উপর নির্ভর করবে, একটি উদ্দেশ্যমূলক রায় দেওয়ার জন্য, আমাদের কিছু কর্মক্ষমতা পরীক্ষা করতে হবে, এখানে কিছু ফলাফল রয়েছে, আপনি এগুলি এখানে চালাতে পারেন :

ক্রোম 6:

ফায়ারফক্স 3.6:

ফায়ারফক্স 4.0b2:

সাফারি 5:

আইই 9 প্ল্যাটফর্ম পূর্বরূপ 3:


1
আমি আশ্চর্য হই যে কীভাবে লুপের বিপরীতগুলি এইগুলির বিরুদ্ধে দাঁড়ায় ... for (var i=o.length; i--;)... এই পরীক্ষাগুলিতে 'লুপের জন্য' কী প্রতিটি পুনরাবৃত্তির দৈর্ঘ্যের সম্পত্তি পুনর্বিবেচনা করেছিল?
দাগ ন্যাবিট

14

সবচেয়ে দ্রুত এবং ক্রস ব্রাউজারটি হ'ল

for(var i=-1,l=nl.length;++i!==l;arr[i]=nl[i]);

আমি হিসাবে তুলনা

http://jsbin.com/oqeda/98/edit

* ধারণার জন্য ধন্যবাদ @ সিএমএস!

ক্রোমিয়াম (গুগল ক্রোমের অনুরূপ) ফায়ারফক্স অপেরা


1
লিঙ্কটি ভুল বলে মনে হচ্ছে, আপনি যে পরীক্ষাটি উল্লেখ করেছেন তাতে 89 টির পরিবর্তে 91 টি হওয়া উচিত be এবং 98 সবচেয়ে সম্পূর্ণ এক মনে হয়।
ইয়ারোস্লাভ ইয়াকোলেভ

9

ES6 এ আপনি ব্যবহার করতে পারেন:

  • Array.from

    let array = Array.from(nodelist)

  • স্প্রেড অপারেটর

    let array = [...nodelist]


পূর্ববর্তী উত্তরে ইতিমধ্যে যা লেখা হয়েছে তাতে নতুন কিছু যুক্ত হয় না।
স্টিফান বেকার

7
NodeList.prototype.forEach = Array.prototype.forEach;

এখন আপনি ডকুমেন্ট.কুইয়ারসিলিটরআল ('ডিভ') করতে পারেন forএর জন্য (ফাংশন () ...)


ভাল ধারণা, ধন্যবাদ @ জন! তবে, NodeListকাজ করছে না তবে Objectহ'ল: Object.prototype.forEach = Array.prototype.forEach; document.getElementsByTagName("img").forEach(function(img) { alert(img.src); });
আয়ান ক্যাম্পবেল

3
অবজেক্ট.প্রোটোটাইপ ব্যবহার করবেন না: এটি জিকুয়েরি এবং অভিধানের আক্ষরিক সিনট্যাক্সের মতো অনেকগুলি জিনিস ভেঙে দেয়।
নেট সিমার

অবশ্যই, দেশীয় অন্তর্নির্মিত ফাংশন প্রসারিত করা এড়াতে।
রোল্যান্ড

5

দ্রুত এবং খাটো:

// nl is the nodelist
var a=[], l=nl.length>>>0;
for( ; l--; a[l]=nl[l] );

3
কেন >>>0? এবং কেন লুপের প্রথম অংশে অ্যাসাইনমেন্টগুলি রাখেনি?
ক্যামিলো মার্টিন

5
এছাড়াও, এটি বগি। যখন lহয় 0, লুপ শেষ হয়ে যাবে, অতএব 0তম উপাদান অনুলিপি করা যাবে না (রাখবেন সেখানে সূচিতে একটি উপাদান 0)
ক্যামিলো মার্টিন

1
এই উত্তরটি ভালবাসুন, তবে ... যে কেউ ভাবছেন: এখানে প্রয়োজনীয় প্রয়োজন হতে >>> পারে না তবে নোডেলিস্টের দৈর্ঘ্যটি অ্যারে স্পেকের সাথে মেনে চলার গ্যারান্টি হিসাবে ব্যবহৃত হয়; এটি নিশ্চিত করে যে এটি একটি স্বাক্ষরযুক্ত 32-বিট পূর্ণসংখ্যা। এখানে এটি পরীক্ষা করে দেখুন ecma-international.org/ecma-262/5.1/#sec-15.4 আপনি যদি অপঠনযোগ্য কোড পছন্দ করেন তবে @ ক্যামিলোমার্টিনের পরামর্শ সহ এই পদ্ধতিটি ব্যবহার করুন!
টড

@ ক্যামিলোমার্টিনের জবাবে - 'পরিবর্তনশীল উত্তোলন' এর কারণে varএকটি forলুপের প্রথম অংশটির ভিতরে রাখা ঝুঁকিপূর্ণ । ঘোষণাপত্রটি varফাংশনের শীর্ষে 'উত্তোলন' করা হবে, এমনকি varলাইনটি কোথাও নীচে প্রদর্শিত হলেও , এবং এর ফলে পার্শ্ব প্রতিক্রিয়া হতে পারে যা কোড ক্রম থেকে সুস্পষ্ট নয়। উদাহরণস্বরূপ একই ফাংশনে কিছু কোড লুপের আগে ঘটেছিল তার উপর নির্ভর করে aএবং lঅঘোষিত হতে পারে । অতএব আরও পূর্বাভাসযোগ্যতার জন্য, ফাংশনের শীর্ষে আপনার ওয়ারগুলি ঘোষণা করুন (বা যদি ES6 এ থাকে তবে ব্যবহার করুন constবা letপরিবর্তে, যা উত্তোলন করে না)।
ব্রেণ্যানুউং

3

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


মজাদার. আমি এখনই কিছু অনুরূপ পরীক্ষা করেছি এবং ফায়ারফক্স ৩..3.৩ এভাবে কোনওভাবেই গতি বাড়িয়ে দেখায় না, অপেরা 10.6 এর 20% বৃদ্ধি পেয়েছে এবং ক্রোম 6 এর 230% (!) ম্যানুয়াল পুনরাবৃত্তি-ধাক্কা দিয়ে এটি বাড়িয়েছে।
jairajs89

@ jairajs89- কে বেশ আশ্চর্যজনক এটি প্রদর্শিত হয় যে Array.prototype.sliceব্রাউজার-নির্ভর। আমি ভাবছি যে প্রতিটি ব্রাউজার কী অ্যালগরিদম ব্যবহার করছে।
ভিভিন পালিথ


1

এই পোস্টিংয়ের তারিখ অনুসারে এখানে চার্টগুলি আপডেট করা হয়েছে ("অজানা প্ল্যাটফর্ম" চার্ট হ'ল ইন্টারনেট এক্সপ্লোরার 11.15.16299.0):

সাফারি 11.1.2 ফায়ারফক্স 61.0 ক্রোম 68.0.3440.75 ইন্টারনেট এক্সপ্লোরার 11.15.16299.0

এই ফলাফলগুলি থেকে মনে হয় প্রিলোকল্ট 1 পদ্ধতিটি সবচেয়ে নিরাপদ ক্রস ব্রাউজারের বাজি।


1

ধরে নিচ্ছি nodeList = document.querySelectorAll("div"), এটি nodelistঅ্যারেতে রূপান্তর করার একটি সংক্ষিপ্ত রূপ ।

var nodeArray = [].slice.call(nodeList);

এখানে এটি ব্যবহার দেখুন ।

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