क्या आप एक तीर फ़ंक्शन में 'इस' को बांध सकते हैं?


133

मैं थोड़ी देर के लिए ES6 के साथ प्रयोग कर रहा हूं, और मुझे अभी थोड़ी समस्या आई है।

मुझे वास्तव में तीर के कार्यों का उपयोग करना पसंद है, और जब भी मैं कर सकता हूं, मैं उनका उपयोग करता हूं।

हालाँकि, ऐसा प्रतीत होता है कि आप उन्हें बांध नहीं सकते हैं!

यहाँ समारोह है:

var f = () => console.log(this);

यहाँ मैं इस कार्य को बाँधना चाहता हूँ:

var o = {'a': 42};

और यहां बताया fगया है o:

var fBound = f.bind(o);

और फिर मैं सिर्फ फोन कर सकता हूं fBound:

fBound();

जो इसे ( oऑब्जेक्ट) आउटपुट करेगा :

{'a': 42}

ठंडा! लवली! सिवाय इसके कि यह काम नहीं करता है। oऑब्जेक्ट को आउटपुट करने के बजाय , यह windowऑब्जेक्ट को आउटपुट करता है।

तो मैं जानना चाहता हूं: क्या आप तीर फ़ंक्शन को बांध सकते हैं? (और यदि हां, तो कैसे?)


मैंने Google Chrome 48 और Firefox 43 में उपरोक्त कोड का परीक्षण किया है, और परिणाम समान है।


29
तीर के कार्यों का पूरा बिंदु यह है कि वे thisअपने मूल क्षेत्र का उपयोग करते हैं।
loganfsmyth

जवाबों:


158

आप एक तीर फ़ंक्शन में बगावत नहीं कर सकते this। इसे हमेशा उस संदर्भ के रूप में परिभाषित किया जाएगा जिसमें इसे परिभाषित किया गया था। यदि आपको thisसार्थक होने की आवश्यकता है, तो आपको एक सामान्य फ़ंक्शन का उपयोग करना चाहिए।

से ECMAScript 2015 युक्ति :

किसी भी तर्क, सुपर, यह, या new.target के एक ArrowFunction के संदर्भ में एक lexically एन्कोडिंग वातावरण में एक बंधन को हल करना होगा। आमतौर पर यह तुरंत संलग्न फ़ंक्शन का कार्य वातावरण होगा।


7
इस उत्तर का पहला वाक्य गलत है। शायद इसलिए कि सवाल बाध्यकारी भी है और this। दोनों संबंधित हैं, लेकिन समान नहीं हैं। thisएरो फंक्शन के अंदर हमेशा thisएनक्लोजिंग स्कोप से 'इनहेरिट' होता है । यह एरो फ़ंक्शंस की एक विशेषता है। लेकिन आप अभी भी bindएक तीर फ़ंक्शन के अन्य सभी मापदंडों को कर सकते हैं । बस नहीं this
स्टिजिन डी विट

54

पूर्ण होने के लिए, आप तीर फ़ंक्शंस को फिर से बाँध सकते हैं, आप सिर्फ इसका अर्थ नहीं बदल सकते this

bind अभी भी फ़ंक्शन तर्कों के लिए मूल्य है:

((a, b, c) => {
  console.info(a, b, c) // 1, 2, 3
}).bind(undefined, 1, 2, 3)()

इसे यहाँ आज़माएँ: http://jsbin.com/motihanopi/edit?js,console


1
क्या किसी भी वस्तु (तीर) फ़ंक्शन का पता लगाने या उपयोग करने का एक तरीका है, बिना संदर्भित this(जो कि, ज़ाहिर है, शाब्दिक रूप से परिभाषित) है?
फ्लोरि

3
संदर्भ के लिए एक तर्क का उपयोग करें: ((संदर्भ) => {someOtherFunction.apply (संदर्भ)})। बाइंड (willBeIgnored, संदर्भ) ()
cvazac

13

से MDN :

एरो फंक्शन एक्सप्रेशन में फंक्शन एक्सप्रेशंस की तुलना में एक छोटा सिंटैक्स होता है और लेक्सिकली इस वैल्यू को बांधता है (यह अपने आप इस बात पर बहस नहीं करता है, सुपर, या new.target)। एरो फ़ंक्शंस हमेशा गुमनाम होते हैं।

