অ্যারে.প্রোটোটাইপ.স্লাইস.ক্লল () কীভাবে কাজ করে?


474

আমি জানি এটি আর্গুমেন্টগুলিকে আসল অ্যারে তৈরি করতে ব্যবহৃত হয়, তবে ব্যবহারের পরে কী ঘটে তা আমি বুঝতে পারি না Array.prototype.slice.call(arguments)


2
link লিঙ্কটি ডিওএম নোডগুলি সম্পর্কে জিজ্ঞাসা করে এবং আর্গুমেন্টের চেয়ে কিছুটা আলাদা। এবং আমি মনে করি অভ্যন্তরীণভাবে 'এটি' কী তা বর্ণনা করে এখানে উত্তরটি আরও ভাল।
স্কর্ম

উত্তর:


870

হুডের নীচে যা ঘটে তা হ'ল যখন .slice()সাধারণভাবে বলা হয় thisএটি একটি অ্যারে এবং তারপরে এটি কেবল অ্যারেটির উপরে পুনরাবৃত্তি করে এবং এটির কাজটি করে।

কেমন আছে thisমধ্যে .slice()একটি অ্যারের ফাংশন আছে? কারণ আপনি যখন করবেন:

object.method();

... objectস্বয়ংক্রিয়ভাবে এর thisমধ্যে মান হয় method()। তাই দিয়ে:

[1,2,3].slice()

... [1,2,3]অ্যারেটি ইন- এর মান হিসাবে সেট করা thisআছে .slice()


কিন্তু আপনি যদি thisমান হিসাবে অন্য কিছু বিকল্প করতে পারে ? যতক্ষণ আপনি প্রতিস্থাপন করবেন তার একটি সংখ্যাসূচক .lengthসম্পত্তি এবং সংখ্যার সূচকগুলি এমন একগুচ্ছ বৈশিষ্ট্য রয়েছে যতক্ষণ না এটি কাজ করা উচিত। এই ধরণের অবজেক্টকে প্রায়শই অ্যারের মতো বস্তু বলা হয়

.call()এবং .apply()পদ্ধতি আপনাকে ভেতরে যেতে নিজে মান সেট thisএকটি ফাংশন হবে। তাই আপনি যদি আমরা মান সেট thisমধ্যে .slice()একটি অ্যারের মত বস্তু , .slice()শুধু হবে অনুমান এটা একটি অ্যারের সাথে কাজ করছে, এবং তার জিনিস করতে হবে।

উদাহরণ হিসাবে এই সরল বস্তুটি নিন।

var my_object = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    length: 5
};

এটি অবশ্যই কোনও অ্যারে নয়, তবে আপনি যদি এটির thisমান হিসাবে সেট করতে পারেন .slice()তবে এটি ঠিক কাজ করবে কারণ .slice()সঠিকভাবে কাজ করার জন্য এটি অ্যারের মতো যথেষ্ট দেখায় ।

var sliced = Array.prototype.slice.call( my_object, 3 );

উদাহরণ: http://jsfiddle.net/wSvkv/

আপনি কনসোলে দেখতে পাচ্ছেন, ফলাফলটি আমরা প্রত্যাশা করি:

['three','four'];

সুতরাং যখন আপনি কোনও argumentsবস্তুর thisমান হিসাবে সেট করেন এটি ঘটে .slice()। কারণ argumentsএকটি .lengthসম্পত্তি এবং সংখ্যার সূচকগুলির একটি গুচ্ছ রয়েছে, .slice()কেবল এটির কাজটি এমনভাবে চলে যেন এটি কোনও আসল অ্যারে নিয়ে কাজ করে।


7
দুর্দান্ত উত্তর! তবে দুঃখের বিষয় হচ্ছে আপনি যদি কোনও অবজেক্টকে এইভাবে রূপান্তর করতে পারবেন না, যদি আপনার অবজেক্ট কীগুলি সত্যিকারের কথায় যেমন স্ট্রিং মান হয় তবে এটি ব্যর্থ হবে, সুতরাং আপনার অবজেক্টগুলিকে '0': 'মান' হিসাবে রাখুন এবং 'স্ট্রিংনাম' এর মতো নয় : 'মান'।
joopmicroop

6
@ মিশেল: ওপেন সোর্স জেএস বাস্তবায়নের উত্স কোড পড়া সম্ভব, তবে "ECMAScript" ভাষার স্পেসিফিকেশন উল্লেখ করা সহজ। এখানে একটি লিঙ্ক থেকে Array.prototype.sliceপদ্ধতি বর্ণনা।

