জাভাস্ক্রিপ্টে একাধিক তীর ফাংশনগুলির অর্থ কী?


472

আমি প্রচুর reactকোড পড়ছি এবং আমি এমন জিনিস দেখতে পাচ্ছি যা আমি বুঝতে পারি না:

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}

11
কেবল মজাদার জন্য, কাইল সিম্পসন তীরগুলির সমস্ত সিদ্ধান্তের পথগুলি এই প্রবাহের চার্টে রেখেছিলেন । উত্স: গভীরতার মধ্যে ES6 শিরোনামের একটি মজিলা হ্যাকস ব্লগ পোস্টে তাঁর মন্তব্য : তীর ফাংশন
গফুল্লাম

যেহেতু দুর্দান্ত উত্তর এবং এখন একটি অনুগ্রহ রয়েছে। নীচের উত্তরগুলি কভার করে না যে আপনি কী বুঝতে পারছেন না সে সম্পর্কে আপনি কি দয়া করে বিস্তারিত বলতে পারেন।
মাইকেল ওয়ার্নার

5
তীর ফাংশন ফ্লো চার্টের URL টি এখন ভেঙে গেছে কারণ বইটির নতুন সংস্করণ রয়েছে। ওয়ার্কিং URL- এ আছে raw.githubusercontent.com/getify/You-Dont-Know-JS/1st-ed/...
ধীরাজ গুপ্ত

উত্তর:


831

এটি একটি ত্রিযুক্ত ফাংশন

প্রথমে দুটি পরামিতি সহ এই ফাংশনটি পরীক্ষা করুন ...

const add = (x, y) => x + y
add(2, 3) //=> 5

এখানে এটি আবার তরকারী আকারে…

const add = x => y => x + y

এখানে তীর ফাংশন ছাড়াই একই 1 কোডটি রয়েছে ...

const add = function (x) {
  return function (y) {
    return x + y
  }
}

লক্ষ্য করা return

এটি অন্য উপায়ে কল্পনা করতে সহায়তা করতে পারে। আমরা জানি যে তীর ফাংশনগুলি এর মতো কাজ করে - আসুন প্রত্যাবর্তনের মানটির দিকে বিশেষ মনোযোগ দিন ।

const f = someParam => returnValue

সুতরাং আমাদের addফাংশনটি একটি ফাংশন দেয় - আমরা যুক্ত স্পষ্টতার জন্য বন্ধনী ব্যবহার করতে পারি। বোল্ড টেক্সট আমাদের ফাংশনের রিটার্ন মানadd

const add = x => (y => x + y)

addকিছু সংখ্যার অন্য কথায় একটি ফাংশন প্রদান করে

add(2) // returns (y => 2 + y)

কলযুক্ত কার্যাবলী কল করা হচ্ছে

সুতরাং আমাদের কারিড ফাংশনটি ব্যবহার করার জন্য, আমাদের এটিকে কিছুটা আলাদাভাবে কল করতে হবে ...

add(2)(3)  // returns 5

কারণ প্রথম (বহিরাগত) ফাংশন কলটি একটি দ্বিতীয় (অভ্যন্তরীণ) ফাংশন দেয়। আমরা দ্বিতীয় ফাংশনটি কল করার পরেই আমরা আসলে ফলাফলটি পাই। যদি আমরা দুটি লাইনে কলগুলি আলাদা করি তবে এটি আরও স্পষ্ট is

const add2 = add(2) // returns function(y) { return 2 + y }
add2(3)             // returns 5

আপনার কোডে আমাদের নতুন বোঝাপড়া প্রয়োগ করা

সম্পর্কিত: "বাঁধাই, আংশিক প্রয়োগ এবং কারি করার মধ্যে পার্থক্য কী?"

ঠিক আছে, এখন আমরা বুঝতে পারি যে এটি কীভাবে কাজ করে, আসুন আপনার কোডটি দেখুন

handleChange = field => e => {
  e.preventDefault()
  /// Do something here
}

আমরা তীর ফাংশন ব্যবহার না করে এটি উপস্থাপন করে শুরু করব ...

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};

যাইহোক, তীর ফাংশনগুলি সুক্ষ্মভাবে বাঁধাই করার কারণে thisএটি প্রকৃতপক্ষে আরও দেখতে হবে ...

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  }.bind(this)
}.bind(this)