इसका मतलब है कि आप thisजैसा चाहें वैसा मूल्य नहीं बाँध सकते ।


6

सालों से, js Developers ने संदर्भ बाइंडिंग के साथ संघर्ष किया, पूछा कि क्यों thisजावास्क्रिप्ट में बदला गया, संदर्भ बाइंडिंग के कारण वर्षों में इतना भ्रम और thisजावास्क्रिप्ट का अर्थ और thisअधिकांश अन्य OOP भाषाओं में अंतर ।

यह सब मुझे पूछने के लिए प्रेरित करता है, क्यों, क्यों! आप एक तीर फ़ंक्शन को क्यों नहीं बनाना चाहते हैं! उन जहां विशेष रूप से बनाई गई इस सभी मुद्दों और भ्रम और उपयोग करने के लिए होने से बचने के हल करने के लिए bindया callया जो कुछ भी अन्य तरीके से समारोह के दायरे को बचाने के लिये।

टी एल; डॉ

नहीं, आप एरो फ़ंक्शंस को रिबंड नहीं कर सकते।


7
एक क्लीनर और तेज सिंटैक्स प्रदान करने के लिए सबसे पहले एरो फ़ंक्शंस बनाए गए थे। लैम्ब्डा-कैलकुलस सोचो। OO-zealots को बहुत ख़राब करते हैं, जो कि कार्यात्मक JS प्रोग्रामर के जीवन को प्रभावित करता है, ने आक्रमण के संदर्भ को निर्दिष्ट करने की स्वतंत्रता को छीनने का अवसर हड़प लिया।
मार्को फौस्टिनेली

5
का उपयोग करना thisकार्यात्मक नहीं है। लंबोदर होना चाहिए arguments => output। यदि आपको कुछ बाहरी संदर्भ की आवश्यकता है, तो इसे पास करें। बहुत ही thisऐसा है जो ओओ पैटर्न के सभी प्रकार के भाषा में सुविधा प्रदान करता है। आपने इसके बिना "जावास्क्रिप्ट क्लास" शब्द कभी नहीं सुना होगा।
erich2k8

3
आप तीर के कार्यों को रिबंड कर सकते हैं । बस नहीं this
स्टिजिन डी विट

6

आप एक तीर फ़ंक्शन bindके thisअंदर का मान बदलने के लिए उपयोग नहीं कर सकते । हालाँकि, आप एक नया नियमित फ़ंक्शन बना सकते हैं जो पुराने तीर फ़ंक्शन के समान काम करता है और फिर हमेशा की तरह उपयोग callया bindफिर से बाँधने thisके लिए।

हम एक evalफ़ंक्शन का उपयोग करते हैं जिसे आप एक सामान्य फ़ंक्शन के रूप में पास होने वाले एरो फ़ंक्शन को फिर से बनाते हैं और फिर callइसे एक अलग के साथ इनवॉइस करने के लिए उपयोग करते हैं this:

var obj = {value: 10};
function arrowBind(context, fn) {
  let arrowFn;
  (function() {
    arrowFn = eval(fn.toString());
    arrowFn();
  }).call(context);
}
arrowBind(obj, () => {console.log(this)});


3
एक तीर समारोह को एक अलग संदर्भ में बांधने के तरीके के इस उदाहरण को साझा करने के लिए धन्यवाद! भविष्य के पाठकों के लिए उत्तर को समझने में आसान बनाने के लिए, शायद आप यह वर्णन करने के लिए इसे संपादित कर सकते हैं कि कोड कैसे और क्यों काम करता है?
फ्लोर्री

4

क्या ईएस 6 एरो फंक्शन्स वास्तव में "इसे" जावास्क्रिप्ट में हल करते हैं

उपरोक्त लिंक बताता है कि तीर फ़ंक्शंस फ़ंक्शन के thisसाथ नहीं बदलता bind, call, applyहै।

इसे बहुत अच्छे उदाहरण के साथ समझाया गया है।

node v4"अपेक्षित" व्यवहार को देखने के लिए इसे चलाएं ,

this.test = "attached to the module";
var foo = { test: "attached to an object" };
foo.method = function(name, cb){ 
    // bind the value of "this" on the method 
    // to try and force it to be what you want 
    this[name] = cb.bind(this); };
