"सख्त का उपयोग करें" इस उदाहरण में प्रदर्शन 10x में सुधार क्यों करता है?


128

String.prototype प्रदर्शन का विस्तार करने के प्रश्न के बाद, मैं वास्तव में साज़िश कर रहा हूं, क्योंकि सिर्फ "use strict"एक String.prototypeविधि में सुधार करने से प्रदर्शन में 10 गुना सुधार हुआ है। स्पष्टीकरण द्वारा bergi कम है और मेरे लिए यह स्पष्ट नहीं होता। दो लगभग समान तरीकों के बीच इतना नाटकीय अंतर क्यों है, जो केवल "use strict"शीर्ष पर भिन्न है ? क्या आप इसके बारे में अधिक विस्तार से और इसके पीछे के सिद्धांत के साथ समझा सकते हैं?

String.prototype.count = function(char) {
  var n = 0;
  for (var i = 0; i < this.length; i++)
    if (this[i] == char) n++;
  return n;
};

String.prototype.count_strict = function(char) {
  "use strict";
  var n = 0;
  for (var i = 0; i < this.length; i++)
    if (this[i] == char) n++;
  return n;
};
// Here is how I measued speed, using Node.js 6.1.0

var STR = '0110101110010110100111010011101010101111110001010110010101011101101010101010111111000';
var REP = 1e4;

console.time('proto');
for (var i = 0; i < REP; i++) STR.count('1');
console.timeEnd('proto');

console.time('proto-strict');
for (var i = 0; i < REP; i++) STR.count_strict('1');
console.timeEnd('proto-strict');

परिणाम:

proto: 101 ms
proto-strict: 7.5 ms

1
क्या आप इसके साथ एक परीक्षण कर सकते हैं this[i] === charऔर देख सकते हैं कि क्या आपको समान अंतर मिलता है?
नीट द डार्क एबसोल

1
मैंने this[i] === charएक डोम के वातावरण में परीक्षण किया और परिणाम वही है
क्रिस्टियन ट्रेना

2
बर्गी का स्पष्टीकरण कहता है कि जब आप countफ़ंक्शन को कॉल करते हैं, तो thisपैरामीटर को एक स्ट्रिंग शाब्दिक के बजाय एक स्ट्रिंग ऑब्जेक्ट में डालना होता है जबकि सख्त मोड में इसे सही ढंग से संचालित करने के लिए नहीं होता है। यह मामला मेरे से परे क्यों है, मुझे जवाब में बहुत दिलचस्पी है।
निक लार्सन

3
@NickLarsen: यह सिर्फ भाषा कैसे spec'd था। परंपरागत रूप से जेएस यह सुनिश्चित करेगा कि आपके पास हमेशा एक वस्तु के रूप में था this, लेकिन सख्त मोड में यह उस कदम को छोड़ देता है, जिससे आपको आदिम स्ट्रिंग मिलती है , या जो कुछ भी प्रदान किया गया था this

6
यह "use strict";हर जगह लड़कों के लिए समय है ! ग्यूओल्ड
जोनाथन

जवाबों:


155

सख्त मोड में, thisसंदर्भ को ऑब्जेक्ट होने के लिए मजबूर नहीं किया जाता है। यदि आप किसी गैर-ऑब्जेक्ट पर एक फ़ंक्शन कहते हैं, thisतो बस वह गैर-ऑब्जेक्ट होगा।

इसके विपरीत, गैर-सख्त मोड में, thisसंदर्भ हमेशा एक वस्तु में लपेटा जाता है अगर यह पहले से ही एक वस्तु नहीं है। उदाहरण के लिए, (42).toString()पहले wraps 42एक में Numberवस्तु और फिर कॉल Number.prototype.toStringके साथ Numberके रूप में वस्तु thisसंदर्भ। सख्त मोड में, thisसंदर्भ को अछूता छोड़ दिया जाता है और बस संदर्भ के रूप में कॉल Number.prototype.toStringकिया 42जाता thisहै।

(function() {
  console.log(typeof this);
}).call(42); // 'object'

(function() {
  'use strict';
  console.log(typeof this);
}).call(42); // 'number'

आपके मामले में, गैर-सख्त मोड संस्करण ऑब्जेक्ट रैपर्स और बैक stringमें आदिम एस को रैप करने और अलिखित करने में बहुत समय व्यतीत करता है String। दूसरी ओर सख्त मोड संस्करण सीधे आदिम पर काम करता है string, जो प्रदर्शन में सुधार करता है।


1
और हटाने के withभी हर चर देखने के लिए थोड़ा मदद करता है iirc।
zzzzBov

2
@zzzzBov गलत है। बेहदwith मदद करता है हटाने के रूप में यह ब्राउज़र जो कारण चर अभिव्यक्ति किस चर को संदर्भित करने के लिए अनुमति देता है।
जॉन ड्वोरक

2
मुझे अचिंत्य लगता है कि गैर-वस्तु thisहमेशा वस्तु से "कठोर" है this
IllidanS4 चाहता है कि मोनिका वापस

2
@ IllidanS4: यह ज्यादातर मामलों में जहां के बारे में है thisहै nullया undefinedहै, जो खराब मोड में वैश्विक वस्तु होगा।
बरगी १

6
@ IllidanS4: यदि आप चाहें तो इसे "वास्तविक this" बनाम "रैपर this" के रूप में सोचें । ऑब्जेक्ट रैपर एक कीचड़ है जो कभी भी अस्तित्व में नहीं होना चाहिए, इसलिए यह समझ में आता है कि सख्त मोड संभव होने पर उन्हें अधिक से बचाएगा।
Ry-
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.