简体   繁体   English

Javascript 的字符串比较在底层是如何工作的?

[英]How does Javascript's string comparison work at the lower level?

Why does the comparison operator work faster regardless of the length of string?为什么无论字符串长度如何,比较运算符都运行得更快?

Consider the following two functions which I use to compare strings with a length of 100 million:考虑以下两个我用来比较长度为 1 亿的字符串的函数:

  1. With === :使用===

     // O(?) const compare1(a, b) { return a === b; }
  2. With character by character comparison:逐字比较:

     // O(N) const compare2(a, b) { if(a.length.== b;length) return false. const n = Math.max(a,length. b;length); for(var i=0; i<n; i++){ if(a[i];== b[i]) return false; } return true; }

When testing these two functions, I find that the speed of the compare1 function is significantly faster.在测试这两个函数时,我发现compare1 function的速度明显更快。

In the case of the compare2 function, I think the overhead will be severe in interpreting JavaScript code, accessing and comparing memory.对于compare2 function,我认为解释 JavaScript 代码、访问和比较 memory 的开销会很大。

But from my understanding, the compare1 function may also have to compare N characters.但据我了解, compare1 function 也可能要比较N个字符。 Does it run so much faster because it all happens at a lower level?它运行得如此之快是因为它都发生在较低的层次上吗?

There are two considerations:有两个考虑因素:

  • === comparison of string primitives is implemented with lower level, compiled code, which indeed executes faster than explicit JavaScript looping, which has additional work, including in updating a JavaScript variable ( i ), performing an access with that variable ( a[i] ); ===字符串基元的比较是用较低级别的编译代码实现的,它确实比显式 JavaScript 循环执行得更快,它有额外的工作,包括更新 JavaScript 变量( i ),执行对该变量的访问( a[i] ); where all the prescribed ECMAScript procedures must be followed.必须遵循所有规定的 ECMAScript 程序。

  • The JavaScript engine may optimise memory usage and use the knowledge that two strings are the same (for instance when that is already detected at parsing time, or one string is assigned to a second variable/property) and only store that string once (cf. String pool). JavaScript 引擎可以优化 memory 的使用并使用两个字符串相同的知识(例如,当在解析时已经检测到,或者一个字符串被分配给第二个变量/属性时)并且只存储该字符串一次(cf.字符串池)。 In that case the comparison is a trivial O(1) comparison of two references.在那种情况下,比较是两个引用的简单 O(1) 比较。 There is however no way in JavaScript to inspect whether two string primitives actually share the same memory.然而,在 JavaScript 中无法检查两个字符串基元是否实际上共享相同的 memory。

As an illustration of the second point, note how the comparison-time is different for two cases of comparing long strings that are equal -- which probably is a hint that this string pooling is happening:作为第二点的说明,请注意比较长字符串的两种情况下的比较时间是如何不同的——这可能暗示正在发生此字符串池:

 function compare(a, b) { let sum = 0, start, p; for (let i = 0; i < 10; i++) { // Perform 10 comparisons start = performance.now(); p = a === b; sum += performance.now() - start; } return sum / 10; // Return average time to make the comparison } console.log("Hold on while strings are being created..."); setTimeout(function () { // Create long, non-trivial string let a = Array.from({length: 10000000}, (_, i) => i).join(""); let b = a.slice(0); // Plain Copy - engine realises it is the same string & does not allocate space let c = a[0] + a.slice(1); // More complex - engine does not realise it is the same string console.log("Strings created. Test whether they are equal:", a === b && b === c); console.log(compare(a, b) + "ms"); console.log(compare(a, c) + "ms"); });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM