কলব্যাকের অভ্যন্তরে কীভাবে সঠিক - এটি অ্যাক্সেস করবেন?


1425

আমার কাছে একটি কনস্ট্রাক্টর ফাংশন রয়েছে যা ইভেন্ট হ্যান্ডলারটিকে রেজিস্টার করে:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

তবে আমি dataকলব্যাকের অভ্যন্তরে তৈরি হওয়া সামগ্রীর সম্পত্তি অ্যাক্সেস করতে পারছি না । দেখে মনে হচ্ছে এটি thisতৈরি করা অবজেক্টটিকে বোঝায় না তবে অন্য একটিতে।

আমি বেনামে ফাংশনের পরিবর্তে কোনও অবজেক্ট পদ্ধতি ব্যবহার করার চেষ্টা করেছি:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

তবে এটি একই সমস্যাগুলি প্রদর্শন করে।

আমি কীভাবে সঠিক জিনিসটি অ্যাক্সেস করতে পারি?


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



উত্তর:


1789

আপনার যা জানা উচিত this

this(ওরফে "প্রসঙ্গ") প্রতিটি ফাংশন ভিতরে একটি বিশেষ শব্দ এবং এর মান শুধুমাত্র উপর নির্ভর করে কিভাবে ফাংশন, বলা হত কিভাবে / যখন / এটি যেখানে সংজ্ঞায়িত করা হয়। এটি অন্যান্য ভেরিয়েবলের মতো লেক্সিকাল স্কোপগুলি দ্বারা প্রভাবিত হয় না (তীর ফাংশন ব্যতীত নীচে দেখুন)। এখানে কিছু উদাহরন:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

এ সম্পর্কে আরও জানতে this, MDN ডকুমেন্টেশনটি দেখুন


কিভাবে সঠিক উল্লেখ করুন this

ব্যবহার করবেন না this

আপনি আসলে thisবিশেষভাবে অ্যাক্সেস করতে চান না , তবে যে বিষয়টি তাকে বোঝায় । একারণে একটি সহজ সমাধান হ'ল একটি নতুন ভেরিয়েবল তৈরি করা যা সেই বস্তুকে বোঝায়। ভেরিয়েবলের কোনও নাম থাকতে পারে তবে সাধারণগুলি হ'ল selfএবং that

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

যেহেতু selfএকটি সাধারণ পরিবর্তনশীল তাই এটি লেক্সিক স্কোপ বিধি মেনে চলে এবং কলব্যাকের অভ্যন্তরে প্রবেশযোগ্য। এটিরও সুবিধা রয়েছে যে আপনি thisকলব্যাকের মানটি নিজেই অ্যাক্সেস করতে পারবেন ।

স্পষ্টভাবে thisকলব্যাক সেট - অংশ 1

দেখে মনে হতে পারে এর মানটির উপর আপনার কোনও নিয়ন্ত্রণ নেই thisকারণ এর মানটি স্বয়ংক্রিয়ভাবে সেট হয়ে গেছে তবে বাস্তবে তা নয়।

প্রতিটি .bind ফাংশনটিতে পদ্ধতি [ডক্স] থাকে , যা thisএকটি মানকে আবদ্ধ করে একটি নতুন ফাংশন প্রদান করে । ফাংশনটির ঠিক তেমন আচরণ রয়েছে যা আপনি ডেকেছিলেন .bind, কেবল এটিই আপনার thisদ্বারা সেট করা হয়েছিল। কীভাবে বা কখন যে ফাংশনটি বলা হয় তা বিবেচনা করা যায় না, thisসর্বদা উত্তীর্ণ হওয়া মানটি উল্লেখ করে।

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

এই ক্ষেত্রে, আমরা কলব্যাক এর বাঁধাই করা হয় thisএর মান MyConstructorএর this

দ্রষ্টব্য: jQuery- র জন্য প্রসঙ্গ বাঁধাই করার পরিবর্তে jQuery.proxy [ডক্স] এর পরিবর্তে ব্যবহার করুন। এটি করার কারণটি হ'ল যাতে ইভেন্ট কলব্যাক বন্ধন করার সময় আপনাকে ফাংশনের রেফারেন্সটি সঞ্চয় করতে হবে না। jQuery অভ্যন্তরীণভাবে পরিচালনা করে।

ECMAScript 6: তীর ফাংশন ব্যবহার করুন

ইসমাস্ক্রিপ্ট arrow তীর ফাংশনগুলি উপস্থাপন করে যা ল্যাম্বদা ফাংশন হিসাবে বিবেচনা করা যেতে পারে। তাদের নিজস্ব thisবাঁধাই নেই। পরিবর্তে, thisএকটি সাধারণ ভেরিয়েবলের মতো স্কোপের দিকে তাকানো হয়। তার মানে আপনাকে কল করতে হবে না .bind। এটি তাদের একমাত্র বিশেষ আচরণ নয়, আরও তথ্যের জন্য দয়া করে MDN ডকুমেন্টেশন পড়ুন।

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

