কফিস্ক্রিপ্ট, কখন তীর (->) ওভারের চেয়ে চর্বিযুক্ত তীর (=>) ব্যবহার করবেন


133

কফিস্ক্রিপ্টে একটি ক্লাস তৈরি করার সময়, সমস্ত উদাহরণ পদ্ধতিটি =>("ফ্যাট তীর") অপারেটর ব্যবহার করে এবং সমস্ত স্থির পদ্ধতি ->অপারেটর ব্যবহার করে সংজ্ঞায়িত করা উচিত ?


আপনি কিছু নমুনা কোড পোস্ট করতে পারেন?
12'12

এই উত্তরটি দেখুন stackoverflow.com/a/17431824/517371
টোবিয়া

উত্তর:


157

না, এটি আমি ব্যবহার করব এমন নিয়ম নয়।

সংজ্ঞা পদ্ধতিগুলিতে ফ্যাট-অ্যারোর জন্য আমি যে প্রধান ব্যবহারের সন্ধান পেয়েছি তা হ'ল আপনি যখন কোনও পদ্ধতি কলব্যাক হিসাবে ব্যবহার করতে চান এবং সেই পদ্ধতির উল্লেখ ক্ষেত্রগুলি:

class A
  constructor: (@msg) ->
  thin: -> alert @msg
  fat:  => alert @msg

x = new A("yo")
x.thin() #alerts "yo"
x.fat()  #alerts "yo"

fn = (callback) -> callback()

fn(x.thin) #alerts "undefined"
fn(x.fat)  #alerts "yo"
fn(-> x.thin()) #alerts "yo"

আপনি যেমন দেখতে পাচ্ছেন, যদি আপনি ফ্যাট-অ্যারো ব্যবহার না করেন তবে কলব্যাক হিসাবে কোনও উদাহরণের পদ্ধতির রেফারেন্সটি পাস করতে সমস্যা হতে পারে। এটি কারণ চর্বি-তীরটি বস্তুর উদাহরণকে আবদ্ধ করে thisযেখানে পাতলা-তীর থাকে না, তাই উপরের হিসাবে কলব্যাকস নামে পরিচিত পাতলা-তীর পদ্ধতিগুলি উদাহরণের ক্ষেত্রগুলিতে অ্যাক্সেস করতে @msgবা অন্য উদাহরণ পদ্ধতিগুলিতে কল করতে পারে না । পাতলা-তীরটি ব্যবহৃত হয়েছে এমন ক্ষেত্রে লাইনটি শেষের দিকে কাজ করে।


2
আপনি যখন thisপাতলা তীর থেকে ডাকা হবে এটি ব্যবহার করতে চান , তবে আপনি চর্বিযুক্ত তীরের সাথে উদাহরণের পরিবর্তনশীলগুলি কী করতে চান?
অ্যান্ড্রু মাও

যেমনটি আমি বলেছিলাম "পাতলা-তীরটি ব্যবহৃত হয়েছে এমন ক্ষেত্রে শেষ পংক্তিতে একটি কার্যকারিতা রয়েছে।"
নিকোলস্ক্রুচটেন

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

@ অ্যান্ড্রুম্যাও আপনার মন্তব্য সম্পর্কে আমার উত্তর না দেওয়ার চেয়ে এই সাইটটিতে সম্ভবত একটি পূর্ণ প্রশ্ন পোস্ট করা উচিত :)
নিকোলাসক্রুচটেন

এটা ঠিক আছে, প্রশ্ন এত গুরুত্বপূর্ণ নয়। তবে আমি কেবল স্পষ্ট করে বলতে চেয়েছিলাম যে আপনার কোডের শেষ লাইনে আপনি উল্লেখ করছেন এটি নয়।
অ্যান্ড্রু মাও

13

অন্যান্য উত্তরে উল্লেখ করা হয়নি এমন একটি পয়েন্ট যা উল্লেখ করা গুরুত্বপূর্ণ, তা হ'ল চর্বিযুক্ত তীরযুক্ত বাঁধাকরণের কাজগুলি যখন অপ্রয়োজনীয় ফলাফলের দিকে পরিচালিত করে তবে যেমন উদাহরণস্বরূপ একটি শ্রেণীর সাথে আমরা কেবল ডামি ক্লাস কল করব।

class DummyClass
    constructor : () ->
    some_function : () ->
        return "some_function"

    other_function : () =>
        return "other_function"

dummy = new DummyClass()
dummy.some_function() == "some_function"     # true
dummy.other_function() == "other_function"   # true

এক্ষেত্রে ফাংশনগুলি ঠিক কীভাবে প্রত্যাশা করে এবং চর্বিযুক্ত তীর ব্যবহারের কোনও ক্ষতি হয় বলে মনে হয় না, তবে ডাম্মি ক্লাসের প্রোটোটাইপটি সংজ্ঞায়িত হওয়ার পরে আমরা কী করব যখন (কিছু সতর্কতা পরিবর্তন করা বা লগের আউটপুট পরিবর্তন করা) :