সম্ভবত এখন আমরা দেখতে পাচ্ছি যে এটি আরও স্পষ্টভাবে কী করছে। handleChangeফাংশন একটি নির্দিষ্ট একটি ফাংশন তৈরি করছে field। এটি একটি সহজ প্রতিক্রিয়া কৌশল কারণ আপনার অ্যাপ্লিকেশনগুলির স্থিতি আপডেট করতে আপনাকে প্রতিটি ইনপুটটিতে আপনার নিজের শ্রোতাদের সেটআপ করতে হবে। handleChangeফাংশনটি ব্যবহার করে , আমরা সমস্ত অনুলিপি কোডটি অপসারণ করতে পারি যা changeপ্রতিটি ক্ষেত্রের জন্য শ্রোতাদের সেটআপ করার ফলে হবে । শান্ত!

1 এখানে আমাকে সংক্ষিপ্তভাবে আবদ্ধ করতে হয়নি thisকারণ আসল addফাংশনটি কোনও প্রসঙ্গ ব্যবহার করে না, তাই এই ক্ষেত্রে এটি সংরক্ষণ করা গুরুত্বপূর্ণ নয়।


আরও তীর

প্রয়োজনে দুটিরও বেশি তীরের ক্রিয়া ক্রমানুসারে করা যেতে পারে -

const three = a => b => c =>
  a + b + c

const four = a => b => c => d =>
  a + b + c + d

three (1) (2) (3) // 6

four (1) (2) (3) (4) // 10

ত্রিযুক্ত ফাংশনগুলি অবাক করার মতো জিনিসগুলিতে সক্ষম। নীচে আমরা $দুটি প্যারামিটার সহ একটি তরকারী ফাংশন হিসাবে সংজ্ঞায়িত দেখতে পাই , তবুও কল সাইটে এটি প্রদর্শিত হয় যেন আমরা কোনও সংখ্যক যুক্তি সরবরাহ করতে পারি। সংবাহন এর বিমূর্ততা হয় arity -

const $ = x => k =>
  $ (k (x))
  
const add = x => y =>
  x + y

const mult = x => y =>
  x * y
  
$ (1)           // 1
  (add (2))     // + 2 = 3
  (mult (6))    // * 6 = 18
  (console.log) // 18
  
$ (7)            // 7
  (add (1))      // + 1 = 8
  (mult (8))     // * 8 = 64
  (mult (2))     // * 2 = 128
  (mult (2))     // * 2 = 256
  (console.log)  // 256

আংশিক প্রয়োগ

আংশিক প্রয়োগ সম্পর্কিত ধারণা is এটি আমাদের আংশিকভাবে কার্চিংয়ের অনুরূপ ফাংশনগুলি প্রয়োগ করতে দেয়, তবে ফাংশনটি তরকারি আকারে সংজ্ঞায়িত করতে হয় না -

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)

const add3 = (x, y, z) =>
  x + y + z

partial (add3) (1, 2, 3)   // 6

partial (add3, 1) (2, 3)   // 6

partial (add3, 1, 2) (3)   // 6

partial (add3, 1, 2, 3) () // 6

partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3

partialআপনার নিজের ওয়ার্কিং ডেমোটি এখানে আপনার নিজের ব্রাউজারে খেলতে পারেন -

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)
  
const preventDefault = (f, event) =>
  ( event .preventDefault ()
  , f (event)
  )
  
const logKeypress = event =>
  console .log (event.which)
  
document
  .querySelector ('input[name=foo]')
  .addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">


2
এটি অসামান্য! যদিও কেউ কতক্ষণ আসলে '$' বরাদ্দ করে? নাকি প্রতিক্রিয়া জানাতে এটির একটি উপনাম? শেষ পর্যন্ত আমার অজ্ঞতাটি ক্ষমা করুন, কেবল কৌতূহলী কারণ আমি অন্য ভাষায় খুব বেশি সময় একটি কার্যপত্রক পেতে একটি চিহ্ন দেখি না।
ক্যাপেরনিওগিনিস

7
@ ক্রেটারনিওগনিস $ধারণাটি ডেমো করতে ব্যবহার করা হয়েছিল, তবে আপনি যা খুশি নাম রাখতে পারেন। কাকতালীয়ভাবে কিন্তু সম্পূর্ণরূপে সম্পর্কহীন, $ হয়েছে jQuery এর, যেখানে মত জনপ্রিয় লাইব্রেরি ব্যবহার করা $ফাংশন সমগ্র লাইব্রেরী বিশ্বব্যাপী এন্ট্রি পয়েন্ট সাজান। আমি মনে করি এটি অন্যদের মধ্যেও ব্যবহৃত হয়েছে। আপনি যে অন্যটি দেখতে পাবেন তা হ'ল _আন্ডারস্কোর এবং লোড্যাশের মতো লাইব্রেরিতে জনপ্রিয়। একটি প্রতীক অন্য চেয়ে বেশি অর্থবহ নয়; আপনি আপনার প্রোগ্রামটির অর্থ নির্ধারণ করুন । এটি কেবল বৈধ জাভাস্ক্রিপ্ট: ডি
আপনাকে ধন্যবাদ