thisকলব্যাক সেট - অংশ 2

কিছু ফাংশন / পদ্ধতি যা কলব্যাকগুলি গ্রহণ করে সেগুলি এমন একটি মানও গ্রহণ করে যার সাথে কলব্যাকগুলি thisউল্লেখ করা উচিত। এটি মূলত এটি নিজেকে বাঁধাই করার সমান, তবে কার্য / পদ্ধতিটি এটি আপনার জন্য করে। Array#map [ডক্স] হল একটি পদ্ধতি such এর স্বাক্ষরটি হ'ল:

array.map(callback[, thisArg])

প্রথম যুক্তি হ'ল কলব্যাক এবং দ্বিতীয় যুক্তি হ'ল মানটি thisউল্লেখ করা উচিত। এখানে একটি স্বীকৃত উদাহরণ:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

দ্রষ্টব্য: আপনি কোনও মান পাস করতে পারবেন কিনা thisতা সাধারণত সেই ফাংশন / পদ্ধতির ডকুমেন্টেশনে উল্লেখ করা হয়। উদাহরণস্বরূপ, jQuery এর $.ajaxপদ্ধতি [ডক্স] নামক একটি বিকল্প বর্ণনা করে context:

এই অবজেক্টটি সমস্ত অ্যাজাক্স-সম্পর্কিত কলব্যাকের প্রসঙ্গ তৈরি করা হবে।


সাধারণ সমস্যা: কলব্যাক / ইভেন্ট হ্যান্ডলার হিসাবে অবজেক্টের পদ্ধতি ব্যবহার করা

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

নিম্নলিখিত উদাহরণ বিবেচনা করুন:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

ফাংশনটি this.methodক্লিক ইভেন্ট হ্যান্ডলার হিসাবে বরাদ্দ করা হয়েছে, তবে যদি document.bodyক্লিক করা হয় তবে লগ করা মানটি হবে undefined, কারণ ইভেন্ট হ্যান্ডলারের অভ্যন্তরে, উদাহরণটিকে নয় , thisবোঝায় । ইতিমধ্যে শুরুতে উল্লিখিত হিসাবে, কী বোঝায় ফাংশনটি কীভাবে ডাকা হয় তার উপর নির্ভর করে না কীভাবে এটি সংজ্ঞায়িত হয় । কোডটি যদি নীচের মতো হয় তবে এটি আরও স্পষ্ট হতে পারে যে ফাংশনটির অবজেক্টটির অন্তর্নিহিত রেফারেন্স নেই:document.bodyFoo
this

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

সমাধানটি উপরে উল্লিখিত হিসাবে একই: যদি উপলভ্য .bindথাকে তবে স্পষ্টভাবে thisনির্দিষ্ট মানকে আবদ্ধ করতে ব্যবহার করুন

document.body.onclick = this.method.bind(this);

বা স্পষ্টভাবে কলজব্যাক / ইভেন্ট হ্যান্ডলার হিসাবে একটি বেনামি ফাংশন ব্যবহার করে অবজেক্টটির "পদ্ধতি" হিসাবে ফাংশনটি কল করুন এবং অবজেক্টটিকে ( this) অন্য ভেরিয়েবলের জন্য বরাদ্দ করুন :

var self = this;
document.body.onclick = function() {
    self.method();
};

বা একটি তীর ফাংশন ব্যবহার করুন:

document.body.onclick = () => this.method();

39
ফেলিক্স, আমি এই উত্তরটি আগেও পড়েছি তবে কখনও উত্তর দেয় নি। আমি চিন্তিত হয়ে উঠি যে লোকেরা ব্যবহার করে selfএবং thatতা উল্লেখ করে this। আমি এইভাবে অনুভব করি কারণ thisবিভিন্ন প্রসঙ্গে ব্যবহৃত হওয়া একটি ওভারলোডেড ভেরিয়েবল; যদিও selfসাধারণত স্থানীয় উদাহরণের সাথে মিলে যায় এবং thatসাধারণত অন্য কোনও বস্তুকে বোঝায়। আমি জানি যে আপনি এই নিয়মটি সেট করেন নি, যেমনটি আমি দেখেছি এটি অন্যান্য বেশ কয়েকটি স্থানে প্রদর্শিত হয়েছিল, তবে এটিই কেন আমি ব্যবহার শুরু করেছি _thisতবে অ-ইউনিফর্ম অনুশীলন বাদে অন্যেরা কেমন অনুভব করছেন তা নিশ্চিত নই ফলস্বরূপ।
ভোলআরন

