2012-01-07 5 views
20

जावास्क्रिप्ट प्रथम श्रेणी के कार्य होते हैं कथित है, इसलिए इस निम्नलिखित की तरह काम करना चाहिए लगता है:यदि जावास्क्रिप्ट में प्रथम श्रेणी के कार्य हैं, तो इस फ़ंक्शन को एक चरणीय काम में क्यों नहीं बुलाया जाता है?

var f = document.getElementById; 
var x = f('x'); 

लेकिन यह सभी ब्राउज़रों पर विफल रहता है, हर एक पर एक अलग गुप्त त्रुटि संदेश के साथ। सफारी कहते हैं "टाइप त्रुटि"। क्रोम कहता है "अवैध आमंत्रण"। फ़ायरफ़ॉक्स कहता है "जावास्क्रिप्ट तर्क को परिवर्तित नहीं कर सका"।

क्यों?

उत्तर

19

क्योंकि जावास्क्रिप्ट फ़ंक्शंस में बाध्य संदर्भ (this) पर हैं। आप bind() उपयोग कर सकते हैं:

var f = document.getElementById.bind(document); 
+4

'दस्तावेज़ में इस उत्तर,' this' स्पष्ट करने के लिए:

function f(){ return document.getElementById(...arguments); }; 

कोलाहल इस देता है .getElementById() '' दस्तावेज़ 'है, जबकि' यह 'जहां आप अपना दायरा निष्पादित कर रहे हैं वह वैश्विक दायरा है, उर्फ' यह 'विंडो' ऑब्जेक्ट है। –

36

जब आप जावास्क्रिप्ट में obj.method() पर कॉल करते हैं तो विधि objthis के रूप में पारित की जाती है। इसलिए document.getElementById('x') पर कॉलिंग this से document पर सेट करें।

लेकिन अगर तुम सिर्फ f = document.getElementById बारे में आप अब कार्य करने के लिए एक नया संदर्भ है, लेकिन है कि संदर्भ document करने के लिए "बाध्य" नहीं रह गया है।

तो आपका कोड काम नहीं करता है क्योंकि जब आप f को एक नंगे फ़ंक्शन नाम के रूप में कॉल करते हैं तो यह वैश्विक ऑब्जेक्ट (window) तक सीमित हो जाता है। जैसे ही फ़ंक्शन के अंदरूनी भाग this का उपयोग करने का प्रयास करते हैं, यह पता चलता है कि अब document के बजाय window है और यह आश्चर्यजनक रूप से इसे पसंद नहीं करता है।

var x = f.call(document, 'x'); 

जो f कॉल लेकिन स्पष्ट रूप से document के संदर्भ सेट:

आप f काम अगर आप इसे तो फोन कर सकते हैं।

var f = document.getElementById.bind(document); 

और वास्तव में अपने स्वयं के आवरण कि सही ढंग से संदर्भ सेट बनाने के लिए सिर्फ एक सामान्यीकृत शॉर्टकट है:

इसे ठीक करने के दूसरों के साथ वैसा Function.bind() जो ES5 में ही उपलब्ध है उपयोग करने के लिए है

function f(id) { 
    return document.getElementById(id); 
} 
3

ES6 के प्रसार के ऑपरेटर का उपयोग करके आप भी आजमा सकते हैं:

function f() { 
    var _document; 
    return (_document = document).getElementById.apply(_document, arguments); 
}; 
संबंधित मुद्दे

 संबंधित मुद्दे