当我们在 JavaScript 中将原语视为对象时会发生啥?
Posted
技术标签:
【中文标题】当我们在 JavaScript 中将原语视为对象时会发生啥?【英文标题】:What happens when we treat primitives as objects in JavaScript?当我们在 JavaScript 中将原语视为对象时会发生什么? 【发布时间】:2021-09-26 13:53:35 【问题描述】:我正在向javascript.info 学习 JS。现在我正在阅读Methods of primitives。
当我们运行以下代码时
let str = 'hello';
alert( str.toUpperCase() ); // HELLO
在内部发生以下情况 (1) 创建一个特殊对象 (2) 复制 str 变量的值 (3) 修改复制的版本 (4) 在不触及原始 str 变量的情况下返回复制的版本 (5) 最后销毁该特殊对象。
作者是这么说的。但是当我们有这样的东西时
let str = 'Hello';
console.log(str.toUpperCase()); // HELLO
console.log(str.split('l')); // (3) ["He", "", "o"]
console.log(str.startsWith('h')); // false
console.log(str.concat(' JavaScript')); // Hello JavaScript
console.log(str); // Hello
我只想知道,每次我们将原始对象视为对象时,是否都会创建一个特殊对象?从上面的代码中,我认为整个过程(创建一个对象,执行一些过程并销毁)执行了 4 次(因为我调用了 4 个方法)。
这是真的吗?
我也从中读到了以下内容
JavaScript 引擎高度优化了这个过程。它甚至可能完全跳过额外对象的创建。但它仍必须遵守规范并表现得好像它创造了规范一样。
这是什么意思?以上几行让我更加困惑整个过程完成了多少次。
【问题讨论】:
什么是“特殊对象”?是的,可能创建了许多对象,不查看源就无法知道,通常不应该关心。 感谢您的回答!我只想知道这个事实。现在我会继续前进:) 我不明白您所说的第 2 步“复制 str 变量的值”和 3“修改复制的版本”的意思。不涉及复制。 @Bergi 我认为复制是因为 str 变量的原始值在我调用 4 个方法后仍然保持不变。如果我错了,请纠正我。谢谢。 【参考方案1】:我只想知道,每次我们将原始对象视为对象时,是否都会创建一个特殊对象?我在想整个过程做了4次,因为我调用了4个方法。
是的,没错。
JavaScript 引擎高度优化了这个过程。它甚至可能完全跳过额外对象的创建。但它仍必须遵守规范并表现得好像它创造了规范一样。
什么意思?
这意味着创建 4 个对象是浪费 - 一个就足够了,而且您仍然会得到相同的结果(在这种情况下)。该规范是以“表现得好像”的方式编写的,它不规范 javascript 引擎的实现需要如何逐步工作,而只规范它需要具有的可观察行为。如果一个引擎足够聪明,知道它可以跳过一个步骤,例如做不必要的副本或创建未使用的对象,那么只要执行结果仍然相同,它就可以这样做。
对于原始值的方法调用,这是一个相对简单的优化 - 引擎不需要实际在内存中分配对象,它可以直接跳到在假设的特殊对象上查找属性的步骤.
【讨论】:
感谢您的回答。我只想知道这个事实,因为我认为每种方法的整个过程都会影响性能。并且还说JS引擎对这个过程进行了高度优化。这就是为什么我变得困惑。现在很清楚了。以上是关于当我们在 JavaScript 中将原语视为对象时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
当字符串在双引号内有单引号时,如何在Javascript中将此字符串转换为JSON对象