1
যেহেতু অবজেক্ট কীগুলির কোনও অর্ডার নেই তাই এই নির্দিষ্ট প্রদর্শনটি অন্যান্য ব্রাউজারগুলিতে ব্যর্থ হতে পারে। সমস্ত বিক্রেতারা তাদের সৃষ্ট বস্তুর কীগুলি তৈরির ক্রম অনুসারে বাছাই করে না।
vsync

1
@vsync: এটি এমন for-inবিবৃতি যা আদেশের গ্যারান্টি দেয় না। ব্যবহৃত অ্যালগরিদম প্রদত্ত বস্তুর (বা অ্যারে বা যাই হোক না কেন) .slice()দিয়ে শুরু 0এবং শেষ (অ-সমেত) সংখ্যার ক্রম সংজ্ঞায়িত করে .length। সুতরাং আদেশটি সমস্ত বাস্তবায়ন জুড়ে সুসংগত হওয়ার গ্যারান্টিযুক্ত।
কুকি দৈত্য

7
@vsync: এটি অনুমান নয় isn't আপনি যদি এটি প্রয়োগ করেন তবে যে কোনও বস্তু থেকে অর্ডার পেতে পারেন। বলি আমার আছে var obj = {2:"two", 0:"zero", 1: "one"}। যদি আমরা for-inঅবজেক্টটি গণনার জন্য ব্যবহার করি তবে অর্ডারের কোনও গ্যারান্টি নেই। কিন্তু যদি আমরা ব্যবহার for, আমরা ম্যানুয়ালি অর্ডার জোরদার করতে পারেন: for (var i = 0; i < 3; i++) { console.log(obj[i]); }। এখন আমরা জানি যে আমাদের forলুপ দ্বারা আমরা সংজ্ঞায়িত অবজেক্টের বৈশিষ্ট্যগুলি আরোহণের সংখ্যায়িত ক্রমে পৌঁছে যাবে । এটা কি .slice()করে। এটির সত্যিকারের অ্যারে আছে কিনা তা বিবেচ্য নয়। এটি সবে শুরু হয় 0এবং একটি আরোহণ লুপে বৈশিষ্ট্য অ্যাক্সেস করে।
কুকি দৈত্য

88

argumentsবস্তু আসলে একটি অ্যারের একটি দৃষ্টান্ত নয়, এবং এরে যে কোনো পদ্ধতি নেই। সুতরাং, arguments.slice(...)কাজ করবে না কারণ আর্গুমেন্ট অবজেক্টের স্লাইস পদ্ধতি নেই।

অ্যারেগুলির এই পদ্ধতিটি রয়েছে এবং কারণ argumentsবস্তুটি একটি অ্যারের সাথে খুব সমান, তাই দুটি সামঞ্জস্যপূর্ণ। এর অর্থ হ'ল আমরা আর্গুমেন্ট অবজেক্টের সাথে অ্যারে পদ্ধতিগুলি ব্যবহার করতে পারি। আর যেহেতু অ্যারে পদ্ধতিগুলি অ্যারেগুলি মাথায় রেখে নির্মিত হয়েছিল, তাই তারা অন্যান্য যুক্তিযুক্ত বিষয়গুলির চেয়ে অ্যারেগুলি ফিরিয়ে দেবে।

তাহলে কেন ব্যবহার করবেন Array.prototype? Arrayবস্তু যা আমরা (থেকে নতুন অ্যারে তৈরি হয় new Array()), এবং এই নতুন অ্যারে গৃহীত হয় পদ্ধতি এবং সম্পত্তি, ফালি মত। এই পদ্ধতি [Class].prototypeঅবজেক্টে সংরক্ষণ করা হয় । সুতরাং, দক্ষতার জন্য, স্লাইস পদ্ধতিটি দ্বারা (new Array()).slice.call()বা অ্যাক্সেস না করে [].slice.call()কেবল প্রোটোটাইপ থেকে আমরা সরাসরি এটি পাই। এটি তাই আমাদের নতুন অ্যারে আরম্ভ করতে হবে না।

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


আপনি এখানে বর্ণিত কারণে স্লাইস ব্যবহার করতে চাইতে পারেন: jspatterns.com/arguments-considered-harmful
KooiInc

44

সাধারণত কল করা

var b = a.slice();

অ্যারে অনুলিপি aকরা হবে b। যাইহোক, আমরা করতে পারি না

var a = arguments.slice();

কারণ argumentsসত্যিকারের অ্যারে নয় এবং sliceপদ্ধতি হিসাবে এটি নেই । Array.prototype.sliceহয় sliceঅ্যারে জন্য ফাংশন, এবং callসঙ্গে ফাংশন সঞ্চালিত thisসেট arguments