3
@ ফেলিক্সক্লিং কি এটি ধরে রাখা নিরাপদ হবে যে এই অভ্যন্তরীণ প্রোটোটাইপ ফাংশনগুলি ব্যবহার করে তাদের (সাধারণত) বলা যাই হোক না কেন সর্বদা প্রত্যাশিত আচরণ থাকবে? প্রোটোটাইপ ফাংশনগুলির মধ্যে কলব্যাকগুলি ব্যবহার করার সময়, বাঁধনের () বিকল্পের কোনও বিকল্প নেই, স্ব বা এটি?
andig

5
@ ফেলিক্সক্লিং এটি নির্ভর করে Function.prototype.call ()এবং এর উপর সময়ে সময়ে দরকারী হতে পারে Function.prototype.apply ()। বিশেষত apply ()আমি অনেক মাইলেজ পেয়েছি। আমি bind ()কেবল অভ্যাসের বাইরে সম্ভবত ব্যবহার করতে আগ্রহী না যদিও আমি সচেতন (তবে নিশ্চিত না) যে অন্যান্য বিকল্পগুলির সাথে বাইন্ড ব্যবহার করার ক্ষেত্রে সামান্য ওভারহেড সুবিধা থাকতে পারে।
নোলো

5
দুর্দান্ত উত্তর তবে একটি অতিরিক্ত alচ্ছিক সমাধান যোগ করার বিষয়টি বিবেচনা করুন যা কেবল ক্লাস, নতুন বা এটি মোটেও ব্যবহার না করা।
আলুয়ান হাদাদ

4
পুনরুদ্ধার তীর ফাংশন "পরিবর্তে, এটিকে সাধারণ ভেরিয়েবলের মতো স্কোপে দেখানো হয়।" সম্পূর্ণ আমার জন্য এই ক্লিক করেছেন, আপনাকে ধন্যবাদ! () => this.clicked();)
alphanumeric0101

211

সন্তানের প্রসঙ্গে অভ্যন্তরীণ প্রসঙ্গে অ্যাক্সেসের বেশ কয়েকটি উপায় এখানে রয়েছে -

  1. তুমি ব্যবহার করতে পার bind() ফাংশন ।
  2. প্রসঙ্গের জন্য স্টোর রেফারেন্স / এটি অন্য ভেরিয়েবলের অভ্যন্তরে (নীচের উদাহরণ দেখুন)।
  3. ES6 তীর ব্যবহার করুন ফাংশন ।
  4. কোড / ফাংশন ডিজাইন / আর্কিটেকচার পরিবর্তন করুন - এর জন্য আপনার জাভাস্ক্রিপ্টে নকশার নিদর্শনগুলির উপর কমান্ড থাকা উচিত ।

1. bind()ফাংশন ব্যবহার করুন

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

আপনি যদি ব্যবহার করেন underscore.js- http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

2 প্রসঙ্গের জন্য স্টোর রেফারেন্স / এটি অন্য ভেরিয়েবলের মধ্যে

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3 তীর ফাংশন

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

1
বাঁধাই () বিকল্পটি অন্য অবজেক্টটিতে এটি হওয়ার জন্য এই অবজেক্টটির পয়েন্টারটি কেবলমাত্র উত্তীর্ণ করা আশ্চর্যজনক (: ধন্যবাদ!
স্টাভ বডিক

বাঁধাই () কবজির মতো কাজ করে। আপনাকে আমার কাছ থেকে অনেক অনেক ধন্যবাদ :)
অঞ্জনা সিলভা

56

এটি সমস্তই কোনও পদ্ধতি কল করার "যাদু" সিনট্যাক্সে রয়েছে:

object.property();

আপনি যখন বস্তুর কাছ থেকে সম্পত্তিটি পাবেন এবং একযোগে কল করবেন তখন অবজেক্টটি পদ্ধতির প্রসঙ্গ হবে। আপনি যদি একই পদ্ধতিটিকে কল করেন তবে পৃথক পদক্ষেপে প্রসঙ্গটি হ'ল বৈশ্বিক সুযোগ (উইন্ডো) পরিবর্তে:

var f = object.property;
f();

আপনি যখন কোনও পদ্ধতির রেফারেন্স পাবেন, এটি আর কোনও বস্তুর সাথে সংযুক্ত থাকবে না, এটি কেবল একটি সরল ফাংশনের একটি রেফারেন্স। আপনি যখন কলব্যাক হিসাবে ব্যবহারের রেফারেন্স পাবেন তখন একই ঘটনা ঘটে:

this.saveNextLevelData(this.setAll);

আপনি এখানে ফাংশনটির প্রসঙ্গটি আবদ্ধ করবেন:

this.saveNextLevelData(this.setAll.bind(this));