1
পবিত্র ফ্রিজোলি, সুন্দর উত্তর। আশা করি
ওপি

2
@ ব্ল্যাক $এটি কীভাবে ব্যবহৃত হয় তা দেখে আপনি আরও ভাল ধারণা অর্জন করতে পারেন । আপনি যদি নিজেই বাস্তবায়ন সম্পর্কে জিজ্ঞাসা করেন তবে $এমন একটি ফাংশন যা একটি মান পায় xএবং একটি নতুন ফাংশন দেয় k => ...। ফিরে আসা ক্রিয়াকলাপটির প্রধান অংশটি দেখে আমরা দেখতে পেলাম k (x)যে আমরা জানি kযে একটি ফাংশনও হতে হবে এবং ফলাফল যা কিছু হয় তা k (x)আবার ফিরিয়ে আনা হয় $ (...), যা আমরা জানি অন্যটি ফিরে আসে k => ..., এবং তা চালিয়ে যায় ... আপনি যদি এখনও থাকেন আটকে যাচ্ছে, আমাকে জানাতে।
আপনাকে ধন্যবাদ

2
যদিও এই উত্তরণটি ব্যাখ্যা করে যে এটি কীভাবে কাজ করে এবং কী কী পদ্ধতিতে এই কৌশলটি রয়েছে this আমি অনুভব করি যে কেন এটি যে কোনও দৃশ্যেই সর্বোত্তম সমাধান specific কোন পরিস্থিতিতে, abc(1,2,3)তুলনায় আদর্শ কম abc(1)(2)(3)। কোডের যুক্তি সম্পর্কে তর্ক করা আরও শক্ত এবং ফাংশন এবিসি পড়া শক্ত এবং ফাংশন কলটি পড়া আরও শক্ত। আপনাকে কেবল আব্বু কী করে তা জানা দরকার ছিল, এখন আপনি নিশ্চিত নন যে নামবিহীন ফাংশনগুলি এবিসি কী করবে এবং তার মধ্যে দুবার।
মুহাম্মদ উমর

57

তীর ফাংশনগুলির উপলভ্য সিনট্যাক্সগুলি বোঝার ফলে আপনি প্রদত্ত উদাহরণগুলির মতো 'শৃঙ্খলিত' থাকাকালীন তারা কী আচরণ শুরু করছে তা বোঝা যাবে।

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

No arrow funcs              Implicitly return `e=>{…}`    Explicitly return `e=>{…}` 
---------------------------------------------------------------------------------
function (field) {         |  field => e => {            |  field => {
  return function (e) {    |                             |    return e => {
      e.preventDefault()   |    e.preventDefault()       |      e.preventDefault()
  }                        |                             |    }
}                          |  }                          |  }

তীর সিনট্যাক্স ব্যবহার করে বেনামে ফাংশনগুলি লেখার আরেকটি সুবিধা হ'ল এগুলি সংজ্ঞায়িত হয় এমন স্কোপের সাথে তারা নমনীয়ভাবে আবদ্ধ থাকে। থেকে MDN এ 'অ্যারো ফাংশন' :

একটি তীর ফাংশন অভিব্যক্তি তুলনায় খাটো সিনট্যাক্স হয়েছে ফাংশন এক্সপ্রেশন এবং আভিধানিক binds এই মান। তীর ফাংশন সবসময় বেনামে থাকে

এটি আপনার উদাহরণে বিশেষত প্রাসঙ্গিক এটি বিবেচনা করে যে এটি একটি থেকে নেওয়া হয়েছে আবেদন। হিসাবে @naomik দ্বারা সরু আউট হিসাবে, আপনি প্রায়ই একটি অ্যাক্সেস প্রতিক্রিয়া উপাদান এর সদস্য ফাংশন ব্যবহার this। উদাহরণ স্বরূপ:

Unbound                     Explicitly bound            Implicitly bound 
------------------------------------------------------------------------------
function (field) {         |  function (field) {       |  field => e => {
  return function (e) {    |    return function (e) {  |    
      this.setState(...)   |      this.setState(...)   |    this.setState(...)
  }                        |    }.bind(this)           |    
}                          |  }.bind(this)             |  }

53