DummyClass::some_function = ->
    return "some_new_function"

DummyClass::other_function = ->
    return "other_new_function"

dummy.some_function() == "some_new_function"   # true
dummy.other_function() == "other_new_function" # false
dummy.other_function() == "other_function"     # true

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

DummyClass::other_function = =>
    return "new_other_new_function"

dummy.other_function() == "new_other_new_function"    # false

second_dummy = new DummyClass()
second_dummy.other_function() == "new_other_new_function"   # true

এমনকি চর্বিযুক্ত তীর ফ্যাটযুক্ত তীর হিসাবে কাজ করবে না কেবলমাত্র ফাংশনটিকে নতুন দৃষ্টিতে আবদ্ধ করতে হবে (যা প্রত্যাশায় নতুন ফাংশনগুলি অর্জন করে)।

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

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

class SomeClass
    constructor : () ->
        @data = 0
    _do_something : () ->
        return @data
    do_something : () =>
        @_do_something()

something = new SomeClass()
something.do_something() == 0     # true
event_handler = something.do_something
event_handler() == 0              # true

SomeClass::_do_something = -> return @data + 1

something.do_something() == 1     # true
event_handler() == 1              # true

সুতরাং যখন পাতলা / চর্বিযুক্ত তীরগুলি ব্যবহার করা যায় তখন চারটি উপায়ে মোটামুটি সহজভাবে সংক্ষিপ্ত করা যায়:

  1. উভয় শর্ত মেটাতে গেলে পাতলা তীর একা ফাংশন ব্যবহার করা উচিত:

    • ইভেন্ট_হ্যান্ডলারগুলি সহ পদ্ধতিটি কখনই রেফারেন্স দ্বারা পাস করা হবে না eg যেমন আপনার কোনও ক্ষেত্রে কখনও যেমন নেই: কিছু_প্রেমীকরণ = কিছু_ইনস্ট্যান্স.সোম_মোথড; some_reference ()
    • এবং পদ্ধতিটি সমস্ত দৃষ্টান্তের ক্ষেত্রে সর্বজনীন হওয়া উচিত তাই যদি প্রোটোটাইপ ফাংশনটি পরিবর্তিত হয় তবে পদ্ধতিটি সমস্ত দৃষ্টান্তগুলিতে পরিবর্তিত হয়
  2. নিম্নলিখিত শর্তটি পূরণ করার সময় একা ফ্যাট অ্যারো ফাংশন ব্যবহার করা উচিত:

    • উদাহরণটি তৈরির সময় পদ্ধতিটি যথাযথভাবে আবদ্ধ হওয়া উচিত এবং প্রোটোটাইপের জন্য ফাংশন সংজ্ঞা পরিবর্তিত হলেও স্থায়ীভাবে আবদ্ধ থাকা উচিত, এতে ফাংশনটি ইভেন্ট হ্যান্ডলার হওয়া উচিত এবং ইভেন্ট হ্যান্ডলারের আচরণটি সামঞ্জস্যপূর্ণ হওয়া উচিত এমন সব ক্ষেত্রেই এটি অন্তর্ভুক্ত থাকে where
  3. নিম্নোক্ত শর্তগুলি পূরণ করার সময় ফ্যাট অ্যার ফাংশন যা সরাসরি একটি পাতলা তীর ফাংশন বলে used

    • কোনও ইভেন্ট হ্যান্ডলারের মতো পদ্ধতিটি রেফারেন্স দ্বারা কল করা প্রয়োজন
    • এবং ভবিষ্যতে পাতলা তীর ফাংশনটি প্রতিস্থাপন করে বিদ্যমান উদাহরণগুলিকে প্রভাবিত করে কার্যকারিতা পরিবর্তন হতে পারে
  4. নীচের শর্তগুলি পূরণ করার সময় পাতলা তীর ফাংশন যা সরাসরি ফ্যাট এ্যার (প্রদর্শিত হয় না) ফাংশন ব্যবহার করা উচিত:

    • ফ্যাট অ্যার ফাংশনটি সর্বদা উদাহরণের সাথে সংযুক্ত থাকতে হবে
    • তবে পাতলা তীর ফাংশনটি পরিবর্তিত হতে পারে (এমন কোনও নতুন ফাংশনেও যা মূল ফ্যাট তীর ফাংশন ব্যবহার করে না)
    • এবং পাতলা তীর ফাংশনটি কখনই রেফারেন্স দিয়ে পাস করার প্রয়োজন হয় না