আপনি যদি jQuery ব্যবহার করছেন তবে এর $.proxyপরিবর্তে আপনার পদ্ধতিটি ব্যবহার করা উচিত , bindযা সমস্ত ব্রাউজারগুলিতে সমর্থিত নয়:

this.saveNextLevelData($.proxy(this.setAll, this));

33

"প্রসঙ্গ" সাথে ঝামেলা

শব্দ "প্রসঙ্গ" কখনও কখনও বস্তু দ্বারা রেফারেন্সড নির্দেশ করতে ব্যবহার করা হয় এই । এর ব্যবহারের অনুপযুক্ত কারণ এটা হয় শব্দার্থগতভাবে বা টেকনিক্যালি মাপসই করা হবে না সঙ্গে ECMAScript প্রোগ্রামিং এর এই

"প্রসঙ্গ" এর অর্থ এমন কোনও কিছুকে ঘিরে পরিস্থিতি যা অর্থ যোগ করে বা কিছু পূর্ববর্তী এবং নিম্নলিখিত তথ্য যা অতিরিক্ত অর্থ দেয়। "প্রসঙ্গ" শব্দটি ECMAScript এ প্রয়োগের প্রসঙ্গে উল্লেখ করা হয় যা সমস্ত পরামিতি, স্কোপ এবং এটি কিছু নির্বাহী কোডের পরিধির মধ্যে থাকে।

এটি ECMA-262 বিভাগ 10.4.2 এ প্রদর্শিত হবে :

কলিং এক্সিকিউশন প্রসঙ্গের এই বাঁধাইয়ের মতো একই মানটিতে এই বাঁধাইটি সেট করুন

যা স্পষ্টভাবে ইঙ্গিত করে যে এটি একটি সম্পাদন প্রসঙ্গে একটি অংশ।

একটি নির্বাহের প্রসঙ্গটি পার্শ্ববর্তী তথ্য সরবরাহ করে যা সম্পাদিত হচ্ছে এমন কোডের সাথে অর্থ যোগ করে। এটিতে এই বাইন্ডিংয়ের চেয়ে অনেক বেশি তথ্য অন্তর্ভুক্ত রয়েছে ।

তাই এর মান এই "প্রসঙ্গ" নয়, এটি একটি মৃত্যুদন্ড প্রসঙ্গের মাত্র এক অংশ। এটি মূলত একটি স্থানীয় পরিবর্তনশীল যা কোনও বস্তুর কাছে এবং কঠোর মোডে, যে কোনও মূল্যে কল করে সেট করা যায় can


এই উত্তরের সাথে একমত হতে পারে না। "এক্সিকিউশন কনটেস্ট" শব্দটির অস্তিত্ব "প্রাসঙ্গিক" এর অন্যান্য ব্যবহারগুলিকে "মৃত্যুদন্ড" এর অন্যান্য ব্যবহারগুলিকে অস্বীকৃতি জানায় না। বর্ণনার জন্য আরও ভাল শব্দ থাকতে পারে thisতবে এখানে কোনওটিই দেওয়া হয় না এবং "প্রসঙ্গে" দরজাটি বন্ধ করতে তর্কাতীতভাবে দেরি হয়ে যায়।
রোমের -1888

@ রোমের -1888 the সম্পাদনার জন্য আপনাকে ধন্যবাদ। আপনি ঠিক বলেছেন, কিন্তু আমার যুক্তি অন্য কিছু উদ্দেশ্যে "প্রসঙ্গ" এর প্রসঙ্গকে বাদ দিয়ে "কার্যকর করা প্রসঙ্গ" এর অস্তিত্বের উপর নির্ভর করে না। বরং এটি প্রযুক্তিগত এবং শব্দার্থক উভয় দৃষ্টিকোণ থেকে অনুপযুক্ত "প্রসঙ্গের" ভিত্তিতে। আমি আরও মনে করি "এই" এর পরিবর্তে "প্রসঙ্গ" এর ব্যবহার মরে যাচ্ছে। আমি বিকল্প মেয়াদ এটি কোন কারণে দেখতে না এই বা thisBinding , এটা ঠিক obfuscates এবং কিছু বিন্দু আপনি যে "প্রসঙ্গ" ব্যাখ্যা আছে এ উপায়ে আসলে এই , এবং এটি যাহাই হউক না কেন "প্রসঙ্গ" এ নয়। :-)
রবজি

আমি মনে করি না আপনি বলতে পারেন যে এই কোন ভাবেই "প্রসঙ্গ" নয়, যখন আপনি ইতিমধ্যে admittted যে এটি একটি মৃত্যুদন্ড প্রসঙ্গ, যেখানে "সম্পাদন" নিছক বিশেষণ হয় এক অংশ।
রোমের -1888

