টাইমআউট কলব্যাক সেট করতে সঠিক "এই" প্রসঙ্গটি পাস করবেন?


249

আমি কীভাবে প্রসঙ্গটি পাস করব setTimeout? আমি this.tip.destroy()যদি this.options.destroyOnHide1000 এমএসের পরে কল করতে চাই । আমি এটা কিভাবে করবো?

if (this.options.destroyOnHide) {
     setTimeout(function() { this.tip.destroy() }, 1000);
} 

আমি যখন উপরেরটি চেষ্টা করি তখন thisউইন্ডোটি বোঝায়।


4
সদৃশ পতাকাটি কি কার্যকর? এই প্রশ্নটি আসলে আগে জিজ্ঞাসা করা হয়েছিল।
সুই ড্রিম

1
যদি (this.options.destroyOnHide) {setTimeout (ফাংশন () {this.tip.destroy () ind .বাইন্ড (এটি), 1000); }
জিব্রি

উত্তর:


352

সম্পাদনা: সংক্ষেপে, ২০১০ সালে যখন এই প্রশ্নটি সমাধান করার সর্বাধিক সাধারণ উপায়টি জিজ্ঞাসা করা হয়েছিল তখন setTimeoutফাংশন কলটি করা হয়েছে এমন প্রসঙ্গে একটি রেফারেন্স সংরক্ষণ করা হয়েছিল, কারণ বিশ্বব্যাপী অবজেক্টের দিকে ইঙ্গিত setTimeoutকরে ফাংশনটি সম্পাদন করে this:

var that = this;
if (this.options.destroyOnHide) {
     setTimeout(function(){ that.tip.destroy() }, 1000);
} 

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

if (this.options.destroyOnHide) {
     setTimeout(function(){ this.tip.destroy() }.bind(this), 1000);
}

bindফাংশন সঙ্গে একটি নতুন ফাংশন তৈরি করে thisমান প্রাক ভরা।

এখন আধুনিক জেএস-এ, ES6- এ ঠিক তীরের সমস্যার সমাধান হ'ল :

if (this.options.destroyOnHide) {
     setTimeout(() => { this.tip.destroy() }, 1000);
}

অ্যারো ফাংশনগুলির thisনিজস্ব কোনও মান থাকে না, যখন আপনি এটি অ্যাক্সেস করেন, আপনি thisঘেরযুক্ত লেজিকাল স্কোপটির মান অ্যাক্সেস করছেন ।

এইচটিএমএল ২০১১ সালে ফিরে টাইমারকেও মানসম্মত করেছিল এবং আপনি এখন কলব্যাক ফাংশনে যুক্তি পাঠাতে পারেন:

if (this.options.destroyOnHide) {
     setTimeout(function(that){ that.tip.destroy() }, 1000, this);
}

আরো দেখুন:


3
এটা কাজ করে। আমি jsbin স্ক্রিপ্ট দিয়ে ধারণাটি পরীক্ষা করেছি: jsbin.com/etise/7/edit
জন কে

1
এই কোডটিতে একটি অপ্রয়োজনীয় পরিবর্তনশীল তৈরি করা জড়িত (যার ফাংশন-প্রশস্ত সুযোগ রয়েছে); আপনি যদি সঠিকভাবে thisফাংশনে প্রবেশ করেন, আপনি কম কোড, কম সিপিইউ চক্র এবং কম মেমরি ব্যবহার করে এই ক্ষেত্রে, মানচিত্রের জন্য), forEach () ইত্যাদি ইত্যাদির জন্য এই সমস্যাটি সমাধান করে ফেলবেন। *** দেখুন: মিশা রেজলিনের উত্তর।
হোল্ডঅফহাঙ্গার

222

