javascript - 在javascript中将对象作为参数传递的性能

标签 javascript performance function object garbage-collection

理论问题,例如我有一个名为 Order 的大对象,它有大量的属性:字符串、数字、数组、嵌套对象。

我有一个函数:

function removeShipment(order) {
    order.shipment.forEach(
        // remove shipment action
    );
}

这意味着我只访问一个 prop (shipment),但发送了一个大对象。

从垃圾收集和性能的 Angular 来看,传递Order和传递Order.shipment有区别吗?

因为对象通过引用传递,实际上并没有将Order复制到变量中。

最佳答案

正如 ibrahim mahrir 在评论中所说——虽然我不知道他们为什么不发布答案,因为 OP 被激励选择“最佳答案”,因此选择了唯一的、令人困惑的回应——那里在将 order 传递给您的 removeShipment 方法或传递 order.shipment

之间没有实际的性能差异

这是因为 JavaScript 函数是原始类型的“按值传递”,例如 numberboolean,并且它使用一种称为“按值调用”的东西共享”用于传递对象引用的副本(例如您的 order 和假设您的 Array of shipments)。当作为参数传递时,不会复制整个对象,只是在内存中复制对它的引用。传递 orderorder.shipments 的两种方法实际上是相同的。

我确实为此编写了几个计时测试,但实际差异是如此之小,以致于编写一个甚至可以正确测量它的测试都异常困难。为了完整起见,我将在最后包含我的代码,但根据我在 Firefox 和 Chrome 中的有限测试,它们实际上是相同的,正如预期的那样。

与您的问题/答案相同的另一个问题/答案(以及关于为什么“微基准测试”通常不会产生正确结果的精彩视频)证实了我所写的内容,请参阅:does size of argument in a javascript function affects its performance?

请参阅此答案,了解“共享调用”的含义 Is JavaScript a pass-by-reference or pass-by-value language?


您没有具体说明“删除发货操作”实际上“意味着”什么。如果您只是想从订单对象中“删除所有货件”,您可以只执行 testOrder.shipments = []。如果没有别的东西可以到达他们,他们会在这之后的某个时候被垃圾收集。我只是要遍历每个并作为 stub 执行加法操作,否则我担心一切都会被优化掉。

// "num" between 0 inclusive & 26 exclusive
function letter(num)
{
    return String.fromCharCode(num + 65)
}

// Ships have a 3-letter name & a random value between 0 & 1
function getShipment() {
    return { "name": "Ship", "val": Math.random() }
}

// "order" has 100 "Shipments" 
// As well as 676 other named object properties with random "result" values
// e.g. order.AE => Object { result: 14.9815045239037 }
function getOrder() {
    var order = {}
    for (var i = 0; i < 26; i++) 
    for (var j = 0; j < 26; j++) {
        order[letter(i) + letter(j)] = { "result": (i+j) * Math.random() } 
    }
    order.shipments = Array.from({length: 100}).map(getShipment)
    return order
}

function removeShipmentOrder(order) {
    order.shipments.forEach(s => s.val++);
}

function removeShipmentList(shipmentList) {
    shipmentList.forEach(s => s.val++);
}

// Timing tests

var testOrder = getOrder();
console.time()
for(var i = 0; i < 1000000; i++)
    removeShipmentOrder(testOrder)
console.timeEnd()

// Break in-between tests; 
// Running them back-to-back, the second test always took longer.
// I assume it's actually due to some kind of compiler optimisation

var testOrder = getOrder();
console.time()
for(var i = 0; i < 1000000; i++)
    removeShipmentList(testOrder.shipments)
console.timeEnd()

关于javascript - 在javascript中将对象作为参数传递的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42396902/

相关文章:

javascript - 数组推送在数组 forEach 中不起作用 - Javascript

javascript - jQuery 图像 map 响应只有一种方式

c - 我如何制作一个 25 位宽的无符号整数和一个 bool 位?

R 用户定义的函数单独工作,但在与 apply 一起使用时返回不正确的值

javascript - 提交表单时清除特定字段(不是全部)

javascript - 用其他地方的重定向取代 Javascript 重定向

java - VTD XML (Java) VTDNavHuge 将 XPath 结果写入文件

c# - 减少 regex/linq 的 2 GB 内存占用或解决获取不同组值的问题

python - 在 Python 中获取第一个和最后一个函数参数

Wordpress Yoast Breadcrumb 代码 - 过滤器更改包装元素