@ রোমের -1888 — আমি এই কথার আগে এই কথোপকথনটি চালিয়ে যাব না। হ্যাঁ, এই হল অংশ একটি মৃত্যুদন্ড প্রসঙ্গের। বলছে এটা প্রসঙ্গ বলার অপেক্ষা রাখে না একটি দল এক খেলোয়াড় দল ভালো হয়।
রবিজি

রবজি, করুণা আপনি চালিয়ে যেতে চান না। এটি একটি আকর্ষণীয় বিতর্ক। আমাকে আপনার সময় দেওয়ার জন্য ধন্যবাদ
রোমের -1888

31

"এই" কীওয়ার্ড সম্পর্কে আপনার জানা উচিত।

আমার মতামত অনুসারে আপনি তিনটি উপায়ে "এটি" প্রয়োগ করতে পারেন (স্ব / তীর ফাংশন / বাঁধাই পদ্ধতি)

একটি ফাংশনের এই কীওয়ার্ডটি অন্য ভাষার তুলনায় জাভাস্ক্রিপ্টে কিছুটা আলাদাভাবে আচরণ করে।

কড়া মোড এবং অ-কঠোর মোডের মধ্যেও এর কিছু পার্থক্য রয়েছে।

বেশিরভাগ ক্ষেত্রে, এর মান নির্ধারণ করা হয় কীভাবে কোনও ফাংশন বলা হয়।

এক্সিকিউশন চলাকালীন এটি অ্যাসাইনমেন্টের মাধ্যমে সেট করা যায় না এবং প্রতিটি সময় ফাংশনটি বলা হওয়ার পরে এটি আলাদা হতে পারে।

ES5 একটি ফাংশনটির মান নির্ধারণের জন্য বাইন্ড () পদ্ধতিটি প্রবর্তন করে এটি কীভাবে বলা হোক না কেন,

এবং ES2015 তাদের নিজস্ব এই বাঁধাইটি সরবরাহ করে না এমন তীর ফাংশনগুলি প্রবর্তন করেছে (এটি সংলগ্ন লেজিকাল প্রসঙ্গে এই মানটি ধরে রাখে)।

পদ্ধতি 1: স্ব - স্ব প্রসঙ্গ পরিবর্তিত হওয়ায় এটি মূল সম্পর্কিত একটি রেফারেন্স বজায় রাখতে ব্যবহৃত হচ্ছে। এটি প্রায়শই ইভেন্ট হ্যান্ডলারগুলিতে ব্যবহৃত হয় (বিশেষত ক্লোজারে)।

তথ্যসূত্র : https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / অপারেটর / এটি

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}

পদ্ধতি 2 : তীর ফাংশন - একটি তীর ফাংশন এক্সপ্রেশন হ'ল নিয়মিত ফাংশন এক্সপ্রেশনটির সিনট্যাক্টিক্যালি কমপ্যাক্ট বিকল্প,

যদিও এটির সাথে তার নিজস্ব বাঁধন ছাড়াই, আর্গুমেন্টগুলি, সুপার, বা নতুন.তারক কীওয়ার্ড।

তীর ফাংশন এক্সপ্রেশন পদ্ধতি হিসাবে অসুস্থ উপযুক্ত, এবং তারা নির্মাণকারী হিসাবে ব্যবহার করা যাবে না।

তথ্যসূত্র : https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / ফাংশন / অ্যারো_ফিউশনস

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}

পদ্ধতি 3 : বাইন্ড- বাইন্ড () পদ্ধতিটি একটি নতুন ফাংশন তৈরি করে যা,

যখন ডাকা হয়, তার কীওয়ার্ডটি প্রদত্ত মানটিতে সেট করা আছে,

নতুন ফাংশনটি যখন ডাকা হয় তখন কোনও সরবরাহিত পূর্ববর্তী যুক্তিগুলির একটি ক্রম সহ।

তথ্যসূত্র: https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস / ফাংশন / বাইন্ড

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);

25

প্রথমত, আপনার প্রসঙ্গে কিওয়ার্ডের স্পষ্ট বোঝার scopeএবং আচরণের প্রয়োজন ।thisscope

thisএবং scope:


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

সংক্ষেপে, গ্লোবাল স্কোপটি উইন্ডো অবজেক্টকে বোঝায় global বৈশ্বিক স্কোপে ঘোষিত ভেরিয়েবলগুলি যে কোনও জায়গা থেকে অ্যাক্সেসযোগ্য the thisগ্লোবাল স্কোপে কীওয়ার্ড উইন্ডো অবজেক্টকে বোঝায়। thisঅভ্যন্তরীণ ফাংশনটি উইন্ডো অবজেক্টটিকেও বোঝায় we thisআমরা thisআমাদের নিজের পছন্দের প্রসঙ্গে ইঙ্গিত করতে কারচুপির কোনও উপায় না পাওয়া পর্যন্ত উইন্ডোটি সর্বদা উল্লেখ করবে ।

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------