@CMS এর সাথে উত্তর দেওয়া ফাংশন র‌্যাপারটিতে তৈরি শর্টকাটগুলি (সিনট্যাকটিক চিনি) রয়েছে। (নীচে ধরে নিবেন যে আপনি যে প্রসঙ্গটি চান তা হ'ল this.tip)


ইসমাস্ক্রিপ্ট 5 ( বর্তমান ব্রাউজারগুলি , নোড.জেএস) এবং প্রোটোটাইপ.জেএস

আপনি যদি ECMA-262, 5 ম সংস্করণ (ECMAScript 5) বা Node.js এর সাথে সামঞ্জস্যপূর্ণ ব্রাউজারটিকে লক্ষ্য করেন তবে আপনি ব্যবহার করতে পারেন Function.prototype.bindআংশিক ফাংশন তৈরি করতে আপনি কোনও ফাংশন যুক্তি optionচ্ছিকভাবে পাস করতে পারেন ।

fun.bind(thisArg[, arg1[, arg2[, ...]]])

আবার আপনার ক্ষেত্রে এটি ব্যবহার করে দেখুন:

if (this.options.destroyOnHide) {
    setTimeout(this.tip.destroy.bind(this.tip), 1000);
}

একই কার্যকারিতা প্রোটোটাইপ (অন্য কোনও গ্রন্থাগার?) এও প্রয়োগ করা হয়েছে ।

Function.prototype.bindআপনি যদি কাস্টম পিছনের সামঞ্জস্যতা চান তবে এটি প্রয়োগ করা যেতে পারে (তবে দয়া করে নোটগুলি পর্যবেক্ষণ করুন)।


ECMAScript 2015 ( কিছু ব্রাউজার , নোড.জেএস 5.0.0+)

কাটিয়া-বিকাশের বিকাশের জন্য (২০১৫) আপনি চর্বিযুক্ত তীর ফাংশনগুলি ব্যবহার করতে পারেন যা ECMAScript 2015 (সম্প্রীতি / ES6 / ES2015) এর অংশবিশেষ ( উদাহরণ )।

একটি তীর ফাংশন এক্সপ্রেশন ( ফ্যাট অ্যারো ফাংশন নামেও পরিচিত ) ফাংশন এক্সপ্রেশনগুলির তুলনায় একটি সংক্ষিপ্ত বাক্য গঠন করে এবং thisমানটিকে বর্ণিতভাবে আবদ্ধ করে [...]।

(param1, param2, ...rest) => { statements }

আপনার ক্ষেত্রে, এটি চেষ্টা করুন:

if (this.options.destroyOnHide) {
    setTimeout(() => { this.tip.destroy(); }, 1000);
}

jQuery এর

আপনি যদি ইতিমধ্যে jQuery 1.4+ ব্যবহার করে থাকেন তবে thisকোনও ফাংশনের প্রসঙ্গটি সুস্পষ্টভাবে সেট করার জন্য একটি প্রস্তুত ফাংশন রয়েছে।

jQuery.proxy () : একটি ফাংশন নেয় এবং একটি নতুন ফিরিয়ে দেয় যা সর্বদা একটি নির্দিষ্ট প্রসঙ্গ থাকবে।

$.proxy(function, context[, additionalArguments])

আপনার ক্ষেত্রে, এটি চেষ্টা করুন:

if (this.options.destroyOnHide) {
    setTimeout($.proxy(this.tip.destroy, this.tip), 1000);
}

Underscore.js , lodash

এটি 1 , 2 হিসাবে, ইন্ডোরস্কোর.জেএস এবং লোডাশে উপলভ্য_.bind(...)

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

_.bind(function, object, [*arguments])

আপনার ক্ষেত্রে, এটি চেষ্টা করুন:

if (this.options.destroyOnHide) {
    setTimeout(_.bind(this.tip.destroy, this.tip), 1000);
}


কেন ডিফল্ট নয় func.bind(context...)? আমি কি কিছু মিস করছি?
এটিই

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

@ ত্রিনকো: আমি কোনও ব্যয়কে ব্যয়বহুল অপারেশন হিসাবে বাঁধতে দেখছি না, তবে আপনি যদি একই বাউন্ড ফাংশনটিকে একাধিকবার কল করেন তবে আপনি একটি রেফারেন্সও রাখতে পারেন: var boundFn = fn.bind(this); boundFn(); boundFn();উদাহরণস্বরূপ।
জোয়েল পুররা

30

ইন্টারনেট এক্সপ্লোরার ব্যতীত অন্য ব্রাউজারগুলিতে, আপনি বিলম্বের পরে একসাথে ফাংশনটিতে প্যারামিটারগুলি পাস করতে পারেন:

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

সুতরাং, আপনি এটি করতে পারেন:

var timeoutID = window.setTimeout(function (self) {
  console.log(self); 
}, 500, this);

এটি স্কোপ লুকের চেয়ে পারফরম্যান্সের ক্ষেত্রে ( thisটাইমআউট / ইন্টারভাল এক্সপ্রেশনের বাইরে একটি ভেরিয়েবলের ক্যাশে করা) এবং তারপরে একটি ক্লোজার তৈরি করে ( $.proxyবা ব্যবহার করে Function.prototype.bind)।

ওয়েবারব্লেশন থেকে আইইএস এ এটি কাজ করার কোড :

/*@cc_on
(function (modifierFn) {
  // you have to invoke it as `window`'s property so, `window.setTimeout`
  window.setTimeout = modifierFn(window.setTimeout);
  window.setInterval = modifierFn(window.setInterval);
})(function (originalTimerFn) {
    return function (callback, timeout){
      var args = [].slice.call(arguments, 2);
      return originalTimerFn(function () { 
        callback.apply(this, args) 
      }, timeout);
    }
});
@*/

1
প্রোটোটাইপ চেইন ব্যবহার করে ক্লাস তৈরি করার সময় এবং আপনার পদ্ধতিগুলি হলেন প্রোটোটাইপ পদ্ধতি ... 'বাইন্ড' হ'ল একমাত্র জিনিস যা পদ্ধতির মধ্যে 'এটি' কী তা পরিবর্তন করে দেয়। কলব্যাকটিতে একটি প্যারামিটার পাস করার পরে, আপনি 'এটি' ফাংশনে কী রয়েছে তা পরিবর্তন করেন না, সুতরাং এই জাতীয় প্রোটোটাইপ ফাংশনটি এটির মধ্যে 'এটি' ব্যবহার করে রচনা করা যায়নি কারণ অন্য কোনও প্রোটোটাইপ পদ্ধতি পারে। এটি অসঙ্গতি বাড়ে। বাইন্ডটি হ'ল আমরা আসলে যা চাই তার নিকটতম জিনিস, এবং উচ্চতর অনুসন্ধানের জন্য এবং এটি একবারে একাধিকবার তৈরি না করার জন্য ক্লোজারটি 'এটি' তে ক্যাশে করা যেতে পারে।
ট্রায়ঙ্কো

3

দ্রষ্টব্য: এটি IE তে কাজ করবে না

var ob = {
    p: "ob.p"
}

var p = "window.p";

setTimeout(function(){
    console.log(this.p); // will print "window.p"
},1000); 

setTimeout(function(){
    console.log(this.p); // will print "ob.p"
}.bind(ob),1000);

2

আপনি যদি ব্যবহার করেন তবে আপনি ব্যবহার underscoreকরতে পারেন bind

যেমন

if (this.options.destroyOnHide) {
     setTimeout(_.bind(this.tip.destroy, this), 1000);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.