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 中可视化变量赋值过程的方式是这样的。
a = 'foo';
一个新的原始字符串 foo
被创建并添加到内存位置。变量 a
现在指向内存中的那个位置。
b = a
变量b
在内存中指向与a
相同的位置,这意味着它指向foo
。
c = 'foo'
原始字符串foo
已经存在于内存中,所以变量c
只是指向那个
a === b; //true
变量 a
和 b
通过引用进行比较,这意味着唯一要检查的是它们是否指向内存中的相同位置,而不是它们的值是否相同。这意味着无论字符串有多长,这都应该是一个快速的操作。
a = b = c = undefined
变量a
、b
、c
都指向原语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,很多语言都是这样做的
我们都知道 JS 有 objects 和一组 primitives.
让我们检查以下作业。
a = 'foo';
b = a;
c = 'foo'
a === b; //true
a = b = c = undefined;
我多年来在 JS 中可视化变量赋值过程的方式是这样的。
a = 'foo';
一个新的原始字符串 foo
被创建并添加到内存位置。变量 a
现在指向内存中的那个位置。
b = a
变量b
在内存中指向与a
相同的位置,这意味着它指向foo
。
c = 'foo'
原始字符串foo
已经存在于内存中,所以变量c
只是指向那个
a === b; //true
变量 a
和 b
通过引用进行比较,这意味着唯一要检查的是它们是否指向内存中的相同位置,而不是它们的值是否相同。这意味着无论字符串有多长,这都应该是一个快速的操作。
a = b = c = undefined
变量a
、b
、c
都指向原语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,很多语言都是这样做的