2
থ্যাঙ্কস তবে কেন ব্যবহার করবেন prototype? নয় sliceএকটি নেটিভ Arrayপদ্ধতি?
ilo

2
নোট যে Arrayএকটি নির্মাণকারী ফাংশন, এবং সম্পর্কিত "বর্গ" হয় Array.prototype। আপনি ব্যবহার করতে পারেন[].slice
user123444555621

4
IlyaD, sliceপ্রতিটি Arrayউদাহরণের একটি পদ্ধতি , তবে Arrayকনস্ট্রাক্টর ফাংশন নয়। আপনি prototypeকোনও নির্মাণকারীর তাত্ত্বিক উদাহরণগুলির পদ্ধতি অ্যাক্সেস করতে ব্যবহার করেন।
দেলান আজাবানী

23

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

Array.prototype.sliceএর প্রোটোটাইপ থেকে পদ্ধতিটি বের করে । তবে এটি সরাসরি কল করা কার্যকর হবে না, কারণ এটি একটি পদ্ধতি (কোনও ফাংশন নয়) এবং সুতরাং একটি প্রসঙ্গে (কলিং অবজেক্ট, ) প্রয়োজন, অন্যথায় এটি ছুঁড়ে ফেলা হবে ।slice ArraythisUncaught TypeError: Array.prototype.slice called on null or undefined

call()পদ্ধতি একটি পদ্ধতি প্রসঙ্গ উল্লেখ করতে, মূলত এই দুটি কল সমতুল্য তৈরি করার অনুমতি দেয়:

someObject.slice(1, 2);
slice.call(someObject, 1, 2);

পূর্বের ব্যতীত প্রোটোটাইপ শৃঙ্খলে (যেমন এটি প্রযোজ্য ) sliceপদ্ধতি থাকা প্রয়োজন , যদিও পরেরটি প্রসঙ্গটি ( ) ম্যানুয়ালি পদ্ধতিতে পাস করার অনুমতি দেয়।someObjectArraysomeObject

এছাড়াও, পরবর্তীগুলি এর জন্য সংক্ষিপ্ত:

var slice = Array.prototype.slice;
slice.call(someObject, 1, 2);

যা একই:

Array.prototype.slice.call(someObject, 1, 2);

22
// We can apply `slice` from  `Array.prototype`:
Array.prototype.slice.call([]); //-> []

// Since `slice` is available on an array's prototype chain,
'slice' in []; //-> true
[].slice === Array.prototype.slice; //-> true

// … we can just invoke it directly:
[].slice(); //-> []

// `arguments` has no `slice` method
'slice' in arguments; //-> false

// … but we can apply it the same way:
Array.prototype.slice.call(arguments); //-> […]

// In fact, though `slice` belongs to `Array.prototype`,
// it can operate on any array-like object:
Array.prototype.slice.call({0: 1, length: 1}); //-> [1]

16

অ্যারে.প্রোটোটাইপ.স্লাইস কোড (আর্গুমেন্ট) হ'ল আর্গুমেন্টগুলিকে অ্যারেতে রূপান্তর করার পুরানো fashion

ECMAScript 2015 এ আপনি অ্যারে.ফর্ম বা স্প্রেড অপারেটর ব্যবহার করতে পারেন:

let args = Array.from(arguments);

let args = [...arguments];

9

এটি কারণ, এমডিএন নোট হিসাবে

আর্গুমেন্ট অবজেক্ট কোনও অ্যারে নয়। এটি একটি অ্যারের অনুরূপ, তবে দৈর্ঘ্য ব্যতীত কোনও অ্যারের বৈশিষ্ট্য নেই। উদাহরণস্বরূপ, এটিতে পপ পদ্ধতি নেই। তবে এটি একটি বাস্তব অ্যারে রূপান্তর করা যেতে পারে:

এখানে আমরা sliceনেটিভ অবজেক্টের দিকে আহ্বান জানাচ্ছি Arrayএটির প্রয়োগের দিকে নয় এবং কেন অতিরিক্ত why.prototype

var args = Array.prototype.slice.call(arguments);

4

ভুলে যাবেন না, এই আচরণের একটি নিম্ন-স্তরের বেসিকগুলি টাইপ-কাস্টিং যা জেএস-ইঞ্জিনকে পুরোপুরি সংহত করে।

স্লাইসটি কেবল অবজেক্ট গ্রহণ করে (বিদ্যমান আর্গুমেন্টগুলি ngth দৈর্ঘ্যের সম্পত্তিকে ধন্যবাদ) এবং এতে সমস্ত ক্রিয়াকলাপ করার পরে অ্যারে-অবজেক্টকে কাস্ট করা ফেরত দেয়।

