【问题标题】:Javascript object function parameters performanceJavascript对象函数参数性能
【发布时间】:2014-11-08 00:59:28
【问题描述】:

我阅读了一些关于当参数是对象时 javascript 函数参数传递如何工作的线程;我注意到在传递方法上有很多混淆,至少在术语上是这样的:pass-by-reference、pass-by-copy-reference 等等。 这个问题不是关于这个传递方法是如何命名的,或者它是如何在内部工作的,而是涉及到这个问题的某种答案。

我有一些非常大的对象,要作为参数传递给函数;我需要了解对象传递是否意味着对象的某些副本,因此内存消耗、计算量、内存泄漏风险与传递的对象的大小成正比,对于每个函数调用(我有很多调用),或者如果它以非大小比例的后果方式传递。

由于在函数中更改对象的属性会更改外部范围内的对象,但更改对象本身不会,因此我认为函数内部用于存储和“引用”参数的内存不取决于其大小,因为该对象似乎没有被复制,但我需要确定它。

对不起,我的英语解释得不好!

编辑:答案在某种程度上涉及对 JS 传递模式的洞察,但核心问题是实际案例的性能提升,所以任何理论信息都有用,但最重要的信息是关于计算和内存消耗.

用例 1(性能):假设我有一个函数访问其参数的两个成员,并在第三个成员上写入一些结果,在 1000 个不同的对象上执行 1000 次。问题是:如果对象仅由所涉及的 3 个属性组成,并且如果它具有其他 100 个属性,则假设循环将花费几乎相同的时间?仅由参数复制开销或通过选择较大对象内的属性会导致任何差异吗? 实际测试可能很大程度上取决于浏览器,因此我需要对此进行技术性、通用有效的回答。

用例 2:我有 100MB 的对象,传递给一个函数。在执行期间,我的内存占用增加了 100MB 吗?因此,任何引入的内存泄漏,例如由控制不当的外壳引起的,都更加危险。

【问题讨论】:

  • 在 javascript 中,所有复杂类型都是通过引用传递的,因此您将在函数内部进行的所有修改都将使用原始对象 => 复制不会产生额外的内存消耗
  • @shershen:现在你混淆了这些概念。参数永远不会通过引用传递,它们是通过值传递的。参数可以是引用,但仍是按值传递。

标签: javascript performance function object


【解决方案1】:

简短的回答是对象没有被复制,只是对对象的引用作为参数传递。

更准确的答案是,在 Javascript 中,所有参数都是按值传递的。对于像数字这样的简单类型,这意味着该值被复制。 For objects is 意味着对对象的引用被复制。

正如您所指出的,参数本身是一个独立副本,但参数指向的对象与您在调用函数时使用的变量相同。

编辑:

对于用例 1,唯一的区别在于从具有更多属性的对象访问属性。在少数或很多中定位属性的差异很小,您将看到的唯一实际差异来自这样一个事实,即当您遍历它们时必须将对象带入内存缓存,但这与传递它们无关到一个函数。

对于用例 2,对象没有重复,对象在内存中仍然只存在一次。

【讨论】:

  • 案例1,调用对象的函数在循环中,所以我想问一下,对象传递给内部函数的某些属性的恢复过程是否随着对象的大小越来越慢- 从这个意义上说,它涉及将其传递给函数。
  • @Nillus:是的,当然存在差异,但正如我所写的那样,差异很小。属性查找是使用哈希表之类的东西实现的,因此获取属性接近 O(1) 操作。如果有很多属性,有时您可能会遇到哈希冲突,那么它会查看两三个属性以找到正确的属性。您将无法衡量是否真的存在差异,因为较大的对象将如何影响内存缓存将对性能产生更大的影响。
  • 你能把你所说的“证明”链接起来吗? Ecma International 或 Mozila Developer Network 或 V8 源代码或其他一些受人尊敬的权威在哪里说的?实际上,现在您的解释无助于澄清“..参数不是通过引用传递..对术语的混淆..”并且看起来并不比@lexicore 的解释更好
  • @xmojmr:为什么你认为解释无助于澄清术语的混淆?答案非常准确,并准确地解释了它是如何工作的。
  • @Nillus:尽管 Javascript 没有指针,但对象变量包含类似于指向对象的指针的内容,无论内部如何实现。它在功能上与 C# 等托管语言中的引用非常相似,其中它是使用指针实现的,但该语言不允许您操作指针。在 Javascript 中将引用作为参数传递会复制引用,就像分配变量时一样。使用var a = {}; var b = a; 不会创建对象的副本以放置在变量b 中,您只会获得对同一对象的两个引用。
【解决方案2】:

请看这个答案:

Pass Variables by Reference in Javascript

简单来说,您的对象是“通过引用”传递的,从性能的角度来看,使用大对象或小对象调用函数应该没有区别。

话虽如此,整体性能取决于功能。它可能会复制对象、执行 AJAX 调用等,所有这些可能会或可能不会根据对象的大小执行不同的操作。

对于函数调用的性能,独占,应该没有区别。

【讨论】:

  • 您混淆了这些概念。该参数不是通过引用传递的。参数可以是引用,但总是按值传递。
  • 我不是在混音,我是在简化。请注意,我在以“简单来说”开头的句子中用引号写了“通过引用”。严格来说,您是对的,但我不确定这种严格性对于所提出的问题是否绝对必要。
  • 之所以提出这个问题,主要是因为对术语的所有混淆。
  • 从这个角度来看,你绝对是对的。我主要关注性能方面。
  • 性能取决于功能,很清楚。我在问,给定一个执行相同操作的函数,以相同次数访问其参数并写入相同次数,在大小对象的情况下执行时间相同,或者有一些开销更大?我想我可以假设大约没有实质性差异。我说的对吗?