foo.method("bar", () => { console.log(this.test); });
foo.bar(); 

आपसे अनुरोध है कि उत्तर में स्वयं अधिक प्रासंगिक जानकारी प्रदान करें, प्रश्नों का एक नमूना कोड या संपादित संस्करण हो सकता है
Jithin Scaria

// इसे "अपेक्षित" व्यवहार देखने के लिए नोड v4 में चलाएं। यह = मॉड्यूल से जुड़ा हुआ है; var foo = {test: "किसी वस्तु से जुड़ी"}; foo.method = function (नाम, cb) {// पद्धति पर "इस" के मूल्य को बांधें // कोशिश करने के लिए और इसे जबरदस्ती करने के लिए कि आप इसे क्या चाहते हैं [name] = cb.bind (यह); }; foo.method ("बार", () => {कंसोल.लॉग (this.test);}); foo.bar ();
पृथ्वी राज वुप्पलपति

यहाँ क्या दिलचस्प है यह कोशिश करो और फिर इसे फिर से आज़माएं foo.method ('बार', () => {कंसोल.लॉग (this.test);}) की जगह; foo.method ('बार', फ़ंक्शन () {कंसोल.लॉग (this.test);}) के साथ; - पहला संस्करण "मॉड्यूल से जुड़ा हुआ" और दूसरा लॉग "ऑब्जेक्ट से जुड़ा हुआ" है - मैं वास्तव में तीर फ़ंक्शन का उपयोग करके "यह" का अधिक स्थिर उपचार पसंद करता हूं। आप अभी भी विभिन्न पैटर्नों का उपयोग करके अन्य प्रभाव प्राप्त कर सकते हैं और परिणाम अधिक पठनीय और अनुमानित आईएमओ हैं।
मेथडियन

3

मैंने कुछ दिन पहले भी यही सवाल पूछा था।

आप thisपहले से बाइंड होने के बाद से कोई मान नहीं बाँध सकते ।

ईएस 6 => फ़ंक्शन ऑपरेटर के लिए इस दायरे को अलग करना


4
"चूंकि यह पहले से ही thisबंधा हुआ है " - नियमित कार्यों में भी बाध्य है। मुद्दा यह है कि तीर के कार्यों में इसका कोई स्थानीय बंधन नहीं है।
एक बेहतर जैतून

2

लघु, आप तीर कार्यों को बाँध नहीं सकते , लेकिन इस पर पढ़ें:

कल्पना करें कि आपके पास यह तीर फ़ंक्शन है जो thisकंसोल पर प्रिंट करता है:

const myFunc = ()=> console.log(this);

तो इस के लिए जल्दी ठीक सामान्य कार्य का उपयोग किया जाएगा, तो बस इसे बदलने के लिए:

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

तो फिर तुम उपयोग कर किसी भी शाब्दिक पर्यावरण के लिए यह बाध्य कर सकते हैं bindया callया apply:

const bindedFunc = myFunc.bind(this);

और के मामले में यह कहते हैं bind

bindedFunc();

eval()इसे करने के लिए उपयोग करने के तरीके भी हैं , जो दृढ़ता से अनुशंसित नहीं हैं


function myFuncबाइंडेबल होने के अलावा व्यवहारिक रूप से अलग है; एक करीबी मैच होगा const myFunc = function() {...}। मैं भी उत्सुक हूं कि आप eval का उपयोग करने का क्या मतलब है, क्योंकि यह एक ऐसा तरीका है जो मुझे नहीं लगता कि किसी भी उत्तर ने पहले यहां साझा किया है - यह देखना दिलचस्प होगा कि यह कैसे किया जाता है, और फिर पढ़ें कि यह इतनी दृढ़ता से हतोत्साहित क्यों है।
फ्लोरीरी

1

शायद यह उदाहरण आपकी मदद करे:

let bob = {
   _name: "Bob",
   _friends: ["stackoverflow"],
   printFriends:(x)=> {
      x._friends.forEach((f)=> {
         console.log(x._name + " knows " + f);
      });
   }
}

bob.printFriends = (bob.printFriends).bind(null,bob);
bob.printFriends();


gøød सामान ... सौहार्दपूर्ण ढंग से
Aleks
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.