জাভাস্ক্রিপ্টে this
মান খুঁজে বের করা কঠিন হতে পারে, এটি কীভাবে করবেন তা এখানে…
জাভাস্ক্রিপ্টের this
অনেক কৌতুকের বাট, এবং এর কারণ, ভাল, এটি বেশ জটিল। যাইহোক, আমি দেখেছি যে ডেভেলপাররা this
সাথে মোকাবিলা এড়াতে আরও জটিল এবং ডোমেন-নির্দিষ্ট কিছু করে। আপনি যদি this
সম্পর্কে অনিশ্চিত হন, আশা করি এটি সাহায্য করবে। এই আমার this
গাইড.
আমি সবচেয়ে নির্দিষ্ট পরিস্থিতি দিয়ে শুরু করতে যাচ্ছি, এবং সর্বনিম্ন-নির্দিষ্ট দিয়ে শেষ করব। এই নিবন্ধটি অনেকটা বড় if (…) … else if () … else if (…) …
, তাই আপনি সরাসরি প্রথম বিভাগে যেতে পারেন যা আপনি যে কোডটি দেখছেন তার সাথে মেলে।
- যদি ফাংশনটিকে একটি তীর ফাংশন হিসাবে সংজ্ঞায়িত করা হয়
- অন্যথায়, যদি ফাংশন/ক্লাসটিকে
new
দিয়ে কল করা হয় - অন্যথায়, যদি ফাংশনের একটি 'বাউন্ড'
this
মান থাকে - অন্যথায়, যদি
this
কল-টাইমে সেট করা থাকে - অন্যথায়, যদি একটি প্যারেন্ট অবজেক্টের মাধ্যমে ফাংশনটি কল করা হয় (
parent.func()
) - অন্যথায়, যদি ফাংশন বা প্যারেন্ট স্কোপ কঠোর মোডে থাকে
- অন্যথায়
যদি ফাংশনটি একটি তীর ফাংশন হিসাবে সংজ্ঞায়িত করা হয়:
const arrowFunction = () => {
console.log(this);
};
এই ক্ষেত্রে, this
মান সর্বদা অভিভাবক সুযোগে this
মতোই থাকে:
const outerThis = this;
const arrowFunction = () => {
// Always logs `true`:
console.log(this === outerThis);
};
তীর ফাংশনগুলি দুর্দান্ত কারণ this
অভ্যন্তরীণ মান পরিবর্তন করা যায় না, এটি সর্বদা বাইরের this
হিসাবে একই।
অন্যান্য উদাহরণ
তীর ফাংশন সহ, this
মান bind
দিয়ে পরিবর্তন করা যাবে না :
// Logs `true` - bound `this` value is ignored:
arrowFunction.bind({foo: 'bar'})();
তীর ফাংশন সহ, call
বা apply
মাধ্যমে this
মান পরিবর্তন করা যাবে না :
// Logs `true` - called `this` value is ignored:
arrowFunction.call({foo: 'bar'});
// Logs `true` - applied `this` value is ignored:
arrowFunction.apply({foo: 'bar'});
তীর ফাংশনের সাথে, ফাংশনটিকে অন্য বস্তুর সদস্য হিসাবে কল করে this
মান পরিবর্তন করা যাবে না :
const obj = {arrowFunction};
// Logs `true` - parent object is ignored:
obj.arrowFunction();
তীর ফাংশন সহ, ফাংশনটিকে কনস্ট্রাক্টর হিসাবে কল করে this
মান পরিবর্তন করা যাবে না :
// TypeError: arrowFunction is not a constructor
new arrowFunction();
'বাউন্ড' উদাহরণ পদ্ধতি
উদাহরণ পদ্ধতির সাহায্যে, আপনি যদি নিশ্চিত করতে চান this
সর্বদা ক্লাস ইনস্ট্যান্সকে বোঝায়, সর্বোত্তম উপায় হল তীর ফাংশন এবং ক্লাস ক্ষেত্রগুলি ব্যবহার করা:
class Whatever {
someMethod = () => {
// Always the instance of Whatever:
console.log(this);
};
}
উপাদানগুলিতে (যেমন প্রতিক্রিয়া উপাদান, বা ওয়েব উপাদান) ইভেন্ট শ্রোতা হিসাবে উদাহরণ পদ্ধতি ব্যবহার করার সময় এই প্যাটার্নটি সত্যিই কার্যকর।
উপরেরটি মনে হতে পারে যে this
"অভিভাবক সুযোগে this
মতোই হবে" নিয়মটি ভঙ্গ করছে, তবে আপনি যদি কনস্ট্রাক্টরে জিনিসগুলি সেট করার জন্য শ্রেণী ক্ষেত্রগুলিকে সিনট্যাকটিক চিনি হিসাবে মনে করেন তবে এটি বোধগম্য হবে:
class Whatever {
someMethod = (() => {
const outerThis = this;
return () => {
// Always logs `true`:
console.log(this === outerThis);
};
})();
}
// …is roughly equivalent to:
class Whatever {
constructor() {
const outerThis = this;
this.someMethod = () => {
// Always logs `true`:
console.log(this === outerThis);
};
}
}
বিকল্প প্যাটেনগুলি কনস্ট্রাক্টরের মধ্যে একটি বিদ্যমান ফাংশন বাঁধাই বা কনস্ট্রাক্টরে ফাংশন বরাদ্দ করা জড়িত। আপনি যদি কোনো কারণে ক্লাস ক্ষেত্র ব্যবহার করতে না পারেন, তাহলে কনস্ট্রাক্টরে ফাংশন বরাদ্দ করা একটি যুক্তিসঙ্গত বিকল্প:
class Whatever {
constructor() {
this.someMethod = () => {
// …
};
}
}
অন্যথায়, যদি ফাংশন/ক্লাসটিকে new
দিয়ে কল করা হয়:
new Whatever();
উপরোক্ত Whatever
কল করবে (অথবা এটির কন্সট্রাকটর ফাংশন যদি এটি একটি ক্লাস হয়) this
সেটের সাথে Object.create(Whatever.prototype)
এর ফলাফলে।
class MyClass {
constructor() {
console.log(
this.constructor === Object.create(MyClass.prototype).constructor,
);
}
}
// Logs `true`:
new MyClass();
পুরানো শৈলী নির্মাণকারীদের জন্য একই সত্য:
function MyClass() {
console.log(
this.constructor === Object.create(MyClass.prototype).constructor,
);
}
// Logs `true`:
new MyClass();
অন্যান্য উদাহরণ
যখন new
দিয়ে ডাকা হয়, this
মান bind
দিয়ে পরিবর্তন করা যাবে না :
const BoundMyClass = MyClass.bind({foo: 'bar'});
// Logs `true` - bound `this` value is ignored:
new BoundMyClass();
যখন new
এর সাথে কল করা হয়, তখন অন্য বস্তুর সদস্য হিসাবে ফাংশনটিকে কল করে this
মান পরিবর্তন করা যায় না :
const obj = {MyClass};
// Logs `true` - parent object is ignored:
new obj.MyClass();
অন্যথায়, যদি ফাংশনের একটি 'বাউন্ড' থাকে this
মান:
function someFunction() {
return this;
}
const boundObject = {hello: 'world'};
const boundFunction = someFunction.bind(boundObject);
যখনই boundFunction
বলা হয়, তখন তার this
মানটি হবে bind
জন্য পাস করা বস্তুটি ( boundObject
)।
// Logs `false`:
console.log(someFunction() === boundObject);
// Logs `true`:
console.log(boundFunction() === boundObject);
অন্যান্য উদাহরণ
একটি আবদ্ধ ফাংশন কল করার সময়, this
মান call
বা apply
সাথে পরিবর্তন করা যাবে না :
// Logs `true` - called `this` value is ignored:
console.log(boundFunction.call({foo: 'bar'}) === boundObject);
// Logs `true` - applied `this` value is ignored:
console.log(boundFunction.apply({foo: 'bar'}) === boundObject);
একটি আবদ্ধ ফাংশন কল করার সময়, অন্য বস্তুর সদস্য হিসাবে ফাংশন কল করে this
মান পরিবর্তন করা যাবে না :
const obj = {boundFunction};
// Logs `true` - parent object is ignored:
console.log(obj.boundFunction() === boundObject);
অন্যথায়, যদি this
কল-টাইমে সেট করা থাকে:
function someFunction() {
return this;
}
const someObject = {hello: 'world'};
// Logs `true`:
console.log(someFunction.call(someObject) === someObject);
// Logs `true`:
console.log(someFunction.apply(someObject) === someObject);
this
মান হল call
/ apply
জন্য পাস করা বস্তু।
দুর্ভাগ্যবশত this
DOM ইভেন্ট শ্রোতাদের মতো জিনিসগুলির দ্বারা কিছু অন্য মানতে সেট করা হয়েছে এবং এটি ব্যবহার করার ফলে কোড বোঝা কঠিন হতে পারে:
element.addEventListener('click', function (event) { // Logs `element`, since the DOM spec sets `this` to // the element the handler is attached to. console.log(this); });
আমি উপরের মত ক্ষেত্রে this
ব্যবহার করা এড়িয়ে চলুন, এবং পরিবর্তে:
element.addEventListener('click', (event) => { // Ideally, grab it from a parent scope: console.log(element); // But if you can't do that, get it from the event object: console.log(event.currentTarget); });
অন্যথায়, যদি ফাংশনটি একটি প্যারেন্ট অবজেক্টের মাধ্যমে কল করা হয় ( parent.func()
):
const obj = {
someMethod() {
return this;
},
};
// Logs `true`:
console.log(obj.someMethod() === obj);
এই ক্ষেত্রে ফাংশনটিকে obj
এর সদস্য বলা হয়, তাই this
হবে obj
। এটি কল-টাইমে ঘটে, তাই যদি ফাংশনটিকে তার মূল অবজেক্ট ছাড়া বা অন্য কোনও মূল বস্তুর সাথে কল করা হয় তবে লিঙ্কটি ভেঙে যায়:
const {someMethod} = obj;
// Logs `false`:
console.log(someMethod() === obj);
const anotherObj = {someMethod};
// Logs `false`:
console.log(anotherObj.someMethod() === obj);
// Logs `true`:
console.log(anotherObj.someMethod() === anotherObj);
someMethod() === obj
মিথ্যা কারণ someMethod
obj
এর সদস্য বলা হয় না । এইরকম কিছু চেষ্টা করার সময় আপনি এই গোটচাটির সম্মুখীন হতে পারেন:
const $ = document.querySelector;
// TypeError: Illegal invocation
const el = $('.some-element');
এটি ভেঙে যায় কারণ querySelector
এর বাস্তবায়ন তার নিজস্ব this
মানটিকে দেখে এবং এটি একটি DOM নোড হতে আশা করে এবং উপরের সংযোগটি ভেঙে দেয়। উপরেরটি সঠিকভাবে অর্জন করতে:
const $ = document.querySelector.bind(document);
// Or:
const $ = (...args) => document.querySelector(...args);
মজার ঘটনা: সমস্ত API অভ্যন্তরীণভাবে this
ব্যবহার করে না। this
রেফারেন্সগুলি এড়াতে console.log
এর মতো কনসোল পদ্ধতিগুলি পরিবর্তন করা হয়েছে, তাই log
console
সাথে আবদ্ধ করার প্রয়োজন নেই৷
অন্যথায়, যদি ফাংশন বা পিতামাতার সুযোগ কঠোর মোডে থাকে:
function someFunction() {
'use strict';
return this;
}
// Logs `true`:
console.log(someFunction() === undefined);
এই ক্ষেত্রে, this
মান অনির্ধারিত। যদি প্যারেন্ট স্কোপ কঠোর মোডে থাকে (এবং সমস্ত মডিউল কঠোর মোডে থাকে) তাহলে ফাংশনে 'use strict'
প্রয়োজন হয় না।
অন্যথায়:
function someFunction() {
return this;
}
// Logs `true`:
console.log(someFunction() === globalThis);
এই ক্ষেত্রে, this
মান globalThis
এর মতোই।
ফাউ!
আর এটাই! আমি this
সম্পর্কে জানি সব. কোন প্রশ্ন? আমি মিস করেছি কিছু? নির্দ্বিধায় আমাকে টুইট করুন ।
পর্যালোচনা করার জন্য Mathias Bynens , Ingvar Stepanyan , এবং Thomas Steiner- কে ধন্যবাদ।