একটি জাভাস্ক্রিপ্ট ফাংশন পুনরাবৃত্তি কল


90

আমি এর মতো একটি চলকটিতে একটি পুনরাবৃত্ত ফাংশন তৈরি করতে পারি:

/* Count down to 0 recursively.
 */
var functionHolder = function (counter) {
    output(counter);
    if (counter > 0) {
        functionHolder(counter-1);
    }
}

এই সঙ্গে, functionHolder(3);আউটপুট হবে 3 2 1 0। ধরা যাক আমি নিম্নলিখিতগুলি করেছি:

var copyFunction = functionHolder;

copyFunction(3);3 2 1 0উপরে হিসাবে আউটপুট হবে । আমি যদি তারপর functionHolderনিম্নলিখিত পরিবর্তন :

functionHolder = function(whatever) {
    output("Stop counting!");

তারপর functionHolder(3);দিতে হবে Stop counting!, প্রত্যাশিত হিসাবে।

copyFunction(3);এখন 3 Stop counting!এটি functionHolderফাংশন নয় (যা এটি নিজেই এটি নির্দেশ করে) হিসাবে উল্লেখ করে । এটি কিছু পরিস্থিতিতে আকাঙ্ক্ষিত হতে পারে তবে ফাংশনটি লেখার কোনও উপায় আছে যাতে এটি নিজেকে ধরে রাখে এমন পরিবর্তনশীলের পরিবর্তে নিজেকে কল করে?

এটিই কি কেবল লাইনটি পরিবর্তন করা সম্ভব হয় functionHolder(counter-1);যাতে 3 2 1 0আমরা কল করার সময় এই সমস্ত পদক্ষেপের মধ্য দিয়ে যাওয়া এখনও দেয় copyFunction(3);? আমি চেষ্টা করেছি this(counter-1);কিন্তু এটি আমাকে ত্রুটি দেয় this is not a function


4
এনবি কোনও ফাংশনের অভ্যন্তরে, এটি ফাংশনটি সম্পাদনের প্রসঙ্গে বোঝায়, ফাংশনটি নিজেই নয়। আপনার ক্ষেত্রে এটি সম্ভবত বিশ্বব্যাপী উইন্ডো অবজেক্টের দিকে নির্দেশ করছে।
এন্টোইন

উত্তর:


146

নামযুক্ত ফাংশন এক্সপ্রেশন ব্যবহার করে:

আপনি কোনও ফাংশন এক্সপ্রেশনটিকে এমন একটি নাম দিতে পারেন যা প্রকৃতপক্ষে ব্যক্তিগত এবং কেবলমাত্র যদি ফাংশনের অভ্যন্তর থেকে দৃশ্যমান হয় তবে:

var factorial = function myself (n) {
    if (n <= 1) {
        return 1;
    }
    return n * myself(n-1);
}
typeof myself === 'undefined'

এখানে myselfহয় ফাংশন কেবল ভিতরে নিজেই।

ফাংশনটি পুনরাবৃত্তভাবে কল করতে আপনি এই ব্যক্তিগত নামটি ব্যবহার করতে পারেন।

13. Function DefinitionECMAScript 5 টি দেখুন :

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

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

আর্গুমেন্টস ক্যালি ব্যবহার করে:

বিকল্পভাবে আপনি arguments.calleeবর্তমান ফাংশনটি উল্লেখ করতে ব্যবহার করতে পারেন :

var factorial = function (n) {
    if (n <= 1) {
        return 1;
    }
    return n * arguments.callee(n-1);
}

ECMAScript এর 5 তম সংস্করণটি কঠোর মোডে আর্গুমেন্টস ক্যালির () ব্যবহার নিষিদ্ধ করেছে , তবে:

( এমডিএন থেকে ): সাধারণ কোড আর্গুমেন্টে। কলিটি এনক্লোজিং ফাংশনকে বোঝায়। এই ব্যবহারের ক্ষেত্রেটি দুর্বল: কেবল এনক্লোজিং ফাংশনের নাম দিন! তদ্ব্যতীত, আর্গুমেন্টস ক্যালি ইনলাইনিং ফাংশনগুলির মতো অপ্টিমাইজেশনকে যথেষ্ট পরিমাণে বাধা দেয়, কারণ যদি আর্গুমেন্টস ক্যালিতে অ্যাক্সেস করা হয় তবে আন-ইনলাইনড ফাংশনটির জন্য একটি রেফারেন্স সরবরাহ করা সম্ভব হবে। কঠোর মোড ফাংশনগুলির জন্য আর্গুমেন্টস.ক্যালি হ'ল একটি অ-বিয়োগযোগ্য সম্পত্তি যা সেট বা পুনরুদ্ধার করার সময় নিক্ষেপ করে।


4
+1 যদিও এটি IE8 এ সামান্য বগি এবং এর চেয়ে কম myselfএটি বদ্ধ পরিবর্তনশীল পরিবেশে বাস্তবে দৃশ্যমান এবং এটি প্রকৃত ফাংশনের একটি সদৃশকে উল্লেখ myselfকরে। আপনি nullযদিও বাহ্যিক রেফারেন্স সেট করতে সক্ষম হবেন ।
ব্যবহারকারী 113716

উত্তর করার জন্য ধন্যবাদ! দু'জনই 2 টি বিভিন্ন উপায়ে সমস্যার সমাধান করেছিলেন। শেষ পর্যন্ত আমি এলোমেলোভাবে সিদ্ধান্ত নিয়েছি কোনটি গ্রহণ করব: পি
সামথারে

শুধু আমার বুঝতে জন্য। প্রতিটি রিটার্নে ফাংশনটি গুণের পিছনে কারণ কী? return n * myself(n-1);?
চিৎজুই

ফাংশন কেন এইভাবে কাজ করে? jsfiddle.net/jvL5euho/18 এর পরে যদি 4 বার লুপ করে।
প্রশান্ত তাপসে

কিছু রেফারেন্স অনুসারে আর্গুমেন্টস.কলে কঠোর মোডে কাজ করবে না।
ক্রুনাল লিমবাদ

10

আপনি arguments.callee [MDN] ব্যবহার করে নিজেই ফাংশনটি অ্যাক্সেস করতে পারেন :

if (counter>0) {
    arguments.callee(counter-1);
}

তবে এটি কঠোর মোডে ভাঙ্গবে।


6
আমি বিশ্বাস করি যে এটি অবচয় করা হয়েছে (এবং কঠোর মোডে অনুমোদিত নয়)
আর্নাড লে ব্ল্যাঙ্ক

@ ফেলিক্স: হ্যাঁ, "কঠোর মোড" একটি দেবে TypeError, তবে আনুষ্ঠানিকভাবে বলা হয়েছে যে arguments.callee (বা কোনও কঠোর মোডের লঙ্ঘন) "কঠোর মোডের" বাইরে অবহিত হয়েছে anything
ব্যবহারকারী 113716

উত্তর করার জন্য ধন্যবাদ! দু'জনই 2 টি বিভিন্ন উপায়ে সমস্যার সমাধান করেছিলেন। শেষ পর্যন্ত আমি এলোমেলোভাবে সিদ্ধান্ত নিয়েছি কোনটি গ্রহণ করব: পি
সামথারে

6

আপনি ওয়াই-কম্বিনেটর ব্যবহার করতে পারেন: ( উইকিপিডিয়া )

// ES5 syntax
var Y = function Y(a) {
  return (function (a) {
    return a(a);
  })(function (b) {
    return a(function (a) {
      return b(b)(a);
    });
  });
};

// ES6 syntax
const Y = a=>(a=>a(a))(b=>a(a=>b(b)(a)));

// If the function accepts more than one parameter:
const Y = a=>(a=>a(a))(b=>a((...a)=>b(b)(...a)));

এবং আপনি এটি হিসাবে এটি ব্যবহার করতে পারেন:

// ES5
var fn = Y(function(fn) {
  return function(counter) {
    console.log(counter);
    if (counter > 0) {
      fn(counter - 1);
    }
  }
});

// ES6
const fn = Y(fn => counter => {
  console.log(counter);
  if (counter > 0) {
    fn(counter - 1);
  }
});

5

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

  var fn = (function() {
    var innerFn = function(counter) {
      console.log(counter);

      if(counter > 0) {
        innerFn(counter-1);
      }
    };

    return innerFn;
  })();

  console.log("running fn");
  fn(3);

  var copyFn = fn;

  console.log("running copyFn");
  copyFn(3);

  fn = function() { console.log("done"); };

  console.log("fn after reassignment");
  fn(3);

  console.log("copyFn after reassignment of fn");
  copyFn(3);

3

এখানে একটি খুব সাধারণ উদাহরণ:

var counter = 0;

function getSlug(tokens) {
    var slug = '';

    if (!!tokens.length) {
        slug = tokens.shift();
        slug = slug.toLowerCase();
        slug += getSlug(tokens);

        counter += 1;
        console.log('THE SLUG ELEMENT IS: %s, counter is: %s', slug, counter);
    }

    return slug;
}

var mySlug = getSlug(['This', 'Is', 'My', 'Slug']);
console.log('THE SLUG IS: %s', mySlug);

লক্ষ্য করুন যে এর মান counterকী তা বিবেচনায় "পিছনে" গণনা slugকরা হয়েছে। এই, অবস্থান যা আমরা এই মান লগ-ইন করা হয় কারণ হিসাবে ফাংশন পুনরাবৃত্ত হয় লগিং আগে - তাই, আমরা মূলত গভীর এবং গভীর মধ্যে পাখির রাখা কল-স্ট্যাক আগে লগিং সঞ্চালিত হয়।

একবার যখন পুনরাবৃত্তি চূড়ান্ত কল-স্ট্যাক আইটেমটি পূরণ করে, এটি ফাংশন কলগুলির "আউট" ট্রাম্পোলিন করে, যখন, প্রথম বাড়া counterশেষ নেস্টেড কলটির ভিতরে ঘটে।

আমি জানি যে এটি প্রশ্নকারীর কোডের কোনও "ফিক্স" নয়, তবে শিরোনামটি দিয়ে আমি ভেবেছিলাম যে আমি সাধারণভাবে পুনরাবৃত্তির আরও ভাল বোঝার জন্য পুনরাবৃত্তিকে উদাহরণ হিসাবে প্রকাশ করব out

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