আপনি যদি স্ট্রিং-পদ্ধতির কোনও আইএনটি-মান দিয়ে চিকিত্সার চেষ্টা করেন তবে একই যুক্তিগুলি আপনি পরীক্ষা করতে পারেন:

String.prototype.bold.call(11);  // returns "<b>11</b>"

এবং এটি উপরে বিবৃতি ব্যাখ্যা করে।


1

এটি sliceঅ্যারেগুলির পদ্ধতিটি ব্যবহার করে এবং এটিটিকে তার বস্তু thisহিসাবে কল করে arguments। এর অর্থ এটি এটিকে এমনভাবে কল করে যে আপনি arguments.slice()ধরে নিয়েছেন argumentsযে এই জাতীয় পদ্ধতি রয়েছে।

কোনও যুক্তি ছাড়াই একটি স্লাইস তৈরি করা সহজভাবে সমস্ত উপাদানগুলিকে গ্রহণ করবে - সুতরাং এটি উপাদানগুলিকে কেবল argumentsঅ্যারে থেকে অনুলিপি করে ।


1

ধরে নেওয়া যাক আপনার কাছে রয়েছে: function.apply(thisArg, argArray )

প্রয়োগ পদ্ধতিটি কোনও ফাংশনকে আহ্বান করে, অবজেক্টে পাস করে যা এই এবং যুক্তিগুলির একটি alচ্ছিক অ্যারেতে আবদ্ধ হবে।

স্লাইস () পদ্ধতিটি একটি অ্যারের অংশ নির্বাচন করে এবং নতুন অ্যারে প্রদান করে।

আপনি যখন Array.prototype.slice.apply(arguments, [0])অ্যারে কল করেন তখন স্লাইস পদ্ধতিটি আর্গুমেন্টগুলিতে (বাঁধাই করা) ডাকা হয়।


1

কিছুটা দেরি হতে পারে তবে এই সমস্ত গণ্ডগোলের উত্তর হ'ল জেসেসে উত্তরাধিকারের জন্য কল () ব্যবহৃত হয়। যদি আমরা পাইথন বা পিএইচপি এর সাথে এটি তুলনা করি, উদাহরণস্বরূপ, কলটি যথাক্রমে সুপার () হিসাবে ব্যবহৃত হয়। init () বা পিতামাতার :: _ কনস্ট্রাক্ট ()।

এটি এর ব্যবহারের একটি উদাহরণ যা সমস্ত স্পষ্ট করে:

function Teacher(first, last, age, gender, interests, subject) {
  Person.call(this, first, last, age, gender, interests);

  this.subject = subject;
}

তথ্যসূত্র: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Inheritance


0

যখন .স্লাইস () কে সাধারণত বলা হয়, এটি একটি অ্যারে এবং তারপরে এটি কেবল সেই অ্যারের উপরে পুনরাবৃত্তি করে এবং এটির কাজ করে।

 //ARGUMENTS
function func(){
  console.log(arguments);//[1, 2, 3, 4]

  //var arrArguments = arguments.slice();//Uncaught TypeError: undefined is not a function
  var arrArguments = [].slice.call(arguments);//cp array with explicity THIS  
  arrArguments.push('new');
  console.log(arrArguments)
}
func(1,2,3,4)//[1, 2, 3, 4, "new"]

-1

আমি কেবল নিজেকে স্মরণ করিয়ে দেওয়ার জন্য এটি লিখছি ...

    Array.prototype.slice.call(arguments);
==  Array.prototype.slice(arguments[1], arguments[2], arguments[3], ...)
==  [ arguments[1], arguments[2], arguments[3], ... ]

অথবা সর্বাধিক জিনিসগুলিকে অ্যারেতে রূপান্তর করতে কেবল এই হ্যান্ডি ফাংশন $ A ব্যবহার করুন ।

function hasArrayNature(a) {
    return !!a && (typeof a == "object" || typeof a == "function") && "length" in a && !("setInterval" in a) && (Object.prototype.toString.call(a) === "[object Array]" || "callee" in a || "item" in a);
}

function $A(b) {
    if (!hasArrayNature(b)) return [ b ];
    if (b.item) {
        var a = b.length, c = new Array(a);
        while (a--) c[a] = b[a];
        return c;
    }
    return Array.prototype.slice.call(b);
}

উদাহরণস্বরূপ ব্যবহার ...

function test() {
    $A( arguments ).forEach( function(arg) {
        console.log("Argument: " + arg);
    });
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.