সমস্ত পদ্ধতির ক্ষেত্রে এটি অবশ্যই বিবেচনা করা উচিত যেখানে নির্দিষ্ট উদাহরণগুলির জন্য আচরণ সঠিকভাবে আচরণ করবে কিনা তা প্রোটোটাইপ ফাংশনগুলিতে পরিবর্তিত হতে পারে উদাহরণস্বরূপ যদি কোনও ফাংশন ফ্যাট ফর্সের সাথে সংজ্ঞায়িত করা হয় তবে এটি আচরণ করলে এটি এর আচরণের সাথে সামঞ্জস্য হতে পারে না যদি এটি কল করে প্রোটোটাইপের মধ্যে পরিবর্তিত একটি পদ্ধতি


9

সাধারণত, ->ঠিক আছে।

class Foo
  @static:  -> this
  instance: -> this

alert Foo.static() == Foo # true

obj = new Foo()
alert obj.instance() == obj # true

স্থির পদ্ধতি কীভাবে শ্রেণীর অবজেক্টের জন্য thisফেরত দেয় এবং উদাহরণটি উদাহরণ বস্তুর জন্য ফিরে আসে তা নোট করুন this

যা হচ্ছে তা হ'ল আমন্ত্রণ সিনট্যাক্সটি এর মান সরবরাহ করছে this। এই কোডে:

foo.bar()

foobar()ডিফল্টরূপে ফাংশনটির প্রসঙ্গ হবে । সুতরাং এটি কেবল বাছাই কিভাবে আপনি চান কাজ করে। আপনি কেবলমাত্র ফ্যাট তীর প্রয়োজন যখন আপনি এই ফাংশনটিকে অন্য কোনও উপায়ে কল করেন যা বিনয়ের জন্য বিন্দু সিনট্যাক্স ব্যবহার করে না।

# Pass in a function reference to be called later
# Then later, its called without the dot syntax, causing `this` to be lost
setTimeout foo.bar, 1000

# Breaking off a function reference will lose it's `this` too.
fn = foo.bar
fn()

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

->আপনার যতক্ষণ =>না প্রয়োজন অবধি ব্যবহার করুন এবং কখনই =>ডিফল্টরূপে ব্যবহার করবেন না use


1
আপনি যদি এটি করেন তবে এটি ব্যর্থ হবে:x = obj.instance; alert x() == obj # false!
নিকোলাস্ক্রুচেন

2
অবশ্যই এটি হবে তবে এটি "এটি ভুল করে" এর আওতায় পড়বে। আমি এখন আমার উত্তরটি সম্পাদনা করেছি এবং =>শ্রেণীর স্থির / দৃষ্টান্ত পদ্ধতিতে কখন প্রয়োজন হবে তা ব্যাখ্যা করেছি ।
অ্যালেক্স ওয়েইন

Nitpick: // is not a CoffeeScript commentযেহেতু # is a CoffeeScript comment
নিকোলাস্ক্রুচেন

কীভাবে setTimeout foo.bar, 1000"এটি ভুল করছেন"? setTimeout (-> foo.bar()), 1000আইএমএইচও ব্যবহারের চেয়ে ফ্যাট- এ্যার ব্যবহার করা অনেক সুন্দর ।
নিকোলাসক্রুচেন

1
@nicolaskruchten setTimeoutঅবশ্যই সিনট্যাক্সের ক্ষেত্রে অবশ্যই একটি মামলা রয়েছে । তবে আপনার প্রথম মন্তব্যটি কিছুটা স্বতন্ত্র এবং এটি বৈধ ব্যবহারের কেসটি প্রকাশ করে না, তবে কীভাবে এটি ভেঙে যেতে পারে তা কেবল প্রকাশ করে। আমি কেবল বলছি যে আপনার =>যদি কোনও ভাল কারণে প্রয়োজন না হয় তবে আপনি এটি ব্যবহার করবেন না , বিশেষত শ্রেণীর উদাহরণ পদ্ধতিগুলিতে যেখানে এটির জন্য একটি নতুন ফাংশন তৈরির জন্য পারফরম্যান্স ব্যয় রয়েছে যা ইনস্ট্যান্টেশনে আবদ্ধ হওয়া প্রয়োজন।
অ্যালেক্স ওয়েন

5

চর্বিযুক্ত তীর আনস্ট্যান্ড করার জন্য কেবল একটি উদাহরণ

কাজ করে না: (@ স্ক্যানভাস অপরিবর্তিত)

class Test
  constructor: ->
    @canvas = document.createElement 'canvas'
    window.addEventListener 'resize', ->
      @canvas.width = window.innerWidth
      @canvas.height = window.innerHeight

কাজগুলি: (@ স্ক্যানভাস সংজ্ঞায়িত)

class Test
  constructor: ->
    @canvas = document.createElement 'canvas'
    window.addEventListener 'resize', =>
      @canvas.width = window.innerWidth
      @canvas.height = window.innerHeight
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.