thisকলব্যাক ফাংশনের অভ্যন্তরে হেরফের করার বিভিন্ন উপায় :

এখানে আমার পার্সন নামে একটি কনস্ট্রাক্টর ফাংশন রয়েছে। এটা একটা সম্পত্তি বলা nameএবং চার পদ্ধতি বলা sayNameVersion1, sayNameVersion2, sayNameVersion3, sayNameVersion4। তাদের চারজনেরই একটি নির্দিষ্ট কাজ রয়েছে a একটি কলব্যাক গ্রহণ করুন এবং আবেদন করুন call কলব্যাকটিতে একটি নির্দিষ্ট কাজ রয়েছে যা ব্যক্তি কনস্ট্রাক্টর ফাংশনের একটি উদাহরণের নাম সম্পত্তি লগইন করা।

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}

এখন আসুন ব্যক্তি কনস্ট্রাক্টরের কাছ থেকে একটি উদাহরণ তৈরি করুন এবং উদাহরণটি sayNameVersionXউল্লেখ করার niceCallbackজন্য আমরা thisঅভ্যন্তরীণ কলব্যাকটি কয়টি উপায়ে পরিচালনা করতে পারি তা দেখার জন্য (এক্সকে 1,2,3,4 বোঝায়) পদ্ধতির বিভিন্ন সংস্করণ চাই person

var p1 = new Person('zami') // create an instance of Person constructor

বাঁধাই করা :

বাঁধাই করা কী thisকীওয়ার্ডটি সরবরাহ করা মানটিতে সেট করে একটি নতুন ফাংশন তৈরি করা ।

sayNameVersion1এবং কলব্যাক ফাংশনটি sayNameVersion2পরিচালনা করতে বাইন্ড ব্যবহার করুন this

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

প্রথমে thisনিজেই পদ্ধতির অভ্যন্তরে কলব্যাকের সাথে আবদ্ধ হন nd এবং দ্বিতীয়টির জন্য একটি কলব্যাক তার সাথে আবদ্ধ বস্তুর সাথে পাস করা হয়।

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

কল:

first argumentএর callপদ্ধতি হিসেবে ব্যবহার করা হয় thisফাংশন যা দিয়ে প্রার্থনা করা হয় ভিতরেcall এটি সংযুক্ত করা হয়েছে।

sayNameVersion3উইন্ডো অবজেক্টের পরিবর্তে, আমরা যে ব্যক্তির তৈরি বস্তুটি তৈরি করেছি তা উল্লেখ callকরতে হেরফের ব্যবহার করে usesthis

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

এবং এটি নিম্নলিখিত মত বলা হয়:

p1.sayNameVersion3(niceCallback)

প্রয়োগ:

অনুরূপ call, প্রথম আর্গুমেন্টটি applyসেই বস্তুকে বোঝায় যা দ্বারা নির্দেশিত হবেthis

sayNameVersion4ব্যক্তি অবজেক্ট উল্লেখ করার applyজন্য কারচুপি thisকরতে ব্যবহার করে

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

এবং এটি নিম্নলিখিতগুলির মতো বলা হয় imp কেবল কলব্যাকটি পাস হয়ে যায়,

p1.sayNameVersion4(niceCallback)

1
উত্তর সম্পর্কিত যে কোনও গঠনমূলক সমালোচনা প্রশংসিত হবে!
AL-zami

1
গ্লোবাল স্কোপটিতে এই কীওয়ার্ডটি অগত্যা উইন্ডো অবজেক্টটি উল্লেখ করে না । এটি শুধুমাত্র একটি ব্রাউজারে সত্য।
র‌্যান্ডাল ফ্ল্যাগ

1
@ র্যান্ডালফ্লাগ আমি এই উত্তরটি একটি ব্রাউজারের দৃষ্টিকোণ থেকে লিখেছি necessaryযদি প্রয়োজন হয় তবে এই উত্তরটি নিখরচায় প্রকাশ করুন :)
আল-জামি

19

আমরা setTimeout()এটিকে আবদ্ধ করতে পারি না , যেমন এটি সর্বদা বিশ্বব্যাপী অবজেক্ট (উইন্ডো) দিয়ে চালিত হয় , আপনি যদি thisকলব্যাক ফাংশনে প্রসঙ্গটি অ্যাক্সেস করতে চান তবে কলব্যাক ফাংশনটি ব্যবহার করে bind()আমরা যেমন অর্জন করতে পারি:

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

9
বিদ্যমান উত্তরগুলির তুলনায় এটি কীভাবে আলাদা?
ফেলিক্স ক্লিং

13