একটি সাধারণ টিপ, আপনি যদি নতুন কোনও জেএস সিনট্যাক্স সম্পর্কে বিভ্রান্ত হন এবং এটি কীভাবে সংকলিত হবে, আপনি বাবেল পরীক্ষা করতে পারেন । উদাহরণস্বরূপ আপনার বাবেলে কোডটি অনুলিপি করা এবং es2015 প্রিসেটটি নির্বাচন করা এই জাতীয় ফলাফল দেয় output

handleChange = function handleChange(field) {
 return function (e) {
 e.preventDefault();
  // Do something here
   };
 };

Babel


42

এটিকে এভাবে ভাবুন, আপনি যখনই একটি তীর দেখেন, আপনি এটির সাথে প্রতিস্থাপন করেন function
function parametersতীর আগে সংজ্ঞায়িত করা হয়।
সুতরাং আপনার উদাহরণে:

field => // function(field){}
e => { e.preventDefault(); } // function(e){e.preventDefault();}

এবং তারপরে একসাথে:

function (field) { 
    return function (e) { 
        e.preventDefault(); 
    };
}

ডক্স থেকে :

// Basic syntax:
(param1, param2, paramN) => { statements }
(param1, param2, paramN) => expression
   // equivalent to:  => { return expression; }

// Parentheses are optional when there's only one argument:
singleParam => { statements }
singleParam => expression

6
বর্ণিতভাবে আবদ্ধ উল্লেখ করতে ভুলবেন না this
আপনাকে ধন্যবাদ

30

সংক্ষিপ্ত এবং সহজ 🎈

এটি এমন একটি ফাংশন যা সংক্ষিপ্তভাবে লিখিত অন্য ফাংশনটি প্রদান করে।

const handleChange = field => e => {
  e.preventDefault()
  // Do something here
}

// is equal to 
function handleChange(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
  }
}

লোকেরা কেন এটি করে

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

উদাহরণস্বরূপ আমাদের buttonসাথে অনক্লিক কলব্যাক রয়েছে। এবং আমাদের ফাংশনটিতে যেতে হবে id, তবে onClickকেবল একটি প্যারামিটার গ্রহণ করে event, আমরা এর মতো অতিরিক্ত পরামিতিগুলি পাস করতে পারি না:

const handleClick = (event, id) {
  event.preventDefault()
  // Dispatch some delete action by passing record id
}

এটি কাজ করবে না!

অতএব আমরা একটি ফাংশন তৈরি করি যা কোনও বৈশ্বিক ভেরিয়েবলগুলি ব্যতীত নিজস্ব ভেরিয়েবলগুলির নিজস্ব স্কোপ সহ অন্যান্য ফাংশনকে ফিরিয়ে দেবে, কারণ বিশ্বব্যাপী ভেরিয়েবলগুলি খারাপ 😈

ফাংশনটির নীচে handleClick(props.id)}ডাকা হবে এবং একটি ফাংশন ফিরিয়ে দেবে এবং এটি idতার পরিধিতে থাকবে! এটি কতবার চাপবে আইডিগুলি একে অপরকে প্রভাবিত করবে না বা পরিবর্তন করবে না, সেগুলি সম্পূর্ণ বিচ্ছিন্ন।

const handleClick = id => event {
  event.preventDefault()
  // Dispatch some delete action by passing record id
}

const Confirm = props => (
  <div>
    <h1>Are you sure to delete?</h1>
    <button onClick={handleClick(props.id)}>
      Delete
    </button>
  </div
)

2

আপনার প্রশ্নের উদাহরণটি হ'ল এটি curried functionযা প্রথম যুক্তির জন্য ব্যবহার করে arrow functionএবং তা একটি implicit return

অ্যারো ফাংশনটি এটিকে সঠিকভাবে আবদ্ধ করুন অর্থাত্ তাদের নিজস্ব thisযুক্তি নেই তবে thisনিক্ষিপ্ত সুযোগ থেকে মানটি নিয়ে যান

উপরের কোডটির সমতুল্য হবে

const handleChange = (field) {
  return function(e) {
     e.preventDefault();
     /// Do something here
  }.bind(this);
}.bind(this);

আপনার উদাহরণের জন্য আরও একটি বিষয় লক্ষণীয় হ'ল এটি handleChangeকনস্ট বা কোনও ফাংশন হিসাবে সংজ্ঞায়িত । সম্ভবত আপনি এটি একটি শ্রেণিবদ্ধের অংশ হিসাবে ব্যবহার করছেন এবং এটি একটি ব্যবহার করেclass fields syntax

