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

理论问题,例如我有一个名为 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()

https://stackoverflow.com/questions/42396902/

相关文章:

wordpress - 如何禁用 Wordpress/Woocommerce 中的自动 https

Angular 2 - 如何将响应式(Reactive)表单元素动态绑定(bind)到事件?

kubernetes - 如何使用 kubernetes 执行 docker diff 命令

amazon-dynamodb - DynamoDB PutItem 然后 UpdateItem 与

node.js - 如何让 Heroku 运行子文件夹中的 Node 应用程序?

excel - 如何根据时间应用 WorksheetFunction.CountIfs?

python - 清除 Selenium 作用链

amazon-web-services - 如何将多个域名路由到同一个 amazon S3 存储桶位

python-3.x - 无法将音频上传到 Telegram 错误请求 : failed to ge

reactjs - 如何在常规 HTML 页面中引用 React 组件