Javascript 中变量赋值和严格相等的工作原理,更深入一点

How variable assignment and strict equality work in Javascript, in a little more depth

我们都知道 JS 有 objects 和一组 primitives.

让我们检查以下作业。

a = 'foo';
b = a;
c = 'foo'
a === b; //true
a = b = c = undefined;

我多年来在 JS 中可视化变量赋值过程的方式是这样的。

一个新的原始字符串 foo 被创建并添加到内存位置。变量 a 现在指向内存中的那个位置。

变量b在内存中指向与a相同的位置,这意味着它指向foo

原始字符串foo已经存在于内存中,所以变量c只是指向那个

变量 ab 通过引用进行比较,这意味着唯一要检查的是它们是否指向内存中的相同位置,而不是它们的值是否相同。这意味着无论字符串有多长,这都应该是一个快速的操作。

变量abc都指向原语undefined。原语 foo 没有被任何变量指向,所以它被垃圾收集了。

以上所有内容也适用于对象属性。

我 101% 确定这就是 JS 的工作方式,直到今天我与一位同事交谈时他和我一样确信当比较两个变量时,即使是严格相等(===),它们按值比较而不是按引用

因此,如果我们必须比较两个都分配了非常大字符串的变量,例如

a = 'a huge string';
b = 'a huge string';
a === b; //true, takes 1ms

与只为两个变量分配一个字母字符串相比,这种相等性检查将花费更长的时间。例如

a = 'a small string';
b = 'a small string';
a === b; //true, takes 0.1ms

总结

我的要点(我的理解)是否有误?严格相等是否比较值而不是引用?

欢迎并鼓励技术性回答。

谢谢。

当您使用基本类型(数字、字符串、布尔值)时,您是在比较它们的值。

"string one" == "string one";  // true
3 == 3;  // true
false == false;  // true

即使是未定义的也类似:

undefined == undefined;  // true

例外是 NaN:

NaN == NaN;  // false

当你比较对象时,你比较的是它们的引用。例如:

var obj1 = { "name": "Charles" };
var obj2 = { "name": "Charles" };
obj1 == obj2;  // false
obj1 === obj2;  // false

根据 ECMAScript 规范,=== 比较值而不是引用,除非这些值是对象。

对于字符串比较,它们按字典顺序进行比较,如检查所有字符是否按相同顺序相等。

If x and y are exactly the same sequence of code units (same length and same code units at corresponding indices), return true; otherwise, return false.

这是 a === b 的通用算法:

// if both are undefined, return true
// if both are null, return true
// if both are numbers
//    if a is NaN, return false
//    if b is NaN, return false
//    if are equal numeric values, return true
//    if a is +0 and b is -0, return true
//    if b is +0 and a is -0, return true
//    return false
// if both are strings
//    if all chars equal and in the same order, return true
//    return false
// if both are booleans
//    if both are true or both are false, return true
//    return false
// if both are objects
//    if are equal references, return true
//    return false
// return false

我不久前写了一篇 small tool,它演示了 ===== 算法(根据 ES5 规范)可能会有所帮助。

现在,就重用已定义字符串的内存而言,例如您的 a = 'foo'c = 'foo' 示例出于效率原因指向同一内存,这是引擎可以进行的优化使事情变得更快但不是规范的一部分。

其实这个叫String Interning,很多语言都是这样做的