সুতরাং বাইরের ফাংশনটি সরাসরি বাঁধার পরিবর্তে, আপনি এটি ক্লাস কনস্ট্রাক্টরে আবদ্ধ করবেন

class Something{
    constructor(props) {
       super(props);
       this.handleChange = this.handleChange.bind(this);
    }
    handleChange(field) {
        return function(e) {
           e.preventDefault();
           // do something
        }
    }
}

উদাহরণে অন্য একটি বিষয় লক্ষণীয় যা অন্তর্নিহিত এবং সুস্পষ্ট রিটার্নের মধ্যে পার্থক্য।

const abc = (field) => field * 2;

উপরে নিহিত প্রত্যাবর্তনের উদাহরণ উদাহরণস্বরূপ। এটি আর্গুমেন্ট হিসাবে মান ক্ষেত্র গ্রহণ করে এবং ফলাফলটি প্রত্যাবর্তন করে field*2যা ফাংশনটি স্পষ্টভাবে ফিরিয়ে দেয় returns

সুস্পষ্ট ফেরতের জন্য আপনি স্পষ্টভাবে মানটি ফেরত দেওয়ার পদ্ধতিটি বলবেন

const abc = () => { return field*2; }

তীরের ক্রিয়াকলাপগুলি সম্পর্কে আরও একটি বিষয় লক্ষণীয় তা হ'ল তাদের নিজস্ব argumentsনয় তবে এটি পিতামাতার সুযোগ থেকেও উত্তরাধিকার সূত্রে প্রাপ্ত।

উদাহরণস্বরূপ, আপনি যদি ঠিক একটি তীর ফাংশন সংজ্ঞায়িত করেন

const handleChange = () => {
   console.log(arguments) // would give an error on running since arguments in undefined
}

বিকল্প তীর হিসাবে আপনি ব্যবহার করতে পারেন এমন বাকী প্যারামিটারগুলি সরবরাহ করে

const handleChange = (...args) => {
   console.log(args);
}

1

এটি সম্পূর্ণরূপে সম্পর্কিত নয়, তবে যেহেতু উল্লিখিত প্রশ্নটি প্রতিক্রিয়া দেখায় কেসটি ব্যবহার করে (এবং আমি এই সূত্রে টানতে থাকি): ডাবল তীর ফাংশনের একটি গুরুত্বপূর্ণ দিক রয়েছে যা এখানে স্পষ্টভাবে উল্লেখ করা হয়নি। কেবলমাত্র 'প্রথম' তীর (ফাংশন) এর নাম দেওয়া হয় (এবং এভাবে রান-টাইম দ্বারা 'পার্থক্যযোগ্য'), নিম্নলিখিত যে কোনও তীরগুলি বেনামে থাকে এবং প্রতিটি রেন্ডারে একটি নতুন 'অবজেক্ট হিসাবে প্রতিক্রিয়া দৃষ্টিকোণ থেকে গণনা করা হয়।

সুতরাং ডাবল তীর ফাংশন যে কোনও পিওরকমম্পোনেন্টকে সর্বদা রিরেন্ডার করে।

উদাহরণ

পরিবর্তন হ্যান্ডলার সহ আপনার পিতামাতার উপাদান রয়েছে:

handleChange = task => event => { ... operations which uses both task and event... };

এবং রেন্ডার সহ:

{ tasks.map(task => <MyTask handleChange={this.handleChange(task)}/> }

হ্যান্ডেল চেঞ্জ তারপর একটি ইনপুট বা ক্লিক ক্লিক করুন। এবং এই সব কাজ করে এবং খুব সুন্দর দেখাচ্ছে। তবে এর অর্থ হ'ল যে কোনও পরিবর্তন যার ফলে পিতামাতাকে পুনরায় রেন্ডার করতে হবে (সম্পূর্ণ সম্পর্কিত সম্পর্কযুক্ত রাষ্ট্র পরিবর্তনের মতো) এছাড়াও আপনার মাই টাস্কের সমস্ত পুনরায় রেন্ডার করবে যদিও তারা খাঁটি উপাদান রয়েছে।

এটি 'আউটমেস্ট' তীরটি পাস করা বা আপনি যে বস্তুটি এটি দিয়ে খাওয়াবেন তা পছন্দ করে বা কাস্টমস স্টুডআপডেট ফাংশন লিখতে বা নামকরণের ফাংশনগুলি লেখার মতো বেসিকগুলিতে ফিরে যাওয়া (এবং এটি নিজেই বাঁধাই করা ...) এর মতো অনেক উপায়ে হ্রাস করা যায়)

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