প্রশ্নটি thisজাভাস্ক্রিপ্টে কীওয়ার্ডটি কীভাবে আচরণ করে তা চারদিকে ঘোরে । thisনীচের মত আলাদা আচরণ করে,

  1. মুল্য this সাধারণত একটি কার্য সম্পাদন প্রসঙ্গে নির্ধারিত হয়।
  2. গ্লোবাল স্কোপে, thisগ্লোবাল অবজেক্ট ( windowঅবজেক্ট) বোঝায় ।
  3. যদি কোনও ফাংশনের জন্য কঠোর মোড সক্ষম করা থাকে তবে এর মান কড়া মোডের মতো thisহবে undefined, বিশ্বব্যাপী অবজেক্টটি বস্তুর undefinedজায়গায় উল্লেখ করে window
  4. বিন্দুর আগে যে বস্তুটি দাঁড়িয়ে আছে তা হ'ল এই কীওয়ার্ডটি আবদ্ধ হবে।
  5. আমরা সঙ্গে স্পষ্ট রূপে এই মান সেট করতে পারেন call(), bind()এবংapply()
  6. newকীওয়ার্ডটি যখন ব্যবহার করা হয় (কনস্ট্রাক্টর), এটি তৈরি করা নতুন অবজেক্টের সাথে আবদ্ধ।
  7. তীর ফাংশনগুলি আবদ্ধ হয় না this - পরিবর্তে, thisঅবিচলিতভাবে আবদ্ধ (যেমন মূল প্রসঙ্গে

উত্তরগুলির বেশিরভাগ হিসাবে বোঝা যায়, আমরা অ্যারো ফাংশন বা bind()পদ্ধতি বা স্ব- ভের ব্যবহার করতে পারি । আমি গুগল জাভাস্ক্রিপ্ট স্টাইল গাইড থেকে ল্যাম্বডাস (অ্যার ফাংশন) সম্পর্কে একটি পয়েন্ট উদ্ধৃত করব

F.bind (এটি) এর উপরে এবং বিশেষত goog.bind (চ, এটি) এর উপরে তীর ফাংশন ব্যবহার পছন্দ করুন। কনস্ট স্ব - এই লেখাটি এড়িয়ে চলুন। তীর ফাংশন কলব্যাকগুলির জন্য বিশেষভাবে দরকারী, যা কখনও কখনও অপ্রত্যাশিত অতিরিক্ত যুক্তিগুলি পাস করে।

গুগল স্পষ্টভাবে বাঁধাই বা ল্যাম্বডাস ব্যবহার করার পরামর্শ দেয় const self = this

সুতরাং সবচেয়ে ভাল সমাধানটি হ'ল ল্যাম্বডাসটি নীচের মতো ব্যবহার করা হবে,

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

তথ্যসূত্র:

  1. https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
  2. তীর-ফাংশন-বনাম-বেঁধে

এই প্রশ্নটি বিশেষত ফাংশন / পদ্ধতিগুলি কলব্যাক হিসাবে ব্যবহার করার বিষয়ে। আপনার উত্তরটি স্ট্যাকওভারফ্লো . com/q/3127429/218196 এর জন্য আরও ভাল ফিট হতে পারে ।
ফেলিক্স ক্লিং

@ ফেলিক্সক্লিং হ্যাঁ প্রশ্নটি ফাংশন / পদ্ধতিগুলি সম্পর্কে কলব্যাক হিসাবে ব্যবহার করা ছিল কারণ মূল ইস্যুতে মূল শব্দটি হ্যান্ডলিংয়ের thisকারণেই ছিলাম কেন আমি আমার উত্তর দুটি অংশে বিভক্ত করেছি, যার মধ্যে একটি thisএবং দ্বিতীয়টি কলব্যাক হিসাবে ফাংশন / পদ্ধতি ব্যবহার করার বিষয়ে and উত্তর সম্পাদনা করতে নির্দ্বিধায়।
কোড_মোড

আমি আপনার চতুর্থ বিষয়টি দ্ব্যর্থহীনভাবে খুঁজে পেয়েছি। উদাহরণটি বিবেচনা করুন "কলব্যাকস হিসাবে এই বস্তুর সাথে পদ্ধতিগুলি ব্যবহার করার সময়" , যেখানে ডট অবজেক্টটি বিন্দুর আগে দাঁড়িয়ে রয়েছে, তবে এখনও প্রসঙ্গটি সেই অবজেক্ট নয়।
bleistift2

7

ক্লাসগুলি কোড ব্যবহার করা হয় তবে বর্তমানে আরও একটি পদ্ধতির সম্ভাবনা রয়েছে।

শ্রেণীর ক্ষেত্রগুলির সহায়তায় এটি পরবর্তী উপায়ে তৈরি করা সম্ভব:

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // this refers to correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

নিশ্চিতরূপে হুডের নীচে এটি সমস্ত পুরানো ভাল তীর ফাংশন যা প্রসঙ্গকে আবদ্ধ করে তবে এই ফর্মটিতে এটি আরও স্পষ্ট মনে হয় যে সুস্পষ্ট বাইন্ডিং।

এটি পর্যায় 3 প্রস্তাবনা হিসাবে এখনই (08/2018) হিসাবে এটি প্রক্রিয়া করার জন্য আপনার বাবেল এবং উপযুক্ত ব্যাবেল প্লাগইন প্রয়োজন হবে ।


2
আমি public methodName = (params) => { body }ক্লাসের ভিতরে টাইপস্ক্রিপ্টে ঠিক এটি কাজ করতে পেরেছি ।
ইয়েইয়েরম্যান

5

ইভেন্টের শ্রোতাদের সাথে আবদ্ধ হওয়ার জন্য ডিওএম 2-এর পরের অন্য পদ্ধতি, যা আপনাকে সর্বদা শ্রোতাদের অপসারণ করতে দেয় (অন্যান্য উপকারের মধ্যে), ইন্টারফেস থেকে এই পদ্ধতি :thishandleEvent(evt)EventListener

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

ব্যবহার সম্পর্কে বিস্তারিত তথ্য handleEventএখানে পাওয়া যাবে: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38


0

this জেএসে:

thisজেএস- এর মান 100% নির্ধারণ করা হয় যে কোনও ফাংশন কীভাবে বলা হয়, এবং এটি কীভাবে সংজ্ঞায়িত হয় না। আমরা তুলনামূলকভাবে 'ডট রুলের বাম'this দ্বারা মান খুঁজে পেতে পারি :

  1. ফাংশন কীওয়ার্ড ব্যবহার করে যখন ফাংশন তৈরি করা হয় তখন ফাংশনের thisবিন্দুর বাম অবজেক্টের মান বলা হয়
  2. যদি বিন্দুতে কোনও অবজেক্ট না থাকে তবে কোনও thisফাংশনের অভ্যন্তরের মান প্রায়শই বিশ্বব্যাপী অবজেক্ট ( globalনোডে, windowব্রাউজারে) হয়। আমি thisকীওয়ার্ডটি এখানে ব্যবহার করার পরামর্শ দেব না কারণ এটি এমন কিছু ব্যবহার করার চেয়ে কম স্পষ্ট window!
  3. তীর ফাংশন এবং ফাংশন ব্যবহার করে তৈরি করা ফাংশনগুলির মতো কিছু নির্মান রয়েছে Function.prototype.bind()যা এর মান ঠিক করতে পারে this। এগুলি নিয়মের ব্যতিক্রম তবে এর মানটি ঠিক করতে সহায়ক this

নোডজেএস-তে উদাহরণ

module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);

const obj1 = {
    data: "obj1 data",
    met1: function () {
        console.log(this.data);
    },
    met2: () => {
        console.log(this.data);
    },
};

const obj2 = {
    data: "obj2 data",
    test1: function () {
        console.log(this.data);
    },
    test2: function () {
        console.log(this.data);
    }.bind(obj1),
    test3: obj1.met1,
    test4: obj1.met2,
};

obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);

আউটপুট:

এখানে চিত্র বর্ণনা লিখুন

আমাকে 1 দিয়ে 1 আউটপুটগুলিতে আপনাকে চলতে দিন (দ্বিতীয়টি থেকে প্রথম লগটি উপেক্ষা করে):

  1. thisহয় obj2ডট নিয়ম বাম কারণে আমরা দেখতে পারি কিভাবে test1বলা হয় obj2.test1();obj2বিন্দু এবং এইভাবে thisমান বাম হয়।
  2. যদিও obj2বিন্দুটি বাকি আছে, পদ্ধতিটির মাধ্যমে test2আবদ্ধ । সুতরাং মান হয় ।obj1bind()thisobj1
  3. obj2যা বলা হয় ফাংশন থেকে ডট বাম হয়: obj2.test3()। সুতরাং obj2এর মান হবে this
  4. এই ক্ষেত্রে: obj2.test4() obj2বিন্দু বাম তবে তীর ফাংশনটির নিজস্ব thisবাঁধাই নেই। সুতরাং এটি thisবাহ্যিক স্কোপটির মানকে আবদ্ধ করবে যা এটিmodule.exports যা আদিতে লগ করা বস্তু।
  5. আমরা ফাংশনটি thisব্যবহার করে এর মান নির্দিষ্ট করতে পারি call। এখানে আমরা thisএকটি আর্গুমেন্ট হিসাবে পছন্দসই মানটি পাস করতে পারি , যা obj2এই ক্ষেত্রে।
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.