Chrome 59 अपडेट: जैसा कि मैंने अनुमान लगाया था कि बाइंड के नीचे दिए गए उत्तर में अब नए ऑप्टिमाइज़िंग कंपाइलर के साथ धीमी गति नहीं है। यहाँ विवरण के साथ कोड है: https://codereview.chromium.org/2916063002/
ज्यादातर समय यह कोई फर्क नहीं पड़ता।
जब तक आप एक ऐसा एप्लिकेशन नहीं बना रहे हैं, जहां .bind
मुझे अड़चन नहीं है अधिकांश मामलों में पठनीयता की तुलना में पठनीयता अधिक महत्वपूर्ण है। मुझे लगता है कि देशी का उपयोग .bind
आमतौर पर अधिक पठनीय और बनाए रखने योग्य कोड के लिए प्रदान करता है - जो एक बड़ा प्लस है।
हालाँकि, जब यह मायने रखता है - .bind
धीमा है
हां, .bind
क्लोजर की तुलना में काफी धीमा है - कम से कम क्रोम में, कम से कम वर्तमान में जिस तरह से इसे लागू किया गया है v8
। मुझे व्यक्तिगत रूप से प्रदर्शन के मुद्दों के लिए Node.JS में स्विच करना पड़ा है (आमतौर पर, प्रदर्शन गहन स्थितियों में धीमे तरह के होते हैं)।
क्यों? क्योंकि .bind
किसी फ़ंक्शन को दूसरे फ़ंक्शन के साथ लपेटने और उपयोग करने .call
या करने की तुलना में एल्गोरिथ्म बहुत अधिक जटिल है .apply
। (मजेदार तथ्य, यह [देशी फ़ंक्शन] के लिए सेट स्ट्रिंग के साथ एक फ़ंक्शन भी देता है)।
इसे देखने के दो तरीके हैं, विनिर्देश के दृष्टिकोण से, और कार्यान्वयन के दृष्टिकोण से। चलो दोनों का निरीक्षण करते हैं।
- लक्ष्य इस मान होने दें।
- यदि IsCallable (लक्ष्य) गलत है, तो TypeError अपवाद फेंकें।
- आज्ञा देना एक नया (संभवतः खाली) इस तर्क के बाद प्रदान किए गए सभी तर्क मूल्यों की आंतरिक सूची (arg1, arg2 आदि), क्रम में।
...
(21. कॉल करें [[DefineOwnProperty]] F की आंतरिक विधि "दलीलें", तर्कों के साथ, प्रॉपर्टीस्क्रिप्ट {[प्राप्त करें]: फेंकने वाला, [[सेट]]: फेंकने वाला, [[सक्षम]]: झूठा, [[विन्यास योग्य] ]: झूठा}, और झूठा।
(22. रिटर्न एफ।
बहुत जटिल लगता है, सिर्फ एक लपेट से बहुत अधिक।
आइए FunctionBind
v8 (क्रोम जावास्क्रिप्ट इंजन) स्रोत कोड की जाँच करें :
function FunctionBind(this_arg) {
if (!IS_SPEC_FUNCTION(this)) {
throw new $TypeError('Bind must be called on a function');
}
var boundFunction = function () {
"use strict";
if (%_IsConstructCall()) {
return %NewObjectFromBound(boundFunction);
}
var bindings = %BoundFunctionGetBindings(boundFunction);
var argc = %_ArgumentsLength();
if (argc == 0) {
return %Apply(bindings[0], bindings[1], bindings, 2, bindings.length - 2);
}
if (bindings.length === 2) {
return %Apply(bindings[0], bindings[1], arguments, 0, argc);
}
var bound_argc = bindings.length - 2;
var argv = new InternalArray(bound_argc + argc);
for (var i = 0; i < bound_argc; i++) {
argv[i] = bindings[i + 2];
}
for (var j = 0; j < argc; j++) {
argv[i++] = %_Arguments(j);
}
return %Apply(bindings[0], bindings[1], argv, 0, bound_argc + argc);
};
%FunctionRemovePrototype(boundFunction);
var new_length = 0;
if (%_ClassOf(this) == "Function") {
var old_length = this.length;
if ((typeof old_length === "number") &&
((old_length >>> 0) === old_length)) {
var argc = %_ArgumentsLength();
if (argc > 0) argc--;
new_length = old_length - argc;
if (new_length < 0) new_length = 0;
}
}
var result = %FunctionBindArguments(boundFunction, this,
this_arg, new_length);
return result;
हम कार्यान्वयन में यहां महंगी चीजों का एक गुच्छा देख सकते हैं। अर्थात् %_IsConstructCall()
। यह निश्चित रूप से विनिर्देशन का पालन करने की आवश्यकता है - लेकिन यह कई मामलों में एक साधारण आवरण की तुलना में धीमी बनाता है।
किसी अन्य नोट पर, कॉलिंग .bind
भी थोड़ा अलग है, कल्पना नोट्स "फंक्शन ऑब्जेक्ट्स जो फंक्शन.प्रोटोटाइप.बाइंड का उपयोग करके बनाया गया है, उनके पास एक प्रॉपोटाइप प्रॉपर्टी या [[कोड]], [[फॉर्मलपैरमेटर्स]], और [[स्कोप] इंटरनल नहीं है] गुण"